首页
社区
课程
招聘
[原创][新手练习]UnpackMe_006[分析及脱壳-图文+动画]
发表于: 2009-5-16 06:21 14788

[原创][新手练习]UnpackMe_006[分析及脱壳-图文+动画]

2009-5-16 06:21
14788
【文章标题】: UnpackMe_006 分析及脱壳
【文章作者】: RegKiller
【作者邮箱】: 都不用QQ了我也换
【作者QQ号】: 有缘分的论坛给我发短消息获取
【软件名称】: UnpackMe_006
【软件大小】: 很小
【下载地址】: 自己搜索下载
【加壳方式】: 未知壳
【保护方式】: 加壳保护
【编写语言】: MASM32 / TASM32
【操作平台】: 瘟系统都可以
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

考虑了一下,准备给新手详细说说这个文件的脱壳方法及思路,之前的分析在:

http://www.unpack.cn/viewthread.php?tid=35620&extra=page%3D1&page=2

页的 39 楼,本文重新详细地写了分析及脱壳的过程,高手请自觉飘过,飘走之前务必给我加点分,再此先谢过各位朋友了,后面的动画教程由于我电脑比较烂,动画大家将就着看吧。

-------------------------------------------------------------------------------------------------------
【详细过程】

很久没发文了,现在人懒了,希望这篇文章可以给新手点思路,高手路过的也别忘了给我加点分,现在的论坛都要银子才能混啊,不搞收费下载了,没什么技术含量的东西。

先来个快速到达 OEP 方法,目的是让你先有点成功感,想了解为什么这么做,怎么知道要这么做的朋友可以看下面详细分析过程。

后面详细分析过程中我会用不同的方法来脱壳及修复,图文教程用了一种方法,动画中也略有不同,脚本中修复 IAT 又用了跟图文教程中也不一样的方法来修复 IAT。

OD 载入程序后在 00401000 断下个"设置内存写入断点",SHIFT + F9 中断后删除刚才的断点。

然后再下一条指令 POP ESI 上下 F2 断点,中断后删除 F2 断点再在 00401000 断下个"设置内存写入断点"。

中断后删除刚才的断点,因为是 C 或汇编写的程序,所以下 bp GetModuleHandleA 后 SHIFT + F9 4 次就到 OEP 了。

这里断在 00401007 处,真正的 OEP 应该是 00401000。


好了,我们开始:

1 首先查壳及文件是用什么语言编译的。







2 设置 OD 反调试




这里注意一下这项:Anti-RDTSC [基于驱动程序] 这个壳里有大量的 RDTSC 稍候我会简单说下这部分

3 找 OEP
004059F2 >  55              PUSH EBP                                 ; OD 载入后停在 EP 处
004059F3    8BEC            MOV EBP,ESP
004059F5    83C4 F4         ADD ESP,-0C
004059F8    83C4 0C         ADD ESP,0C
004059FB    50              PUSH EAX
004059FC    EB 02           JMP SHORT 00405A00
004059FE    0000            ADD BYTE PTR DS:[EAX],AL
下断 bp GetProcAddress+5 然后 F9 运行

(这里 +5 相当于在函数 GetProcAddress 入口后 5 字节下了断点,这样做的目的是避免壳检测,当然这里可以用其它方法,比如 +7 +9 或在 GetProcAddress 末尾的 RET 处下断,当然也可以直接用硬件断点下断)
7C80AE40 kernel32.GetProcAddress          8BFF            MOV EDI,EDI
7C80AE42                            55              PUSH EBP
7C80AE43                            8BEC            MOV EBP,ESP
7C80AE45                            51              PUSH ECX                                 ; 断在这里
7C80AE46                            51              PUSH ECX
7C80AE47                            53              PUSH EBX
7C80AE48                            57              PUSH EDI
取消断点 ALT+F9 返回
00950AA3      33DB            XOR EBX,EBX                              ; 返回到这里
00950AA5      60              PUSHAD
00950AA6      EB 03           JMP SHORT 00950AAB
00950AA8      EB 03           JMP SHORT 00950AAD
00950AAA      C7              ???                                      ; 未知命令
Ctrl + F 查找 jmp eax 命令,然后在上面下断后 F9 运行

