| 
注册时间2008-5-1
阅读权限10
最后登录1970-1-1UID50202 周游历练 
 
 TA的每日心情|  | 开心 2015-12-7 14:03
 | 
|---|
 签到天数: 2 天 [LV.1]初来乍到 | 
 
| 【文章标题】: 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
 | 
 评分
查看全部评分
 |