即使将数据附加到可移植可执行文件后,它们也仍然有效。据我所知,这是由于可执行代码的offset + size属性所致。
我有一个类似于Winzip中的Zip2Exe的可执行打包应用程序。到目前为止,我一直在将压缩的有效负载添加到可执行文件的末尾,然后是一个8字节的值,表示有效负载的字节大小。
我想做的是让可执行文件存根计算自己的大小,并假定剩余字节为有效负载,而没有任何大小信息。这纯粹是出于好奇,我真正想知道的是,PE可以计算自己的大小并检测是否添加了任何东西。
当然,我知道,如果通过注入或其他方式更改了自己的内容,它将无法验证其自身内容。
为了澄清这个问题,我想要一个.NET中的函数,该函数检查Assembly.GetExecutingAssembly().Location
并弄清楚附加有效负载的偏移量是多少。如果此偏移量与文件大小相同,则将没有有效负载。
最佳答案
请注意,我对C#不太满意,所以这是一个一般性的答案。
由于Assembly.GetExecutingAssembly().Location
似乎返回图像的路径,因此您有一个“平面”文件路径,即磁盘上的图像而不是内存中的图像。解析比在内存中容易,而且您已经知道它是有效的PE文件,因此可以跳过所有有效性检查。
在使用C#探索图像文件时,您可能需要检查“ Exploring pe file headers using managed code”和Pinvoke.net上的各种结构。
要查找图像文件末尾是否有有效载荷:
打开文件:)
获取文件大小
该文件以IMAGE_DOS_HEADER(pinvoke)开头
关注e_lfanew
成员以找到IMAGE_NT_HEADERS
IMAGE_NT_HEADERS(pinvoke; msdn)有两种类型:IMAGE_NT_HEADERS32(PE32:32位PE)和IMAGE_NT_HEADERS64(PE32 +:64位PE)
在IMAGE_NT_HEADERS中,Signature
和FileHeader
(IMAGE_FILE_HEADER结构)字段相同,只有OptionalHeader
会更改。
从IMAGE_FILE_HEADER(pinvoke; msdn)中检查Machine
以查看您具有哪种类型:0x014c(Intel 386)= PE32; 0x8664 = PE32 +
从IMAGE_FILE_HEADER,获取NumberOfSections
字段。
完全跳过(跳过)IMAGE_NT_HEADERS结构:无论大小如何,其大小都是恒定的。
您将落在IMAGE_SECTION_HEADER
(pinvoke; msdn)数组上。该数组中的条目数是NumberOfSections
字段(来自IMAGE_FILE_HEADER)。
在PointerToRawData
数组中找到所有IMAGE_SECTION_HEADER
字段的最大值/最大值(通常是数组中的最后一个条目,但是请确保检查数组中的所有条目)。
现在,您具有上一节开头的文件偏移量。
从具有最高IMAGE_SECTION_HEADER
的PointerToRawData
中,获取SizeOfRawData
字段。
您现在拥有上一节的大小
添加PointerToRawData
和SizeOfRawData
字段:如果结果小于文件大小,您将知道PE文件末尾有一个有效负载。
简单(可视)示例:
上图代表calc.exe中的所有IMAGE_SECTION_HEADER
。如您所见,PointerToRawData
(标记为“原始地址”)的最大值为0xE3A00,相应的节大小(SizeOfRawData
,标记为“原始大小”)为0x600。
0xE3A00 + 0x600 = 0xe4000 = 933888
calc.exe的文件大小相同(933888字节):
因此,文件末尾没有有效负载。如果文件大小大于933888(上述计算结果),则文件末尾将有一个有效负载。
关于c# - PE格式的自检,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29587560/