不识庐山真面目 只缘身在此山中(编写PE)

发布时间:2010-09-18 21:12:12   来源:文档文库   
字号:

不识庐山真面目 只缘身在此山中

#include
void main()
{
    MessageBoxA(0,"Hello World ",0,0);
}
VC6编译运行上面的代码,你会发现简单显示下面这一个提示,背景是MS-DOS,点击确定后退出。

你可能说嘿!太简单了,谁都会写。你用WinHex工具打开编译后的EXE看看,全是数字,可能会让你晕,为什么会变成这样呢,因为上面的C代码仅是数字与字母的组合,计算机不可能运行的,我们都知道它运行的是机器码。那怎么办?这就是VC6要做的事,它帮我们把容易理解的C代码转换成相应的机器码,并用一定的格式放存在磁盘里。双击附件里的helloworld.exe,你会发现显示一样的界面,但这个不是由上面C代码编译生成的哦,是我一个一个机器码写成的。要写这么多数字,你一定怕了,别担心,经过下面我的解析,你也可以做得到。

先看看什么是PE?我们用C\\C++ASM编译连接后能运行的程序就是PE,如后缀为exe,dll,sys等有相以结构的都称为PE。编写程序我们可以像下面的机器码一样直接写,但为什么还要编译器,还有编程语言?大家可以看看下面的图,可以发现全是机器码,我们很难理解是做什么用的,如果我们直接写,那么一但错了一个数字都会出问题,并且很难发现,有了编译器就可以帮我做一些检查,帮我们生成标准的PE结构。

