删除PE_Overlay
找到最后一个节的区块,在那之后的数据全部删除掉。
其实不删掉也行,不过学习起来的时候就不方便区别最后一个节和Overlay了。
网上有资料说PE_Overlay指PE结构的最后一个节的末尾位置,通常用于存储自定义资源
[!NOTE]
PE结构的基础上,增加了处理逻辑代码+自定义的资源PE_Overlay指PE结构的最后一个节的末尾位置,通常用于存储自定义资源
PE结构的最后一个节末尾+1个字节的位置就是OverLay的起点。(last_section.Raw_offset + last_section.Raw_size) = Overlay;
PE_Overlay指的是PE(Portable Executable)文件格式中的Overlay ,它是PE文件的最后一个节(section)的末尾位置之后的额外数据。 在PE文件加载时,操作系统会将整个文件映射到内存中,其中Overlay部分通常被忽略。这部分数据可以用于存储任意类型的自定义资源,例如图像、音频、配置文件等,而不影响PE文件的正常执行。
Overlay的存在可以让开发者在不修改PE文件的基本结构的情况下,向其添加额外的数据。这对于包含了大量资源或者需要动态更新的程序来说非常有用。在安装包中,Overlay常常被用来存储自定义资源,例如软件的图标、帮助文件、配置文件等等。虽然Overlay不是PE文件的必需部分,但它为软件开发者提供了一个便捷的方式来扩展程序的功能。
关闭随机基址
将1改为0
添加节表
插入节表空间
在最后一个节表的地方插入n个字节大小的区域,这一块区域是为了写节表
这个n是参考 NT头的可选文件头里的FileAlignment
的,如果是0x200就插入0x200个字节
快捷键:{Ctrl+Shift+I
}
然后第一个节到最后一个节的PointerToRawData添加0x200,即节在磁盘文件上的偏移
如:400h->600h
Tips:如果想要插入的节表的空间足够0x28,那么就不用插入了,可以直接覆盖数据。
但是我编译出来的HelloWorld是需要插入了,就拿HelloWorld.exe学习了。
修改节的数量
NT头--文件头--节的数量:15改成16
修改SizeOfHeader
SizeOfHeaders是DOS头+PE头+区块表的总大小,后面的区块表更新了,所以这个也要更新的来着。
400h->600h
修改插入的节表的数据
参照着上面的填,
节表名字取名为.custom
union:实际使用的区块大小,该值可以不准确,所以申请了多少填多少,主要看壳代码的大小,学习示例申请1000h
VirtualAddresss:装载到内存中的RVA,这个要参照页对齐大小(在NT头的可选文件头里SectionAlignment
),是0x1000h,所以在虚拟内存中,上一个表的0x11000+0x200=0x11200会对齐为0x12000h
SizeOfRawData:1000h,参考union,主要看壳代码的大小
PointerToRawData:6A00h,在磁盘文件中的偏移,上一个表的0x6800h+0x200h计算得到的
在节表最后的地方对Characteristics进行修改,修改可读可写可执行权限:0h->1h
添加节
申请空间
在最后一个节的末位插入申请的字节空间:0x1000h
修改节为壳的代码
为了简化学习,壳变成以下汇编
add ecx,0x17
jmp ???
其中,???为程序原始入口地址,如下图,原入口为:0x4014E0
然后将exe文件拖入IDA或者OD用插件patch得到对应字节码,然后在010里面修改
83 C1 17
E9 D8 F4 FE FF
修改入口点
AddressOfEntryPoint
表示的是代码入口的RVA地址。也就是说,把一个文件加载到内存的时候,基地址加上AddressOfEntryPoint就是我们的入口代码地址
首先清楚这个0x14E0h是怎么计算得到的:
在磁盘文件中,实际的代码地址是8E0h,位于第一个表中
首先得到第一个表的信息:
第一个表在磁盘文件中的偏移为400h,实际代码地址为8E0h,
也就是说 实际的代码地址相对于第一个表的起始地址的偏移为4E0h,
这个地址位于第一个表的第0x4E0处,然后加上第一个表的VirtualAddress虚拟起始地址0x1000h,最后就得到了0x14E0h
注意:加的不是BaseOfCode,例如:如果换成了第二个表中的代码的话,那么就是需要用第二个表的VirtualAddress了。
然后要将0x14E0h修改为壳的VirtualAddress+偏移为0(因为是直接就在表的开始就注入了那两条简易汇编了)=0x12000h
实际上就三个值:
第一个值:汇编所在的表的 PointerToRawData
第二个值:磁盘文件中的 入口汇编代码 的地址
第三个值:汇编所在的表的 VirtualAddress
AddressOfEntryPoint
=2-1+3
那是将0x14E0h改为0x6A00h吗?
错误!0x6A00h对应的是磁盘文件的入口,不是映像内存的入口,需要通过以上方法计算:
第一个值:6A00h
第二个值:6A00h
第三个值:12000h
==>相对偏移=0,所以直接就是VirtualAddress=0x12000h
修改SizeOfCode
1E00h还要再加上壳的代码的大小(0x1000h)=2E00h
修改SizeOfImage
映像装入内存后的总大小,必须满足页对齐
加上壳的代码的大小,12000h->13000h
最后成功加壳并运行!