Portable Executable 32 File Header And NT Header Structure
typedef struct {
uint32_t signature;
uint16_t cputype;
uint16_t objcnt;
uint32_t tdstamp;
uint32_t reserved1;
uint32_t reserved2;
uint16_t nthdrsize;
uint16_t flags;
uint16_t reserved3;
uint16_t lmajor;
uint16_t lminor;
uint16_t reserved4;
uint32_t reserved5;
uint32_t reserved6;
uint32_t entrypointrva;
uint32_t reserved7;
uint32_t reserved8;
uint32_t imagebase;
uint32_t objectalign;
uint32_t filealign;
uint16_t osmajor;
uint16_t osminor;
uint16_t usermajor;
uint16_t userminor;
uint16_t subsysmajor;
uint16_t subsysminor;
uint32_t reserved9;
uint32_t imagesize;
uint32_t hdrsize;
uint32_t filechecksum;
uint16_t subsystem;
uint16_t dllflags;
uint32_t stackreservesize;
uint32_t stackcommitsize;
uint32_t heapreservesize;
uint32_t heapcommitsize;
uint32_t reserved10;
uint32_t _rvasizes;
struct {
uint32_t rva;
uint32_t size;
} tables[];
} win32_pe32_fhdr;
#define WIN32_PE32_TABLE_EXPORT 0x00
#define WIN32_PE32_TABLE_IMPORT 0x01
#define WIN32_PE32_TABLE_RESOURCE 0x02
#define WIN32_PE32_TABLE_EXCEPTION 0x03
#define WIN32_PE32_TABLE_SECURITY 0x04
#define WIN32_PE32_TABLE_FIXUP 0x05
#define WIN32_PE32_TABLE_DEBUG 0x06
#define WIN32_PE32_TABLE_IMAGEDESC 0x07
#define WIN32_PE32_TABLE_MACHSPEC 0x08
#define WIN32_PE32_TABLE_THREADLOC 0x09
#define WIN32_PE32_TABLE_UNKNOWN1 0x0A
#define WIN32_PE32_TABLE_UNKNOWN2 0x0B
#define WIN32_PE32_TABLE_IMPORTADDR 0x0C
#define WIN32_PE32_TABLE_UNKNOWN3 0x0D
#define WIN32_PE32_TABLE_CLRRTHDR 0x0E
typedef struct {
uint32_t rva;
uint32_t size;
} win32_clr20_datadir;
/* http://ntcore.com/files/dotnetformat.htm */
typedef struct {
uint32_t cb;
uint16_t rtmajor;
uint16_t rtminor;
win32_clr20_datadir meta;
uint32_t flags;
uint32_t entrypointrva; /* entry point rva */
win32_clr20_datadir resources; /* resources */
win32_clr20_datadir strongnamsig; /* strong name signature */
win32_clr20_datadir codemantab; /* code manager table */
win32_clr20_datadir vtabfixups; /* vtable fixups */
win32_clr20_datadir exaddrtabjumps; /* export address table jumps */
} win32_clr20_hdr;
win32_pe32_fhdr *fhdr;
win32_pe32_ohdr *ohdr;
uint32_t pe_off;
/* get pe32 header offset */
pe_off = ((uint32_t*)(buffer + 0x3c))[0];
printf("peoff:%x\n", pe_off);
if(memcmp(buffer + pe_off, "PE\0\0", 4) == 0)
{
printf("Yes, this is a PE header.\n");
}else{
printf("No, this is not a PE header.\n");
}
fhdr = (win32_pe32_fhdr*)(buffer + pe_off);
printf("imagebase: %x\n", fhdr->imagebase);
printf("CLRRTHDR_RVA:%x\nCLRRTHDR_SIZE:%x\n",
fhdr->tables[WIN32_PE32_TABLE_CLRRTHDR].rva,
fhdr->tables[WIN32_PE32_TABLE_CLRRTHDR].size);
clr_rva = fhdr->tables[WIN32_PE32_TABLE_CLRRTHDR].rva;
clr_size = fhdr->tables[WIN32_PE32_TABLE_CLRRTHDR].size;
/*
The array of objects follow the headers. But, my header does
not include the size for the data dictionary array. So to
include that we get the number of entries in the data dictionary
and multiple this by eight since each one is eight bytes in PE32.
*/
ohdr = (win32_pe32_ohdr*)(buffer + pe_off + sizeof(win32_pe32_fhdr) + (fhdr->_rvasizes * 8));
/* find the object that the CLRRTHDR is in and point header there */
for(x = 0; x < fhdr->objcnt; ++x)
{
printf("object rva %x %s\n", ohdr[x].rva, &ohdr[x].name[0]);
if(clr_rva >= ohdr[x].rva)
{
/* calculating relative to file offset not memory */
clr_off = ohdr[x].poff + (clr_rva - ohdr[x].rva);
printf("found object for CLRRTHDR, with rva %x\n", ohdr[x].rva);
break;
}
}
clr_hdr = (uint8_t*)(buffer + clr_off);
printf("clr-metatable:%x [size:%x]\n", clr_hdr->meta.rva, clr_hdr->meta.size);
meta_rva = clr_hdr->meta.rva;
meta_size = clr_hdr->meta.size;
/* find the object that the metadata is in and point header there */
for(x = 0; x < fhdr->objcnt; ++x)
{
printf("object rva %x %s\n", ohdr[x].rva, &ohdr[x].name[0]);
if(meta_rva >= ohdr[x].rva)
{
/* calculating relative to file offset not memory */
meta_off = ohdr[x].poff + (meta_rva - ohdr[x].rva);
printf("found object for CLR-METADATA, with rva %x\n", ohdr[x].rva);
break;
}
}
/* offset is relative to our buffer so that (buffer + meta_off) is start and meta_size is size */