首页
社区
课程
招聘
[原创]用SMC让EXE文件的重定位表起作用
发表于: 2007-5-5 21:34 9657

[原创]用SMC让EXE文件的重定位表起作用

2007-5-5 21:34
9657
写了《通过ReverseMe学习PE文件结构-重定位表》之后我就在想解决这个问题的办法除了我那个不是办法的办法,还有没有是办法的办法?:)
想到SMC,想到重定位的原理,就想出了这个办法。

=====
重定位表的使用方法为(我自己的理解):
文件的实际装入地址-文件的建议装入地址=修正值
实际装入地址+VirtualAddress+重定位项中的地址=需要重定位的代码在内存中的位置
修正值+需要重定位的代码=正确的代码(只需要把地址加上修正值)
只需要定位到需要重定位的代码在内存中的位置把该处的代码修改成正确的代码即可。
注:上面说的代码应该是用于立即寻址的地址。

=====
算法:
1.计算修正值(修正值=文件的实际装入地址-文件的建议装入地址)
2.读取一个IMAGE_BASE_RELOCATION结构
3.VirtualAddress字段为0则算法结束
4.对所有重定位项执行步骤5-6后跳到2
5.计算需要重定位的地址在内存中的位置
6.修正地址(将需要修正的地址加上修正值)

=====
OllyDBG里的代码:
0040101B      55            push    ebp
0040101C      8BEC          mov     ebp, esp
0040101E      A1 1D404000   mov     eax, dword ptr [<&Reversed_.MyMe>;  获得需要重定位的文件的装入基址
00401023      66:33C0       xor     ax, ax
00401026      8BC8          mov     ecx, eax
00401028      0340 3C       add     eax, dword ptr [eax+3C]          ;  获得目标模块的建议装入基址
0040102B      8B50 34       mov     edx, dword ptr [eax+34]
0040102E      8BD9          mov     ebx, ecx
00401030      2BDA          sub     ebx, edx                         ;  计算修正值,放在EBX中
00401032      8BF1          mov     esi, ecx
00401034      8BD1          mov     edx, ecx                         ;  EDX中是实际装入基址
00401036      03B0 A0000000 add     esi, dword ptr [eax+A0]          ;  定位目标模块的重定位表,ESI是当前处理的重定位项地址
0040103C      8B06          mov     eax, dword ptr [esi]             ;  EAX中是VirtualAddress
0040103E      83C6 04       add     esi, 4                           ;  2.读取一个IMAGE_BASE_RELOCATION结构
00401041      85C0          test    eax, eax                         ;  3.VirtualAddress字段为0则算法结束
00401043      74 29         je      short 0040106E
00401045      03C2          add     eax, edx                         ;  EAX中是 实际装入地址+VirtualAddress
00401047      8B0E          mov     ecx, dword ptr [esi]
00401049      83C6 04       add     esi, 4
0040104C      85C9          test    ecx, ecx
0040104E    ^ 74 EC         je      short 0040103C                   ;  4.对所有重定位项执行步骤5-6后跳到2
00401050      83E9 08       sub     ecx, 8
00401053      D1C9          ror     ecx, 1
00401055      85C9          test    ecx, ecx
00401057    ^ 74 E3         je      short 0040103C
00401059      33FF          xor     edi, edi                         ;  5.计算需要重定位的地址在内存中的位置
0040105B      66:8B3E       mov     di, word ptr [esi]
0040105E      83C6 02       add     esi, 2
00401061      03F8          add     edi, eax
00401063      81EF 00300000 sub     edi, 3000                        ;  EDI中是需要修正的地址的地址
00401069      011F          add     dword ptr [edi], ebx
0040106B      49            dec     ecx
0040106C    ^ EB E9         jmp     short 00401057
0040106E      5D            pop     ebp
0040106F      C3            retn

=====
这个方法稍微有点通用性了,不过还需要手工给出一个目标模块中的一个函数的入口地址,虽说只是一个地址(见0040101E处的语句),毕竟还是有手动部分。要改成全自动的:)
观察一下0040101E处的语句,发现该处命令的地址参数实际上是输入表中的一项,如此便简单了:我们遍历当前模块的输入表,查找文件名后缀名不是"DLL"或"dll"的输入表项,然后从该表中取一个输入函数即可。