(这里简单说下找这个 jmp eax 命令是怎么来的,当我们上面 ALT +F9 返回后,可以用 F7 及 F8 单步跟踪,走到最后就是这个命令了。
当我们用 F7 及 F8 走的时候会遇到很多的 RDTSC 指令,这条指令会通过时间差来检测程序是否被调试,如果我们没开 OD 反调试插件里的 Anti-RDTSC [基于驱动程序],那么后面可能会遇到类似下面的代码:
00940B42    83C4 04         ADD ESP,4
00940B45    85D2            TEST EDX,EDX
00940B47  ^ 75 D6           JNZ SHORT 00940B1F
00940B49    61              POPAD
打开反调试插件后这个 JNZ 是应该不跳的,但我发现如果把 OD 晾在那很久后再遇到这样的代码,那么这个 JNZ 可能还会跳,这里可以手动 NOP 掉这行代码,或者在下一行代码处鼠标右键"在此处新建 EIP",也就相当与跳过了上面的代码,相对于 NOP 掉的好处是如果后面壳检测代码是否被修改了,那么我们可能就少走弯路了。

如果你很不幸跟着那个 JNZ 跳了,那么你会来到类似如下的指令处:
00940B1F    F0:0FC7C8       LOCK CMPXCHG8B EAX                       ; 非法使用寄存器
00940B23    EB 03           JMP SHORT 00940B28
00940B25    EB 03           JMP SHORT 00940B2A
00940B27    C7              ???                                      ; 未知命令
估计很多新人都是挂在 LOCK CMPXCHG8B EAX 这条指令上了(偷笑中。。。),没关系,Ctrl + F2 重新来过,下次小心点OK了。
)
009511D3      C40485 D275D661 LES EAX,FWORD PTR DS:[EAX*4+61D675D2]
009511DA      8B85 AD234000   MOV EAX,DWORD PTR SS:[EBP+4023AD]
009511E0      894424 1C       MOV DWORD PTR SS:[ESP+1C],EAX
009511E4      61              POPAD
009511E5      FFE0            JMP EAX                                  ; 找到这里,在这句上下断
009511E7      60              PUSHAD
009511E8      8BF0            MOV ESI,EAX
009511EA      8BF9            MOV EDI,ECX
断下后我们 F8 让程序跳到 EAX 所指定的地址 :00970000
00970000      C7C7 72AFB4DF   MOV EDI,DFB4AF72                         ; 这下面可以一直 F8 大步走了
00970006      8D3D 5FBA581A   LEA EDI,DWORD PTR DS:[1A58BA5F]
0097000C      FFCF            DEC EDI
0097000E      0FACF7 F2       SHRD EDI,ESI,0F2
00970012      0FBDFE          BSR EDI,ESI
。。。 中间代码省略,F8 一直走到底就是 OEP 了 。。。
009707EB      8BFE            MOV EDI,ESI
009707ED      19F7            SBB EDI,ESI
009707EF      6A 00           PUSH 0                                ; 这里偷了 OEP 处的第一句的代码
009707F1      65:81E7 70E3980>AND EDI,398E370
009707F8      65:87FF         XCHG EDI,EDI
009707FB      F2:             PREFIX REPNE:
。。。 中间代码省略,F8 一直走到底就是 OEP 了 。。。
00970C4A      69FE CB2BC651   IMUL EDI,ESI,51C62BCB
00970C50      85F7            TEST EDI,ESI
00970C52      F7C7 1CDC4C87   TEST EDI,874CDC1C
00970C58      81E7 43C67893   AND EDI,9378C643
00970C5E    - E9 9F03A9FF     JMP UnpackMe.00401002                    ; 到 OEP 了
00970C63      0000            ADD BYTE PTR DS:[EAX],AL
00970C65      0000            ADD BYTE PTR DS:[EAX],AL
00970C67      0000            ADD BYTE PTR DS:[EAX],AL
00970C69      0000            ADD BYTE PTR DS:[EAX],AL
(关于 009707EF PUSH 0 这条指令,这里我们有几种处理方法,如果你已经到 OEP 了,那么你会发现堆栈窗口中如下的代码:
0012FF98   00000000
0012FF9C   00405A12  返回到 UnpackMe.00405A12 来自 UnpackMe.00405A36
0012FFA0   FFFFFFFF
0012FFA4   0012FFC0
0012FF98   00000000 这里就是刚才 009707EF PUSH 0 过来的,程序本身是 MASM32 / TASM32 汇编语言写的-本文开始处查壳工具全都误报了,所以正确的 OEP 应该在 00401000 处。如何知道这程序本身是什么语言写的 1 有原始未加壳的程序 2 根据经验。刚好在这个程序上这两条我都有。稍候给你们份原版未加壳的大家研究下。

好了,我们通过鼠标右键菜单把 EIP 新建在 00401000 处,然后补上被偷掉的 PUSH 0 刚好是两个字节,这里注意一下,如果你现在这么做了,并且还要继续跟踪程序,那么记得先把堆栈 0012FF98   00000000 POP 出来,保持堆栈平衡是不只是个好习惯,通过鼠标右键完成。

如果你现在的 EIP 还在 009707EF 的 PUSH 0 处,也就是你还没到 OEP 呢,那么直接把这句 NOP 掉,或者把这条指令改成 mov edi,edi 相当于两个 NOP 了,也刚好是两个字节。然后去 00970C5E JMP 00401002 处直接把 JMP 00401002 改成 JMP 00401000 后到 OEP 处还原那句 PUSH 0 就可以免去 POP 掉堆栈 0012FF98   00000000 这个步骤了。

到 OEP 后如果 OD CPU 窗口中的代码如下:
00401002      E8            DB E8
00401003      F3            DB F3
00401004      0E            DB 0E
00401005      00            DB 00
00401006      00            DB 00
00401007      A3            DB A3
00401008      4C            DB 4C                                    ;  CHAR 'L'
00401009      36            DB 36                                    ;  CHAR '6'
0040100A      40            DB 40                                    ;  CHAR '@'
0040100B      00            DB 00
0040100C      6A            DB 6A                                    ;  CHAR 'j'
0040100D      00            DB 00
0040100E      68            DB 68                                    ;  CHAR 'h'
0040100F      66            DB 66                                    ;  CHAR 'f'
00401010      10            DB 10
00401011      40            DB 40                                    ;  CHAR '@'
00401012      00            DB 00
00401013      6A            DB 6A                                    ;  CHAR 'j'
00401014      00            DB 00
00401015      68            DB 68                                    ;  CHAR 'h'
那么用鼠标右键菜单:分析->从模块删除分析就可以了,删除分析后代码如下:
00401000    6A 00           PUSH 0                                   ; 这里就是 OEP 了
00401002    E8 F30E0000     CALL 00401EFA
00401007    A3 4C364000     MOV DWORD PTR DS:[40364C],EAX
0040100C    6A 00           PUSH 0
0040100E    68 66104000     PUSH 00401066
00401013    6A 00           PUSH 0
00401015    68 00304000     PUSH 00403000                            ; ASCII "TESTWIN"
0040101A    FF35 4C364000   PUSH DWORD PTR DS:[40364C]
00401020    E8 750E0000     CALL 00401E9A
00401025    50              PUSH EAX
00401026    E8 C30E0000     CALL 00401EEE
0040102B    C3              RETN
0040102C    8925 803D4000   MOV DWORD PTR DS:[403D80],ESP
00401032    68 F4344000     PUSH 004034F4                            ; ASCII "Unpack started..."
00401037    E8 9B020000     CALL 004012D7
0040103C    E8 A9060000     CALL 004016EA
)

