流程:修改可选头里的IMPORT表,添加DLL名及起码一个DLL的导出函数名
要点:RAW【文件偏移地址】=RVA【内存偏移地址】-VirtualAdress【内存中的节区起始位置】+PointerToRawData【文件中的节区起始位置】
相关结构
- typedef struct _IMAGE_IMPORT_DESCRIPTOR { //简称IID,20个字节
- union {
- DWORD Characteristics;
- DWORD OriginalFirstThunk;
- } DUMMYUNIONNAME;
- DWORD TimeDateStamp;
- DWORD ForwarderChain;
- DWORD Name; //存放DLL名称的地址
- DWORD FirstThunk; //IAT表,存放导入函数表的地址
- } IMAGE_IMPORT_DESCRIPTOR;
- typedef struct _IMAGE_SECTION_HEADER { //节区表,
- BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //8个字节
- 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, *PIMAGE_SECTION_HEADER
- typedef struct _IMAGE_DATA_DIRECTORY { //可选头的成员表,由16个该结构组成。
- ULONG VirtualAddress;
- ULONG Size;
- } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
修改思路
一,查看IDT是否有足够空间(IDT即为IMPORT表内容)
IDT是个IID的结构数组,每个DLL对应一个IID结构,占20字节(0x16),整个IDT空间为(DLL个数+1)*20个字节,末尾用一个空的IID结构填充。
二,如果存放不下就移动IDT,先查看所在节区的空间,有没有足够大的空白区,如果没有就考虑在文件末尾添加一个节区吧。
一般节区的大小都是0200的倍数,极有可能有空余的。
三,修改导入表的RVA值,删除绑定导入表【可选头第12个表,可选,用以提高DLL的加载速度】
四,移动好IDT后添加新的IID,设置好Name【DLL名称】,INT【RVA数组,导入名称表】,IAT【同INT,也可以不同,影响不大】
五,修改IAT节区的属性值,PE加载到内存时,PE装载器会修改IAT,写入函数的实际地址,所以相关节区一定要有WRITE属性
时间: 2024-10-21 03:54:25