ASPR1.23RC4脱壳之advanced im password Recovery+简单MD5爆破
【目 标】: advanced im password Recovery v2.31
【工 具】:Olydbg1.1(diy版)、LORDPE、ImportREC1.6F ASPRDBGR1.0,IDA
【任 务】:先脱马甲,然后hehe……
【操作平台】:WINXP pro sp1
【作 者】:loveboom[DFCG][FCG]
【相关链接】:
www.elcomsoft.com
【简要说明】:也算有一段时间没有发破文了,因水平菜,时间等问题,所以难的搞不定,易的已经有很多朋友写了,这篇文章也算是搞一点积分吧,再则,很久没看见自己的贴有个精,所以想这篇文章看看能不能再混个精,其它就没多少研究价值了。
【详细过程】:
用PEID查一下发现是ASProtect 1.23 RC4 - 1.3.08.24 -> Alexey Solodovnikov,一开始还以为是ASPR1.3XXX的呢,所以有点想打道回府,但又想,既然来了,不管怎么样也要试上把,反正输了,也没有人知道,最多是“浪费”一点时间。还好有惊无险,跟到后面发现原来是个软柿子,让我占了个便宜。好了,留点口水到后面用。
打开OD设置为取消忽略内存异常,去掉RING3的检测,一路shift+f9飞到最后一次异常(我这里是第25次后到最后异常):
009C39EC 3100
XOR DWORD PTR DS:[
EAX],
EAX
009C39EE 64:8F05 0000000>
POP DWORD PTR FS:[0]
009C39F5 58
POP EAX
009C39F6 833D B07E9C00 0>
CMP DWORD PTR DS:[9C7EB0],0
009C39FD 74 14
JE SHORT 009C3A13
009C39FF 6A 0C
PUSH 0C
009C3A01 B9 B07E9C00
MOV ECX,9C7EB0
009C3A06 8D45 F8
LEA EAX,
DWORD PTR SS:[
EBP-8]
009C3A09 BA 04000000
MOV EDX,4
009C3A0E E8 2DD1FFFF
CALL 009C0B40
009C3A13 FF75 FC
PUSH DWORD PTR SS:[
EBP-4]
009C3A16 FF75 F8
PUSH DWORD PTR SS:[
EBP-8]
009C3A19 8B45 F4
MOV EAX,
DWORD PTR SS:[
EBP-C]
009C3A1C 8338 00
CMP DWORD PTR DS:[
EAX],0
009C3A1F 74 02
JE SHORT 009C3A23
009C3A21 FF30
PUSH DWORD PTR DS:[
EAX]
009C3A23 FF75 F0
PUSH DWORD PTR SS:[
EBP-10]
009C3A26 FF75 EC
PUSH DWORD PTR SS:[
EBP-14]
009C3A29 C3
RETN ;这里下断
看到了c3吧,对就这里下断,在009c3a29处下f2断点,然后shift+f9就会断下来。断下后取消该断点(怎么取消,晕倒,对没有一点基础知识的朋友,请去看相关文档,不用来问我了,因我没有这么多时间来回答,这里也随便回答一下,上次有朋友问我,用了我的幻影的脱壳脚本后如何dump+fixdump,这个问题我不好怎么讲,只能说你们自己去看看最基础的东西先)
唔,开小差就开到这里先,取消断点后下硬件访问断点hr [
ESP+C](这里也就相当于hr 12ffa4),下断完毕当然是F9运行了,下面的东西要有一点基础,要不看那些代码就有点飞的感觉。
运行后这里断下,断下后取消硬件访问断点:
009D5CA3 F3: PREFIX
REP:
; 这里断下
009D5CA4 EB 02
JMP SHORT 009D5CA8
下面就要小心点按F8来找到stolen code,
009D5CF5 BE C55C9D00
MOV ESI,9D5CC5
009D5CFA FF56 3F
CALL DWORD PTR DS:[
ESI+3F]
;这里F7跟进去,要不就真的飞了,进去后就按f8一直跟到stolen code处
009D5D67 896C24 00
MOV DWORD PTR SS:[
ESP],
EBP ;***** ;这里就是push ebp了
009D5D6B 8BEC
MOV EBP,
ESP ;*****
009D5D6D 6A FF
PUSH ?1
;*****
009D5D6F 68 48A44200
PUSH 42A448
;*****
009D5D74 68 F4514200
PUSH 4251F4
;*****
009D5D79 64:A1 00000000
MOV EAX,
DWORD PTR FS:[0]
;*****
009D5D7F 66:8105 895D9D0>
ADD WORD PTR DS:[9D5D89],4916
……
009D5DBB 894424 00
MOV DWORD PTR SS:[
ESP],
EAX ;*****
009D5DBF 64:8925 0000000>
MOV DWORD PTR FS:[0],
ESP ;*****
009D5DC6 83EC 58
SUB ESP,58
;*****
……
009D5E05 895C24 00
MOV DWORD PTR SS:[
ESP],
EBX ;*****
……
009D5E45 897424 00
MOV DWORD PTR SS:[
ESP],
ESI ;*****
……
009D5E85 897C24 00
MOV DWORD PTR SS:[
ESP],
EDI ;***** ; ntdll.77F944A8
009D5E89 8965 E8
MOV DWORD PTR SS:[
EBP-18],
ESP ;*****
009D5E8C F3: PREFIX
REP:
009D5E95 68 F8FF4100
PUSH 41FFF8
;看到这里,只要跟过aspr的朋友都知道下面就是清场代码,我们没必要去跟。
009D5E9A 68 015C9D00
PUSH 9D5C01
009D5E9F C3
RETN
现在我们直接执行g 41fff8,这样就到这里停下来了.
0041FFF8 FF15 C4914200
CALL DWORD PTR DS:[4291C4]
;到这里下车
0041FFFE 33D2
XOR EDX,
EDX
00420000 8AD4
MOV DL,
AH
00420002 8915 84BE4300
MOV DWORD PTR DS:[43BE84],
EDX
00420008 8BC8
MOV ECX,
EAX
好了,现在总结一下stolen code:
0041FFD2 55
PUSH EBP
0041FFD3 8BEC
MOV EBP,
ESP
0041FFD5 6A FF
PUSH -1
0041FFD7 68 48A44200
PUSH AIMPR.0042A448
0041FFDC 68 F4514200
PUSH AIMPR.004251F4
0041FFE1 64:A1 00000000
MOV EAX,
DWORD PTR FS:[0]
0041FFE7 50
PUSH EAX
0041FFE8 64:8925 0000000>
MOV DWORD PTR FS:[0],
ESP
0041FFEF 83EC 58
SUB ESP,58
0041FFF2 53
PUSH EBX
0041FFF3 56
PUSH ESI
0041FFF4 57
PUSH EDI
0041FFF5 8965 E8
MOV DWORD PTR SS:[
EBP-18],
ESP
补上这些代码后,打开asprdbgr 1.0并载入目标,加载后,出现对框就点yes直到目标程序运行:
AsprDbgr v1.0beta (:P) Made by me... Manko.
iEP=401000 (C:\Program Files\AIMPR\AIMPR.exe)
GST returns to: 9B2667
Trick aspr GST... (
EAX=12121212h)
GV returns to: 9C1A61
IAT Start: 429000
End: 42938C
Length: 38C
IATentry 4290E4 = 9C1CF0 resolved as
FreeResource
IATentry 4290E8 = 9C1C64 resolved as GetModuleHandleA
IATentry 4290F4 = 9C1CC8 resolved as
LockResource
IATentry 42913C = 9C17A4 resolved as
GetProcAddress
IATentry 4291A4 = 9C1CB8 resolved as
GetCurrentProcess
IATentry 4291C4 = 9C1C8C resolved as
GetVersion
IATentry 4291CC = 9C1CD8 resolved as GetCommandLineA
IATentry 4292C8 = 9C1D14 resolved as DialogBoxParamA
0 invalid entries erased.
Dip-Table at adress: 9C7AB4
0 0 0 0 0 0 0 0 0 0 41DA10 41DA00 41D9F0 0
Last SEH passed. Searching for signatures. Singlestepping to OEP!
Call + OEP-jump-setup at: 9D5E3F ( Code: E8000000 5D81ED )
Mutated, stolen bytes at: 9D5E8A ( Code: 61F3EB02 CD20F3EB )
Erase of stolen bytes at: 9D5DEE ( Code: 9CFCBF2D 5E9D00B9 )
Repz ... found. Skipping erase of stolen bytes.
;)
Dip from pre-OEP: 41FFF8 (Reached from: 9D5DFF)
现在打开imp设置OEP为1fff8,然后就可以得到全部的iat,真是好东西,给我等懒人用最好不过了.得到全部输入表后把oep改回1FFD2,当然,如果你喜欢的话也可以一开始就设OEP 为1FFD2。
现在DUMP+FIXDUMP后程序就能运行了,到此脱壳也就算完成了
衣服已经脱掉了,现在我们就要进行强暴(强力暴破,你可不要想坏了哦,本来想不脱衣服直接强暴,但又想一下,如果直接强暴的话,不就文字太少了,也就不能成为一篇文章嘛)了,
载入脱后的文件,运行之,打开注册对话框输入你的大名,然后下断bpx GetDlgitemTextA
这样断在这里:
lbl_GetSN:
; CODE XREF: seg000:0041DE61 j
seg000:0041DE70
mov eax,
ds:dword_43BE3C
seg000:0041DE75
xor ecx,
ecx
seg000:0041DE77
mov cx, [
eax+300h]
seg000:0041DE7E
add eax, 200h
seg000:0041DE83
push ecx ; Count
seg000:0041DE84
push eax ; 缓冲区,等下会返回注册码的长度
seg000:0041DE85
push 0FFAh
; 这里就是ID了
seg000:0041DE8A
push edi ; 这个就是句柄来的
seg000:0041DE8B
call ds:GetDlgItemTextA
seg000:0041DE91
mov edx,
ds:dword_43BE3C
seg000:0041DE97
add edx, 200h
seg000:0041DE9D
push edx ; EDX保存了我们输入的注册码
seg000:0041DE9E
call lbl_CheckSn
; 这里跟进,要不就over了
seg000:0041DEA3
add esp, 4
seg000:0041DEA6
test eax,
eax
seg000:0041DEA8
jnz short loc_41DEB3
; 这里要注意了,不要以为这里改成jmp就会ok
seg000:0041DEA8
; 了,这里改是没有用的,因为后面还会进上面
seg000:0041DEA8
; 那个CALL里检查是否正确
seg000:0041DEAA
push edi
seg000:0041DEAB
call sub_41DD80
seg000:0041DEB0
add esp, 4
进入上面的call到这里
lbl_CheckSn
proc near
; CODE XREF: seg000:0041DE9E p
seg000:0041DB90
; sub_41E030+12 p ...
seg000:0041DB90
seg000:0041DB90 var_6C =
dword ptr -6Ch
seg000:0041DB90 var_5C =
dword ptr -5Ch
seg000:0041DB90 arg_0 =
dword ptr 4
seg000:0041DB90
seg000:0041DB90
sub esp, 6Ch
seg000:0041DB93
or ecx, 0FFFFFFFFh
seg000:0041DB96
xor eax,
eax
seg000:0041DB98
push ebx
seg000:0041DB99
push ebp
seg000:0041DB9A
mov ebp, [
esp+74h+arg_0]
seg000:0041DB9E
push edi
seg000:0041DB9F
mov edi,
ebp
seg000:0041DBA1
repne scasb ; 这里也就是得出注册码的长度
seg000:0041DBA3
not ecx
seg000:0041DBA5
dec ecx
seg000:0041DBA6
cmp ecx, 6
; 比较注册长度是否大于六,不就是over了
seg000:0041DBA9
jge short lbl_Next1
; 如果没问题的话,就跳去下一步
seg000:0041DBAB
pop edi
seg000:0041DBAC
pop ebp
seg000:0041DBAD
pop ebx
seg000:0041DBAE
add esp, 6Ch
seg000:0041DBB1
retn ; 如果到了这里的RET的话,就要重来了
seg000:0041DBB2
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
seg000:0041DBB2
seg000:0041DBB2 lbl_Next1:
; CODE XREF: lbl_CheckSn+19 j
seg000:0041DBB2
and ecx, 80000001h
seg000:0041DBB8
jns short loc_41DBBF
; 这里跳,
seg000:0041DBBA
dec ecx
seg000:0041DBBB
or ecx, 0FFFFFFFEh
seg000:0041DBBE
inc ecx
seg000:0041DBBF
seg000:0041DBBF loc_41DBBF:
; CODE XREF: lbl_CheckSn+28 j
seg000:0041DBBF
jz short lbl_Next2
; 这里也跳,这两个地方我们一般不用管它
seg000:0041DBC1
pop edi
seg000:0041DBC2
pop ebp
seg000:0041DBC3
xor eax,
eax
seg000:0041DBC5
pop ebx
seg000:0041DBC6
add esp, 6Ch
seg000:0041DBC9
retn ; 到这里的话也是over哦
seg000:0041DBCA
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
seg000:0041DBCA
seg000:0041DBCA lbl_Next2:
; CODE XREF: lbl_CheckSn+2F j
seg000:0041DBCA
mov edi,
ebp ; 注册码入edi
seg000:0041DBCC
or ecx, 0FFFFFFFFh
seg000:0041DBCF
xor eax,
eax
seg000:0041DBD1
push esi
seg000:0041DBD2
repne scasb ; 这里再次计算注册码的长度
seg000:0041DBD4
not ecx
seg000:0041DBD6
dec ecx
seg000:0041DBD7
lea eax, [
esp+7Ch+var_5C]
seg000:0041DBDB
mov ebx,
ecx ; 注册码长度入EBX
seg000:0041DBDD
push eax
seg000:0041DBDE
add ebx, 4
seg000:0041DBE1
shr ebx, 1
; 如果没有什么意外的话就到这里
seg000:0041DBE3
call lbl_InitMD5
; 这里跟进后可以看到是MD5算法来的
进来看看吧:
seg000:0041C7F0
; 〓〓〓〓〓〓〓〓 S U B R O U T I N E 〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
seg000:0041C7F0
seg000:0041C7F0
seg000:0041C7F0 lbl_InitMD5
proc near
; CODE XREF: sub_409E20+128 p
seg000:0041C7F0
; sub_414D80+8 p ...
seg000:0041C7F0
seg000:0041C7F0 arg_0 =
dword ptr 4
seg000:0041C7F0
seg000:0041C7F0
mov eax, [
esp+arg_0]
seg000:0041C7F4
xor ecx,
ecx
seg000:0041C7F6
mov dword ptr [
eax], 67452301h
;看到这些东西就不用我再说了吧
seg000:0041C7FC
mov dword ptr [
eax+4], 0EFCDAB89h
seg000:0041C803
mov dword ptr [
eax+8], 98BADCFEh
seg000:0041C80A
mov dword ptr [
eax+0Ch], 10325476h
seg000:0041C811
mov [
eax+10h],
ecx
seg000:0041C814
mov [
eax+14h],
ecx
seg000:0041C817
mov [
eax+58h],
ecx
seg000:0041C81A
retn
seg000:0041C81A lbl_InitMD5
endp
seg000:0041C81A
seg000:0041C81A
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
看完后,回到老地方:
seg000:0041DBE9
lea ecx, [
esp+84h+var_5C]
seg000:0041DBED
push ebp ; 注册码入栈
seg000:0041DBEE
push ecx
seg000:0041DBEF
call sub_41C820
seg000:0041DBF4
lea edx, [
esp+8Ch+var_5C]
seg000:0041DBF8
lea eax, [
esp+8Ch+var_6C]
seg000:0041DBFC
push edx
seg000:0041DBFD
push eax
seg000:0041DBFE
call sub_41D8B0
seg000:0041DC03
add esp, 18h
seg000:0041DC06
mov ecx, 4
seg000:0041DC0B
mov edi,
offset unk_43714C
seg000:0041DC10
lea esi, [
esp+7Ch+var_6C]
seg000:0041DC14
xor edx,
edx
seg000:0041DC16
repe cmpsd
seg000:0041DC18
pop esi
seg000:0041DC19
jz short lbl_Next3
; **** 看到MD5我就头疼,一疼就一直按f8跑到这里,
seg000:0041DC19
; 这里一定要跳,
seg000:0041DC1B
pop edi
seg000:0041DC1C
pop ebp
seg000:0041DC1D
xor eax,
eax
seg000:0041DC1F
pop ebx
seg000:0041DC20
add esp, 6Ch
seg000:0041DC23
retn
seg000:0041DC24
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
seg000:0041DC24
seg000:0041DC24 lbl_Next3:
; CODE XREF: lbl_CheckSn+89 j
seg000:0041DC24
lea eax, [
esp+78h+var_5C]
seg000:0041DC28
push eax
seg000:0041DC29
call lbl_InitMD5
seg000:0041DC2E
mov edi,
ebp
seg000:0041DC30
or ecx, 0FFFFFFFFh
seg000:0041DC33
xor eax,
eax
seg000:0041DC35
repne scasb
seg000:0041DC37
not ecx
seg000:0041DC39
dec ecx
seg000:0041DC3A
push ecx
seg000:0041DC3B
lea ecx, [
esp+80h+var_5C]
seg000:0041DC3F
push ebp ; 注册码入栈
seg000:0041DC40
push ecx
seg000:0041DC41
call sub_41C820
seg000:0041DC46
lea edx, [
esp+88h+var_5C]
seg000:0041DC4A
lea eax, [
esp+88h+var_6C]
seg000:0041DC4E
push edx
seg000:0041DC4F
push eax
seg000:0041DC50
call sub_41D8B0
seg000:0041DC55
lea ecx, [
esp+90h+var_6C]
seg000:0041DC59
push ecx
seg000:0041DC5A
call sub_41DB20
seg000:0041DC5F
add esp, 1Ch
seg000:0041DC62
test eax,
eax
seg000:0041DC64
jnz short lbl_Next4
; ***** 不一会按F8到了这里,这里也要跳哦.
seg000:0041DC66
pop edi
seg000:0041DC67
pop ebp
seg000:0041DC68
pop ebx
seg000:0041DC69
add esp, 6Ch
seg000:0041DC6C
retn
seg000:0041DC6D
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
seg000:0041DC6D
seg000:0041DC6D lbl_Next4:
; CODE XREF: lbl_CheckSn+D4 j
seg000:0041DC6D
mov eax,
ds:dword_43BE40
seg000:0041DC72
test eax,
eax
seg000:0041DC74
jnz short lbl_RegOK
; ***** 呵呵一不小心就跳到光明之处了,这里也跳,不跳也完了
seg000:0041DC76
push ebx
seg000:0041DC77
push ebp
seg000:0041DC78
call sub_41DA80
seg000:0041DC7D
add esp, 8
seg000:0041DC80
mov ds:dword_43BE40, 1
seg000:0041DC8A
seg000:0041DC8A lbl_RegOK:
; CODE XREF: lbl_CheckSn+E4 j
seg000:0041DC8A
pop edi
seg000:0041DC8B
pop ebp ; 呵呵看到注册码出栈了吧
seg000:0041DC8C
mov eax, 1
; 这里赋eax为1,如果注册成功的话
seg000:0041DC91
pop ebx
seg000:0041DC92
add esp, 6Ch
seg000:0041DC95
retn
seg000:0041DC95 lbl_CheckSn
endp
到这里就知道怎么强暴了吧,改那几个用*的地方,改成jmp XXX:
0041DC19 . EB 09
JMP SHORT dumped1_.0041DC24
0041DC64 . EB 07
JMP SHORT dumped1_.0041DC6D
0041DC74 . EB 14
JMP SHORT dumped1_.0041DC8A
改好后,保存一下,再运行看一下,是不是已经注册了,这样就收工了?你不觉得改三个地方,改的太多了点吗?既然是强暴,当然要怎么样快就改哪里了,
我的改法:
seg000:0041DB90
seg000:0041DB90
sub esp, 6Ch
;改这里
seg000:0041DB93
or ecx, 0FFFFFFFFh
seg000:0041DB96
xor eax,
eax
seg000:0041DB98
push ebx
改为:
0041DB90 B8 01000000
MOV EAX,1
0041DB95 C3
RETN
这里够爽了吧,到了这里也就全部操作完成,因这个软件纯用来做教学的,所以不敢保证没有暗桩哦,如果你发现有暗桩或有什么别人好的方法或搞定了全部的算法,请告之本人,谢谢!
特别感谢老菜鸟给我一个好我武器IDA,没有他,可能我今天还是用w32dasm写文章给大家看.也算是我的IDA NO1 TUT吧!
Greetz:
Fly.Jingulong,yock,tDasm.David.ahao.vcasm.UFO(brother).alan(sister).all of my friends
and you!
By loveboom[DFCG][FCG]
Email:bmd2chen@tom.com
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。