PE学习(4) 新增节添加代码

上文提到在代码节空白区内添加代码或SHELLCODE

如果空白区大小不够,可以考虑新增一个节来添加代码

 

准备工作

现在的目标是添加0x1000个字节

整体流程如下:读取EXE文件,添加新节修改节表等信息后,保存到新EXE文件

基本处理:判断DOS头和NT/PE头合法

在当前文件基础上增加0x1000大小字节,并malloc分配内存,设置初始值为0

最后一行memcpy将目前的文件完整地复制过去(新增节在当前基础上新增)

解析PE头部分代码在之前文章中出现过多次:

目前得到了第一个节表的信息,新增节并不是插入,而是在末尾加入节,需找到最后一节

其实加一个括号或许更好理解,

 

计算空间

在末尾添加新节的限制条件是:有足够的空间添加新节表

参考图片,节表位于SizeOfHeaders计算的内容中,包含了多个其他头,以及一部分的保留字节

新的节表信息应该写在这部分保留字节中,且需要确保能够最后保留一个全0的节表,据海哥说Windows中一般认为某个节表全0的情况是结束,需要多保留一份节表表示结束

节表的大小其实是固定的28H十进制为40字节,在宏中已经定义

回到计算空间的主题,其实这里用不到40长度这个信息,提到它仅是一个参考

参考上图,得到计算公式

对应代码如下(其中PE头大小等信息是固定的,也可以不使用sizeof

如果小于两个节表的大小认为不可添加新节表

 

新增节表

取出当前NumberOfSections字段作为偏移,NewSec指向末尾新节

找到新节各种字段的指针,用于后续修改

节表数量加一

暂时认为新增的节是0x1000大,设置SizeOfImage

设置新节名字(长度为8)

设置新节的Misc对其前大小为0x1000

新增节的VirtualAddress字段由最后一节计算得来

从最后节Misc.VirtualSizeSizeOfRawData中找到一个更大的,认为是实际需要的偏移

设置新节VirtualAddress字段,参考上文的图片,得到新节的起始偏移

 

对齐检查

当前pSecVirtualAddress没有检查是否内存对齐

如果和SectionAlignment除不尽,认为没有对齐,需要自行对齐。先做触发拿到舍弃余数的值,加一后乘以内存对齐参数,得到对齐后的VirtualAddress

以上解决了内存对齐的问题,接下来处理文件对齐

设置文件属性SizeOfRawData0x1000

根据上一个节算出下一个节的PointToRawData(参考开头的图)

检查对齐类似内存方式

 

属性设置,采用第一节(代码节)的属性内容

返回新ImageBuffer指针(这里代码有一些歧义,实际上不是拉伸后的ImageBuffer而是FileBuffer

 

写入 SHELLCODE

现在新增了0x1000长度的节,可以随意地写入SHELLCODE

修改上文的代码,即可将SHELLCODE写入到新增节中

 

截图:

 

进一步限制

本文已经默认了节表到第一节之间的垃圾数据足够写入两个节表,当这个空间不足时,应该如何解决问题?

注意到DOS头的e_lfanew记录了NT头地址,在DOS头和NT头之间的部分填充了垃圾数据,可以将NT头以及后续所有字节向上提到紧接着DOS头的地方,并修改e_lfanew为紧接的地址

如果这样还是不够,可以考虑下一篇的办法:扩大节