若要对PE文件填充自己的代码,然后发现字节空间不足,这时候就需要对节表进行操作
此处主要讲节的三种操作,分别为扩大节、新增节、合并节
对文件的节表进行扩大,为了方便操作,只需对最后一个节进行扩大OK了
此处演示扩大1000(16进制)个字节的操作
首先将程序拖入到CFF Explorer工具,查看PE属性
例如文件对齐与内存对齐的值,此处内存对齐的值是1000
再查看最后一个节(rsrc)的Virtual Size(节的实际大小)和Raw Size(节文件对齐后的大小)
此处rsrc节的Virtual Size值为1E0, Raw Size的值为200, 两者取最大值200
再取200与1000(内存对齐)的最小公倍数,结果为1000
1000再加上1000(需扩大的字节数), 结果为2000
随后将Virtual Size和Raw Size的值都修改为2000
节内存对齐所增加的字节 = 节内存对齐后的大小(1000) - 节文件对齐后的大小(200), 计算结果为E00, 这个值在后面用winhex工具添加字节的操作中要用到
转到PE扩展头查看SizeOfimage(整个PE文件内存对齐后的大小),此处值为9000
将其修改成9000+1000(扩大的字节数), 即修改成10000
将文件保存后拖入到winhex中打开,将光标拖到最后一个字节,执行如下图操作
要插入的字节数 = E00(节内存对齐增加的字节) + 1000(需扩大的字节) = 1E00, 此处需换算成10进制,即为7680
然后winhex保存文件, 执行文件,若程序成功运行则说明扩大节操作成功
扩大节扩出来的空白区还需要考虑节的权限问题,若扩大出来的节没有执行代码的权限,那么还要修改整个节的权限属性,节的权限属性由节表结构体的最后一个成员Characteristics决定
因为新增的节可以自己设置权限,所以相比扩大节而言还是方便挺多的
将文件拖入CFE Explorer中,找到段头部(节表属性)
在最后一个节的后面新增节, 以此方便后续的操作
对着最后一个节鼠标右键,为了研究原理,这里选择add section(Header Only), 意思为仅添加节表头。
若不想自己添加节数据,可以选择add section(File data)
对节表进行修改, 如下列表所示
节的成员 | 含义 | 修改后的值 |
---|---|---|
Name | 节的名字 | .fuck |
Virtual Size | 节的实际大小 | 1000(要新增节的大小) |
Virtual Address | 节在内存中的偏移地址 | 9000(上一个节.Virtual Address + 上一个节内存对齐后的大小) |
Raw Size | 节文件对齐后的大小 | 1000(新增节的大小) |
Raw Address | 节在文件中的偏移地址 | 4E00(上一个节.RawAdress + 上一个节.Raw Size) |
Characteristics | 节的属性 | 0(即可读可写可执行) |
切换到PE扩展头,修改SizeOfimage的值为10000(原先值9000+新增的字节1000)
文件保存后拖入到Winhex,新增4096个字节(16进制的1000),这里就不演示了,上面扩大节的操作就演示过了
新增节有一个前提条件,最后一个节后面至少要有40个字节的空白区
若前提条件不满足, 那只能合并节,即将多个节合并成一个节,多余的空间就可以用于新增节
为了进行后面的合并节,需要先将所有的节进行内存对齐
内存对齐的意思是令节文件对齐后的大小和内存对齐后的大小相等
这里我们要将所有的节合并,所以全部节表都要进行内存对齐
只需修改节表三个成员值,分别是Virtual Size、Raw Size、Raw Address
此处演示的PE文件内存对齐值为1000
首先是第一个text节,将Virtual Size与Raw Size的值修改成内存对齐后的大小, 即修改成3000
注意: 由于是第一个节, 所以Raw Address的值就不用修改
第二个是rdata节,同样将Virtual Size与Raw Size的值修改成内存对齐后的大小
Raw Address = text节.Raw Address + text节.Raw Size
后面节的操作按上述演示来就行了,下图是所有节内存对齐前和内存对齐后的对比
计算出每个节的末尾地址, 随后在每个节的末尾地址填充字节
首先计算text节的内存对齐所增加的大小,称之为差值
差值 = 节内存对齐后的大小(3000) - 节文件对齐后的大小(2E00) = 200
text节的末尾地址 = 下一个节.RawAddress(3400) - 差值(200) = 3200
将程序拖入winhex, 点击工具栏的转到偏移量,输入text节的末尾地址, 随后光标会跳转到text节的末尾地址处
右键编辑插入0字节,插入512(十六进制的200,即差值)个字节
根据以上的步骤来完成对后面节的内存对齐, 这里特别注意下最后一个节的内存对齐
例如这里最后一个节的差值为E00, 不用计算它的节末尾地址, 直接将光标拖到文件末尾, 插入3584(差值)个字节即可
内存对齐后再将文件拖入CFE Explorer, 只需修改第一个节的属性
将Vitrual Size和Raw Size的值修改成所有节内存对齐后大小的总和(3000+2000+1000+1000+1000=8000), 即修改成8000
将characteristics(节权限)的值修改成所有节的characteristics值相互异或运算后的结果, 即修改为E0000060, 这样修改的目的是令第一个节拥有所有节表的权限属性
将其他的节表头删掉,只留下一个text节表
将PE头里的NumberOfSections(节表个数)的值修改成1
后面程序执行成功则代表节合并成功