4 关于 IAT 的修复

IAT的修复本例子有至少两种方法:

1 手工修复,2 写个脚本修复 3 找别人给你修复(不推荐但又是最省时间最省事的方法;) )。这里我们先看看代码后再考虑怎么修复

看下 00401002      E8 F30E0000     CALL 00401EFA  这句,回车进入代码如下:

00401EFA    - FF25 C2039600   JMP DWORD PTR DS:[9603C2] 再回车进入
009603C6     /EB 01           JMP SHORT 009603C9
009603C8     |C9              LEAVE
009603C9     \60              PUSHAD
009603CA      0F31            RDTSC
009603CC      EB 01           JMP SHORT 009603CF
下面很多类似的代码,看下这里有不少 RDTSC ,比如 009603CA 这行,避免继续 F7 挂掉,把 Olly Advanced 插件里的“反调试 II” 选项卡里的"Anti-RDTSC [基于驱动程序]"启用,选"方式1"就可以了。然后从 009603C6 这行 F7 往下走不远就看到 :
009603F5      61              POPAD
009603F6      EB 01           JMP SHORT 009603F9
009603F8      C7              ???                                               ; 未知命令
009603F9      68 41B7807C     PUSH kernel32.GetModuleHandleA                    ; 这就是我们要找的东西了
009603FE      EB 01           JMP SHORT 00960401
00960400    - E9 C3EB01E9     JMP E997EFC8
009603F9  PUSH kernel32.GetModuleHandleA ,壳用 PUSH 函数然后 RET 跳到这个函数的方法来访问函数。

在 CPU 窗口中先删除 OD 的分析,然后我们到数据窗口中看内容

