【文章标题】: Obsidium脱壳手记
【文章作者】: imagic
【作者邮箱】: afeiw@163.com
【作者主页】: http://imagic.tk
【作者QQ号】: 99970077
【软件名称】: CrackMe
【加壳方式】: Obsidium 1.3.4.2
【保护方式】: 全保护
【编写语言】: delphi
【使用工具】: OD
【操作平台】: WIN XP SP3
——————————————————————————–
【详细过程】
Obsidium的壳比较变态的地方在于模拟了一些系统API函数,还有一些API没有模拟但是已经事先被壳给出运行结果,例如:
GetVersion,GetCommandLine等函数,但是大不部分的API地址都能写脚本跟踪出来,这里,我是在到达OEP后来修复IAT的,
大致步骤如下:
1.到达OEP,用内存断点可以直接到达伪OEP,头部被偷了一段
2.OEP断下后,随便找个API进入IAT领空,记下IAT的段首和段尾,然后跟踪下API,一路F8,不出意外就会看到解密的API。
当然你有可能跟踪的正好是一个模拟的API,那样就很难辨别了,这属于人品问题。
3.基本上跟出第一个API后,写个脚本,将API还原,这样就可以搞定一大部分的API。
4.剩下几个模拟的API,我跟的方法是这样:在IAT的地址下断,断下后返回到调用CALL,然后在调用CALL后面下断,此时
分析下压入的参数,然后SHIFT+F9,到CALL后断下,分析返回值。十有八九就能知道这个CALL调用的API。
5.最后找个DELPHI的程序对照下头,修复被偷的几个字节。
注意:dump的时候记得先改掉内存的属性,不然不让DUMP。
详细过程如下:
0046C000 > /EB 02 jmp short CrackMe_.0046C004
0046C002 |6A FD push -3
0046C004 \E8 26000000 call CrackMe_.0046C02F
0046C009 EB 03 jmp short CrackMe_.0046C00E
载入后,ALT+M 到代码段下内存访问断点,SHIFT+F9
0046E1E2 C702 33C0C300 mov dword ptr ds:[edx],0C3C033
0046E1E8 EB 02 jmp short CrackMe_.0046E1EC
0046E1EA 0BDE or ebx,esi
断下后,ALT+M 到资源段下内存访问断点,SHIFT+F9
0096AD64 8B02 mov eax,dword ptr ds:[edx]
0096AD66 85C0 test eax,eax
0096AD68 74 13 je short 0096AD7D
0096AD6A A9 00000080 test eax,80000000
0096AD6F 75 04 jnz short 0096AD75
断下后,继续到代码段下内存的断点,SHIFT+F9
0044D32B E8 348DFBFF call CrackMe_.00406064 ; THIS IS OEP
0044D330 A1 B8EF4400 mov eax,dword ptr ds:[44EFB8]
0044D335 8B00 mov eax,dword ptr ds:[eax]
0044D337 E8 C8E5FFFF call CrackMe_.0044B904
刚好断在DELPHI程序的第一个CALL,前面被偷了一些字节。一般DELPHI程序里第一个CALL里有一个GetModuleHandle的调用
F7跟进,跟进前找到IAT的段首和段尾 00451114-004516D4
009B02F0 60 pushad
009B02F1 9C pushfd
009B02F2 66:BD 73D5 mov bp,0D573
009B02F6 B3 81 mov bl,81
009B02F8 – E9 1949FBFF jmp 00964C16
009B02FD 60 pushad
一路F8下去
00964D58 6A 01 push 1
00964D5A 50 push eax
00964D5B 6A 00 push 0
00964D5D FF76 04 push dword ptr ds:[esi+4]
00964D60 FF37 push dword ptr ds:[edi]
00964D62 FF53 54 call dword ptr ds:[ebx+54]
跟到这里就到API了,这个CALL返回后EAX就是API地址了,需要注意的是像这样获取API的CALL,类型有三个,不同API,CALL
有时候会不一样,这个多试着跟踪几个API就会发现。
得到API地址后,将API地址写会IAT。
具体的IAT还原可以参照下脚本。
这步IAT完成后,剩下的几个自己慢慢跟,基本上都能出来。
最后修复被偷代码,找个DELPHI程序对比下,发现少了几行
0044D320 > $ 55 push ebp
0044D321 . 8BEC mov ebp,esp
0044D323 . 83C4 F0 add esp,-10
0044D326 . B8 40D14400 mov eax,CrackMe.0044D140
找个空位补上,然后改下内存属性,dump, 然后抓取IAT,保存完事。
——————————————————————————–
【经验总结】
跟踪壳的一部分代码后,发现可以用内存断点到达OEP。
壳开头的一段异常很有意思,记录下:
0046C000 > /EB 02 jmp short CrackMe_.0046C004
0046C002 |6A FD push -3
0046C004 \E8 26000000 call CrackMe_.0046C02F
0046C009 EB 03 jmp short CrackMe_.0046C00E
0046C00B CE into
0046C00C FE ??? ; 未知命令
0046C00D B5 EB mov ch,0EB
0046C00F 0105 8B54240C add dword ptr ds:[C24548B],eax
0046C015 EB 02 jmp short CrackMe_.0046C019
0046C017 6923 8382B800 imul esp,dword ptr ds:[ebx],0B88283
0046C01D 0000 add byte ptr ds:[eax],al
0046C01F 24 EB and al,0EB
0046C021 0387 A68D33C0 add eax,dword ptr ds:[edi+C0338DA6]
0046C027 EB 01 jmp short CrackMe_.0046C02A
0046C029 2D C3EB02B1 sub eax,B102EBC3
0046C02E 88EB mov bl,ch
0046C030 02ED add ch,ch
0046C032 36: prefix ss:
0046C033 64:67:FF36 0000 push dword ptr fs:[0]
0046C039 EB 03 jmp short CrackMe_.0046C03E
0046C03B CA E661 retf 61E6
0046C03E 64:67:8926 0000 mov dword ptr fs:[0],esp
0046C044 EB 03 jmp short CrackMe_.0046C049
0046C046 98 cwde
0046C047 61 popad
0046C048 ^ E0 EB loopdne short CrackMe_.0046C035
0046C04A 0373 FD add esi,dword ptr ds:[ebx-3]
0046C04D 2C 50 sub al,50
0046C04F EB 04 jmp short CrackMe_.0046C055
0046C051 2307 and eax,dword ptr ds:[edi]
0046C053 E5 09 in eax,9
0046C055 33C0 xor eax,eax
0046C057 EB 03 jmp short CrackMe_.0046C05C
0046C059 90 nop
0046C05A B5 B2 mov ch,0B2
0046C05C 8B00 mov eax,dword ptr ds:[eax]
0046C05E EB 03 jmp short CrackMe_.0046C063
0046C060 F4 hlt
0046C061 68 C6C3EB03 push 3EBC3C6
0046C066 A9 740CE9FA test eax,FAE90C74
0046C06B 0000 add byte ptr ds:[eax],al
0046C06D 00EB add bl,ch
0046C06F 03BF ED2DE8D5 add edi,dword ptr ds:[edi+D5E82DED]
0046C075 FFFF ??? ; 未知命令
0046C077 FFEB jmp far ebx ; 非法使用寄存器
0046C079 0141 EB add dword ptr ds:[ecx-15],eax
0046C07C 036A EE add ebp,dword ptr ds:[edx-12]
0046C07F 3358 EB xor ebx,dword ptr ds:[eax-15]
0046C082 04 5D add al,5D
0046C084 34 91 xor al,91
0046C086 A2 EB042A28 mov byte ptr ds:[282A04EB],al
0046C08B A7 cmps dword ptr ds:[esi],dword ptr es:[edi]
0046C08C 5A pop edx
0046C08D 64:67:8F06 0000 pop dword ptr fs:[0] ; 异常出口
0046C093 EB 04 jmp short CrackMe_.0046C099
0046C095 9D popfd
0046C096 44 inc esp
0046C097 1D FA83C404 sbb eax,4C483FA
0046C09C EB 01 jmp short CrackMe_.0046C09F
0046C09E 3BE8 cmp ebp,eax
0046C0A0 C3 retn
——————————————————————————-
/////////////////////////////////
//Obsidium 1.3.4.2参考脚本
//可能有不完善之处,仅供参考
////////////////////////////////
VAR IAT_Start
var IAT_End
var IAT_CurrentAddr
var Des_Addr
var cmpData
MOV IAT_Start ,451114 //IAT起始地址
MOV IAT_CurrentAddr,451114
MOV IAT_End , 4516D4 //IAT结束地址
bprm 401000,FF
ESTO
bpmc 401000,FF
bprm 464000,FFF
ESTO
bpmc 464000,FFF
bprm 401000,62000
ESTO
bpmc 401000,62000
cmt eip,”THIS IS OEP”
ADD IAT_CurrentAddr,4
mov Des_Addr,[IAT_CurrentAddr]
mov eip,Des_Addr
sto
sto
sto
sto
sto
mov Des_Addr,eip
find eip,#506A00FF7604FF37FF5354#
mov Des_Addr,$RESULT
add Des_Addr,8
bp Des_Addr
find eip,#52515068342CE0496A00FF5318#
mov Des_Addr,$RESULT
add Des_Addr,a
bp Des_Addr
find eip,#6A006A456A0068CC971025FF37FF5354#
mov Des_Addr,$RESULT
add Des_Addr,d
bp Des_Addr //上面是寻找解密CALL特征,然后下断
jmp lable1
loop1:
ADD IAT_CurrentAddr,4
mov Des_Addr,[IAT_CurrentAddr]
cmp IAT_CurrentAddr,IAT_End
jae lable2
mov eax,0
mov ax,[Des_Addr]
cmp eax,9c60
JNZ loop1
cmp Des_Addr,9b05bb
JZ loop1
mov eip,Des_Addr
lable1:
ESTO
sto
mov [IAT_CurrentAddr],eax
Jmp loop1
lable2:
mov [4516D4],0
MSG “修复IAT完成”
RET
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)