利用pe添加节的方法添加代码实现简单的加壳

<>强利用pe添加节的方法添加代码实现简单的加壳

大致流程如下

要达到的目的是添加一个新节在新节中添加自己的代码让程序运行时先运行自己的代码

而自己的代码就是为了解开之前对程序进行的加密执行完后再继续运行原程序的路线。


详细步骤

<强>第一步

先写程序将采用文件映射的方法将待修改的exe加载进来获取所有我们需要的信息
它仅仅,,CreateFileMapping MapViewOfFile(返回文件基地址Pp_w_picpath)
GetFileSize(用于修改文件大小)

<强>第二步

初始化pe头信息DOS=PIMAGE_DOS_HEADER (Pp_w_picpath);其他初始化略
验证pe的有效性MZ和pe

<强>第三步

开始加节因为后边要修改bgi所在的节的内容
所以先将此节的属性设置为可读可写,IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
(此处很关键自己修改的事飞秋结果修改完后一直不能运行卡了很长时间切记)

加节

找1到最后一节的地址
PIMAGE_SECTION_HEADER lastsec=节+(文件→NumberOfSections-1);
,确定新加节的地址
PIMAGE_SECTION_HEADER newsec=lastsec + 1,
,节表数目加1
文件→NumberOfSections + +;
验证一下在节表头最后到第一个节内容开始有没有40个字节
(一般都有,没有考虑不够的情况)
验证方法(主要明白SizeOfHeaders的真实含义)

NEWSIZE计算的是(dos + dos存根)+ nt +,新加节后的节表头总大小(纯粹大小未对齐)
DWORD NEWSIZE=(dos→e_lfanew) + sizeof (IMAGE_OPTIONAL_HEADER32) + sizeof (IMAGE_SECTION_HEADER) * NumberOfSections;
(不要忘记dos存根,直接用(sizeof (IMAGE_DOS_HEADER))尽管没有神马影响但是事实必须这样计算)

让它跟原SizeOfHeaders比较
SizeOfHeaders是,dos + dos存根+ nt +所有节表头总大小(对齐后的),,,可以用作第一个节内容的开始位置

2
大小满足之后,对新加节的所有属性进行初始化(函数是用来对齐的参数1大2小对齐粒度)

memcpy (newsec→名称、“.NewSec”8);

newsec→Misc.VirtualSize=实际大小(大小);节内容的实际大小,SizeOfRawData用到

newsec→SizeOfRawData=https://www.yisu.com/zixun/Up(大小、pe.OPTION ->队列);文件中的大小

newsec→VirtualAddress在内存中的RVA重要可以利用上一个节的数据得到

DWORD持续=((lastsec→SizeOfRawData), pe.OPTION→SectionAlignment) + lastsec→VirtualAddress;
DWORD持续=((lastsec→Misc.VirtualSize), pe.OPTION→SectionAlignment) + lastsec→VirtualAddress;

两个去年相等因为SizeOfRawData是混杂。VirtualSize按文件对齐得到的
文件对齐粒512度内存对齐粒4096度所以肯定相等
不过为了准确采用后者
其实这个最后也就是体育文件载入内存后经过SectionAlignment对齐后的总大小SizeOfImage

newsec→PointerToRawData=https://www.yisu.com/zixun/lastsec-> PointerToRawData + lastsec -> SizeOfRawData;同理
newsec→特征=IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;可读可写

其他属性没有什么影响故均设置为0,到此初始化完毕

3

需要修改的其他地方的参数
(必须)文件在磁盘上的总大小即第一步中的GetFileSize返回的值再加上一页的大小4096
,用于CreateFileMapping创建文件映射对象函数把大小设置为修改后的大小即加上4096后的值
b(必须)文件映射内存后的总大小
,选项→SizeOfImage +=(大小、pe.OPTION→SectionAlignment);
c(不必须的)
,pe.DATA [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT] .Size=0;
,pe.DATA [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT] .VirtualAddress=0;
,pe.OPTION→SizeOfCode +=(大小、pe.OPTION→SectionAlignment);
,pe.OPTION→SizeOfInitializedData +=(大小、pe.OPTION→SectionAlignment);

4至此加节成功

<强>第四步

取反
因为是对bgi所在节的内容取反所以要找到bgi所在节
方法获取bgi=选项→AddressOfEntryPoint然后循环遍历各个节表头的起始地址进行比较
(int i=0;i<文件→NumberOfSections;我+ +)
{
PIMAGE_SECTION_HEADER秒=PIMAGE_SECTION_HEADER(部分+ i);
如果eop>=秒→VirtualAddress,,,,,eop<=(sec→VirtualAddress +秒→SizeOfRawData))
{返回秒;}
}
找到所在节后,是要对在磁盘上此节的内容进行修改所以获取
PVOID地址=秒→PointerToRawData + p_w_picpath;//文件的地址
DWORD披散下来,=秒→SizeOfRawData;,,,,,//文件的大小

取反函数
空白,_stdcall QF(双字PVOID地址,len)
{
表示我=0;
PBYTE buf=(PBYTE)地址;
(i=0;i<兰;我+ +)
{buf[我]=~ buf[我];}
}
函数中有一个关键字_stdcall,作用是函数执行完后自己跳转到之前压栈的地址用于返回bgi的使用

利用pe添加节的方法添加代码实现简单的加壳