转移自之前的博客
judge PE
简单的判断文件是否为pe文件:
- pe 指纹: 开头为 4D 5A (MZ); 3C 处为一个值 ; 查找该值的地址为 50 45(PE)。
PE 文件概论
PE(portable Executable)windows系统下的可执行文件格式
1 . 32位可执行文件-PE32 ;
64位可执行文件-PE+/PE32+ ,是PE文件的扩展形式。
分类:可执行系列 exe scr ;库系列 dll ocx cpl drv ;驱动程序系列 sys vxd ;对象文件系列 obj (唯一不可执行)。
基本结构
DOS头到节区头是PE的头部分;
文件中使用偏移offset,内存中使用VA(virtual address 虚拟地址)表示位置;
- VA指进程虚拟内存的绝对地址,RVA指从某个基准位置开始的相对地址。
RVA+ImageBase=VA
PE头(1)
DOS部分
- DOS头:IMAGE_DOS_HEADER结构体 –0x40个字节
1 |
1 | e_magic:DOS签名(4D5A 签名值MZ) |
- DOS存根(stub) –可选项,大小不固定/DOS环境才会执行
PE文件头部分
- NT头: IMAGE_NT_HEADERS结构体 –32位:0xF8个字节。64位: 0x108
1 | 签名(50450000) |
- 标准PE header:IMAGE_FILE_HEADER结构体 该结构体重要成员(设置不正确,程序无法运行)
- 可选头: IMAGE_OPTIONAL_HEADER32 (PE头结构体中最大的)
重要成员
- 节区头: IMAGE_SECTION_HEADER 不同内存属性访问权限:code rwx /data rw /resource r 重要成员
PE头(2)
- 内存地址与文件偏移间的映射:RVA to RAW(即file offset)
公式:RAW - PointerToRawData = RVA -VirtualAddress
RAW = RVA -VirtualAddress + PointerToRawData
eg:
RVA = 5000 位于第一节区(.text),VA = 1000(该节区内存的的起始地址),
PointerToRawData= 400 (该节区文件的起始地址) 。
RAW = 5000 -1000 +400 =4400.
- DLL(动态链接库)
不把库包含在程序中,而是单独组成DLL文件,需要时调用即可/更新库时只需要替换DLL文件即可/内存映射使加载后的DLL代码,资源在多个进程中实现共享。
Windows版本不同,环境不同,被调用函数的位置(地址)也不相同。
为了确保在所有环境中都能正常调用被调用函数,编译器保存了被调用函数实际地址的位置。PE装载器将被调用函数的地址写到该位置。
DLL重定位。DLL的ImageBase默认为1000000,若某个程序使用a.dll与b.dll时,a已被装载到内存的10000000处,PE装载器只能查找其他空白的内存空间,将b装载进去。
PE头表示地址用RVA 而不是VA。
3.IAT(Import Address Table 导入地址表):用来记录程序正在使用库中的哪些函数。