在 CPU 窗口中的 00401EFA  - FF25 C2039500   JMP DWORD PTR DS:[9503C2] 上鼠标右键:跟随到数据窗口->选定内容,然后在数据窗口中鼠标右键:反汇编,这样我们可以在数据窗口中看到汇编代码。




我很想知道 JMP DWORD PTR DS:[9503C2] 里的 9503C2 这个地址是怎么来的,所以方法如下:

数据窗口中 00401EFA  - FF25 C2039500   JMP DWORD PTR DS:[9503C2]

地址是 401EFA 去掉前面的 JMP 指令也就是那个 FF25 那么正确的地址就是 401EFA + 2 = 401EFC

可以在 OD 的命令行中输入 D 401EFC,也可以不输入命令直接用鼠标在数据窗口中 CTRl + 键盘下箭头来单个字节地移动窗口中的数据显示,当然这方法在 OD 的 CPU 等窗口中也适用。




在数据窗口中 00401EFC C2 0395 RETN 9503 处鼠标右键:断点->硬件写入->Dword 下个写入断点,然后 Ctrl + F2 重新加载程序来看看程序什么时候把 00401EFA JMP DWORD PTR DS:[xxxxxxxx] 写入了 9503C2 这个地址。

重新载如程序后和开始一样,下 bp GetProcAddress+5 断点,断下后 ALT +F9 返回,刚才下了硬件写入断点,这里我们继续 Shift +F9 运行程序,断下后来到这里:
00940BFC    A8 83           TEST AL,83
00940BFE    C40485 D275D661 LES EAX,FWORD PTR DS:[EAX*4+61D675D2]
00940C05    8901            MOV DWORD PTR DS:[ECX],EAX
00940C07    83C7 04         ADD EDI,4                                ; 中断后停在此处
00940C0A    FECB            DEC BL
00940C0C    58              POP EAX
00940C0D    80FB 00         CMP BL,0
看下寄存器窗口中的数据
EAX 009503C2
ECX 00401EFC UnpackMe.00401EFC
EDX 7C99E178 ntdll.7C99E178
EBX 00000001
ESP 0012FF7C
EBP 00004A00
ESI 00970000
EDI 00970124
EIP 00940C07
这里比较重要的就是 EAX 和 ECX 了。看看他们的值你就知道是 00940C05 MOV DWORD PTR DS:[ECX],EAX 也就是我们断下后的上一条指令写入的。

这里如果你有兴趣可以在 00940C05 行上下个硬件执行断点 Shift + F9 多跑几次研究一下。我说了这么多,其实这里都不是本例的重点,我只希望让大家能够了解修复 IAT 前如何分析程序操作 IAT 地址及内容的方法而已。

好了,我们开始修复 IAT 了,Ctrl + F2 重新载入程序,然后清掉你 OD 中的所有类型的断点,老办法,下 bp GetProcAddress+5 中断后 ALT + F9 返回。

还记得 RDTSC 这个检测吧,过检测的方法前面已经说了,这里不罗嗦了,我们 F7 及 F8 配合着往下单步走:
00940AA3    33DB            XOR EBX,EBX
00940AA5    60              PUSHAD
00940AA6    EB 03           JMP SHORT 00940AAB
00940AA8    EB 03           JMP SHORT 00940AAD
00940AAA    C7              ???                                      ; 未知命令
00940AAB  ^ EB FB           JMP SHORT 00940AA8
从 00940AA3 处开始往下一直走,这里需要点耐心,如果遇到前天提到的那个 JNZ 记得别跟着跳过去,走到如下代码处:

过程中很多花指令,可以写个去花的东西,OD 有去花插件,而且本例程序不会检测,这里不多说了。
00941568    83C4 04         ADD ESP,4
0094156B    85D2            TEST EDX,EDX
0094156D  ^ 75 D6           JNZ SHORT 00941545                       ; 这类 RDTSC 的检测全部都别跳
0094156F    61              POPAD
00941570    0385 B1234000   ADD EAX,DWORD PTR SS:[EBP+4023B1]
00941576    894424 1C       MOV DWORD PTR SS:[ESP+1C],EAX
0094157A    E8 00000000     CALL 0094157F
0094157F    5B              POP EBX
00941580    81C3 61020000   ADD EBX,261
00941586    8933            MOV DWORD PTR DS:[EBX],ESI               ; 这里就关键代码了
00941588    8BF8            MOV EDI,EAX
0094158A    60              PUSHAD
0094158B    EB 03           JMP SHORT 00941590
0094158D    EB 03           JMP SHORT 00941592
0094158F    C7              ???                                      ; 未知命令
通过前面的单步分析我们得知 00941586 MOV DWORD PTR DS:[EBX],ESI 这里直接把 ESI 的值写入到 [EAX] 里,这里 [] 相当于把指定的值写入到指定寄存器中地址所指定的空间。假设 EBX 为 401000,ESI 为 200 那么过了这句后 ESI 中的 200 被传送到了 401000 这个地址中,而 EBX 的值还是原来的 401000,这里 [EBX] 其实是个指向 401000 的指针。