0040101D      55            push    ebp
0040101E      8BEC          mov     ebp, esp
00401020      E8 00000000   call    00401025                         ;  获得基址
00401025      58            pop     eax
00401026      66:33C0       xor     ax, ax
00401029      8BD0          mov     edx, eax                         ;  EDX中是基址
0040102B      0340 3C       add     eax, dword ptr [eax+3C]          ;  PE文件头
0040102E      66:8B80 80000>mov     ax, word ptr [eax+80]            ;  输入表
00401035      8B38          mov     edi, dword ptr [eax]
00401037      85FF          test    edi, edi
00401039      74 74         je      short 004010AF                   ;  遍历整个输入表,直到找到满足条件的输入文件
0040103B      8BD8          mov     ebx, eax
0040103D      83C0 14       add     eax, 14
00401040      83C3 0C       add     ebx, 0C
00401043      8BFB          mov     edi, ebx
00401045      8B3F          mov     edi, dword ptr [edi]
00401047      03FA          add     edi, edx
00401049      8A0F          mov     cl, byte ptr [edi]
0040104B      80E9 2E       sub     cl, 2E                           ;  定位文件后缀名
0040104E      74 03         je      short 00401053
00401050      47            inc     edi
00401051    ^ EB F6         jmp     short 00401049
00401053      8B0F          mov     ecx, dword ptr [edi]
00401055      81E9 2E646C6C sub     ecx, 6C6C642E                    ;  判断后缀名是否是"DLL"或"dll"
0040105B    ^ 74 D8         je      short 00401035
0040105D      81C1 2E646C6C add     ecx, 6C6C642E
00401063      81E9 2E444C4C sub     ecx, 4C4C442E
00401069    ^ 74 CA         je      short 00401035
0040106B      83E8 04       sub     eax, 4                           ;  找到了目标文件,开始找导入函数
0040106E      66:8B00       mov     ax, word ptr [eax]
.....;后面与上面的那个版本从00401023开始的相同,略去了

OllyDBG中用于二进制复制/粘贴的代码:
E8 00 00 00 00 58 66 33 C0 8B D0 03 40 3C 66 8B 80 80 00 00 00 8B 38 85 FF 74 74 8B D8 83 C0 14
83 C3 0C 8B FB 8B 3F 03 FA 8A 0F 80 E9 2E 74 03 47 EB F6 8B 0F 81 E9 2E 64 6C 6C 74 D8 81 C1 2E
64 6C 6C 81 E9 2E 44 4C 4C 74 CA 83 E8 04 66 8B 00 A1 1D 40 40 00 66 33 C0 8B C8 03 40 3C 8B 50
34 8B D9 2B DA 8B F1 8B D1 03 B0 A0 00 00 00 8B 06 83 C6 04 85 C0 74 29 03 C2 8B 0E 83 C6 04 85
C9 74 EC 83 E9 08 D1 C9 85 C9 74 E3 33 FF 66 8B 3E 83 C6 02 03 F8 81 EF 00 30 00 00 01 1F 49 EB
E9 5D C3

=====
这样子就有通用性了,以后给目标程序建立重定位表之后,只需要把这段代码粘贴到调用目标程序的程序中就可以了。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (1)
雪    币: 259
活跃值: (56)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
大概明白意思,不过最关键还是如何自动构造exe当dll使用时的重定位表,难道所有的CALL dword ptr [????????],JMP dword ptr [????????],PUSH ########,CALL dword ptr [R32+????????]之类的都得手动改?
高手有没有更好的方法
2011-5-14 17:07
0
游客
登录 | 注册 方可回帖
返回
//