吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 819|回复: 7
收起左侧

[原创] ASProtect 2.1x SKE 脱壳分析

[复制链接]
tie1zhu 发表于 2026-1-25 04:08
本帖最后由 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-查壳)
    1-查壳.png

  • 使用OllyDbg调试,出现标题为"压缩代码?"的对话框,选否。

  • 选项-调试设置-异常-全部取消勾选。(2-1)
    2-1.png

  • 插件-StrongOD-Options-取消勾选 Skip Some Exceptions-Save。(2-2)
    2-2.png

  • 执行 shift+F9 (忽略异常继续执行)   大概36次,第二次出现以下代码,即可停下。(2-3)

    • 00ABFAA5    C700 EFCA5C85   mov dword ptr ds:[eax],0x855CCAEF  

      2-3.png

  • 按Alt+M,在00401000 CODE段下F2断点,Shift+F9运行,到达OEP:10CC。(2-4,2-5)
    2-4.png
    2-5.png

  • 注意:下面的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)
    2-6.png
    2-7.png
    2-8.png

  • 上下翻一下,显然这个IAT不完整,有些IAT项被加密了,地址004062e0的内容是00000000,这是用来分隔不同DLL函数地址的,下一个地址004062E4是IAT的起点。 (2-9)
    2-9.png

  • 重新载入程序,数据区,右键-转到-表达式-输入 004062E4-OK,在 004062E4 右键-断点-硬件访问-Byte。(3-1)
    3-1.png

  • 执行 shift+F9 (忽略异常继续执行)   直到 004062E4 变为 8A14F25D。删除硬件断点。(3-2,3-3)
    3-2.png
    3-3.png

  • 执行 shift+F9 (忽略异常继续执行)   直到 出现 mov byte ptr ds:[ecx],0xB6 ,在这一行按F2下断点00ABEA7A    59  pop ecx ,执行 shift+F9 (忽略异常继续执行)  ,按F2取消断点 。(3-4)
    3-4.png

  • 往下翻,直到发现2个ASCII "85\r\n",在这2个ASCII "85\r\n"中间的call XXXX7818按F2下断点,执行 shift+F9 (忽略异常继续执行)  ,按F2取消断点 。(3-5)
    3-5.png

  • F7单步步入。(3-6)
    3-6.png

  • 往下翻,直到发现00AB795A这一行,这一行的代码是call XXXX75B8。按F2下断点,执行 shift+F9 (忽略异常继续执行)  ,按F2取消断点 。(3-7)
    3-7.png

  • F7单步步入。(3-8)
    3-8.png

  • 往下翻,直到发现00AB75F2这一行,这一行的代码是cmp esi,eax,在这一行按F2下断点,F9运行,注意ESI的值跟下面两行跳转是否执行的对应关系。(3-9)
    3-9.png

  • 重新载入程序,不断调试直到00AB75F2这一行,插件-StrongOD-Alloc Memory,分配一段内存,我分配到的是00D00000开头的一段内存,右键-转到-EIP,在00AB75F4,右键-汇编-jmp 00D00000-OK,注意取消修改下面的6个NOP。(4-1,4-2)
    4-1.png
    4-2.png

  • 右键-转到-表达式-00D00000-OK,右键-汇编,添加以下代码。(4-3)

    • 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

      4-3.png

  • 先取消所有断点,再右键-转到-表达式-00AB7989-OK,按F2下断点,执行 shift+F9 (忽略异常继续执行)  ,按F2取消断点 。这时IAT重建完成了。(4-4)
    4-4.png

    第三部分:修复被改过call。

  • 右键-转到-表达式-00AB75F4-OK,右键-撤销选择处修改。(5-1)
    5-1.png

  • 执行 shift+F9 (忽略异常继续执行)  直到第二次出现以下代码,即可停下。

    • 00ABFAA5    C700 EFCA5C85   mov dword ptr ds:[eax],0x855CCAEF  
  • 按Alt+M,在00401000 CODE段下F2断点,Shift+F9运行,到达OEP:10CC。(5-2)
    5-2.png

  • 右键-转到-表达式-00AB7190-OK,把这行代码 00AB7190    E8 B7B3FDFF     call 00A9254C  汇编为 右键-汇编-jmp 00D00037-OK,注意是00D00037。(5-3)
    5-3.png

  • 右键-转到-表达式-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
      

      5-4.png

  • 添加完代码之后,左键单击00D00000这一行,右键-此处为新EIP。

  • F9运行 ,使用 LordPE,抓取内存映像【dump】,使用 ImportREConstructor,重建输入表。

  • 运行成功,脱壳成功。

第四部分:整体思路。

找OEP思路:最后一次异常法+code段内存镜像法。

这个壳的特色:

  • 特色一,这个壳进行了IAT加密。有的项加密,有的项不加密。

  • 特色二,这个壳修改了程序内部的代码,把许多call 【api-address】改为了 call 【xxxx0000】。

解决特色一的方法:

经过不断的调试发现 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

免费评分

参与人数 2吾爱币 +4 热心值 +2 收起 理由
bypasshwid + 3 + 1 用心讨论,共获提升!
helian147 + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

炫迈 发表于 2026-1-27 09:51
找OEP用最后一次异常法确实稳,但得注意StrongOD的Skip Some Exceptions一定要关掉,不然会漏掉关键异常直接跑飞,我当年就在这栽过跟头,另外WinXP虚拟机跑这壳最稳,Win7以上系统有时候会因为DEP或者ASLR干扰异常流程,导致OEP定位偏移,IAT修复那块你提到的esi==77加密逻辑很关键,其实ASProtect这代壳有个特点,它会根据esi的值决定走加密还是明文分支,77是加密,89是明文,你改esi=89这招确实能绕过加密直接拿到完整IAT,不过得卡在cmp esi,eax那行下断,晚一步就进加密流程了,call 00CE0000那块是壳的stub跳板,它内部会根据call的地址偏移去IAT里找对应API,所以修复的时候得先让程序跑一遍把映射关系建立起来再dump,不然直接dump出来的call全是废的,还有个小技巧,LordPE抓dump的时候记得勾上Fix Import Table,虽然不一定能自动修好,但能省点事,最后提醒下这壳脱完记得用PEiD或者Exeinfo再扫一遍,有时候壳会留个暗桩在.reloc段,运行时会校验代码完整性,脱壳后直接运行可能崩,得把那段校验nop掉,老壳虽然过时了但思路现在还能用,比如IAT加密和call stub这套现在不少商业壳还在玩,学透了对理解现代壳有帮助,感谢楼主分享。
Nevvb1e251111 发表于 2026-1-25 08:45
pojiestudy 发表于 2026-1-25 08:52
tzblue 发表于 2026-1-25 09:09
值得仔细研究学习。感谢楼主分享!
m_h 发表于 2026-1-25 13:41
我还以为是win7+ x64dbg,怎么都没人写这种文章。
我在w7 x64dbg上脱壳过
神奇的人鱼 发表于 2026-1-26 10:57
不懂为什么不用x64 dbg 这个是不是比 od更好啊
fcguo800 发表于 2026-1-26 12:49
非常不错的教程,感谢分享。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-1-28 04:12

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表