我目前正在做一些工作,需要我从PE格式的可执行文件中删除部分。 首先,我刚刚删除了IMAGE_SECTION_HEADER ,更改了IMAGE_FILE_HEADER中的 NumberOfSections字段,重新计算了IMAGE_OPTIONAL_HEADER中的 SizeOfImage / SizeOfHeaders,并将以下部分的原始地址移动了已删除部分的原始大小。 但是,Windows拒绝加载错误消息“XXX不是有效的Win32应用程序”的文件。 我一直在挣扎一会儿,但也试图通过删除部分的虚拟大小来移动以下部分的虚拟地址,一切工作正常。
什么是虚拟地址需要连续的原因,不能有任何差距? 我试图通过正式的体育文件阅读,但没有成功。 我一直认为,只要SizeOfImage具有正确的值,那么每个部分的地址是什么都没有关系。
大多数应用程序不需要在部分之间有很大的差距 – 那些可以使用单独的DLL或通过VirtualAlloc动态分配内存。
更新:经过更多的测试后,我发现部分之间的差距必须是对齐下一部分以满足SectionAlignment所需的。 因此,将两个4096字节的部分分隔开0x20000字节需要将整个exe的SectionAlignment字段设置为0x20000。 (例如0x12000的间隔是不可能的。)这个128kB的间隔不会出现在进程的内存映射中,并且不会消耗内存,但是如果您尝试在间隙内分配内存,则VirtualAlloc仍然会以ERROR_INVALID_ADDRESS失败。
这是一个GCC / MinGW的最小测试用例,它演示了Win32 exe中的部分必须是连续的 。
测试用例:
.global _main .section .text _main: push $1 call _Sleep@4 xor %eax, %eax ret .section .bss .lcomm buf, NUMBYTES
这产生一个有效的可执行文件
gcc -m32 -Wl,--image-base=0x00400000 -Wl,-Ttext=0x00401000 -Wl,-Tbss=0x00402000 -DNUMBYTES=0xfe000 -Wl,--section-start=.idata=0x00500000 -s -nostartfiles -o contiguous.exe testcase.S
这会产生无效的可执行文件(gap.exe不是有效的Win32应用程序):
gcc -m32 -Wl,--image-base=0x00400000 -Wl,-Ttext=0x00401000 -Wl,-Tbss=0x00402000 -DNUMBYTES=0x200 -Wl,--section-start=.idata=0x00500000 -s -nostartfiles -o gap.exe testcase.S
与十六进制编辑器和objdump相比,两个文件之间只有16个字节的差异。 改变的是: