-
-
在PE中添加,删除SECTION
-
发表于:
2009-12-14 14:20
14079
-
在PE中添加,删除SECTION
这两天空闲,自己写了个添加,删除SECTION的程序,发现里面的技巧很多,需要注意的地方也很多,现把心得写上,希望能给正在学习PE文件的朋友提供方便。
关于PE的格式,PE的基本知识,请参看其他相关文章。
添加SECTION
添加SECTION的前提是在最后一个SECTION与第一个区块之间有足够的空间)添加一个新SECTION 40字节。通常情况下,是有40字节的空间的,但是如果没有就需要想办法腾出40字节空间来。
通常有2种方法腾空间
重新编排PE头
通常IMAGE_DOS_HEADER 和 IMAGE_NT_HEADER不是紧挨着,中间有一些其他数据,比如DOS占位程序,这些数据基本上没用,可以将NT头以及SECTION数据前移覆盖这些数据达到扩充PE头空余空间添加新SECTION。
IMAGE_DOS_HEADER 的e_flanew 指向NT头相对于文件头的偏移,将NT头前移,只需修改e_flanew的值即可。
优点:相对于扩充PE头,不需要修改所有SECTION的PointerToRawData指向,不用移动所有区块。
缺点:腾出来的尺寸只能加入有限的新SECTION.
扩充PE头
这种方法通常将SizeOfHeader的尺寸扩大文件对齐字节,0x200字节,然后把所有SECTION的PointerToRawData值得加上0x200字节,然后再将所有区块数据向后移动0x200字节。当然SizeOfHeader 也需要加0x200字节。
优点:使用这种方法可以实现无限的添加新SECTION。
缺点:需要改动的地方比较多。
注意绑定输入表
有了空间不一定就能添加新SECTION,还需要查看绑定输入表,绑定输入表和其他节表不同,绑定输入表紧挨着最后的一个SECTION存放,绑定输入表而且必须在PE头区内,由IMAGE_DATA_DIRECTORY[11]来指向。
我手上的PE编辑工具,LoardPE,PETools,StudPE都忽视了这个问题,添加SECTION后都覆盖了绑定输入表数据,而且也没有IMAGE_DATA_DIRECTORY[11],导致添加节区后PE文件不能运行。
如果不想保留绑定输入,那么添加SECTION的时候直接把IMAGE_DATA_DIRECTORY[11]内的数据置0.
如果想保留绑定输入表,那么就先把绑定数据拷贝出来,添加完SECTION再把数据复制到这个SECTION的后面,然后修改IMAGE_DATA_DIRECTORY[11]的指向就可以。
IMAGE_SECTION_HEADER 结构内容
Name 新区块的名字,注意不能超过8字节大小。
VirtualAddress 虚拟地址;这个地址就是PE文件装载后,这个区块所在的内存地址。地址必须是"内存页对齐",必须紧挨着上一个区块。计算公式就是上一个区 块的VirtualAddress + VirtualSize 内存页对齐后的值。
VirtualSize 区块内数据的实际大小;通过数据的实际大小,就可以计算出文件对齐后的数据大小。
SizeOfRawData 区块数据文件对齐后的数据大小。根据VirtualSize计算可计算出文件对齐后的尺寸。
PointerToRawData 区块相对于文件头的文件偏移, 在文件中两区块数据之间不必紧挨着,但起始地址必须是"文件对齐"的。
Characteristics 区块的属性,可根据添加区块的实际目的设置属性,拿不准就设置E0000060代表可读,可写,可执行,包含代码,包含初始化数据。
添加SECTION后还需要添加这个SCTION的区块数据,首先需要把文件尺寸扩大,扩大的尺寸就是区块数据文件对齐后的大小。
最后将IMAGE_OPTIONAL_HEADER32的SizeOfImage 加上新区块数据的VirtualAddress。
将IMAGE_FILE_HEADER 的NumberOfSection 加 1。
删除SECTION
删除一个SECTION,需要考虑的比较多;
删除SECTION不能根据名称删除,应该根据序号删除,因为允许存在同名的Section。
如果删除的Section位于中间位置,后面Section的PointerToRawData文件偏移可以向上移动,但是VirtualAddress虚拟地址就不能简单的向上移动了,因为如果某个节区的VA发生变化,那么这个节区里的所有RVA也会发生变化,而要修复这些RVA工作量就太大了。处理办法就是,把要删除的这个Section的上一个Section的VirtualSize扩大,也就是加上要删除的这个Section的VirtualSize,这样,后面的所有Section的VirtualAddress不变,只修正PointerToRawData就可以。当然SizeOfImage也就不用调整了,PE映像大小没变,只改变了PE文件大小。
如果删除的是最后一个Section,那么删除后将SizeOfImage减小就可以,不存在VA问题。
如果删除的Section和IMAGE_NT_HEADER的DATA_DIRECTORY有关,比如重定位表,TLS表,那么必须要清除数据目录的VirtualAddress,和VirtualSize。
最后,如果有绑定数据,需要在文件中上移一个IMAGE_SECTION_HEADER尺寸,然后修正数据目录表的指向。
附上一段小代码,一个完整的添加删除SECTION例子:
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!