看下当前各寄存器的值:
EAX 00950000
ECX 00401ED8 UnpackMe.00401ED8
EDX 7C99E178 ntdll.7C99E178
EBX 009417E0
ESP 0012FF58
EBP 00004A00
ESI 77D18C2E user32.SetTimer
EDI 00970018
EIP 00941586
ESI 中放的是正确的函数地址,EAX 就是我们希望写入的地址了,所以这里我们把 00941586 处的 MOV DWORD PTR DS:[EBX],ESI 改为 MOV DWORD PTR DS:[EAX],ESI,但只改这句还不行,后面我发现程序中还有两个地方又把 00950000 这里的内容修改掉了。

改好上面这句后我们继续 F7 及 F8 往下走,经过刚才修改过的那行代码后我们可以在数据窗口中 d 00950000 来观察写入的内容:
00950000  77D18C2E  user32.SetTimer
00950004  00000000
继续往下走,直到走到下面的代码处:
0094162A    85D2            TEST EDX,EDX
0094162C  ^ 75 D6           JNZ SHORT 00941604                                 ; 检测调试器,不跳
0094162E    61              POPAD
0094162F    8BF3            MOV ESI,EBX
00941631    81EE 38000000   SUB ESI,38
00941637    B9 4A000000     MOV ECX,4A
0094163C    FC              CLD
0094163D    F3:A4           REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]       ; 关键代码
0094163F    8B85 A5234000   MOV EAX,DWORD PTR SS:[EBP+4023A5]
00941645    0385 B1234000   ADD EAX,DWORD PTR SS:[EBP+4023B1]
0094164B    60              PUSHAD
0094164C    EB 03           JMP SHORT 00941651
走到 0094163D REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] 我们看下寄存器窗口中的内容:
EAX 00950000
ECX 0000004A
EDX 7C99E178 ntdll.7C99E178
EBX 009417E0
ESP 0012FF58
EBP 00004A00
ESI 009417A8
EDI 00950000
EIP 0094163D
ESI 所指向的 009417A8 中是垃圾数据,EDI 中的值又是我们刚才刚刚修改代码后写入的正确函数,所以这句要 NOP 掉。

NOP 掉 0094163D 这行指令后继续往下走:
00941792    83C4 04         ADD ESP,4
00941795    85D2            TEST EDX,EDX
00941797  ^ 75 D6           JNZ SHORT 0094176F                                 ; 调试器检测
00941799    61              POPAD
0094179A    8918            MOV DWORD PTR DS:[EAX],EBX                         ; 关键代码
0094179C    8185 B1234000 4>ADD DWORD PTR SS:[EBP+4023B1],4A
009417A6    61              POPAD
009417A7    C3              RETN
009417A8    0000            ADD BYTE PTR DS:[EAX],AL
来到 0094179A MOV DWORD PTR DS:[EAX],EBX 后看下寄存器窗口中的数据:
EAX 00950000
ECX 0000004A
EDX 7C99E178 ntdll.7C99E178
EBX 00950004
ESP 0012FF58
EBP 00004A00
ESI 009417A8
EDI 00950000
EIP 0094179A
这里 EBX 的值就是我们未修复 IAT 前到 OEP 后 CALL 函数中的 JMP DWORD PTR DS:[xxxxxxxx] 中的值了。程序这里要把我们写好的正确地址再次写如垃圾,所以这句也 NOP 掉你就离脱壳越来越近了。

