ASProtect 1.23RC4脱壳+错误修复+去NAG注册
【文章标题】: ASProtect 1.23RC4脱壳+错误修复+去NAG注册
【文章作者】: 黄仁来
【软件名称】: Bubble Ice Age
【下载地址】: http://www.realore.com/games/iceage/
【加壳方式】: ASProtect 1.23RC4
【保护方式】: 回壳+序列号
【编写语言】: VC++
【操作平台】: VBOX(XP_SP3)
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
最近对脱壳比较感兴趣,学多了。哪怕是一些很老的壳,手动操练一下或许对自己有所提高。
这个小游戏PEiD查得 ASProtect 1.23 RC4 - 1.3.08.24 -> Alexey Solodovnikov,是一个非常老的壳了。
网上关于它的脱壳文章满天飞。
基本上通过最后一次异常法 + 内存断点法 可以迅速到达OEP,此程序也有Stolen Code,经过追踪,可还原如下:
push ebp
MOV EBP,ESP
PUSH -1
PUSH 4512A0
PUSH 4357BC
MOV EAX,DWORD PTR FS:[0]
push eax
MOV DWORD PTR FS:[0],ESP
SUB ESP,58
push ebx
push esi
push edi
MOV DWORD PTR SS:[EBP-18],ESP
但遗憾的是,手动脱壳后,在修复IAT时,有四个指针追踪不到,修复后的程序无法运行,太郁闷了。
后来还是请出stripper直接把它Dump了。但是脱壳不完全,偷窃代码段还有许多花指令,F7一直单步到OEP
后,手动补全偷窃代码,OD直接Dump,非常干净。
脱壳后的程序可以运行,但是显示错误提示:
这种提示明显不是脱壳错误的或附加数据丢失的错误,应该是程序内部算法的错误,可能通过修改代码来解决。
bp MessageBoxA 下断,可以得到 出错地址
0041DE80 /$ 6A 04 push 0x4 ; /ProcNameOrOrdinal = #4
0041DE82 |. 6A FF push -0x1 ; |hModule = FFFFFFFF
0041DE84 |. FF15 4C014500 call dword ptr ds:[<&kernel32.GetProcAdd>; \GetProcAddress
0041DE8A |. 85C0 test eax,eax
0041DE8C |. A3 D4124600 mov dword ptr ds:[0x4612D4],eax
0041DE91 |. 75 16 jnz short _IceAge.0041DEA9
0041DE93 |. 6A 10 push 0x10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
0041DE95 |. 68 50674500 push _IceAge.00456750 ; |Title = "Plugin"
0041DE9A |. 68 E0664500 push _IceAge.004566E0 ; |Text = "Crypt API not found. Please re-install application and contact with AEE support ()."
0041DE9F |. 50 push eax ; |hOwner = NULL
0041DEA0 |. FF15 40024500 call dword ptr ds:[<&user32.MessageBoxA>>; \MessageBoxA
0041DEA6 |. 33C0 xor eax,eax
0041DEA8 |. C3 retn
0041DEA9 |> B8 01000000 mov eax,0x1
0041DEAE \. C3 retn
直接把 0041DE91处 的 jnz short _IceAge.0041DEA9 修改为 jmp 跳过,搞定这个错误。
接下来,解决NAG窗口和注册的问题。
点register进入 注册窗口,输入假码:1234567890,下断 bp GetWindowTextA,点确定后马上被中断。
来到算法处。
00421EC0 . 68 FF000000 push 0xFF ; /Count = FF (255.)
00421EC5 . 52 push edx ; |Buffer = 0012F5E8
00421EC6 . 50 push eax ; |hWnd = FFFFFFFF
00421EC7 . FF15 34024500 call dword ptr ds:[<&user32.GetWindowTex>; \GetWindowTextA
00421ECD . 8D4424 64 lea eax,dword ptr ss:[esp+0x64]
00421ED1 . 50 push eax
00421ED2 . E8 58100100 call _IceAge.00432F2F
00421ED7 . 8D4C24 68 lea ecx,dword ptr ss:[esp+0x68]
00421EDB . 51 push ecx
00421EDC . E8 CFFCFFFF call _IceAge.00421BB0
00421EE1 . 8D5424 6C lea edx,dword ptr ss:[esp+0x6C]
00421EE5 . 52 push edx
00421EE6 . E8 F5CDFFFF call _IceAge.0041ECE0 ; 关键CALL
00421EEB . 83C4 0C add esp,0xC
进入关键CALL call _IceAge.0041ECE0,是把注册码保存到注册表。
0041ECE0 /$ 56 push esi
0041ECE1 |. 8B7424 08 mov esi,dword ptr ss:[esp+0x8]
0041ECE5 |. 85F6 test esi,esi
0041ECE7 |. 74 43 je short _IceAge.0041ED2C
0041ECE9 |. 8D4424 08 lea eax,dword ptr ss:[esp+0x8]
0041ECED |. 57 push edi
0041ECEE |. 50 push eax ; /pHandle = FFFFFFFF
0041ECEF |. 68 10684500 push _IceAge.00456810 ; |Subkey = "SOFTWARE\Realore\Bubble Ice Age"
0041ECF4 |. 68 02000080 push 0x80000002 ; |hKey = HKEY_LOCAL_MACHINE
0041ECF9 |. FF15 08004500 call dword ptr ds:[<&advapi32.RegCreateK>; \RegCreateKeyA
0041ECFF |. 8BFE mov edi,esi
注册码保存在 HKEY_LOCAL_MACHINE\SOFTWARE\Realore\Bubble Ice Age 的Code值下。
于是重新载入OD,下断 bp RegQueryValueExA ;中断后看堆栈读 Code 值时,删除断点,Alt + F9返回。
0012FCE8 0041EC5A /CALL 到 RegQueryValueExA 来自 _IceAge.0041EC58
0012FCEC 00000070 |hKey = 70
0012FCF0 00456808 |ValueName = "Code"
0012FCF4 00000000 |Reserved = NULL
0012FCF8 0012FD18 |pValueType = 0012FD18
0012FCFC 00000000 |Buffer = NULL
0012FD00 0012FD10 \pBufSize = 0012FD10
返回到注册算法过程。
0041ED30 /$ 81EC 44010000 sub esp,0x144
0041ED36 |. 8D8424 040100>lea eax,dword ptr ss:[esp+0x104]
0041ED3D |. 53 push ebx
0041ED3E |. 55 push ebp
0041ED3F |. 56 push esi
0041ED40 |. 57 push edi ; ntdll.7C930228
0041ED41 |. 50 push eax
0041ED42 |. E8 C9FEFFFF call _IceAge.0041EC10
0041ED47 |. 8DBC24 180100>lea edi,dword ptr ss:[esp+0x118]
0041ED4E |. 83C9 FF or ecx,-0x1
0041ED51 |. 33C0 xor eax,eax
0041ED53 |. 83C4 04 add esp,0x4
0041ED56 |. F2:AE repne scas byte ptr es:[edi]
0041ED58 |. F7D1 not ecx
0041ED5A |. 49 dec ecx
0041ED5B |. 83F9 16 cmp ecx,0x16 ; 注册码长度必须是22位
0041ED5E |. 73 0D jnb short _IceAge.0041ED6D
0041ED60 |> 5F pop edi ; _IceAge.004115FF
0041ED61 |. 5E pop esi ; _IceAge.004115FF
0041ED62 |. 5D pop ebp ; _IceAge.004115FF
0041ED63 |. 33C0 xor eax,eax
0041ED65 |. 5B pop ebx ; _IceAge.004115FF
0041ED66 |. 81C4 44010000 add esp,0x144
0041ED6C |. C3 retn
0041ED6D |> 8DBC24 140100>lea edi,dword ptr ss:[esp+0x114]
0041ED74 |. 83C9 FF or ecx,-0x1
0041ED77 |. 33C0 xor eax,eax
0041ED79 |. 8D9424 140100>lea edx,dword ptr ss:[esp+0x114]
0041ED80 |. F2:AE repne scas byte ptr es:[edi]
0041ED82 |. F7D1 not ecx
0041ED84 |. 49 dec ecx
0041ED85 |. 51 push ecx
0041ED86 |. 8D8C24 040100>lea ecx,dword ptr ss:[esp+0x104]
0041ED8D |. 51 push ecx
0041ED8E |. 52 push edx
0041ED8F |. E8 3CFEFFFF call _IceAge.0041EBD0 ; 把假码进行MD5加密
0041ED94 |. B0 36 mov al,0x36
0041ED96 |. B2 2E mov dl,0x2E
0041ED98 |. 884424 2C mov byte ptr ss:[esp+0x2C],al
0041ED9C |. 884424 37 mov byte ptr ss:[esp+0x37],al
0041EDA0 |. B0 F7 mov al,0xF7
0041EDA2 |. B3 88 mov bl,0x88
0041EDA4 |. B1 E5 mov cl,0xE5
0041EDA6 |. 83C4 0C add esp,0xC
0041EDA9 |. C64424 21 B6 mov byte ptr ss:[esp+0x21],0xB6
0041EDAE |. C64424 22 A0 mov byte ptr ss:[esp+0x22],0xA0
……省略N行代码……
0041F35D |. C68424 FE0000>mov byte ptr ss:[esp+0xFE],0xF
0041F365 |. C68424 FF0000>mov byte ptr ss:[esp+0xFF],0xC5
0041F36D |. 33C0 xor eax,eax
0041F36F |. 8D5424 20 lea edx,dword ptr ss:[esp+0x20]
0041F373 |> B9 04000000 /mov ecx,0x4
0041F378 |. 8BFA |mov edi,edx
0041F37A |. 8DB424 000100>|lea esi,dword ptr ss:[esp+0x100]
0041F381 |. 33ED |xor ebp,ebp
0041F383 |. F3:A7 |repe cmps dword ptr es:[edi],dword ptr d>; 循环对比黑名单
0041F385 |.^ 0F84 D5F9FFFF |je _IceAge.0041ED60 ; 如果假码的MD5和上述黑名单一致,则注册失败
0041F38B |. 40 |inc eax
0041F38C |. 83C2 10 |add edx,0x10
0041F38F |. 83F8 0E |cmp eax,0xE
0041F392 |.^ 72 DF \jb short _IceAge.0041F373
0041F394 |. 8D8424 000100>lea eax,dword ptr ss:[esp+0x100]
0041F39B |. 50 push eax
0041F39C |. E8 BFF7FFFF call _IceAge.0041EB60
0041F3A1 |. 83C4 04 add esp,0x4
0041F3A4 |. 85C0 test eax,eax
0041F3A6 |. 74 10 je short _IceAge.0041F3B8
0041F3A8 |. 5F pop edi ; _IceAge.004115FF
0041F3A9 |. 5E pop esi ; _IceAge.004115FF
0041F3AA |. 5D pop ebp ; _IceAge.004115FF
0041F3AB |. B8 01000000 mov eax,0x1
0041F3B0 |. 5B pop ebx ; _IceAge.004115FF
0041F3B1 |. 81C4 44010000 add esp,0x144
0041F3B7 |. C3 retn
0041F3B8 |> 8D8C24 000100>lea ecx,dword ptr ss:[esp+0x100]
0041F3BF |. 6A 0C push 0xC
0041F3C1 |. 8D9424 180100>lea edx,dword ptr ss:[esp+0x118]
0041F3C8 |. 51 push ecx
0041F3C9 |. 52 push edx
0041F3CA |. E8 01F8FFFF call _IceAge.0041EBD0 ; 又来MD5计算
0041F3CF |. 83C4 0C add esp,0xC
0041F3D2 |. B9 04000000 mov ecx,0x4
0041F3D7 |. 8D7C24 10 lea edi,dword ptr ss:[esp+0x10]
0041F3DB |. 8DB424 000100>lea esi,dword ptr ss:[esp+0x100]
0041F3E2 |. 33C0 xor eax,eax
0041F3E4 |. C64424 10 32 mov byte ptr ss:[esp+0x10],0x32
0041F3E9 |. C64424 11 E1 mov byte ptr ss:[esp+0x11],0xE1
……省略N行代码……
0041F462 |. 51 push ecx
0041F463 |. 52 push edx
0041F464 |. E8 67F7FFFF call _IceAge.0041EBD0 ; 继续MD5
0041F469 |. 8B8424 1B0100>mov eax,dword ptr ss:[esp+0x11B]
0041F470 |. 8B8C24 180100>mov ecx,dword ptr ss:[esp+0x118]
0041F477 |. 8B9424 150100>mov edx,dword ptr ss:[esp+0x115]
0041F47E |. 25 FF000000 and eax,0xFF
0041F483 |. C1E0 04 shl eax,0x4
0041F486 |. 81E1 FF000000 and ecx,0xFF
0041F48C |. 81E2 FF000000 and edx,0xFF
0041F492 |. 0BC1 or eax,ecx
0041F494 |. 8B8C24 120100>mov ecx,dword ptr ss:[esp+0x112]
0041F49B |. C1E0 05 shl eax,0x5
0041F49E |. 0BC2 or eax,edx
0041F4A0 |. 8B9424 0F0100>mov edx,dword ptr ss:[esp+0x10F]
0041F4A7 |. C1E0 05 shl eax,0x5
0041F4AA |. 81E1 FF000000 and ecx,0xFF
0041F4B0 |. 81E2 FF000000 and edx,0xFF
0041F4B6 |. 0BC1 or eax,ecx
0041F4B8 |. 8B8C24 0C0100>mov ecx,dword ptr ss:[esp+0x10C]
0041F4BF |. C1E0 05 shl eax,0x5
0041F4C2 |. 0BC2 or eax,edx
0041F4C4 |. 81E1 FF000000 and ecx,0xFF
0041F4CA |. C1E0 05 shl eax,0x5
0041F4CD |. 83C4 0C add esp,0xC
0041F4D0 |. 0BC1 or eax,ecx
0041F4D2 |. 33D2 xor edx,edx
0041F4D4 |. 83F8 FF cmp eax,-0x1
0041F4D7 |. 5F pop edi ; _IceAge.004115FF
0041F4D8 |. 5E pop esi ; _IceAge.004115FF
0041F4D9 |. 0F94C2 sete dl
0041F4DC |. 5D pop ebp ; _IceAge.004115FF
0041F4DD |. 8BC2 mov eax,edx
0041F4DF |. 5B pop ebx ; _IceAge.004115FF
0041F4E0 |. 81C4 44010000 add esp,0x144
0041F4E6 \. C3 retn
这个算法过程看似很复杂,没有多去分析。只知道结果必须是 EAX返回1。
把上述那个CALL定为 关键CALL 1,返回后,回到以下代码:
0042231F |> \E8 0CCAFFFF call _IceAge.0041ED30 ; 关键CALL 1
00422324 |. 85C0 test eax,eax
00422326 |. 74 05 je short _IceAge.0042232D
00422328 |. E8 83BBFFFF call _IceAge.0041DEB0 ; 关键CALL 2
0042232D |> A1 CC664500 mov eax,dword ptr ds:[0x4566CC]
00422332 |. 8B0D D8124600 mov ecx,dword ptr ds:[0x4612D8]
00422338 |. 48 dec eax
00422339 |. 3BC8 cmp ecx,eax
0042233B |. 75 0D jnz short _IceAge.0042234A
0042233D |. 68 80EE3600 push 0x36EE80
00422342 |. E8 09FFFFFF call _IceAge.00422250
00422347 |. 83C4 04 add esp,0x4
0042234A |> E8 51FFFFFF call _IceAge.004222A0
0042234F |. A3 0C134600 mov dword ptr ds:[0x46130C],eax
00422354 |. 33C0 xor eax,eax
00422356 \. C3 retn
进入关键CALL 2后,发现一个非常爽的东西。
0041DEB0 /$ 83EC 50 sub esp,0x50
0041DEB3 |. A0 A8034600 mov al,byte ptr ds:[0x4603A8]
0041DEB8 |. 57 push edi ; ntdll.7C930228
0041DEB9 |. 884424 04 mov byte ptr ss:[esp+0x4],al
0041DEBD |. B9 13000000 mov ecx,0x13
0041DEC2 |. 33C0 xor eax,eax
0041DEC4 |. 8D7C24 05 lea edi,dword ptr ss:[esp+0x5]
0041DEC8 |. F3:AB rep stos dword ptr es:[edi]
0041DECA |. 66:AB stos word ptr es:[edi]
0041DECC |. AA stos byte ptr es:[edi]
0041DECD |. A1 DC124600 mov eax,dword ptr ds:[0x4612DC]
0041DED2 |. 85C0 test eax,eax
0041DED4 |. 74 0A je short _IceAge.0041DEE0
0041DED6 |. B8 01000000 mov eax,0x1
0041DEDB |. 5F pop edi ; _IceAge.004115FF
0041DEDC |. 83C4 50 add esp,0x50
0041DEDF |. C3 retn
0041DEE0 |> 8D4C24 04 lea ecx,dword ptr ss:[esp+0x4]
……省略N行代码……
0041DF11 |. 74 0F je short _IceAge.0041DF22
0041DF13 |. B8 01000000 mov eax,0x1
0041DF18 |. 5F pop edi ; _IceAge.004115FF
0041DF19 |. A3 DC124600 mov dword ptr ds:[0x4612DC],eax ; 好东西在这里,全局注册标志!!I like it!
0041DF1E |. 83C4 50 add esp,0x50
0041DF21 |. C3 retn
0041DF22 |> 6A 10 push 0x10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
0041DF24 |. 68 50674500 push _IceAge.00456750 ; |Title = "Plugin"
0041DF29 |. 68 58674500 push _IceAge.00456758 ; |Text = "Decryption error. Please re-install application and contact with AEE support ()."
0041DF2E |. 6A 00 push 0x0 ; |hOwner = NULL
0041DF30 |. FF15 40024500 call dword ptr ds:[<&user32.MessageBoxA>] ; \MessageBoxA
0041DF36 |> 33C0 xor eax,eax
0041DF38 |. 5F pop edi ; _IceAge.004115FF
0041DF39 |. 83C4 50 add esp,0x50
0041DF3C \. C3 retn
那个非常爽的东西就是0041DF19句中的 地址:0x4612DC
这是个全局变量,保存注册标志,为1是表示已经注册,0为未注册。
这真正我没有分析算法的原因。
解决办法只需要把这个值赋值为1即可。于是直接在 关键CALL 1 的最前面
直接把这个标志位赋值为1即可。
修改位置及代码如下:
0041ED30 B8 01000000 mov eax,0x1
0041ED35 8946 18 mov dword ptr ds:[0x4612DC],eax
0041ED38 C3 retn
保存修改为新文件,运行后NAG窗口已经不见,而且已经注册成功。
2012年04月03日 12:40:40