ReloX v1.0 是ImportREC 作者MackT在2003年写的一款重定表重建工具,其原理是是比较2个不同基址DLL的内存映像,根据不同数据,生成一张重定位表,原版只支持32位的PE文件。最近在准备《加密与解密》第五版中的64位PE文件重定表一块,花点时间将这个工具扩展了一下,让其支持64位的PE文件。
1) - 在“Original”行上使用“...”按钮选择第一个基址映像。
基址会自动生成。如果不正确,请修改它。
2) - 在“Compare to”行上使用“...”按钮选择第二个基址映像。
基址会自动生成。如果不正确,请修改它。
3) - 点击“Select Sections”选择包含代码进行比较的所有部分(默认是全部)。
4) - 点击“Compare”开始两个映像文件的比较。
结果将显示在列表控件中。
5) - 点击“Fix PE Module”选择一个PE文件,并使用新的“.reloc”节修复它。
一、支持PE32+重定位表类型IMAGE_REL_BASED_DIR64
32位程序和64位程序重定位结构基本一样,区别就在于32位程序重定位类型都是IMAGE_REL_BASED_HIGHLOW(16进制值是3),64位程序的重定位类型都是IMAGE_REL_BASED_DIR64(16进制的值是0xA,十进制是10)。
重定位表结构:
IMAGE_BASE_RELOCATION STRUCT
VirtualAddress DWORD ? ;重定位数据的开始RVA地址
SizeOfBlock DWORD ? ;重定位块的长度
TypeOffset WORD ? ;重定位项数组
IMAGE_BASE_RELOCATION ENDS
IDA打开ReloX1.exe,搜索字符串“IMAGE_REL_BASED_HIGHLOW”,找到两处调用,改成指向新的字符串“IMAGE_REL_BASED_DIR64”
.text:00405473 push offset aImageRelBasedH ; "IMAGE_REL_BASED_HIGHLOW (3)"
.text:00405478 push 1 ; int
.text:0040547A push eax ; wParam
.text:0040547B mov ecx, edi
.text:0040547D call sub_419AFD
……
.text:0040623E push offset aImageRelBasedH ; "IMAGE_REL_BASED_HIGHLOW (3)"
.text:00406243 push 1 ; int
.text:00406245 push eax ; wParam
.text:00406246 mov ecx, edi
.text:00406248 call sub_419AFD
修改成:
00405473 push 0042B70C ; ASCII "IMAGE_REL_BASED_DIR64(10)"
00405478 push 1
0040547A push eax
0040547B mov ecx, edi
0040547D call 00419AFD
……
0040623E push 0042B70C ; ASCII "IMAGE_REL_BASED_DIR64(10)"
00406243 push 1
00406245 push eax
00406246 mov ecx, edi
00406248 call 00419AFD
导出的Relocs文本文件,改这里:
.text:0040710B push 3 ; IMAGE_REL_BASED_HIGHLOW,改成push 0xA
.text:0040710D mov eax, [edx+esi*4]
.text:00407110 push eax ; int
.text:00407111 push offset a08xX ; "%08X\t%X\n"
.text:00407116 push ebp ; Stream
.text:00407117 call _fprintf
对TypeOffset进行处理
改成与 IMAGE_REL_BASED_DIR64(0xA)
004049B7 mov dx, word ptr [eax+edi*4]
004049BB mov eax, dword ptr [esp+E0]
004049C2 and edx, 0FFF
004049C8 or dh, 0A0 // IMAGE_REL_BASED_DIR64
004049CB mov word ptr [eax+ebx], dx
004049CF mov ebx, dword ptr [esp+10]
经过这样处理,生成的重定位表,就符合PE32+要求了。
二、修正IMAGE_DATA_DIRECTORY 中的Base relocation Table
32位PE和64位PE32+,其IMAGE_DATA_DIRECTORY偏移不同,这部分代码需要修正,不然生成的文件,重定位表地址是错的。
32位PE文件,IMAGE_DATA_DIRECTORY离IMAGE_OPTIONAL_HEADER距离为0x78-0x18=0x60,64位PE32+文件,这个距离为0x88-0x18=0x70
找到处理32位PE的代码如下
0040351D | 8D3402 | lea esi,dword ptr ds:[edx+eax] | ESI=IMAGE_OPTIONAL_HEADER32
00403520 | 89B1 C8000000 | mov dword ptr ds:[ecx+C8],esi |
00403526 | 83C6 60 | add esi,60 | IMAGE_OPTIONAL_HEADER32+60=DataDirectory //改成add esi,70
00403529 | 89B1 D0000000 | mov dword ptr ds:[ecx+D0],esi |
这样修改后,就可以处理64位PE文件了。
三、让程序同时支持PE和PE32+
32位64位程序判断原理
DOS头:PE文件以DOS头(64字节)开始。前两个字节是魔术数字e_magic,通常为0x5A4D(ASCII码“MZ”)。在DOS头的最后4个字节有一个偏移量e_lfanew,指向PE头的位置。
PE头:PE头以PE\0\0(0x00004550)开始,这标志着这是一个有效的PE文件。
可选头:紧接在PE头之后的是可选头,包含了更多的细节。可选头的前两个字节是Magic字段,可以判断文件是32位还是64位:
0x10B表示32位(PE32)。
0x20B表示64位(PE32+)。
0040351D . 8D3402 lea esi, dword ptr [edx+eax] //ESI=IMAGE_OPTIONAL_HEADER
00403520 . E9 C3ED0100 jmp 004222E8 //跳到空白处
00403525 90 nop
00403526 > 83C6 60 add esi, 60
00403529 > 89B1 D0000000 mov dword ptr [ecx+D0], esi
补丁代码:
004222E8 > \60 pushad //保存环境,寄存器内容没变化,这句可删除
004222E9 . 9C pushfd
004222EA . 66:813E 0B02 cmp word ptr [esi], 20B
004222EF . 74 0D je short 004222FE
004222F1 . 9D popfd
004222F2 . 61 popad
004222F3 . 89B1 C8000000 mov dword ptr [ecx+C8], esi
004222F9 .^ E9 2812FEFF jmp 00403526
004222FE > C605 0C714000 0A mov byte ptr [40710C], 0A
00422305 . C705 74544000 0CB74200 mov dword ptr [405474], 0042B70C
0042230F . C705 3F624000 0CB74200 mov dword ptr [40623F], 0042B70C
00422319 . C605 CA494000 A0 mov byte ptr [4049CA], 0A0
00422320 . 9D popfd
00422321 . 61 popad
00422322 89B1 C8000000 mov dword ptr [ecx+C8], esi
00422328 83C6 70 add esi, 70
0042232B .^ E9 F911FEFF jmp 00403529
四、成品效果
将测试DLL复制一份,用不同进程x64dbg加载并Dump出,就可以得到不同基址的DLL。
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
最后于 2024-5-22 14:56
被kanxue编辑
,原因: