diff --git a/Makefile.in b/Makefile.in
index d013488..4ea6c36 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -156,7 +156,7 @@ PPNMOBJS = $(PPNMSRCS:.cpp=.o)
WAVPKSRCS = archive/wavpack_helper.c
WAVPKOBJS = $(WAVPKSRCS:.c=.o)
-DISPACKSRCS = filters/dispack/dis.cpp
+DISPACKSRCS = filters/dispack/dis.cpp archive/dispack_helper.cpp
DISPACKHDRS = filters/dispack/dis.hpp filters/dispack/types.hpp
DISPACKOBJS = $(DISPACKSRCS:.cpp=.o)
@@ -235,7 +235,7 @@ BASE_CPPFLAGS = -I. -I./lzma -I./lzfx -I./lz4 -I./rabin -I./bsdiff -DNODEFAULT_P
-I./crypto/scrypt -I./crypto/aes -I./crypto @KEYLEN@ -I./rabin/global \
-I./crypto/keccak -I./filters/transpose -I./crypto/blake2 $(EXTRA_CPPFLAGS) \
-I./crypto/xsalsa20 -I./archive -pedantic -Wall -I./filters -fno-strict-aliasing \
- -Wno-unused-but-set-variable -Wno-enum-compare -I./filters/analyzer \
+ -Wno-unused-but-set-variable -Wno-enum-compare -I./filters/analyzer -I./filters/dispack \
@COMPAT_CPPFLAGS@ @XSALSA20_DEBUG@ -I@LIBARCHIVE_DIR@/libarchive -I./filters/packjpg \
-I./filters/packpnm @ENABLE_WAVPACK@
COMMON_CPPFLAGS = $(BASE_CPPFLAGS) -std=gnu99
diff --git a/archive/dispack_helper.cpp b/archive/dispack_helper.cpp
new file mode 100644
index 0000000..ca2e55b
--- /dev/null
+++ b/archive/dispack_helper.cpp
@@ -0,0 +1,151 @@
+/*
+ * This file is a part of Pcompress, a chunked parallel multi-
+ * algorithm lossless compression and decompression program.
+ *
+ * Copyright (C) 2014 Moinak Ghosh. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program.
+ * If not, see .
+ *
+ * moinakg@belenix.org, http://moinakg.wordpress.com/
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "utils.h"
+#include "winsupport.h"
+#include "types.hpp"
+#include "dis.hpp"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned char uchar_t;
+
+#pragma pack(1)
+struct FileHeader
+{
+ sU32 SizeBefore; // number of bytes before start of code section
+ sU32 SizeAfter; // number of bytes after code section
+ sU32 SizeTransformed; // size of transformed code section
+ sU32 SizeOriginal; // size of untransformed code section
+ sU32 Origin; // virtual address of first byte
+};
+#pragma pack()
+
+size_t
+dispack_filter_encode(uchar_t *inData, size_t len, uchar_t **out_buf)
+{
+ uchar_t *pos;
+ FileHeader hdr;
+
+ *out_buf = (uchar_t *)malloc(len);
+ if (*out_buf == NULL)
+ return (0);
+
+ // assume the input file is a PE executable.
+ IMAGE_DOS_HEADER *doshdr = (IMAGE_DOS_HEADER *) inData;
+ IMAGE_NT_HEADERS *nthdr = (IMAGE_NT_HEADERS *) (inData + doshdr->e_lfanew);
+
+ if (nthdr->FileHeader.Machine != IMAGE_FILE_MACHINE_I386 ||
+ nthdr->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ // Only 32-bit PE files for x86 supported
+ return (0);
+ }
+
+ sU32 imageBase = nthdr->OptionalHeader.ImageBase;
+ sU32 codeStart = nthdr->OptionalHeader.BaseOfCode;
+ sU32 codeSize = nthdr->OptionalHeader.SizeOfCode;
+ sU32 fileOffs = 0; // find file offset of first section
+
+ // find section containing code
+ IMAGE_SECTION_HEADER *sec = IMAGE_FIRST_SECTION(nthdr);
+ for (sInt i=0;iFileHeader.NumberOfSections;i++) {
+ if (codeStart >= sec[i].VirtualAddress && codeStart <
+ sec[i].VirtualAddress + sec[i].SizeOfRawData)
+ fileOffs = sec[i].PointerToRawData + (codeStart - sec[i].VirtualAddress);
+ }
+
+ if (fileOffs == 0) {
+ // Code section not found!
+ return (0);
+ }
+
+ // Keep space for header
+ pos = *out_buf + sizeof (hdr);
+
+ // transform code
+ sU32 transSize = len - sizeof (hdr);
+ if (DisFilter(inData + fileOffs, codeSize, imageBase + codeStart, pos, transSize) == NULL)
+ return (0);
+ pos += transSize;
+
+ // Now plonk the header
+ hdr.SizeBefore = fileOffs;
+ hdr.SizeAfter = len - (fileOffs + codeSize);
+ hdr.SizeTransformed = transSize;
+ hdr.SizeOriginal = codeSize;
+ hdr.Origin = imageBase + codeStart;
+ memcpy(*out_buf, &hdr, sizeof (hdr));
+
+ // Copy rest of the data
+ memcpy(pos, inData, hdr.SizeBefore);
+ pos += hdr.SizeBefore;
+ memcpy(pos, inData + (fileOffs + codeSize), hdr.SizeAfter);
+ pos += hdr.SizeAfter;
+
+ return (pos - *out_buf);
+}
+
+size_t
+dispack_filter_decode(uchar_t *inData, size_t len, uchar_t **out_buf)
+{
+ uchar_t *decoded;
+ FileHeader *hdr = (FileHeader *)inData;
+
+ sU8 *transformed = inData + sizeof (FileHeader);
+ sU8 *before = transformed + hdr->SizeTransformed;
+ sU8 *after = before + hdr->SizeBefore;
+
+ // alloc buffer for unfiltered code
+ *out_buf = (uchar_t *)malloc(len);
+ if (*out_buf == NULL)
+ return (0);
+
+ decoded = *out_buf;
+ memcpy(decoded, before, hdr->SizeBefore);
+ decoded += hdr->SizeBefore;
+
+ if (!DisUnFilter(transformed, hdr->SizeTransformed, decoded,
+ hdr->SizeOriginal, hdr->Origin)) {
+ return (0);
+ }
+ decoded += hdr->SizeOriginal;
+ memcpy(decoded, after, hdr->SizeAfter);
+ decoded += hdr->SizeAfter;
+
+ return (decoded - *out_buf);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/archive/pc_arc_filter.c b/archive/pc_arc_filter.c
index b4121d1..55b9949 100644
--- a/archive/pc_arc_filter.c
+++ b/archive/pc_arc_filter.c
@@ -61,6 +61,10 @@ extern size_t wavpack_filter_decode(uchar_t *in_buf, size_t len, uchar_t **out_b
ssize_t wavpack_filter(struct filter_info *fi, void *filter_private);
#endif
+size_t dispack_filter_encode(uchar_t *inData, size_t len, uchar_t **out_buf);
+size_t dispack_filter_decode(uchar_t *inData, size_t len, uchar_t **out_buf);
+ssize_t dispack_filter(struct filter_info *fi, void *filter_private);
+
void
add_filters_by_type(struct type_data *typetab, struct filter_flags *ff)
{
@@ -90,6 +94,18 @@ add_filters_by_type(struct type_data *typetab, struct filter_flags *ff)
}
#endif
+ if (ff->exe_preprocess) {
+ if (!sdat) {
+ sdat = (struct scratch_buffer *)malloc(sizeof (struct scratch_buffer));
+ sdat->in_buff = NULL;
+ sdat->in_bufflen = 0;
+ }
+ slot = TYPE_EXE32_PE >> 3;
+ typetab[slot].filter_private = sdat;
+ typetab[slot].filter_func = dispack_filter;
+ typetab[slot].filter_name = "Dispack";
+ }
+
#ifdef _ENABLE_WAVPACK_
if (ff->enable_wavpack) {
if (!sdat) {
@@ -111,7 +127,7 @@ type_tag_from_filter_name(struct type_data *typetab, const char *fname, size_t l
{
size_t i;
- for (i = 0; i < NUM_SUB_TYPES; i++)
+ for (i = 0; i <= NUM_SUB_TYPES; i++)
{
if (typetab[i].filter_name &&
strncmp(fname, typetab[i].filter_name, len) == 0)
@@ -507,3 +523,103 @@ wavpack_filter(struct filter_info *fi, void *filter_private)
}
#endif /* _ENABLE_WAVPACK_ */
+ssize_t
+dispack_filter(struct filter_info *fi, void *filter_private)
+{
+ struct scratch_buffer *sdat = (struct scratch_buffer *)filter_private;
+ uchar_t *mapbuf, *out;
+ uint64_t len, in_size = 0, len1;
+
+ len = archive_entry_size(fi->entry);
+ len1 = len;
+ if (len > WVPK_FILE_SIZE_LIMIT) // Bork on massive files
+ return (FILTER_RETURN_SKIP);
+
+ if (fi->compressing) {
+ mapbuf = mmap(NULL, len, PROT_READ, MAP_SHARED, fi->fd, 0);
+ if (mapbuf == NULL) {
+ log_msg(LOG_ERR, 1, "Mmap failed in Dispack filter.");
+ return (FILTER_RETURN_ERROR);
+ }
+
+ /*
+ * No check for supported 32-bit exe here. EXE types are always
+ * detected by file header analysis. So no need to duplicate here.
+ */
+ } else {
+ /*
+ * Allocate input buffer and read archive data stream for the entry
+ * into this buffer.
+ */
+ ensure_buffer(sdat, len);
+ if (sdat->in_buff == NULL) {
+ log_msg(LOG_ERR, 1, "Out of memory.");
+ return (FILTER_RETURN_ERROR);
+ }
+
+ in_size = copy_archive_data(fi->source_arc, sdat->in_buff);
+ if (in_size != len) {
+ log_msg(LOG_ERR, 0, "Failed to read archive data.");
+ return (FILTER_RETURN_ERROR);
+ }
+
+ /*
+ * First 8 bytes in the data is the compressed size of the entry.
+ * LibArchive always zero-pads entries to their original size so
+ * we need to separately store the compressed size.
+ */
+ in_size = LE64(U64_P(sdat->in_buff));
+ mapbuf = sdat->in_buff + 8;
+
+ /*
+ * No check for supported EXE types needed here since supported
+ * and filtered files are tagged in the archive using xattrs during
+ * compression.
+ */
+ }
+
+ /*
+ * Compression case.
+ */
+ if (fi->compressing) {
+ out = NULL;
+ len = dispack_filter_encode(mapbuf, len, &out);
+ if (len == 0 || len >= (len1 - 8)) {
+ munmap(mapbuf, len1);
+ free(out);
+ return (FILTER_RETURN_SKIP);
+ }
+ munmap(mapbuf, len1);
+
+ fi->fout->output_type = FILTER_OUTPUT_MEM;
+ fi->fout->out = out;
+ fi->fout->out_size = len;
+ fi->fout->hdr.in_size = LE64(len1);
+ return (ARCHIVE_OK);
+ }
+
+ /*
+ * Decompression case.
+ */
+ out = NULL;
+ if ((len = dispack_filter_decode(mapbuf, in_size, &out)) == 0) {
+ /*
+ * If filter failed we indicate a soft error to continue the
+ * archive extraction.
+ */
+ free(out);
+ out = malloc(len);
+ memcpy(out, sdat->in_buff, len);
+
+ fi->fout->output_type = FILTER_OUTPUT_MEM;
+ fi->fout->out = out;
+ fi->fout->out_size = len;
+ return (FILTER_RETURN_SOFT_ERROR);
+ }
+
+ fi->fout->output_type = FILTER_OUTPUT_MEM;
+ fi->fout->out = out;
+ fi->fout->out_size = len;
+ return (ARCHIVE_OK);
+}
+
diff --git a/archive/pc_arc_filter.h b/archive/pc_arc_filter.h
index 9bda44f..8978a64 100644
--- a/archive/pc_arc_filter.h
+++ b/archive/pc_arc_filter.h
@@ -90,6 +90,7 @@ struct filter_info {
struct filter_flags {
int enable_packjpg;
int enable_wavpack;
+ int exe_preprocess;
};
typedef ssize_t (*filter_func_ptr)(struct filter_info *fi, void *filter_private);
diff --git a/archive/pc_archive.c b/archive/pc_archive.c
index dfe0ba5..7da9608 100644
--- a/archive/pc_archive.c
+++ b/archive/pc_archive.c
@@ -63,7 +63,7 @@ static struct ext_hash_entry {
int type;
} *exthtab = NULL;
-static struct type_data typetab[NUM_SUB_TYPES];
+static struct type_data typetab[NUM_SUB_TYPES+1];
/*
AE_IFREG Regular file
@@ -1100,6 +1100,7 @@ copy_file_data(pc_ctx_t *pctx, struct archive *arc, struct archive_entry *entry,
&fout, 1, pctx->level);
if (rv != FILTER_RETURN_SKIP &&
rv != FILTER_RETURN_ERROR) {
+ pctx->ctype = TYPE_UNKNOWN; // Force analyzer on filter output
if (fout.output_type == FILTER_OUTPUT_MEM) {
archive_entry_xattr_add_entry(entry, FILTER_XATTR_ENTRY,
fname, strlen(fname));
@@ -1176,6 +1177,7 @@ do_map:
&fout, 1, pctx->level);
if (rv != FILTER_RETURN_SKIP &&
rv != FILTER_RETURN_ERROR) {
+ pctx->ctype = TYPE_UNKNOWN; // Force analyzer on filter output
if (fout.output_type == FILTER_OUTPUT_MEM) {
archive_entry_xattr_add_entry(entry,
FILTER_XATTR_ENTRY,
@@ -1997,7 +1999,7 @@ detect_type_by_data(uchar_t *buf, size_t len)
if (id == 0x8664)
return (TYPE_BINARY|TYPE_EXE64);
else
- return (TYPE_BINARY|TYPE_EXE32);
+ return (TYPE_BINARY|TYPE_EXE32_PE);
} else {
return (TYPE_BINARY);
}
diff --git a/filters/dispack/dis.cpp b/filters/dispack/dis.cpp
index 9273435..113281b 100644
--- a/filters/dispack/dis.cpp
+++ b/filters/dispack/dis.cpp
@@ -637,10 +637,10 @@ struct DisFilterCtx
/****************************************************************************/
-static sU8 *
-DisFilter(DisFilterCtx &ctx, sU8 *src, sU32 size, sU32 origin, sU8 *dst, sU32 &outputSize)
+sU8 *
+DisFilter(sU8 *src, sU32 size, sU32 origin, sU8 *dst, sU32 &outputSize)
{
-// DisFilterCtx ctx(origin,origin+size);
+ DisFilterCtx ctx(origin,origin+size);
// main loop: handle everything but the last few bytes
sU32 pos = 0;
@@ -707,7 +707,7 @@ static inline sU32 Copy32(sU8 *&d,sU8 *&s) { sU32 v = Fetch32B(s); Write32(d,
#define Copy16Chk(strm) do { CheckSrcDst(strm,2); Copy16(dest,stream[strm]); } while(0)
#define Copy32Chk(strm) do { CheckSrcDst(strm,4); Copy32(dest,stream[strm]); } while(0)
-static sBool
+sBool
DisUnFilter(sU8 *source,sU32 sourceSize,sU8 *dest,sU32 destSize,sU32 memStart)
{
sU8 *stream[ST_MAX];
@@ -902,6 +902,10 @@ DisUnFilter(sU8 *source,sU32 sourceSize,sU8 *dest,sU32 destSize,sU32 memStart)
return sTRUE;
}
+/*
+ * NOTE: function unused. Retained for future need.
+ */
+#if 0
/*
* Try to estimate if the given data block contains 32-bit x86 instructions
* especially of the call and jmp variety.
@@ -926,6 +930,7 @@ is_x86_code(uchar_t *buf, int len)
avgFreq = ln>>8;
return (freq[0x8b] > avgFreq && freq[0x00] > avgFreq * 2 && freq[0xE8] > 6);
}
+#endif
#ifdef __cplusplus
extern "C" {
@@ -1007,6 +1012,10 @@ Inverse_E89(uint8_t *src, uint64_t sz)
return (0);
}
+/*
+ * NOTE: function unused. Retained for future need.
+ */
+#if 0
/*
* 32-bit x86 executable packer top-level routines. Detected x86 executable data
* are passed through these encoding routines. The data chunk is split into 32KB
@@ -1106,7 +1115,12 @@ dispack_encode(uchar_t *from, uint64_t fromlen, uchar_t *to, uint64_t *dstlen)
#endif
return (0);
}
+#endif
+/*
+ * This function retained for ability to decode older archives encoded using raw block
+ * dispack.
+ */
int
dispack_decode(uchar_t *from, uint64_t fromlen, uchar_t *to, uint64_t *dstlen)
{
diff --git a/filters/dispack/dis.hpp b/filters/dispack/dis.hpp
index 73c8da7..723c044 100644
--- a/filters/dispack/dis.hpp
+++ b/filters/dispack/dis.hpp
@@ -26,12 +26,12 @@
#define __DIS_HPP__
#include
+#include "types.hpp"
#ifdef __cplusplus
extern "C" {
#endif
-int dispack_encode(uchar_t *from, uint64_t fromlen, uchar_t *to, uint64_t *_dstlen);
int dispack_decode(uchar_t *from, uint64_t fromlen, uchar_t *to, uint64_t *dstlen);
int Forward_E89(uint8_t *src, uint64_t sz);
@@ -41,4 +41,9 @@ int Inverse_E89(uint8_t *src, uint64_t sz);
}
#endif
+#ifdef __cplusplus
+sU8 *DisFilter(sU8 *src, sU32 size, sU32 origin, sU8 *dst, sU32 &outputSize);
+sBool DisUnFilter(sU8 *source,sU32 sourceSize,sU8 *dest,sU32 destSize,sU32 memStart);
+#endif
+
#endif
diff --git a/filters/dispack/types.hpp b/filters/dispack/types.hpp
index f672e1f..c382f98 100644
--- a/filters/dispack/types.hpp
+++ b/filters/dispack/types.hpp
@@ -39,12 +39,14 @@ typedef uint64_t sU64;
typedef int64_t sS64;
typedef int sInt;
typedef char sChar;
-typedef bool sBool;
typedef float sF32;
typedef double sF64;
+#ifdef __cplusplus
+typedef bool sBool;
#define sTRUE true
#define sFALSE false
+#endif
#define _byteswap_ushort htons
#define _byteswap_ulong htonl
diff --git a/pcompress.c b/pcompress.c
index 817592f..4458b3f 100644
--- a/pcompress.c
+++ b/pcompress.c
@@ -223,7 +223,6 @@ preproc_compress(pc_ctx_t *pctx, compress_func_ptr cmp_func, void *src, uint64_t
stype = PC_SUBTYPE(btype);
dict = 0;
analyzed = 0;
-
if (btype == TYPE_UNKNOWN || stype == TYPE_ARCHIVE_TAR || stype == TYPE_PDF || interesting) {
analyze_buffer(src, srclen, &actx);
analyzed = 1;
@@ -3140,6 +3139,7 @@ init_pc_context(pc_ctx_t *pctx, int argc, char *argv[])
pctx->advanced_opts = 0;
ff.enable_packjpg = 0;
ff.enable_wavpack = 0;
+ ff.exe_preprocess = 0;
pthread_mutex_lock(&opt_parse);
while ((opt = getopt(argc, argv, "dc:s:l:pt:MCDGEe:w:LPS:B:Fk:avmKjxiTn")) != -1) {
@@ -3315,6 +3315,7 @@ init_pc_context(pc_ctx_t *pctx, int argc, char *argv[])
case 'x':
pctx->advanced_opts = 1;
pctx->exe_preprocess = 1;
+ ff.exe_preprocess = 1;
break;
case 'T':
@@ -3625,10 +3626,13 @@ init_pc_context(pc_ctx_t *pctx, int argc, char *argv[])
ff.enable_packjpg = 1;
ff.enable_wavpack = 1;
}
+ if (pctx->level > 8) {
+ pctx->exe_preprocess = 1;
+ ff.exe_preprocess = 1;
+ }
init_filters(&ff);
pctx->enable_packjpg = ff.enable_packjpg;
pctx->enable_wavpack = ff.enable_wavpack;
- if (pctx->level > 8) pctx->exe_preprocess = 1;
}
/*
@@ -3658,8 +3662,10 @@ init_pc_context(pc_ctx_t *pctx, int argc, char *argv[])
*/
ff.enable_packjpg = 1;
ff.enable_wavpack = 1;
+ ff.exe_preprocess = 1;
pctx->enable_packjpg = 1;
pctx->enable_wavpack = 1;
+ pctx->exe_preprocess = 1;
init_filters(&ff);
}
pctx->inited = 1;
diff --git a/utils/utils.h b/utils/utils.h
index e1bf39d..73de3c2 100644
--- a/utils/utils.h
+++ b/utils/utils.h
@@ -278,7 +278,7 @@ typedef enum {
/*
* Sub-types.
*/
-#define NUM_SUB_TYPES 34
+#define NUM_SUB_TYPES 35
TYPE_EXE32 = 8,
TYPE_JPEG = 16,
TYPE_MARKUP = 24,
@@ -312,7 +312,8 @@ typedef enum {
TYPE_PACKPNM = 248,
TYPE_WAV = 256,
TYPE_ENGLISH = 264,
- TYPE_MEDIA_BSC = 272
+ TYPE_MEDIA_BSC = 272,
+ TYPE_EXE32_PE = 280
} data_type_t;
/*
diff --git a/utils/winsupport.h b/utils/winsupport.h
new file mode 100644
index 0000000..1f759c0
--- /dev/null
+++ b/utils/winsupport.h
@@ -0,0 +1,143 @@
+/*
+ * This file is a part of Pcompress, a chunked parallel multi-
+ * algorithm lossless compression and decompression program.
+ *
+ * Copyright (C) 2014 Moinak Ghosh. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program.
+ * If not, see .
+ *
+ * moinakg@belenix.org, http://moinakg.wordpress.com/
+ *
+ */
+
+#ifndef __WINSUPPORT_H__
+#define __WINSUPPORT_H__
+
+/*
+ * Windows data types.
+ */
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int DWORD;
+typedef long LONG;
+typedef int INT;
+
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
+#define IMAGE_SIZEOF_SHORT_NAME 8
+#define IMAGE_FILE_MACHINE_I386 0x014c
+#define IMAGE_FILE_MACHINE_AMD64 0x8664
+#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
+#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
+
+typedef struct _IMAGE_DOS_HEADER
+{
+ WORD e_magic;
+ WORD e_cblp;
+ WORD e_cp;
+ WORD e_crlc;
+ WORD e_cparhdr;
+ WORD e_minalloc;
+ WORD e_maxalloc;
+ WORD e_ss;
+ WORD e_sp;
+ WORD e_csum;
+ WORD e_ip;
+ WORD e_cs;
+ WORD e_lfarlc;
+ WORD e_ovno;
+ WORD e_res[4];
+ WORD e_oemid;
+ WORD e_oeminfo;
+ WORD e_res2[10];
+ INT e_lfanew;
+} IMAGE_DOS_HEADER;
+
+typedef struct _IMAGE_DATA_DIRECTORY {
+ DWORD VirtualAddress;
+ DWORD Size;
+} IMAGE_DATA_DIRECTORY;
+
+typedef struct _IMAGE_SECTION_HEADER {
+ BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ DWORD PhysicalAddress;
+ DWORD VirtualSize;
+ } Misc;
+ DWORD VirtualAddress;
+ DWORD SizeOfRawData;
+ DWORD PointerToRawData;
+ DWORD PointerToRelocations;
+ DWORD PointerToLinenumbers;
+ WORD NumberOfRelocations;
+ WORD NumberOfLinenumbers;
+ DWORD Characteristics;
+} IMAGE_SECTION_HEADER;
+
+typedef struct _IMAGE_FILE_HEADER {
+ WORD Machine;
+ WORD NumberOfSections;
+ DWORD TimeDateStamp;
+ DWORD PointerToSymbolTable;
+ DWORD NumberOfSymbols;
+ WORD SizeOfOptionalHeader;
+ WORD Characteristics;
+} IMAGE_FILE_HEADER;
+
+typedef struct _IMAGE_OPTIONAL_HEADER {
+ WORD Magic;
+ BYTE MajorLinkerVersion;
+ BYTE MinorLinkerVersion;
+ DWORD SizeOfCode;
+ DWORD SizeOfInitializedData;
+ DWORD SizeOfUninitializedData;
+ DWORD AddressOfEntryPoint;
+ DWORD BaseOfCode;
+ DWORD BaseOfData;
+ DWORD ImageBase;
+ DWORD SectionAlignment;
+ DWORD FileAlignment;
+ WORD MajorOperatingSystemVersion;
+ WORD MinorOperatingSystemVersion;
+ WORD MajorImageVersion;
+ WORD MinorImageVersion;
+ WORD MajorSubsystemVersion;
+ WORD MinorSubsystemVersion;
+ DWORD Win32VersionValue;
+ DWORD SizeOfImage;
+ DWORD SizeOfHeaders;
+ DWORD CheckSum;
+ WORD Subsystem;
+ WORD DllCharacteristics;
+ DWORD SizeOfStackReserve;
+ DWORD SizeOfStackCommit;
+ DWORD SizeOfHeapReserve;
+ DWORD SizeOfHeapCommit;
+ DWORD LoaderFlags;
+ DWORD NumberOfRvaAndSizes;
+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} IMAGE_OPTIONAL_HEADER;
+
+typedef struct _IMAGE_NT_HEADERS {
+ DWORD Signature;
+ IMAGE_FILE_HEADER FileHeader;
+ IMAGE_OPTIONAL_HEADER OptionalHeader;
+} IMAGE_NT_HEADERS;
+
+#define IMAGE_FIRST_SECTION(ntheader) \
+ ((IMAGE_SECTION_HEADER *)((unsigned char *)&((IMAGE_NT_HEADERS *)(ntheader))->OptionalHeader + \
+ ((IMAGE_NT_HEADERS *)(ntheader))->FileHeader.SizeOfOptionalHeader))
+
+#endif