把 0094179A MOV DWORD PTR DS:[EAX],EBX 这句 NOP 掉后清除所有类型的断点,然后 Ctrl + F 查找 JMP EAX 命令,找到后在这条命令上下个断点,然后用前面的方法就可以到 OEP 了。到 OEP 后 Ctrl + A 分析一下代码,看到如下内容:
00401000   .  6A 00         PUSH 0                               ; /这里就是 OEP 了
00401002   .  E8 F30E0000   CALL 00401EFA                        ; \GetModuleHandleA
00401007   .  A3 4C364000   MOV DWORD PTR DS:[40364C],EAX
0040100C   .  6A 00         PUSH 0                               ; /lParam = NULL
0040100E   .  68 66104000   PUSH 00401066                        ; |DlgProc = UnpackMe.00401066
00401013   .  6A 00         PUSH 0                               ; |hOwner = NULL
00401015   .  68 00304000   PUSH 00403000                        ; |pTemplate = "TESTWIN"
0040101A   .  FF35 4C364000 PUSH DWORD PTR DS:[40364C]           ; |hInst = NULL
00401020   .  E8 750E0000   CALL 00401E9A                        ; \DialogBoxParamA
00401025   .  50            PUSH EAX                             ; /ExitCode
00401026   .  E8 C30E0000   CALL 00401EEE                        ; \ExitProcess
0040102B   .  C3            RETN
0040102C  /$  8925 803D4000 MOV DWORD PTR DS:[403D80],ESP
00401032  |.  68 F4344000   PUSH 004034F4                        ;  ASCII "Unpack started..."
00401037  |.  E8 9B020000   CALL 004012D7
0040103C  |.  E8 A9060000   CALL 004016EA
00401041  |.  E8 7E0C0000   CALL 00401CC4
00401046  |.  E8 8B060000   CALL 004016D6
0040104B  |.  E8 6F060000   CALL 004016BF
00401050  |.  E8 46020000   CALL 0040129B
00401055  |.  FF15 B8354000 CALL DWORD PTR DS:[4035B8]
0040105B  |.  68 06354000   PUSH 00403506                        ;  ASCII "Unpack ended..."
00401060  |.  E8 72020000   CALL 004012D7
00401065  \.  C3            RETN
00401066  /.  55            PUSH EBP
00401067  |.  8BEC          MOV EBP,ESP
00401069  |.  817D 0C 10010>CMP DWORD PTR SS:[EBP+C],110
00401070  |.  75 5B         JNZ SHORT 004010CD
00401072  |.  68 08304000   PUSH 00403008                        ; /lParam = 403008
00401077  |.  6A 00         PUSH 0                               ; |wParam = 0
00401079  |.  6A 0C         PUSH 0C                              ; |Message = WM_SETTEXT
0040107B  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]            ; |hWnd
0040107E  |.  E8 470E0000   CALL 00401ECA                        ; \SendMessageA
00401083  |.  68 F4010000   PUSH 1F4                             ; /RsrcName = 500.
00401088  |.  FF35 4C364000 PUSH DWORD PTR DS:[40364C]           ; |hInst = NULL
0040108E  |.  E8 2B0E0000   CALL 00401EBE                        ; \LoadIconA
这里看到 CALL 函数都显示出来了。我们随便找个 CALL 上回车跟进:
00401E8E   $- FF25 78039500 JMP DWORD PTR DS:[950378]            ;  user32.wsprintfA
00401E94   $- FF25 2E039500 JMP DWORD PTR DS:[95032E]            ;  user32.CheckDlgButton
00401E9A   $- FF25 E4029500 JMP DWORD PTR DS:[9502E4]            ;  user32.DialogBoxParamA
00401EA0   $- FF25 9A029500 JMP DWORD PTR DS:[95029A]            ;  user32.EndDialog
00401EA6   $- FF25 50029500 JMP DWORD PTR DS:[950250]            ;  user32.GetDlgItem
00401EAC   $- FF25 06029500 JMP DWORD PTR DS:[950206]            ;  user32.IsDlgButtonChecked
00401EB2   $- FF25 BC019500 JMP DWORD PTR DS:[9501BC]            ;  user32.IsWindowVisible
00401EB8   $- FF25 72019500 JMP DWORD PTR DS:[950172]            ;  user32.KillTimer
00401EBE   $- FF25 28019500 JMP DWORD PTR DS:[950128]            ;  user32.LoadIconA
00401EC4   $- FF25 DE009500 JMP DWORD PTR DS:[9500DE]            ;  user32.MessageBoxA
00401ECA   $- FF25 94009500 JMP DWORD PTR DS:[950094]            ;  user32.SendMessageA
00401ED0   $- FF25 4A009500 JMP DWORD PTR DS:[95004A]            ;  user32.SetDlgItemTextA
00401ED6   $- FF25 00009500 JMP DWORD PTR DS:[950000]            ;  user32.SetTimer
00401EDC   $- FF25 F0069500 JMP DWORD PTR DS:[9506F0]            ;  kernel32.CloseHandle
00401EE2   $- FF25 3A079500 JMP DWORD PTR DS:[95073A]            ;  kernel32.CreateFileA
00401EE8   $- FF25 84079500 JMP DWORD PTR DS:[950784]            ;  kernel32.CreateFileMappingA
00401EEE   .- FF25 0C049500 JMP DWORD PTR DS:[95040C]            ;  kernel32.ExitProcess
00401EF4   $- FF25 CE079500 JMP DWORD PTR DS:[9507CE]            ;  kernel32.GetFileSize
00401EFA   $- FF25 C2039500 JMP DWORD PTR DS:[9503C2]            ;  kernel32.GetModuleHandleA
00401F00   $- FF25 18089500 JMP DWORD PTR DS:[950818]            ;  kernel32.GetProcAddress
00401F06   $- FF25 A6069500 JMP DWORD PTR DS:[9506A6]            ;  kernel32.GetVersionExA
00401F0C   $- FF25 5C069500 JMP DWORD PTR DS:[95065C]            ;  kernel32.LoadLibraryA
00401F12   $- FF25 12069500 JMP DWORD PTR DS:[950612]            ;  kernel32.MapViewOfFile
00401F18   $- FF25 C8059500 JMP DWORD PTR DS:[9505C8]            ;  kernel32.ReadProcessMemory
00401F1E   $- FF25 7E059500 JMP DWORD PTR DS:[95057E]            ;  ntdll.RtlZeroMemory
00401F24   $- FF25 34059500 JMP DWORD PTR DS:[950534]            ;  kernel32.SetEndOfFile
00401F2A   $- FF25 EA049500 JMP DWORD PTR DS:[9504EA]            ;  kernel32.SetFilePointer
00401F30   $- FF25 A0049500 JMP DWORD PTR DS:[9504A0]            ;  kernel32.UnmapViewOfFile
00401F36   $- FF25 56049500 JMP DWORD PTR DS:[950456]            ;  kernel32.lstrcpyA
00401F3C   $- FF25 62089500 JMP DWORD PTR DS:[950862]            ;  comdlg32.GetOpenFileNameA
00401F42   $- FF25 AC089500 JMP DWORD PTR DS:[9508AC]            ;  shell32.DragQueryFileA
JMP 函数也全是正确的了。在 00401000 处用 LoadPE 转存,此时用 Import REConstructor 还不能修复 IAT ,原因是这里函数名地址的对齐是不正确的。乱序,如果你用 Import REConstructor 把所有错误的指针全部剪切掉,那么程序修复后会丢失部分指针。如下图:





这样修复脱壳后的程序修复后是肯定无法执行的。这里我们先用 Universal Import Fixer 来重建一张 IAT 表出来。然后再用 Import REConstructor 去修复转存文件。

在 OD 菜单中:文件->挂接,在弹出的窗口中找红色的那行就是当前进程了,我这里当前进程的PID(这里是16进制的)是 0x1400




在 Universal Import Fixer 的 Process ID 中输入 1400 把后面的 Hex 打钩,因为是 16 进制的

在 OD 窗口总点 M 按钮,或者打开查看菜单中的内存,快捷键是 Alt + M,这里看一下当前进程的代码起始地址和结束地址,我这里的起始地址是:401000 结束地址是 404000 这个段的大小是 4000,那么在 Universal Import Fixer 的 Code Star:中输入 401000 Code End:中输入 404000 + 4000 也就是 408000



New Iat Va 这里我们先在 OD 中用内存插件分配一块内存用来保存新的 IAT,Universal Import Fixer 手册中说 Code Star Code End 和 New Iat Va 如果输入 0 那么 Universal Import Fixer 会自动为你查找及分配,不过有些时候尤其是脱壳的时候可能成功几率比较小,所以我们全手动指定比较准确一点。

这里我在 OD 中分配了地址为:10400000 大小为:1000 的内存空间。指定 10400000 这个地址是为了一会在 Import REConstructor 中填写地址直接减掉 00400000 这个 Image Base,没让 Universal Import Fixer 自动分配也是因为我现在懒的计算了。一会直接写如 10000000 就 OK 了,输入全都输入后点 Start 开始重建输入表了,点 Start 之前你可以在 OD 的数据窗口中:d 10400000 来观看重建的输入表。






重建后在 Import REConstructor 中添入正确的地址就可以了,我这里:

OEP:00001000
RVA:10000000
SIZE:00000088




修正转存后 PEID 再查就显示为:MASM32 / TASM32 了。



--------------------------------------------------------------------------------------------------------
【版权声明】: 本文原创于UnPacKcN论坛及看雪技术论坛等,论坛排名不分先后, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年05月16日 5:29:43

脱壳动画网盘下载 - 任选一个就可以:

http://www.namipan.com/d/UnPackMe-006-UnPack.rar/1ff5e773708738541282404164afd1e312a97473d89b7c00

http://www.vdisk.cn/go/index?3571667A3901

http://www.brsbox.com/filebox/down/fc/adaad13be6efa71a56a9dd0775285bbd

不想看动画的朋友也可以直接下载下面的附件,附件中有脱壳脚本,不过脚本在修复 IAT 的时候使用的是到 OEP 后的另一种修复方法:

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
免费 7
支持
分享
最新回复 (29)
雪    币: 7905
活跃值: (3081)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
好文,下载收藏之
2009-5-16 07:10
0
雪    币: 443
活跃值: (200)
能力值: ( LV9,RANK:1140 )
在线值:
发帖
回帖
粉丝
3
我爱深南大道
2009-5-16 07:57
0
雪    币: 107
活跃值: (1623)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
4
好文 听说是AlexProtect
2009-5-16 08:10
0
雪    币: 191
活跃值: (335)
能力值: ( LV9,RANK:450 )
在线值:
发帖
回帖
粉丝
5
28 篇精华,膜拜你啊。QQ 里好久没看到你了?在哪个群里呢?我Q里人太多,找不到你了。呵呵。
2009-5-16 08:34
0
雪    币: 443
活跃值: (200)
能力值: ( LV9,RANK:1140 )
在线值:
发帖
回帖
粉丝
6
我天天都看到你啊,你天天这个群那个群发。。。。。实在受不了来顶下。。。
2009-5-16 09:57
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
经典,收藏了!!!!
2009-5-16 10:03
0
雪    币: 213
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
哈哈,书生也受不了啊。
2009-5-16 10:12
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
好文,下载收藏之
2009-5-16 11:31
0
雪    币: 557
活跃值: (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
10
好详细  图文并茂...
2009-5-16 11:34
0
雪    币: 240
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
呵呵,非常棒,学习了
2009-5-16 21:40
0
雪    币: 240
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
前辈,怎么能到这里啊?
00941586    8933            MOV DWORD PTR DS:[EBX],ESI               ; 这里就关键代码了
00941588    8BF8            MOV EDI,EAX
0094158A    60              PUSHAD
0094158B    EB 03           JMP SHORT 00941590
0094158D    EB 03           JMP SHORT 00941592
0094158F    C7              ???
我现在就只会一步一步的来,太长了
2009-5-16 21:53
0
雪    币: 236
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
这个动画包括了好多知识。!
2009-5-17 11:58
0
雪    币: 191
活跃值: (335)
能力值: ( LV9,RANK:450 )
在线值:
发帖
回帖
粉丝
14
[QUOTE=xlyvip;625248]前辈,怎么能到这里啊?
00941586    8933            MOV DWORD PTR DS:[EBX],ESI               ; 这里就关键代码了
00941588    8BF8            MOV EDI,EAX
0094158A    60 ...[/QUOTE]

建议你把图文教程和动画一起看一下,就明白了。
2009-5-17 12:20
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
太强了,好好学习一下,哈哈
2009-5-17 12:40
0
雪    币: 306
活跃值: (153)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
写的很不错,适合我这样的新手
2009-5-17 12:45
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
谢谢楼主分享,下载学习
2009-5-17 13:17
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
好帖,谢谢,收藏了仔细研究
2009-5-17 14:04
0
雪    币: 358
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
楼主可否把  Olly Advanced 1.26 beta 12  汉化版插件 共享一下啊?
2009-5-17 17:56
0
雪    币: 2899
活跃值: (1753)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
20
路过,顶成热贴
2009-5-17 18:59
0
雪    币: 191
活跃值: (335)
能力值: ( LV9,RANK:450 )
在线值:
发帖
回帖
粉丝
21
我正准备换回英文版呢。呵呵。
上传的附件:
2009-5-18 12:27
0
雪    币: 93908
活跃值: (200199)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
22
Thanks for share.
2009-5-18 12:39
0
雪    币: 358
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
真的很精彩
LZ写的很认真  
冲着LZ这点  也该顶一下
另外谢谢你共享的工具
2009-5-18 13:11
0
雪    币: 1432
活跃值: (823)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
学习~~~~~~~~~~~~~
2009-5-18 13:15
0
雪    币: 238
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
我是纯过来支持楼主的
2009-5-19 15:11
0
游客
登录 | 注册 方可回帖
返回
//