我目前正在开展工作,需要我从PE格式的可执行文件中删除该部分。首先,我刚刚删除了IMAGE_SECTION_HEADER,更改了IMAGE_FILE_HEADER中的NumberOfSections字段,重新计算了IMAGE_OPTIONAL_HEADER中的SizeOfImage / SizeOfHeaders,并将以下部分的原始地址移动了已删除部分的原始大小。但是,Windows拒绝加载文件,并显示错误消息" XXX不是有效的Win32应用程序"。我已经苦苦挣扎了一段时间,但试图通过删除部分的虚拟大小移动以下部分的虚拟地址,一切正常。
虚拟地址需要连续且没有任何差距的原因是什么?我试图阅读官方PE文档,但没有成功。我一直认为,只要SizeOfImage具有正确的值,单个部分的地址就不重要。
答案 0 :(得分:2)
大多数应用程序不需要在各个部分之间有大的间隙 - 那些部分可以使用单独的DLL或通过VirtualAlloc动态分配内存。
更新:经过更多测试后,我发现部分之间的间隙必须是对齐下一部分以满足SectionAlignment所需的间隔。因此,间隔两个4096字节的区间0x20000字节需要将整个exe的SectionAlignment字段设置为0x20000。 (间隔为,例如,0x12000是不可能的。)这个128kB的间隙不会出现在进程的内存映射中,也不会消耗内存,但如果你试图在间隙内分配内存,VirtualAlloc仍会因ERROR_INVALID_ADDRESS而失败。
以下是GCC / MinGW的最小测试用例,证明 Win32 exe中的各个部分必须是连续的。
testcase.S:
.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个字节的差异。改变了: