我目前正在做的工作,需要我删除的部分,从可执行文件的pe格式。首先,我刚刚删除了IMAGE_SECTION_HEADER,更改了IMAGE_FILE_HEADER中的numberofsections字段,重新计算了IMAGE_OPTIONAL_HEADER中的sizeofimage/sizeofheaders,并按删除节的原始大小移动了以下节的原始地址。但是,Windows拒绝加载带有错误消息“XXX不是有效的win32应用程序”的文件。我已经挣扎了一段时间,但也试图移动虚拟地址的以下部分的虚拟大小删除节,一切正常。
为什么虚拟地址必须是连续的并且不能有任何间隔?我试过阅读正式的体育文件,但没有成功。我一直认为,只要sizeofimage具有正确的值,各个部分的地址都不重要。
最佳答案
大多数应用程序不需要在各个部分之间留有很大的间隙——这些应用程序可以使用单独的dll或通过VirtualAlloc动态分配内存。
更新:经过更多的测试,我发现节之间的间隙必须是对齐下一节所需的间隙,以满足节对齐的要求。因此,间隔两个4096字节的节0x20000字节需要将整个exe的节对齐字段设置为0x20000。(例如,0x12000的间隔是不可能的。)这个128KB的间隔不会出现在进程的内存映射中,也不会消耗内存,但是如果您试图在间隔内分配内存,virtualloc仍然会失败,并返回错误无效的地址。
下面是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字节的差异。改变的是:
时间戳(4字节变化)。
校验和(4字节变化)。
.bss节的大小(8字节更改)。在continuous.exe中,.bss节的大小为0xfe000字节,而在gap.exe中,.bss节的大小为0x200字节,在它和.idata节之间创建大小为0xfc000字节的间隙。
关于windows - 为什么部分虚拟地址需要连续?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32378033/