一、添加代码的方式
- 我们现在学过的有:①直接在任意节的空白区添加代码;②新增节添加代码;③扩大最后一个节添加代码
- 今天要学习:④合并节并添加代码
二、合并节思路
-
使用拉伸后的合并更方便计算节合并后的大小,而且可以保证计算的正确性。如果用FileBuffer算,算地址或者大小时还要担心节中未初始化数据在拉伸后导致节变大等等情况。
-
合并节就是:把第一个节开始一直到最后一个节的结尾都当成第一个节
-
但是可能会造成合并后文件变大,因为文件对齐粒度一般都要小于内存对齐粒度,所以虚拟内存中每个节的空白区一般比文件空白区要大一些,现在合并节是把虚拟内存中从第一个节开始到文件结束都当成一个节,最后再变成FileBuffer就会变大。
-
步骤:
-
NumberOfSections改成1
-
修改第一个节表的字段
- VirtualSize:
- 方法一:SizeOfImage - 第一个节VirtualAddress
- 方法二:还可以通过最后一个节的VirtualAddress + 最后一个节的VirtualSize内存对齐后的大小 - SizeOfHeader内存对齐后的大小
- SizeOfRawData:等于VirtualSize即可
- VirtualSize:
-
将第一个节的属性改为包含所有节的属性,即用第一个节的属性与其他的节的属性做或运算
-
三、作业
1.扩大最后一个节,保证程序正常运行(手动)
day33.1中写过用编程实现扩大节,所以今天再试着用手动的方式体会一下扩大节,由于手动的时候是在FileBuffer中操作,所以有些值的计算包括扩大的大小都是需要计算的,没有在ImageBuffer中扩大节那么方便
-
打开notepad.exe程序,如果我们想扩大0x1000字节,则需要修改SizeOfImage,0x13000 + 0x1000内存对齐后 = 0x14000(我们知道notepad.exe的内存对齐为0x1000;文件对齐为0x200)
-
接着找到最后一个节表,修改VirtualSize = 原来的0x8948内存对齐后0x9000 + 0x1000内存对齐后 = 0xA000
-
SizeOfRawData = VirtualSize即可
-
最后将最后一个节的属性0x40000040与0x60000020亦或得到0x60000060
-
最后最关键的一步就是在最后一个节末尾扩大节,我们知道如果在ImageBuffer中扩大节,就直接在末尾加上0x1000字节即可,但是由于现在是在FileBuffer中操作,不能直接扩大0x1000了,不然就跟SizeOfRawData对不上,我们要通过计算来得到:原来的SizeOfRawData为0x8A00,而扩大后的SizeOfRawData = 0xA000,所以只需要扩大0xA000 - 0x8A00 = 0x1600即可,换算成十进制为5632。所以在文件末尾0x101FF处右键–Edit–Paste Zero Bytes–输入5632
-
保存运行,再拖入PEtool中查看是否修改成功
2.编码实现合并节
#include "stdafx.h"
#include <stdlib.h>
#include <string.h>
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef unsigned char BYTE;
#define MZ 0x5A4D
#define PE 0x4550
#define IMAGE_SIZEOF_SHORT_NAME 8
#define MessageBox_Address 0x77D36476 //宏定义记事本的MessageBox内存地址
//shellcode
BYTE shellcode

本文详细介绍了如何手动和编程方式在PE文件中进行节的扩大及合并操作,涉及调整SizeOfImage、VirtualSize、SizeOfRawData等字段,并通过示例代码展示了合并节的实现过程。此外,还提供了计算对齐后大小的函数。
最低0.47元/天 解锁文章
656






