近段时间一直在研究这个传说中的猛壳,确实对于我们这种小菜鸟来说,真的好猛,入口点知道在哪里,可就是断不下来,断下后可恶的输入表不好修复,对我而言能分析代码其实就足够了,彻底脱壳对我来说也没什么实际意义,当然有哪位大牛有OEP的短法也请赐教。
但是这该死的 IAT 修复起来真要命,一直在 safengine 段中跟了好久也要不就是跟丢要不就是跟过。。这个 Nooby 这可恨!我恨死他了~但是说回来,safengine VM 的功底肯定没 VMP TMD 之类的强,毕竟他们靠这个吃饭的,safengine 做足了反调试、反DUMP、antiAnything的功夫,但是要想在 VM 界立足一个 nooby 大牛还是不够的。
最后希望广大壳友不要气馁,矛与盾总是步步紧逼的,越是有挑战性的壳,越是号称“最强”的壳,崩溃的速度越快。safengine 这个壳做了很多宣传,用 10 万块来吸引眼球,并不是想证明他的壳有多强,只是一种炒作手段,最简单不过的手段,他一个 nooby 能抵抗千千万万的大牛吗?答案是肯定的,那就是“NO”!
=======================================================
求人不如求己是我一贯的作风。再也不做标题党!
经过仔细分析后,简单的写了中低复杂度的 IAT 修复脚本。
这种 复杂度的在SE壳中的 CALL 大概会占到 60% 左右,以下是 代码。
101A4AC9 50 PUSH EAX
101A4ACA 60 PUSHAD
101A4ACB 9C PUSHFD
101A4ACC B8 879A950B MOV EAX,0B959A87
101A4AD1 BB B15F8304 MOV EBX,4835FB1
101A4AD6 03C3 ADD EAX,EBX
101A4AD8 8B00 MOV EAX,DWORD PTR DS:[EAX]
101A4ADA 33C3 XOR EAX,EBX
101A4ADC 874424 24 XCHG DWORD PTR SS:[ESP+24],EAX
101A4AE0 FF4424 28 INC DWORD PTR SS:[ESP+28]
101A4AE4 9D POPFD
101A4AE5 61 POPAD
101A4AE6 C3 RETN <--- 难度最低的时候 EIP 到这里的时候 ESP 就是 API。
稍微再高一个级别的在 C3 处不返回 API,而是返回后到下面这里:
0944068B 68 F1893564 PUSH 643589F1
09440690 F71424 NOT DWORD PTR SS:[ESP]
09440693 813424 CA7659E7 XOR DWORD PTR SS:[ESP],E75976CA
0944069A C3 RETN
也有可能是 RETN 4 的比如以下代码:
09440663 68 E03659E7 PUSH E75936E0
09440668 68 10718F6D PUSH 6D8F7110
0944066D F71424 NOT DWORD PTR SS:[ESP]
09440670 C10C24 05 ROR DWORD PTR SS:[ESP],5
09440674 C2 0400 RETN 4
所以脚本如下: 这是第一版,没有对 RETN 进行判断,随后会发一个完善一些的脚本,并且不再需要UIF修复,供菜鸟们学习。
var codebase
var secode1
var secode2
var apiaddr
var calladdr
var fixaddr
var retaddr
var temaddr
var oep
var temeax
var temebx
var temecx
var temedx
var temebp
var temesp
var temesi
var temedi
mov codebase,10001000
mov secode1,1018d000
mov secode2,10317000
mov oep,eip
mov temeax,eax
mov temebx,ebx
mov temecx,ecx
mov temedx,edx
mov temebp,ebp
mov temesp,esp
mov temesi,esi
mov temedi,edi
mov eip,codebase
findcall:
find eip,#E8??????00#
cmp $RESULT,0
je exit
mov calladdr,$RESULT
GCI calladdr,DESTINATION
mov fixaddr,$RESULT
find fixaddr,#50609cb8????????#,8
cmp $RESULT,0
jne startfix //这里发现低复杂度 CALL,直接开始处理了
find fixaddr,#e9??????00#,5
cmp $RESULT,0
je nextcall
mov sejmp,$RESULT
GCI sejmp,DESTINATION
mov fixaddr,$RESULT
find fixaddr,#68????????9c81442404????????9d#,0f
cmp $RESULT,0
jne next // 高复杂度的暂时忽略
nextcall:
add calladdr,1
mov eip,calladdr
jmp findcall
startfix:
mov esp,temesp
mov eip,calladdr
findret:
sti
find eip,#C3#, 1 //第一阶段直接查找 RETN
cmp $RESULT,0
mov retaddr,$RESULT
je findret
gn [esp] // 如果有返回但是ESP 又不是 API的则进入第二阶段
cmp $RESULT,0
jne fixret
findret2:
sti
find eip,#C3#,1
cmp $RESULT,0
mov retaddr,$RESULT
jne findiat
find eip,#C2??00#,3 // 这里查 RETN 4\8\C\10 之类,第二版中会做判断,根据他来读取寄存器里的返回地址,并作为下一个 EIP
mov retaddr,$RESULT
cmp $RESULT,0
je findret2
findiat:
gn [esp] //分析 APIname
cmp $RESULT,0
je findret2
fixret:
mov apiaddr,[esp] // 直接 asm call APIAddress,用 UIF 修复就可以了
eval "call {apiaddr}"
asm calladdr,$RESULT
next:
add calladdr,1
mov eip,calladdr
mov esp,temesp
mov eax, 0
mov ebx, 0
mov ecx, 0
mov edx, 0
mov esi, 0
mov edi, 0
mov ebp, 0
jmp findcall
exit:
mov eip,oep
mov esp,temesp
mov edi,temedi
mov esi,temesi
mov ebp,temebp
mov eax,temeax
mov ebx,temebx
mov ecx,temecx
mov edx,temedx
ret
以下是复杂度高的:
10193E8A /E9 08770400 JMP ms.101DB597
跳过来以后,会反复执行以下代码,听说有特征码,可我还没能找到。因为我的SE 是 2090 的
101DB597 68 D6339FA0 PUSH A09F33D6
101DB59C 9C PUSHFD
101DB59D 814424 04 61137>ADD DWORD PTR SS:[ESP+4],6F7F1361
101DB5A5 9D POPFD
101DB5A6 C3 RETN
再比这个高的复杂度最后加这种结构,其实说回来复杂度不同就是结合的问题而已。
0944068B 68 F1893564 PUSH 643589F1
09440690 F71424 NOT DWORD PTR SS:[ESP]
09440693 813424 CA7659E7 XOR DWORD PTR SS:[ESP],E75976CA
0944069A C3 RETN
其实复杂度高度都可以用我的脚本跑起来的,但是不保证完全正确,有时会跟丢的。
另外提示下,其实SE 的反调试并不是想象的那么恐怖,用strongOD v0.4.5.810 轻松忽悠SE。如果被发现,Ctrl+F2 几次就可以。
本脚本只适合菜鸟使用~~~呵呵 只是娱乐而已
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)