好友
阅读权限10
听众
最后登录1970-1-1
|
本帖最后由 tie1zhu 于 2026-1-25 04:11 编辑
ASProtect 2.1x SKE 脱壳分析
20年前的老壳了,尝试后脱壳成功,写个帖子记录一下。
目录
第一部分:寻找OEP。
第二部分:修复IAT。
第三部分:修复被改过call。
第四部分:整体思路。
第五部分:踩过的坑。
工具
- Windows XP虚拟机。
- PEiD:查壳工具。
- 吾爱破解 OllyDbg:调试程序,寻找OEP。
- LordPE:抓取内存映像【dump】。
- ImportREConstructor:重建输入表。
下文中的演示文件是 98NOTEPAD 。
第一部分:寻找OEP。
使用最后一次异常法+code段内存镜像法寻找OEP。
具体的步骤:
-
查壳,ASProtect 2.1x SKE 壳,加密壳。(1-查壳)
-
使用OllyDbg调试,出现标题为"压缩代码?"的对话框,选否。
-
选项-调试设置-异常-全部取消勾选。(2-1)
-
插件-StrongOD-Options-取消勾选 Skip Some Exceptions-Save。(2-2)
-
执行 shift+F9 (忽略异常继续执行) 大概36次,第二次出现以下代码,即可停下。(2-3)
-
按Alt+M,在00401000 CODE段下F2断点,Shift+F9运行,到达OEP:10CC。(2-4,2-5)
-
注意:下面的call 00CE0000代码,好多条call都被修改成这个样子了,具体原因,第四部分解释。
-
此时,使用 LordPE,抓取内存映像【dump】,使用 ImportREConstructor,重建输入表。发现无法运行。
第二部分:修复IAT。
-
现在 EIP 在 OEP :004010CC。
-
顺便再看下这行代码: 004010E2 FF15 F4644000 call dword ptr ds:[0x4064F4] ; user32.CharNextA ,这行代码告诉我们IAT的大致位置。
-
数据区,右键-转到-表达式-输入 004064F4-OK,可以看到IAT了。(2-6,2-7,2-8)
-
上下翻一下,显然这个IAT不完整,有些IAT项被加密了,地址004062e0的内容是00000000,这是用来分隔不同DLL函数地址的,下一个地址004062E4是IAT的起点。 (2-9)
-
重新载入程序,数据区,右键-转到-表达式-输入 004062E4-OK,在 004062E4 右键-断点-硬件访问-Byte。(3-1)
-
执行 shift+F9 (忽略异常继续执行) 直到 004062E4 变为 8A14F25D。删除硬件断点。(3-2,3-3)
-
执行 shift+F9 (忽略异常继续执行) 直到 出现 mov byte ptr ds:[ecx],0xB6 ,在这一行按F2下断点00ABEA7A 59 pop ecx ,执行 shift+F9 (忽略异常继续执行) ,按F2取消断点 。(3-4)
-
往下翻,直到发现2个ASCII "85\r\n",在这2个ASCII "85\r\n"中间的call XXXX7818按F2下断点,执行 shift+F9 (忽略异常继续执行) ,按F2取消断点 。(3-5)
-
F7单步步入。(3-6)
-
往下翻,直到发现00AB795A这一行,这一行的代码是call XXXX75B8。按F2下断点,执行 shift+F9 (忽略异常继续执行) ,按F2取消断点 。(3-7)
-
F7单步步入。(3-8)
-
往下翻,直到发现00AB75F2这一行,这一行的代码是cmp esi,eax,在这一行按F2下断点,F9运行,注意ESI的值跟下面两行跳转是否执行的对应关系。(3-9)
-
重新载入程序,不断调试直到00AB75F2这一行,插件-StrongOD-Alloc Memory,分配一段内存,我分配到的是00D00000开头的一段内存,右键-转到-EIP,在00AB75F4,右键-汇编-jmp 00D00000-OK,注意取消修改下面的6个NOP。(4-1,4-2)
-
右键-转到-表达式-00D00000-OK,右键-汇编,添加以下代码。(4-3)
-
先取消所有断点,再右键-转到-表达式-00AB7989-OK,按F2下断点,执行 shift+F9 (忽略异常继续执行) ,按F2取消断点 。这时IAT重建完成了。(4-4)
第三部分:修复被改过call。
-
右键-转到-表达式-00AB75F4-OK,右键-撤销选择处修改。(5-1)
-
执行 shift+F9 (忽略异常继续执行) 直到第二次出现以下代码,即可停下。
-
按Alt+M,在00401000 CODE段下F2断点,Shift+F9运行,到达OEP:10CC。(5-2)
-
右键-转到-表达式-00AB7190-OK,把这行代码 00AB7190 E8 B7B3FDFF call 00A9254C 汇编为 右键-汇编-jmp 00D00037-OK,注意是00D00037。(5-3)
-
右键-转到-表达式-00D00000-OK,右键-汇编,添加以下代码。(5-4)
-
00D00000 BA 00104000 mov edx,NOTEPAD.<ModuleEntryPoint>
00D00005 803A E8 cmp byte ptr ds:[edx],0xE8
00D00008 75 12 jnz short 00D0001C
00D0000A 8B42 01 mov eax,dword ptr ds:[edx+0x1]
00D0000D 03C2 add eax,edx
00D0000F 83C0 05 add eax,0x5
00D00012 3D 0000CE00 cmp eax,0xCE0000
00D00017 75 03 jnz short 00D0001C
00D00019 EB 0C jmp short 00D00027
00D0001B 90 nop
00D0001C 42 inc edx
00D0001D 81FA E04F4000 cmp edx,0x404FE0
00D00023 ^ 72 E0 jb short 00D00005
00D00025 - EB FE jmp short 00D00025
00D00027 8915 0001D000 mov dword ptr ds:[0xD00100],edx
00D0002D 60 pushad
00D0002E - FFE2 jmp edx
00D00030 90 nop
00D00031 90 nop
00D00032 90 nop
00D00033 90 nop
00D00034 90 nop
00D00035 90 nop
00D00036 90 nop
00D00037 60 pushad
00D00038 B8 E4624000 mov eax,0x4062E4
00D0003D 90 nop
00D0003E 3910 cmp dword ptr ds:[eax],edx
00D00040 75 20 jnz short 00D00062
00D00042 8B0D 0001D000 mov ecx,dword ptr ds:[0xD00100]
00D00048 C701 FF150000 mov dword ptr ds:[ecx],0x15FF
00D0004E 8941 02 mov dword ptr ds:[ecx+0x2],eax ; NOTEPAD.004010CC
00D00051 61 popad
00D00052 90 nop
00D00053 8B15 0001D000 mov edx,dword ptr ds:[0xD00100]
00D00059 90 nop
00D0005A 90 nop
00D0005B 90 nop
00D0005C ^ EB BE jmp short 00D0001C
00D0005E 90 nop
00D0005F 90 nop
00D00060 90 nop
00D00061 90 nop
00D00062 83C0 04 add eax,0x4
00D00065 3D 24654000 cmp eax,0x406524
00D0006A ^ 7E D2 jle short 00D0003E
00D0006C ^ EB E3 jmp short 00D00051
-
二进制代码如下:
-
BA 00 10 40 00 80 3A E8 75 12 8B 42 01 03 C2 83 C0 05 3D 00 00 CE 00 75 03 EB 0C 90 42 81 FA E0
4F 40 00 72 E0 EB FE 89 15 00 01 D0 00 60 FF E2 90 90 90 90 90 90 90 60 B8 E4 62 40 00 90 39 10
75 20 8B 0D 00 01 D0 00 C7 01 FF 15 00 00 89 41 02 61 90 8B 15 00 01 D0 00 90 90 90 EB BE 90 90
90 90 83 C0 04 3D 24 65 40 00 7E D2 EB E3
-
添加完代码之后,左键单击00D00000这一行,右键-此处为新EIP。
-
F9运行 ,使用 LordPE,抓取内存映像【dump】,使用 ImportREConstructor,重建输入表。
-
运行成功,脱壳成功。
第四部分:整体思路。
找OEP思路:最后一次异常法+code段内存镜像法。
这个壳的特色:
解决特色一的方法:
经过不断的调试发现 if esi==77,then 加密,else 不加密。只有在esi==77的情况下,做出 把esi改为89 的操作,才会出现所有IAT项都不加密的情况。
因此注入以下代码:
00D00000 - 0F84 F375DBFF je 00AB75F9
00D00006 81FE 89000000 cmp esi,0x89
00D0000C - 0F84 4276DBFF je 00AB7654
00D00012 BE 89000000 mov esi,0x89
00D00017 - E9 3876DBFF jmp 00AB7654
解决特色二的方法:
既然加壳后这个call 【xxxx0000】可以实现调用API函数功能,那么函数内部一定会出现某个API函数【api-address】,而且这个API函数跟XXX0000函数被调用的地址绑定了,所以这个CALL一共做了两件事情,先根据自身的位置获取对应的API,接着调用这个API。所以我们做个补丁在这个函数内部获取到API的地方,跳到我们写的代码中去修复。
当然整个修复代码逻辑顺序是这样的,遍历代码块找到一处为call 【xxxx0000】的地址,先记下该地址因为后面要根据这个地址去修改,然后跳到这个地址去执行
call 【xxxx0000】,执行到我们的补丁处此次就获得了与该地址绑定的API函数地址了,因为补丁是jmp aaa0037,直接跳到我们代码中去了,因为在执行call 【xxxx0000】之前,我们已经保存当前需要修复的地址,又知道当前需要修复的函数名,下一步需要通过函数名遍历IAT表获取存放该函数的地址的地址,获取到地址后,就开始修复,修复完毕。保存刚刚修复好的地址,继续遍历修复。
先找到XXXX0000函数内部获取到API名称的地方,跟踪这个函数肯定可以找到,慢慢调试一定可以找到,就是 00AB7190 E8 B7B3FDFF call 00A9254C 。
将它改成 jmp 00D00037。
-
00D00000 BA 00104000 mov edx,NOTEPAD.<ModuleEntryPoint>
00D00005 803A E8 cmp byte ptr ds:[edx],0xE8
00D00008 75 12 jnz short 00D0001C
00D0000A 8B42 01 mov eax,dword ptr ds:[edx+0x1]
00D0000D 03C2 add eax,edx
00D0000F 83C0 05 add eax,0x5
00D00012 3D 0000CE00 cmp eax,0xCE0000
00D00017 75 03 jnz short 00D0001C
00D00019 EB 0C jmp short 00D00027
00D0001B 90 nop
00D0001C 42 inc edx
00D0001D 81FA E04F4000 cmp edx,0x404FE0
00D00023 ^ 72 E0 jb short 00D00005
00D00025 - EB FE jmp short 00D00025
00D00027 8915 0001D000 mov dword ptr ds:[0xD00100],edx
00D0002D 60 pushad
00D0002E - FFE2 jmp edx
00D00030 90 nop
00D00031 90 nop
00D00032 90 nop
00D00033 90 nop
00D00034 90 nop
00D00035 90 nop
00D00036 90 nop
00D00037 60 pushad
00D00038 B8 E4624000 mov eax,0x4062E4
00D0003D 90 nop
00D0003E 3910 cmp dword ptr ds:[eax],edx
00D00040 75 20 jnz short 00D00062
00D00042 8B0D 0001D000 mov ecx,dword ptr ds:[0xD00100]
00D00048 C701 FF150000 mov dword ptr ds:[ecx],0x15FF
00D0004E 8941 02 mov dword ptr ds:[ecx+0x2],eax ; NOTEPAD.004010CC
00D00051 61 popad
00D00052 90 nop
00D00053 8B15 0001D000 mov edx,dword ptr ds:[0xD00100]
00D00059 90 nop
00D0005A 90 nop
00D0005B 90 nop
00D0005C ^ EB BE jmp short 00D0001C
00D0005E 90 nop
00D0005F 90 nop
00D00060 90 nop
00D00061 90 nop
00D00062 83C0 04 add eax,0x4
00D00065 3D 24654000 cmp eax,0x406524
00D0006A ^ 7E D2 jle short 00D0003E
00D0006C ^ EB E3 jmp short 00D00051
-
二进制代码如下:
-
BA 00 10 40 00 80 3A E8 75 12 8B 42 01 03 C2 83 C0 05 3D 00 00 CE 00 75 03 EB 0C 90 42 81 FA E0
4F 40 00 72 E0 EB FE 89 15 00 01 D0 00 60 FF E2 90 90 90 90 90 90 90 60 B8 E4 62 40 00 90 39 10
75 20 8B 0D 00 01 D0 00 C7 01 FF 15 00 00 89 41 02 61 90 8B 15 00 01 D0 00 90 90 90 EB BE 90 90
90 90 83 C0 04 3D 24 65 40 00 7E D2 EB E3
第五部分:踩过的坑。
- 第1次注入,忘记了取消修改下面的6个NOP。
- 在第2次注入前,应该先到达OEP。
- 第2次注入,应该是00D00037,我写错了。
- 00D00000 BA 00104000 mov edx,NOTEPAD.<ModuleEntryPoint> ---写好代码后在这里新建EIP
|
-
-
示例程序.7z
160.51 KB, 下载次数: 6, 下载积分: 吾爱币 -1 CB
免费评分
-
查看全部评分
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|
|