飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 6145|回复: 18

[原创] Delphi程序脱TMD修复OEP

[复制链接]
  • TA的每日心情
    开心
    2015-12-7 14:03
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2010-1-11 11:11:06 | 显示全部楼层 |阅读模式
    【文章标题】: Delphi程序脱TMD修复OEP
    【文章作者】: wuqing1501
    【软件名称】: 某软件
    【下载地址】: 不便提供
    【使用工具】: 老三样
    【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
    --------------------------------------------------------------------------------
    【详细过程】
      朋友给的软件让我破解,因为我是菜鸟不会破,所以就没有破解但是看到加壳是TMD的 而且是Delphi的,就想学习一下怎么脱TMD并修复OEP 于是就有了下文,基本上操作多是参看的 KISSY的视频的。
      
      我们这里只是学习OEP的修复,至于IAT处理就使用脚本吧!此文仅为了那些和我一样在黑暗中慢慢摸索的菜鸟,大牛们就飘过吧!
      
      好了,进入正题吧!
      
      首先查壳
      
      Themida/WinLicense V1.8.X-V2.X -> Oreans Technologies   * Sign.By.fly * 20080131 *
      
      OD载入
      
      009E0014 X>  B8 00000000        mov eax,0                             ; OD载入后停在这里
      009E0019     60                 pushad
      009E001A     0BC0               or eax,eax
      009E001C     74 68              je short XX.009E0086
      009E001E     E8 00000000        call XX.009E0023
      009E0023     58                 pop eax
      009E0024     05 53000000        add eax,53
      009E0029     8038 E9            cmp byte ptr ds:[eax],0E9
      009E002C     75 13              jnz short XX.009E0041
      009E002E     61                 popad
      009E002F     EB 45              jmp short XX.009E0076
      009E0031     DB2D 37009E00      fld tbyte ptr ds:[9E0037]
      009E0037     FFFF               ???                                   ; 未知命令
      009E0039     FFFF               ???                                   ; 未知命令
      009E003B     FFFF               ???                                   ; 未知命令
      009E003D     FFFF               ???                                   ; 未知命令
      009E003F     3D 40E80000        cmp eax,0E840
      
      
      很明显的TMD入口
      
      好了我们使用这个脚本跑吧
      
      TMDScript-1.9.1+_1.0 final_修正集成版.osc
      
      OD载入脚本 运行完后停在这里
      
      
      004061E4     53                 push ebx                              ; 脚本运行完 停在这里
      004061E5     8BD8               mov ebx,eax
      004061E7     33C0               xor eax,eax
      004061E9     A3 A0104B00        mov dword ptr ds:[4B10A0],eax
      004061EE     6A 00              push 0
      004061F0     E8 2BFFFFFF        call XX.00406120                      ; jmp 到 kernel32.GetModuleHandleA
      004061F5     A3 68464B00        mov dword ptr ds:[4B4668],eax
      004061FA     A1 68464B00        mov eax,dword ptr ds:[4B4668]
      004061FF     A3 AC104B00        mov dword ptr ds:[4B10AC],eax
      00406204     33C0               xor eax,eax
      00406206     A3 B0104B00        mov dword ptr ds:[4B10B0],eax
      0040620B     33C0               xor eax,eax
      0040620D     A3 B4104B00        mov dword ptr ds:[4B10B4],eax
      00406212     E8 C1FFFFFF        call XX.004061D8
      00406217     BA A8104B00        mov edx,XX.004B10A8
      0040621C     8BC3               mov eax,ebx
      0040621E     E8 D1DBFFFF        call XX.00403DF4
      00406223     5B                 pop ebx
      00406224     C3                 retn
      
      这个就是程序的第一个CALL
      
      此时 EAX的值为004B09D0
      
      有这些我们可以写出OEP的前几句
      
      push ebp
      mov ebp,esp
      add esp,-10
      mov eax,004B09D0//第一个call时 EAX的值
      call 004061E4//第一个CALL的地址
      
      好了 我们按 F8  一直运行到
      
      00406224     C3                 retn
      
      此时记下寄存器的数值
      
      EAX 00000000
      ECX 0012FF70
      EDX 0012FF88
      EBX 0012FF9C
      ESP 0012FF80
      EBP 0012FF94
      ESI 5E0000BA
      EDI FFFAAF8C
      
      然后继续按F8将进入到TMD的VM中
      
      00C2AD4A     68 E266860C        push 0C8666E2
      
      
      然后再按F8几次 走过第一个JMP后 在CODE段 00401000处F2断点,F9运行 然后再在在CODE段 00401000处F2断点再运行 直到停在第二个CALL内
      
      00478CE0     53                 push ebx                              ; 第二个CALL
      00478CE1     A1 64304B00        mov eax,dword ptr ds:[4B3064]
      00478CE6     8338 00            cmp dword ptr ds:[eax],0
      00478CE9     74 0A              je short XX.00478CF5
      00478CEB     8B1D 64304B00      mov ebx,dword ptr ds:[4B3064]         ; XX.004B4044
      00478CF1     8B1B               mov ebx,dword ptr ds:[ebx]
      00478CF3     FFD3               call ebx
      00478CF5     5B                 pop ebx
      00478CF6     C3                 retn
      
      此时我们记下第二个CALL的地址 和寄存器的内容
      
      EAX 03181804
      ECX 0012FF70
      EDX 0012FF88
      EBX 0012FF9C
      ESP 0012FF80
      EBP 0012FF94
      ESI 5E0000BA
      EDI FFFAAF8C
      
      然后我们与第一次记录的寄存器比较,发现只有EAX发生了变化 ,我们按CTRL+B搜索二进制 04 18 18 03 找到了地址004B1484,这时我们可以补充OEP为
      
      push ebp
      mov ebp,esp
      add esp,-10
      mov eax,004B09D0//第一个call时 EAX的值
      call 004061E4//第一个CALL的地址
      mov eax,dword ptr ds:[4B1484]//如果找不到的话可以直接写成mov eax,004B1484
      mov eax,dword ptr ds:[eax]
      CALL  00478CE0
      
      
      然后我们继续按F8直到走完第二个CALL
      
      00478CF6     C3                 retn
      
      此时我们再记录下寄存器的数据
      
      EAX 00000001
      ECX 76AB67F0 ole32.76AB67F0
      EDX 76AB67F0 ole32.76AB67F0
      EBX 0012FF9C
      ESP 0012FF80
      EBP 0012FF94
      ESI 5E0000BA
      EDI FFFAAF8C
      
      然后我们继续安装上面的步骤执行 直到程序运行到第三个CALL
      
      00406428     55                 push ebp                              ; 第三个call
      00406429     8BEC               mov ebp,esp
      0040642B     8B45 10            mov eax,dword ptr ss:[ebp+10]
      0040642E     50                 push eax
      0040642F     837D 0C 01         cmp dword ptr ss:[ebp+C],1
      00406433     1BC0               sbb eax,eax
      00406435     40                 inc eax
      00406436     83E0 7F            and eax,7F
      00406439     50                 push eax
      0040643A     8B45 08            mov eax,dword ptr ss:[ebp+8]
      0040643D     50                 push eax
      0040643E     E8 DDFFFFFF        call XX.00406420                      ; jmp 到 kernel32.CreateMutexA
      00406443     5D                 pop ebp
      00406444     C2 0C00            retn 0C
      
      此时我们记下 第三个CALL的地址和寄存器的数据
      
      EAX 00000001
      ECX 76AB67F0 ole32.76AB67F0
      EDX 76AB67F0 ole32.76AB67F0
      EBX 0012FF9C
      ESP 0012FF74
      EBP 0012FF94
      ESI 5E0000BA
      EDI FFFAAF8C
      此时寄存器与我们上次记录的数据相比 只有ESP发生了变换 变化值为:0012FF74-0012FF80=-c 这时我们可以修复OEP为
      
      push ebp
      mov ebp,esp
      add esp,-10
      mov eax,004B09D0//第一个call时 EAX的值
      call 004061E4//第一个CALL的地址
      mov eax,dword ptr ds:[4B1484]//如果找不到的话可以直接写成mov eax,004B1484
      mov eax,dword ptr ds:[eax]
      CALL  00478CE0
      add esp,-c
      call 00406428
      
      然后我们继续F8做完第三个CALL 记下寄存器的数据
      
      EAX 00000208
      ECX 0012FEF8
      EDX 7C92E514 ntdll.KiFastSystemCallRet
      EBX 0012FF9C
      ESP 0012FF74
      EBP 0012FF94
      ESI 5E0000BA
      EDI FFFAAF8C
      
      然后继续按F8走到VM中,然后和上面一样继续CODE段下断点,直到程序停在非VM 中,中间遇到 012214DE     F3:A4              rep movs byte ptr es:[edi],byte ptr d>  这样的可以 F7一次,然后再F8一次走过去,然后继续下断点运行
      
      运行几次后发现程序停在了这里
      
      
      004B0E50     E8 D356F5FF        call XX.00406528                      ; jmp 到 ntdll.RtlGetLastWin32Error 最后停在这里了
      004B0E55     3D B7000000        cmp eax,0B7
      004B0E5A     75 10              jnz short XX.004B0E6C
      004B0E5C     A1 48534B00        mov eax,dword ptr ds:[4B5348]
      004B0E61     50                 push eax
      004B0E62     E8 9955F5FF        call XX.00406400                      ; jmp 到 kernel32.CloseHandle
      004B0E67     E9 C2000000        jmp XX.004B0F2E
      004B0E6C     A1 78314B00        mov eax,dword ptr ds:[4B3178]
      
      走到这里我们可以直到已经运行到程序的部分了,这里就是OEP的附近了
      
      此时我们记下寄存器中的数据
      
      EAX 00000208
      ECX 0012FEF8
      EDX 7C92E514 ntdll.KiFastSystemCallRet
      EBX 0012FF9C
      ESP 0012FF84
      EBP 0012FF94
      ESI 5E0000BA
      EDI FFFAAF8C
      
      此时与上面的寄存器比较一下 还是只有 ESP发生变化 变化值为 0012FF84-0012FF74=10
      
      好了我们可以把OEP修复为
      
      push ebp
      mov ebp,esp
      add esp,-10
      mov eax,004B09D0//第一个call时 EAX的值
      call 004061E4//第一个CALL的地址
      mov eax,dword ptr ds:[4B1484]//如果找不到的话可以直接写成mov eax,004B1484
      mov eax,dword ptr ds:[eax]
      CALL  00478CE0
      add esp,-c
      call 00406428
      add esp,10
      
      这样我们就找到了所有被VM的的OEP了,其实整个过程就是 看每次寄存器那些数据发生了变化 我们把相应的变化写出来就可以了
      
      此时我们分析一下数据 看看OEP的具体位置在哪里?
      
      根据Delphi程序的入口 OEP一般位于
      
      0044CA7C   . \4C364200      dd delphi7.0042364C
      0044CA80   .  ACC64400      dd delphi7.0044C6AC
      0044CA84   .  50C64400      dd delphi7.0044C650
      0044CA88   .  88C84400      dd delphi7.0044C888
      0044CA8C   .  58C84400      dd delphi7.0044C858
      0044CA90      00            db 00
      0044CA91      00            db 00
      0044CA92      00            db 00
      0044CA93      00            db 00
      0044CA94   .  90C84400      dd delphi7.0044C890//根据Delphi程序的入口 OEP一般位于这个下面
      
      看我们分析后的代码
      
      
      
      004B0E02    ?  4A               dec edx
      004B0E03    ?  00CC             add ah,cl
      004B0E05    ?  F7               ???                                   ;  未知命令
      004B0E06    ?  4A               dec edx
      004B0E07    ?  00A0 094B0064    add byte ptr ds:[eax+64004B09],ah
      004B0E0D    ?  094B 00          or dword ptr ds:[ebx],ecx
      004B0E10       00               db 00
      004B0E11       00               db 00
      004B0E12       00               db 00
      004B0E13       00               db 00
      004B0E14       A8094B00         dd XX.004B09A8
      004B0E18       77               db 77                                 ;  CHAR 'w'
      004B0E19       3D               db 3D                                 ;  CHAR '='
      004B0E1A       D6               db D6
      
      那我们的OEP地址应该就是004B0E18 了
      
      好我们把我们修复好的代码从这里开始写上去 发现写好后
      
      
      004B0E50     E8 D356F5FF        call XX.00406528这个代码与我们写的代码之间还有些数据,我们可以直接用个跳转跳到这里也可以直接把中间的代码都NOP掉,我就直接NOP掉了
      
      好了 到了这里我们的工作基本上就算完成了
      
      恩 在004B0E18 新建EIP吧,
      
      然后用LordPE DUMP出来,再用ImportREC修复一下就可以了,看看怎么样软件运行了吧!
      
      再此,多谢GUC大牛的帮助,帮我大半个晚上,刚开始一直是DUMP修复好的文件不能运行一直有错误提示,后来发现是系统的问题,经过重新启动电脑后,DUMP修复好的文件可以正常运行了。
      
      其实这个壳的低版本是可以用OKDODO的脱壳机脱掉的,但是脱掉的 带了太多的VM 那样我们破解的时候就发现好多字符串是看不到的,但是我们还原了OEP以后 在搜下字符串吧,有了新的发现了吧!
      
      好了就到这里吧 太晚 了 要休息了!
      
      写下此文,以作纪念!
      
      软件我就不提供了想学习的可以自己用TMD加壳自己再脱!
      
      
      
    --------------------------------------------------------------------------------
    【经验总结】
      1,自己动手脱一边壳,比看上百遍的视屏和教程都有用!
      
      2,通过脱这个过程熟悉了被TMD VM 了的OEP 的还原,很重要的一点就是要熟悉常见程序的OEP特征!
      
      3,由于水平有限,小菜鸟一个,不知道怎么处理IAT的,这个还要以后多学习了!
      
    --------------------------------------------------------------------------------
    【版权声明】: 本文原创于wuqing1501[Upk],  菜鸟一个没有版权,欢迎转载,转载请注明作者并保持文章的完整, 谢谢!

                                                           2010年01月11日 AM 01:09:54

    评分

    参与人数 1威望 +8 飘云币 +40 收起 理由
    野猫III + 8 + 40 TMD一直表现不错,支持兄弟!

    查看全部评分

    PYG19周年生日快乐!
  • TA的每日心情

    4 天前
  • 签到天数: 391 天

    [LV.9]以坛为家II

    发表于 2010-1-23 18:53:48 | 显示全部楼层
    呵呵 不错 谢谢
    要是语音教程就更好了
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2019-1-15 21:28
  • 签到天数: 171 天

    [LV.7]常住居民III

    发表于 2010-1-30 17:29:12 | 显示全部楼层
    呵呵 不错 谢谢
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2010-2-14 10:09:50 | 显示全部楼层
    提示: 作者被禁止或删除 内容自动屏蔽
    PYG19周年生日快乐!
  • TA的每日心情

    2021-3-15 02:34
  • 签到天数: 347 天

    [LV.8]以坛为家I

    发表于 2010-2-18 00:24:39 | 显示全部楼层
    /:10 嘿嘿,学习下了。。。
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2010-4-3 16:03:16 | 显示全部楼层
    就一个CALL的是底版本还是高版本呢
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2010-5-5 20:12:17 | 显示全部楼层
    看不懂啊,郁闷
    PYG19周年生日快乐!
  • TA的每日心情

    2017-7-19 15:45
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2010-5-22 14:09:19 | 显示全部楼层
    放弃脚本更好
    PYG19周年生日快乐!
  • TA的每日心情
    奋斗
    2017-4-20 22:12
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2010-5-22 15:59:42 | 显示全部楼层
    强力的顶一下,现在很少看到delphi的了!
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2010-5-26 11:21:57 | 显示全部楼层
    顶下,,厉害,,
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

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