BlowFish 2000(Software by Design)
一日,查Blowfish算法解密,不小心下了它,安装后发现是用来加密文件的,郁闷,查壳发现是Armadillo 3.78 - 4.xx,刚好练手。
1.脱壳:
Armadillo 3.78 - 4.xx -> Silicon Realms Toolworks
双进程
OD载入后用脚本分离双进程,等待提示转换ok后,用2次断点法,即是:
bp GetModuleHandleA/he GetModuleHandleA
bp GetCurrentThreadId
bp GetModuleHandleA
77E80B1A > 55 push ebp ; 第一次断点
77E80B1B 8BEC mov ebp,esp
77E80B1D 837D 08 00 cmp dword ptr ss:[ebp+8],0
77E80B21 75 0E jnz short KERNEL32.77E80B31 ; 转-下断
说明,有些程序第一次断点使用bp GetModuleHandleA+7断不下来,所以第一次使用bp GetModuleHandleA,然后转bp GetModuleHandleA+7,因为该程序在返回时机前最后一次会检查GetModuleHandleA处的断点。
注意堆栈,接连看到 "VirtualAlloc"和 "VirtualFree",就要在下一站下车了:
00128CAC /0012CF48
00128CB0 |00A90445 返回到 00A90445 来自 KERNEL32.GetModuleHandleA
00128CB4 |00AA3D68 ASCII "kernel32.dll"
00128CB8 |00AA4F30 ASCII "VirtualAlloc"
00128CBC |00000001
00128CAC /0012CF48
00128CB0 |00A90462 返回到 00A90462 来自 KERNEL32.GetModuleHandleA
00128CB4 |00AA3D68 ASCII "kernel32.dll"
00128CB8 |00AA4F24 ASCII "VirtualFree"
00128CBC |00000001
00128A24 /00128CB0
00128A28 |00A799C1 返回到 00A799C1 来自 KERNEL32.GetModuleHandleA
00128A2C |00128B64 ASCII "kernel32.dll" ; 可以返回了
00128A30 |00000000
返回的时机参考各位前辈的经验,取消断点返回:
00A799C1 8B0D 2091AA00 mov ecx,dword ptr ds:[AA9120] ; 返回处
00A799C7 89040E mov dword ptr ds:[esi+ecx],eax
00A799CA A1 2091AA00 mov eax,dword ptr ds:[AA9120]
00A799CF 393C06 cmp dword ptr ds:[esi+eax],edi
00A799D2 75 16 jnz short 00A799EA
00A799D4 8D85 B4FEFFFF lea eax,dword ptr ss:[ebp-14C]
00A799DA 50 push eax
00A799DB FF15 D4E0A900 call dword ptr ds:[A9E0D4] ; KERNEL32.LoadLibraryA
00A799E1 8B0D 2091AA00 mov ecx,dword ptr ds:[AA9120]
00A799E7 89040E mov dword ptr ds:[esi+ecx],eax
00A799EA A1 2091AA00 mov eax,dword ptr ds:[AA9120]
00A799EF 393C06 cmp dword ptr ds:[esi+eax],edi
00A799F2 0F84 B3000000 je 00A79AAB ; MAGIC JUMP
修改MAGIC JUMP后,换第二个断点:bp GetCurrentThreadId
第一次:
001285E8 66001E3A /CALL 到 GetCurrentThreadId 来自 66001E34
001285EC 00000001
001285F0 66001C1E 返回到 66001C1E 来自 66001DE6
第二次:
001285C8 66003505 /CALL 到 GetCurrentThreadId 来自 660034FF
001285CC 00000000
001285D0 6610E470
第三次:
0012D770 00A98B18 /CALL 到 GetCurrentThreadId 来自 00A98B12
0012D774 0012FF04
0012D778 00000000
堆栈00A98B18就是程序领空的,可以返回了:
00A98B18 A3 A8D6AA00 mov dword ptr ds:[AAD6A8],eax ; 返回处
00A98B1D E8 9511FEFF call 00A79CB7
一直F8往下,直到来到call edi:
00A98BA1 A1 90D5AA00 mov eax,dword ptr ds:[AAD590]
00A98BA6 8B88 80000000 mov ecx,dword ptr ds:[eax+80]
00A98BAC 3348 38 xor ecx,dword ptr ds:[eax+38]
00A98BAF 3348 30 xor ecx,dword ptr ds:[eax+30]
00A98BB2 2BF9 sub edi,ecx
00A98BB4 FFD7 call edi ; 就是这里了
进call edi:
004110BF 55 push ebp ; OEP
004110C0 8BEC mov ebp,esp
004110C2 6A FF push -1
LORDPE,dump。
ImportREC_fix.exe修复:
OEP:000110BF;
自动搜索IAT:RVA=00019000,SIZE=00000344
DD 00419000查看IAT的SIZE是否足够:
00419000 796ED804 ADVAPI32.RegCreateKeyExA
00419004 796EF4C0 ADVAPI32.RegOpenKeyExA
00419008 796F45B2 ADVAPI32.RegCloseKey
0041900C 796EE841 ADVAPI32.RegSetValueExA
...
00419338 7CF2EB69 ole32.CoUninitialize
0041933C 7CF1C242 ole32.CoCreateInstance
00419340 7CF40E8F ole32.CoInitialize
00419344 00A7AA49
00419348 243F6A88
0041934C 85A308D3
SIZE的确没错。
修复后运行ok,PEID:Armadillo 1.xx - 2.xx -> Silicon Realms Toolworks
估计误报,W32Dasm可以得到串参考。
脱壳的程序入口点下面:
004110E5 FF15 AC914100 call dword ptr ds:[<&kernel32.GetVersion>]
看来是VC6.0。
2.脱壳后问题
问题:运行脱壳后的程序,help菜单2个变灰(contents&search),点击注册确认按钮跳出提示框提示:ArmAccess.dll,Error detected loading this DLL library Module Code 126。
是不是没能脱干净?
OD载入脱壳或者未脱壳程序(修改为单进程并MAGIC JUMP),都一样的问题,看来不是脱壳修复的问题。
跟踪调试后发现程序先取用户名及注册码,紧接着判断程序是否有错:
004088DE E8 CD710000 call BlowFish.0040FAB0 ; 用户名
004088F0 E8 BB710000 call BlowFish.0040FAB0 ; 注册码
00408903 E8 88090000 call BlowFish.00409290 ; 出错的call
有2个错误:
一个就是:ArmAccess.dll Error detected loading this DLL library Module Code 126。
如果修改跳转出现第二个错误:
Procedure: InstallKey Error detected locating the Procedure Address Code 127。
详细代码如下:
00409290 56 push esi
00409291 68 04CF4100 push BlowFish.0041CF04 ; ASCII "ArmAccess.dll"
00409296 FF15 60914100 call dword ptr ds:[419160] ; KERNEL32.LoadLibraryA
0040929C 8BF0 mov esi,eax ; 脱壳后eax=0
0040929E 85F6 test esi,esi
004092A0 75 25 jnz short BlowFish.004092C7 ; 此处要跳,不跳就完
004092A2 FF15 48914100 call dword ptr ds:[419148] ; KERNEL32.GetLastError
004092A8 50 push eax
004092A9 8B4424 0C mov eax,dword ptr ss:[esp+C]
004092AD 68 04CF4100 push BlowFish.0041CF04 ; ASCII "ArmAccess.dll"
004092B2 68 C5EA0000 push 0EAC5
004092B7 68 88130000 push 1388
004092BC 50 push eax
004092BD E8 7ED8FFFF call BlowFish.00406B40
004092C2 83C4 14 add esp,14
004092C5 5E pop esi
004092C6 C3 retn
004092C7 68 F8CE4100 push BlowFish.0041CEF8 ; ASCII "InstallKey"
004092CC 56 push esi
004092CD FF15 5C914100 call dword ptr ds:[41915C] ; KERNEL32.GetProcAddress
004092D3 85C0 test eax,eax ; 脱壳后eax=0
004092D5 75 25 jnz short BlowFish.004092FC ; 此处要跳不跳就完
004092D7 FF15 48914100 call dword ptr ds:[419148] ; KERNEL32.GetLastError
004092DD 8B4C24 08 mov ecx,dword ptr ss:[esp+8]
004092E1 50 push eax
004092E2 68 F8CE4100 push BlowFish.0041CEF8 ; ASCII "InstallKey"
004092E7 68 E3EA0000 push 0EAE3
004092EC 68 88130000 push 1388
004092F1 51 push ecx
004092F2 E8 49D8FFFF call BlowFish.00406B40
004092F7 83C4 14 add esp,14
004092FA 5E pop esi
004092FB C3 retn
只有通过了上面的2个跳转才能继续。但是如果修改004092D5处跳转,使其强跳的话,往下就碰到call eax,而eax=0,出现异常over。
如果载入未脱壳程序并运行,因为是双进程的,所以没戏,但是如果载入未脱壳程序,然后转成单进程运行,可以下断,并且也能通过上面提到的2个错误,然后来到:
004092FC 8B5424 10 mov edx,dword ptr ss:[esp+10] ; zcm
00409300 8B4C24 0C mov ecx,dword ptr ss:[esp+C] ; yhm
00409304 57 push edi
00409305 52 push edx
00409306 51 push ecx
00409307 FFD0 call eax ; eax=00A98117
00409309 25 FF000000 and eax,0FF
0040930E 56 push esi
0040930F 8BF8 mov edi,eax
00409311 FF15 58914100 call dword ptr ds:[419158] ; GetModuleHandleA
00409317 8BD7 mov edx,edi
00409319 8B4424 0C mov eax,dword ptr ss:[esp+C]
0040931D F7DA neg edx
0040931F 1BD2 sbb edx,edx
00409321 81E2 BA28FFFF and edx,FFFF28BA
00409327 81C2 CFEA0000 add edx,0EACF
0040932D 52 push edx
0040932E 68 88130000 push 1388
00409333 50 push eax
00409334 E8 07D8FFFF call BlowFish.00406B40 ; 提示成功或者失败的地方!
00409339 83C4 0C add esp,0C
0040933C 8BC7 mov eax,edi
0040933E 5F pop edi
0040933F 5E pop esi
00409340 C3 retn
至此,问题解决了,OD载入后转换成单进程,然后运行,因为我们获得了断点(从脱壳后的程序那里获得)然后按常规下断跟踪即可。
关键就在:00409307 FFD0 call eax ; eax=00A98117
3.总结:
本来Arm的壳脱壳后就可以取消掉试用,不过该程序还要注册。
该程序虽然脱壳成功,但是没办法注册,只是方便找断点。
于是载入未脱壳程序,脚本转单进程后运行,下断可以断下,而且解决了脱壳后的问题。
难道注册码的运算隐藏在Armadillo的代码中?带壳也可以调试出注册算法?
我在壳中游啊游,没能靠上岸,晕头转向的看不出注册码怎么运算。
有没有谁感兴趣调试,然后指导下小弟我。
[课程]FART 脱壳王!加量不加价!FART作者讲授!