typedef struct _IMAGE_DOS_HEADER { WORD e_magic; // 5A4D WORD e_cblp; // 0090 WORD e_cp; // 0003 WORD e_crlc; // 0000 WORD e_cparhdr; // 0004 WORD e_minalloc; // 0000 WORD e_maxalloc; // FFFF WORD e_ss; // 0000 WORD e_sp; // 00B8 WORD e_csum; // 0000 WORD e_ip; // 0000 WORD e_cs; // 0000 WORD e_lfarlc; // 0040 WORD e_ovno; // 0000 WORD e_res[4]; // 0000000000000000 WORD e_oemid; // 0000 WORD e_oeminfo; // 0000 WORD e_res2[10]; // 0000000000000000000000000000000000000000 DWORD e_lfanew; // 000000E0 }IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
上面是打开Windows XP环境下的notepad.exe文件显示的对应IMAGE_DOS_HEADER -----> DOS头 下面是winhex非运行情况下在硬盘打开查看对应的位置
上面选中的部分就是DOS头,对应工具的显示
后面就是DOS Stub数据,这里的数据在现在的常用系统来看是没用的,有的人成为垃圾数据,因为这是微软在设计的时候给16位系统设计使用的,知道就可以,下面选中的部分是对应winhex展示
从上面来看到PE Signature之前是站16进制的D0 ---> 十进制208 --> 208/4=52 这个52表示在winhex里面要以每4个字节进行移动,因为每行winhex是4x4=16个字节,所以再除以4 ---> 52/4=13 ,那么就可以在文件的起始位置向下数13行即可
即:00000000 ----> 000000D0 刚好13行,然后下面就是PE Signature ;
PE Signature和PE标准文件头代码
typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; }IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; DWORD Signature; 4个字节 0x00004550 typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; }IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
上面是选中的PE Signature 0x00004550 ;根据上述代码 _IMAGE_FILE_HEADER 结构体里面含有3个DWORD 4个WORD 总共算起来理解为5个DWORD,也就是5个4字节的宽度,4x5=20个字节,那么算的按照行来算好找些,向后数5个4字节内容即可
上面选中的就是_IMAGE_FILE_HEADER说站的宽度,下面是对应工具的展示
到了这里就要开始找_IMAGE_OPTIONAL_HEADER 就是可选PE头数据,因为可选PE头数据每个不同的应用程序都不一样,所以是不确定的,但是在上面的IMAGE_FILE_HEADER的倒数第二个字段SizeOfOptionHeader已经给出了可选PE头对齐前的实际大小宽度 ---> 00E0 --> 224 --> 224/4 = 56 --> 56/4=14 这里跟上面计算到PE Signature是一样的方法 ,所以得出结论就是从000000F8位置向后移动224字节,也就是按照行来算移动14行
上图选中的部分就是可选PE头数据,后面就是节表了,至此我们就找到了节表的起始位置
上图是对应的工具解析的可选PE头数据,不过我们发现后面还有一段数据,过来之后再到节表的起始位置,对应上图有字段的数据部分
没有字段的部分