像虚拟内存载入PE文件时(EXE/DLL/SYS/OCX/COM),加载到PE头的ImageBase所知的地址处。
PE头(DOS头/DOS存根/NT头:文件头/NT:可选头/节区头及其下属构成)
PE重定位指的是PE文件将要载入的ImageBase所指的位置已被占用,再加载到其他地址发生的行为。
EXE默认的ImageBase为00 400 000,DLL默认的ImageBase为10 000 000。另外DDK(驱动开发工具包)开发的SYS文件默认的ImageBase为10 000。
另外EXE(等)文件载入内存的地址是随机的。即重定位的目标地址不确定。
DLL的重定位,如下图。
PE重定位
(基址重定位表(?)查看/根据“IMAGE_BASE_RELOCATION”结构体的定义可知)VA基准地址和SizeOfBlock成员的值以及TypeOffset。
TypeOffset由4位的Type和12位的Offset合成。
IMAGE_BASE_RELOCATION结构体
{
}
VA+TypeOffset=RVA。查找该RVA的数据值-ImageBase+实际加载地址=目标。
.reloc节区(PE文件重定位节区)
删除.reloc节区头
使用PEview查看的节区头(IMAGE_SECTION_HEADER .reloc)
图中原始数据指针(Pointer to Raw Data)数据值位C000即.reloc节区起始偏移地址位C000。
此处,Virtual Size值为VS=E40。
从270开始往下到294.295.296.297全部用0覆盖达到删除效果。
删除.reloc节区
.reloc节区起始偏移地址位C000。
删除数据,使用HxD的“Deter”功能方便。
修改IMAGE_FLE_HEARDER(更改节区数量)
同样使用PEview查看。因为只需要删除一个.reloc的节区所以,节区数量需要减一。如下图Number of Sections 的Data为0005,所以需要将其数据改为0004.
修改IMAGE_OPTIONAL_HEARDER
因为删除了.reloc节区所以相应的映像需要减小(类似掏空了一部份区域,这块区域需要被移出)。映像的大小存储在IMAGE_OPTIONAL_HEARDER-Size of Image中。
需要对此数据进行修改。目前Size of Image = 11 000。
VS=E40(需要减少的大小)(因为“需要对齐”)
Section Alignment(对齐值)=1000(大多数情况)
公式Size of Image = Size of Image - VS(此处=Section Alignment对齐值)。
Size of Image = 10 000。
------------------------------------------------------------------------------
------------------------------------------------------------------------------
UPack压缩文件
使用PEview发现与普通的PE相比缺少了标志的IMAGE_OPTIONAL_HEADER与IMAGE_SECTION_HEADER。无法读取到PE头。
对应UPack压缩的文件可以使用stud_PE工具来查看。
优势就是能更加直观的查看到PE头里的各项数值,但是强大的功能也导致其界面的更加复杂。
尝试比较一下原文件与UPack压缩过的文件对比
源文件
其中MZ与PE之间有DOS存根,PE往下就是一些零星的字符。
UPack压缩过的文件
明显能看出MZ与PE是紧挨在一起的,DOS的存根消失不见,其次PE往下的零星字符被大量的字符代替,甚至还能看见API的函数名GetProcAddress,所以可能还含有代码。
------------------------------------------------------------------------------
------------------------------------------------------------------------------
分析UPack的PE文件头
技法①:重叠文件头
即将MZ文件头(IMAGE_DOS_HEADER)与PE文件头(IMAGE_NT_HEADER)重叠(压缩)在一起,节省空间,复杂化文件头。
使用Stud_PE查看MZ文件头。Header—>Basic HEADERS tree view in hexeditor。如下。
MZ头文件(IMAGE_DOS_HEADER)的两个重要成员。
(当前offset 0) e_magic
: Magic NUmber =4D5A (‘MZ’)
(当前offset 3C) e_flanew
(10) : File address of new exe header
因为IMAGE_NT_HEADER(PE文件头)的起始位置是可变的,并且由e_flanew的值决定
一般情况e_flanew的计算公式如下
e_lfanew = MZ文件头大小(40)
+ DOS存根的大小(可变:VC++下为A0)
= E0
所以重叠文件头其实是使其PE与MZ位置接近,导致内容混合?