VC6WinHex打开helloworld.exe看到的像下面的图

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00000000   4D 5A 00 00 00 00 00 00  00 00 00 00 00 00 00 00   MZ..............
00000010   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000020   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000030   00 00 00 00 00 00 00 00  00 00 00 00 B0 00 00 00   ............?...
00000040   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000050   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000060   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000070   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000080   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000090   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000000A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000000B0   50 45 00 00 4C 01 03 00  00 00 00 00 00 00 00 00   PE..L...........
000000C0   00 00 00 00 E0 00 02 00  0B 01 00 00 00 00 00 00   ....?...........
000000D0   00 00 00 00 00 00 00 00  00 10 00 00 00 00 00 00   ................
000000E0   00 00 00 00 00 00 40 00  00 10 00 00 00 02 00 00   ......@.........
000000F0   00 00 00 00 00 00 00 00  04 00 00 00 00 00 00 00   ................
00000100   00 40 00 00 00 04 00 00  00 00 00 00 02 00 00 00   .@..............
00000110   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000120   00 00 00 00 10 00 00 00  00 00 00 00 00 00 00 00   ................
00000130   00 20 00 00 00 00 00 00  00 00 00 00 00 00 00 00   . ..............
00000140   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000150   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000160   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000170   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000180   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000190   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000001A0   00 00 00 00 00 00 00 00  2E 74 65 78 74 00 00 00   ........ .text...
000001B0   00 00 00 00 00 10 00 00   00 02 00 00 00 04 00 00   ................
000001C0   00 00 00 00 00 00 00 00  00 00 00 00 20 00 00 60   ............ ..`
000001D0   2E 69 64 61 74 61 00 00  00 00 00 00 00 20 00 00   .idata....... ..
000001E0   00 02 00 00 00 06 00 00  00 00 00 00 00 00 00 00   ................
000001F0   00 00 00 00 40 00 00 40  2E 64 61 74 61 00 00 00   ....@..@.data...
00000200   00 00 00 00 00 30 00 00  00 02 00 00 00 08 00 00   .....0..........
00000210   00 00 00 00 00 00 00 00  00 00 00 00 40 00 00 C0   ............@..?
00000220   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000230   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000240   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000250   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000260   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000270   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000280   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000290   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000002A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000002B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000002C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000002D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000002E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000002F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000300   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000310   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000320   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000330   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000340   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000350   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000360   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000370   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000380   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000390   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000003A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000003B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000003C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000003D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000003E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000003F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000400   55 8B EC 6A 00 6A 00 68  00 30 40 00 6A 00 FF 15   Uj.j.h.0@.j ..
00000410   40 20 40 00 8B E5 5D C3  00 00 00 00 00 00 00 00   @ @.]?.......
00000420   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000430   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000440   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000450   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000460   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000470   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000480   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000490   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000004A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000004B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000004C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000004D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000004E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000004F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000500   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000510   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000520   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000530   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000540   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000550   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000560   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000570   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000580   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000590   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000005A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000005B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000005C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000005D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000005E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000005F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000600   30 20 00 00 00 00 00 00  00 00 00 00 70 20 00 00   0 ..........p ..
00000610   40 20 00 00 00 00 00 00  00 00 00 00 00 00 00 00   @ ..............
00000620   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000630   60 20 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ` ..............
00000640   60 20 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ` ..............
00000650   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000660   00 00 4D 65 73 73 61 67  65 42 6F 78 41 00 00 00   ..MessageBoxA...
00000670   75 73 65 72 33 32 2E 64  6C 6C 00 00 00 00 00 00   user32.dll ......
00000680   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000690   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000006A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000006B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000006C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000006D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000006E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000006F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000700   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000710   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000720   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000730   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000740   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000750   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000760   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000770   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000780   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000790   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000007A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000007B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000007C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000007D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000007E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000007F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000800   48 65 6C 6C 6F 20 57 6F  72 6C 64 00 00 00 00 00   Hello World.....
00000810   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000820   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000830   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000840   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000850   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000860   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000870   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000880   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000890   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000008A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000008B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000008C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000008D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000008E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000008F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000900   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000910   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000920   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000930   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000940   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000950   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000960   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000970   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000980   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
00000990   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000009A0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000009B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000009C0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000009D0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000009E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
000009F0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

上面的PE图用了不同的色彩表示不同的结构,基本PE结构像这样的
                    IMAGE_DOS_HEADER  40h字节
                    DOS STUB  70h字节
                    NT Signature  4字节
                    IMAGE_FILE_HEADER  14h字节
                    IMAGE_OPTIONAL_HEADER  E0h字节
                    IMAGE_SECTION_HEADER(.text段结构属性) 28h字节
                    IMAGE_SECTION_HEADER(.idata段结构属性)28h字节
                    IMAGE_SECTION_HEADER (.data段结构属性)28h字节
                    .text段的代码开始       200h字节
                    .idata段的导入表开始 200h字节
                    .data段的数据开始      200h字节

0000000000000010000009F0 等这些并不是PE里的内容,只是软件标识文件的编移(FileOffset ),
指示我们好找到位置,0-F里的才是真正PE内容。我们发现有好多都为00只是为了对齐用的

相对虚拟地址RVA(Relative Virtual Address)= 虛址地址VA(VirtualAddress)) - 基址BA(Base Address)
VA=0x401000 ,BA=0x400000,那么RVA=0x401000 - 0x400000
如果一个地址是0x112233444字节,那么在文件和内存中是这样表示的:底地址在前,高地址在后44 33 22 11
如果是2字节地址:0x5678 ,文件表示:78 56,所以如果我们看到文件或内存的地址是00 40 BF AA 如果我们取4字节那么便是0xAABF4000,如果我们取2字节便是0x4000 

跑龙套的---->DOS模式

IMAGE_DOS_HEADER这个结构最重要的是第一个成员e_magic和最后一个成员e_lfanew
e_magic的值必须是4D 5A,字符"MZ"e_lfanew的值是指向IMAGE_NT_HEADER结构的文件编移
其余的成员值可为00,下面的结构的有些成员我未解说也是相以的,并不太重要,所以我未进行解说,如果大家觉得有必要可以查文档或查安装VC目录下,像这些结构是从WINNT.H头文件取出来的。文件编移00000040—000000A0的共70H字节为DOS STUBWINDOWS下并不用,我们相应保留

我是导演,你得听从我的---->真正的PE开始

IMAGE_FILE_HEADER最后一个成员Characteristics占二字节16
           0 :置1表示该PE没有重定向信息
           1 :置1表示该PE是可执行文件exe
           2 :置1表示该PE没有行数信息
           3 :置1表示该PE没有局部符号信息
           8 :置1表示该PE希望机器为32位机
           9 :置1表示该PE没有调试信息
           11:置1表示该PE不能在网上运行
           12:置1表示该PE是一个系统文件例如驱动序         
           13:置1表示文该PE是一个动态链接库DLL

IMAGE_OPTIONAL_HEADER结构

typedef struct _IMAGE_OPTIONAL_HEADER {
  //
    // Standard fields.
    //
    WORD   Magic; 总是0B 01
    BYTE   MajorLinkerVersion;
    BYTE   MinorLinkerVersion;
    DWORD  SizeOfCode;
    DWORD  SizeOfInitializedData;
    DWORD  SizeOfUninitializedData;
    DWORD  AddressOfEntryPoint; OEP代码入口的RVA地址,程序从这里开始执行,指向00000400
    DWORD  BaseOfCode;
    DWORD  BaseOfData;
    //
    // NT additional fields.
    //
    DWORD  ImageBase; 载入程序的RVA地址,LOADER可以改变
    DWORD  SectionAlignment; 段加载后在内存的对齐值
    DWORD  FileAlignment; 段在文件中的对齐值
    WORD   MajorOperatingSystemVersion;
    WORD   MinorOperatingSystemVersion;
    WORD   MajorImageVersion;
    WORD   MinorImageVersion;
    WORD   MajorSubsystemVersion; 子系统版本号基本是04 00
    WORD   MinorSubsystemVersion;
    DWORD  Win32VersionValue;
    DWORD  SizeOfImage;
    DWORD  SizeOfHeaders; 所有文件头长度之和
    DWORD  CheckSum;
    WORD   Subsystem; 子系统 02 00 03 00
    WORD   DllCharacteristics;
    DWORD  SizeOfStackReserve;
    DWORD  SizeOfStackCommit;
    DWORD  SizeOfHeapReserve;
    DWORD  SizeOfHeapCommit;
    DWORD  LoaderFlags;
    DWORD  NumberOfRvaAndSizes; 目录表个数
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];  
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

IMAGE_OPTIONAL_HEADER32这个结构被称为可选头,它的成员MagicMajorSubsystemVersionSubsystem一般都是上面这值,别的成员没有解译的一般不太重要,直接写00便可

SectionAlignment 指的是PE加载到内存后对齐,现上面的值设为00 10 00 00也就是0x00001000
FileAlignment 指的是PE在磁盘文件中对齐,现上面的值设值00 02 00 00也就是0x00000200
那什么是对齐呢?有一大教室,假如对齐值为50,如果只有38个学生,那么只要在教室里放上38个书棹就够了
但是因为有了对齐这个说法,并且这里为50,就算只有38个学生,也要放50个棹子,空的书棹没人坐也要放着。
再一看看,半学期后有20位学生加入这个班,这时总学生为58位,原来有的50个书棹又不够用了,
对齐值我们仍然为50,那么还要多少书棹呢?理论上加多8个书棹就行了,但有了对齐,原有的50个书棹上要再加多50个书棹。那么现在的情况是,58位学生,100个书棹才是正确的。

ImageBase PE被加载进虚拟内存后通常不在00000000处加载,而是一般在0x00400000处加载,当然这个值也是可以改变的。SizeOfHeaders是指PE头在文件中对齐后的大小,那么PE头包括那些呢?包括IMAGE_DOS_HEADER,DOS STUB,IMAGE_NT_HEADER(这个结构又包括了二个结构IMAGE_FILE_HEADER,IMAGE_OPTIONAL_HEADER),IMAGE_SECTION_HEADER,那么目前上面的加起来占了0x21F字节(看文件偏移0000021F处),但由于FileAlignment对齐值为0x000002000x21F超大了,那么理应为0x400 ,所以要对齐到文件编移00000400

NumberOfRvaAndSizes目录个数(可以从下面定义看到有16个,16进制值0x10)
#define IMAGE_DIRECTORY_ENTRY_EXPORT          0   // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT          1   // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE        2   // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3   // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY        4   // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC       5   // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG           6   // Debug Directory
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7   // (X86 usage)
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7   // Architecture Specific Data
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8   // RVA of GP
#define IMAGE_DIRECTORY_ENTRY_TLS             9   // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10   // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11   // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT            12   // Import Address Table
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13   // Delay Load Import Descriptors
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14   // COM Runtime descriptor
                                             15   // 这个保留
可以看到我们上面只列到了二个表,IMAGE_DIRECTORY_ENTRY_EXPORTIMAGE_DIRECTORY_ENTRY_IMPORT
并且只有IMAGE_DIRECTORY_ENTRY_IMPORT表有值(看00000130外的前8字节),可以知道一个表占可选头的8字节,
它们按数组排列,看可选头最后一个成员是一个IMAGE_DATA_DIRECTORY结构数组DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]   

我是内务大总管,我安排你站那个位置--->各个段                                                                                     

上面只包含了.text .idata .data三段,这些段名是可以改成别的名称。因为三段所以上面IMAGE_FILE_HEADER结构第二个成员NumberOfSections文件编移000000B6处二字节为03 00
如果有更多的段可以跟在上面三段的后面也是相同的结构

IMAGE_SECTION_HEADER的最后一个成员Characteristics是段的属性代表如这段是否可读可写等

#define IMAGE_SCN_CNT_CODE                  0x00000020  // Section contains code .
#define IMAGE_SCN_CNT_INITIALIZED_DATA      0x00000040  // Section contains initialized data.
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA    0x00000080  // Section contains uninitialized data.
#define IMAGE_SCN_LNK_NRELOC_OVFL           0x01000000  // Section contains extended relocations.
#define IMAGE_SCN_MEM_DISCARDABLE           0x02000000  // Section can be discarded.
#define IMAGE_SCN_MEM_NOT_CACHED            0x04000000  // Section is not cachable.
#define IMAGE_SCN_MEM_NOT_PAGED             0x08000000  // Section is not pageable.
#define IMAGE_SCN_MEM_SHARED                0x10000000  // Section is shareable.
#define IMAGE_SCN_MEM_EXECUTE               0x20000000  // Section is executable.
#define IMAGE_SCN_MEM_READ                  0x40000000  // Section is readable.
#define IMAGE_SCN_MEM_WRITE                 0x80000000  // Section is writeable.

.text000001CC处的4字节 20 00 00 60 是从下面的三个标志与得来的
#define IMAGE_SCN_CNT_CODE                  0x00000020  // 表示该段为代码段.
#define IMAGE_SCN_CNT_INITIALIZED_DATA      0x00000040  // 表示该段包含初始化数据
#define IMAGE_SCN_MEM_EXECUTE               0x20000000  // 表示该段可执行

.idata000001F4处的4字节 40 00 00 40 是从下面的三个标志与得来的
#define IMAGE_SCN_CNT_INITIALIZED_DATA      0x00000040  // 表示该段包含初始化数据
#define IMAGE_SCN_MEM_READ                  0x40000000  // 表示该段可读

.data0000021C处的4字节 40 00 00 C0 是从下面的三个标志与得来的
#define IMAGE_SCN_CNT_INITIALIZED_DATA      0x00000040  // 表示该段包含初始化数据
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA    0x00000080  // 表示该段包含未初始化数据
#define IMAGE_SCN_MEM_READ                  0x40000000  // 表示该段可读

我是制片人,我要制定规则---->地址转换

如果知道文件编移FileOffset,那里PE被加载进内存后的虚拟地址是多少呢?
VA = ImageBase +SizeOfRawData+ FileOffset - PointerToRawData
ImageBase IMAGE_OPTIONAL_HEADER32结构的成员,SizeOfRawDataPointerToRawData
IMAGE_SECTION_HEADER结构的成员。如果是.text段的就取.text段的IMAGE_SECTION_HEADER结构的成员值,
如果是.idata段的就取.idata段的IMAGE_SECTION_HEADER结构的成员值.这里有一点要注意,
FileOffset必须等于或大于PointerToRawData的值,如果是小于的,
那么公式变成VA = ImageBase +FileOffset

例:FileOffset 000000B0的内存地址是多少?
0xB0这个地址不在任何段内是在PE头上的地址,所以VA = ImageBase(0x400000)+FileOffset(0xB0) =0x4000B0

例:FileOffset 00000400的内存地址是多少?
0x400这个地址在.text段内且等于IMAGE_SECTION_HEADER结构的成员PointerToRawData0x400
所以VA = ImageBase(0x400000) +SizeOfRawData(0x1000)+ FileOffset(0x400) - PointerToRawData(0x400)=0x401000

例:FileOffset 00000640的内存地址是多少?
0x640这个地址在.idata段内且大于IMAGE_SECTION_HEADER结构的成员PointerToRawData0x600
所以VA = ImageBase(0x400000) +SizeOfRawData(0x2000)+ FileOffset(0x640) - PointerToRawData(0x600)=0x402040

如果知道虚拟地址VA,能知道文件偏移FileOffset吗?看上面的公式,可以变过来的
FileOffset=VA-ImageBase-SizeOfRawData+PointerToRawData 注意如果VA不在段内则变成FileOffset=VA-ImageBase

例:虚拟地址0x402040的文件偏移地址是多少?
FileOffset=VA(0x402040)-ImageBase(0x400000)-SizeOfRawData(0x2000)+PointerToRawData(0x600)=0x640

主角登场,我来演戏---->程序开始

00000400   55 8B EC 6A 00 6A 00 68  00 30 40 00 6A 00 FF 15   Uj.j.h.0@.j ..
00000410   40 20 40 00 8B E5 5D C3  00 00 00 00 00 00 00 00   @ @.]?.......
这里便是机器码了,能直接被执行,还原成汇编
55                  push ebp
8B EC               mov ebp,esp
6A 00               push 0
6A 00               push 0
68 00 30 40 00      push 00403000 这个是虚拟地址转换后指向在文件偏移00000800处,
                                  我们发现是个存放Hello World字符串地址
6A 00               push 0
FF 15 40 20 40 00   call 00402040 这个是虚拟地址指向在文件偏移00000640处的前4字节
8B E5               mov esp,ebp
5D                  pop ebp
C3                  ret
这段机器码虽然只占24字节,但为了对齐,因为文件的FileAlignment 对齐值0x200
所以占从0000040000000600这文件空间。

资源仓库---->导入表

看看文件偏移处00000640,这个地址转为虚拟内存便是00402040,所以上面call 00402040,现在00000640处上的值是60 20 00 00,这什值实际上是指向了文件编移00000660MessageBoxA的地址。当PE加载进内存后,这个00402040上的值不再是60 20 00 00了,它会是MessageBoxA函数的真正地址,那么这个函数的真正地址是多少呢?由PE加载器确定,在PE没加载进内存时我们无从可知,当加载PE进内存后我们调试是可以知道的。

最后,我可能听到了你的声音:我还是不懂呢?我还是在混沌世界中。再看看配套的视频

本文来源:https://www.2haoxitong.net/k/doc/bec6c035eefdc8d376ee32e6.html

《不识庐山真面目 只缘身在此山中(编写PE).doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式