KuNgBiM的UnPaCkIt脱壳
日期:2005年3月18日 脱壳人:csjwaman[DFCG]
―――――――――――――――――――――――――――――――――――――――――――
【软件名称】:KuNgBiM的UnPaCkIt
【软件大小】: KB
【下载地址】:见附件。
【脱壳声明】:初学Crack,只是感兴趣,没有其它目的。失误之处敬请诸位大侠赐教!
【操作系统】:win2k
【脱壳工具】:OD等传统工具
―――――――――――――――――――――――――――――――――――――――――――
【脱壳过程】:
KuNgBiM的UnPaCkIt是hying旧壳修改壳,我的感觉是变化不大,只是在反跟踪和IAT加密上作了修改。也许是我没发现:)
下面就来脱它吧。
一、找入口:
用OD载入,忽略所有异常,然后bp VirtualAlloc,运行程序后断在:
77E7E845 > 55 push ebp///断在函数入口。 ; NOTEPAD.<ModuleEntryPoint>
77E7E846 8BEC mov ebp,esp
77E7E848 FF75 14 push dword ptr ss:[ebp+14]
77E7E84B FF75 10 push dword ptr ss:[ebp+10]
77E7E84E FF75 0C push dword ptr ss:[ebp+C]
77E7E851 FF75 08 push dword ptr ss:[ebp+8]
77E7E854 6A FF push -1
77E7E856 E8 1B000000 call KERNEL32.VirtualAllocEx
77E7E85B 5D pop ebp
77E7E85C C2 1000 retn 10
取消断点后,ALT+F9返回:
01010174 50 push eax///返回到这里。
01010175 8985 BB000000 mov dword ptr ss:[ebp+BB],eax
0101017B 8B9D 8F000000 mov ebx,dword ptr ss:[ebp+8F]
01010181 03DD add ebx,ebp
01010183 50 push eax
01010184 53 push ebx
01010185 E8 05000000 call NOTEPAD.0101018F
0101018A 5A pop edx
0101018B 52 push edx
0101018C 55 push ebp
0101018D FFE2 jmp edx
现在往下找,一直来到:
0101021F E8 EEFFFFFF call NOTEPAD.01010212
01010224 13C9 adc ecx,ecx
01010226 E8 E7FFFFFF call NOTEPAD.01010212
0101022B ^ 72 F2 jb short NOTEPAD.0101021F
0101022D C3 retn
0101022E 2B7C24 28 sub edi,dword ptr ss:[esp+28]
01010232 897C24 1C mov dword ptr ss:[esp+1C],edi
01010236 61 popad
01010237 C2 0800 retn 8////在这里F2下断。
在01010237断下2次后,看到返回地址为00283055。此时解码结束。F8返回:
00283055 8B0C2B mov ecx,dword ptr ds:[ebx+ebp]////返回这里。
00283058 56 push esi
00283059 F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[es>
0028305B 5E pop esi
0028305C 53 push ebx
0028305D 68 00800000 push 8000
00283062 6A 00 push 0
00283064 56 push esi
00283065 FF95 00070000 call dword ptr ss:[ebp+700]
0028306B 5B pop ebx
一直往下找,来到:
002832CC /EB 05 jmp short 002832D3
002832CE |5D pop ebp
002832CF |5B pop ebx
002832D0 |59 pop ecx
002832D1 |5A pop edx
002832D2 |5E pop esi
002832D3 -\FFE0 jmp eax////找到这里。直接F4下来,程序停下时EAX=01006420。这就是入口了。 ; NOTEPAD.01006420
002832D5 50 push eax
002832D6 60 pushad
002832D7 E8 06000000 call 002832E2
002832DC 8B6424 08 mov esp,dword ptr ss:[esp+8]
F7来到:
01006420 FFD7 call edi////入口。入口代码被偷了! ; NOTEPAD.01006422
01006422 58 pop eax
01006423 6A FF push -1
01006425 68 88180001 push NOTEPAD.01001888
0100642A 68 D0650001 push NOTEPAD.010065D0
0100642F 64:A1 00000000 mov eax,dword ptr fs:[0]
01006435 50 push eax
01006436 64:8925 00000000 mov dword ptr fs:[0],esp
0100643D 83C4 98 add esp,-68
01006440 53 push ebx
01006441 56 push esi
01006442 57 push edi
01006443 8965 E8 mov dword ptr ss:[ebp-18],esp
01006446 C745 FC 00000000 mov dword ptr ss:[ebp-4],0
0100644D 6A 02 push 2
0100644F 90 nop
01006450 E8 80CE27FF call 002832D5
01006455 83C4 04 add esp,4
01006458 C705 38990001 FFFF>mov dword ptr ds:[1009938],-1
01006462 C705 3C990001 FFFF>mov dword ptr ds:[100993C],-1
0100646C 90 nop
0100646D E8 63CE27FF call 002832D5
01006472 8B0D 44880001 mov ecx,dword ptr ds:[1008844]
01006478 8908 mov dword ptr ds:[eax],ecx
0100647A 90 nop
0100647B E8 55CE27FF call 002832D5
到入口后可以发现不少CALL 002832D5之类的指令。从前面的跟踪可知002832D5是壳中的地址。其实就是加密了IAT。
二、解密IAT:
进入01006450 处的CALL 002832D5:
0002832D5 50 push eax
002832D6 60 pushad
002832D7 E8 06000000 call 002832E2
002832DC 8B6424 08 mov esp,dword ptr ss:[esp+8]
002832E0 EB 20 jmp short 00283302
002832E2 64:FF35 00000000 push dword ptr fs:[0]
002832E9 64:8925 00000000 mov dword ptr fs:[0],esp
002832F0 9C pushfd
002832F1 810C24 00010000 or dword ptr ss:[esp],100
002832F8 9D popfd
002832F9 90 nop
002832FA 64:8F05 00000000 pop dword ptr fs:[0]
00283301 - E9 648F0500 jmp 002DC26A
00283306 0000 add byte ptr ds:[eax],al
00283308 0058 E8 add byte ptr ds:[eax-18],bl
0028330B 04 00 add al,0
0028330D 0000 add byte ptr ds:[eax],al
0028330F 68 2D28005D push 5D00282D
00283314 8B6D 00 mov ebp,dword ptr ss:[ebp]
00283317 8B7C24 24 mov edi,dword ptr ss:[esp+24]
0028331B 8BB5 AF060000 mov esi,dword ptr ss:[ebp+6AF]
00283321 03F5 add esi,ebp
00283323 8B06 mov eax,dword ptr ds:[esi]
00283325 33D2 xor edx,edx
00283327 B9 02000000 mov ecx,2
0028332C F7E1 mul ecx
0028332E D1E8 shr eax,1
00283330 0385 83060000 add eax,dword ptr ss:[ebp+683]
00283336 2B85 8F060000 sub eax,dword ptr ss:[ebp+68F]
0028333C 3BF8 cmp edi,eax
0028333E 75 0A jnz short 0028334A
00283340 0AD2 or dl,dl
00283342 75 04 jnz short 00283348
00283344 EB 09 jmp short 0028334F
00283346 EB 02 jmp short 0028334A
00283348 EB 2F jmp short 00283379
0028334A 83C6 08 add esi,8
0028334D ^ EB D4 jmp short 00283323
0028334F 8B46 04 mov eax,dword ptr ds:[esi+4]///ds:[00284104]=EFA06354 eax=01006455 (NOTEPAD.01006455)
00283352 03BD 8F060000 add edi,dword ptr ss:[ebp+68F]
00283358 2BBD 83060000 sub edi,dword ptr ss:[ebp+683]
0028335E 2BC7 sub eax,edi///相减。edi=01006455 (NOTEPAD.01006455) eax=EFA06354
00283360 F7D0 not eax///取反
00283362 C1C0 10 rol eax,10///循环左移
00283365 0385 83060000 add eax,dword ptr ss:[ebp+683]
0028336B 2B85 8F060000 sub eax,dword ptr ss:[ebp+68F]
00283371 8B00 mov eax,dword ptr ds:[eax]///ds:[01001160]=7800513A (msvcrt.__set_app_type) eax=01001160 (NOTEPAD.01001160), ASCII ":Q"
00283373 894424 20 mov dword ptr ss:[esp+20],eax
00283377 61 popad
00283378 C3 retn///返回到函数入口!
从以上代码可以看出,IAT加密其实也很简单。只是相减-取反-循环左移而已。现在的问题是上面的EAX和EDI中的数据是哪里来的?如果弄清了这个问题,则解密IAT就迎刃而解了。
重新载入程序,在DUMP区01006450处的4个字节上下内存访问断点(不能下硬件断点!)。
F9,断下:
0028321C 8DB5 6D050000 lea esi,dword ptr ss:[ebp+56D]
00283222 8B07 mov eax,dword ptr ds:[edi]////取地址放入EAX=01006455。此时EDI=284100。
00283224 0BC0 or eax,eax
00283226 75 02 jnz short 0028322A
00283228 EB 1D jmp short 00283247
0028322A 25 FFFFFF7F and eax,7FFFFFFF
0028322F 0385 83060000 add eax,dword ptr ss:[ebp+683]
00283235 2B85 8F060000 sub eax,dword ptr ss:[ebp+68F]
0028323B 8BDE mov ebx,esi
0028323D 2BD8 sub ebx,eax
0028323F 8958 FC mov dword ptr ds:[eax-4],ebx////断在这里。
00283242 83C7 08 add edi,8
00283245 ^ EB DB jmp short 00283222////跳回继续。
00283247 64:FF35 30000000 push dword ptr fs:[30]
断下时EBX=FF27CE80 EAX=01006455 EDI=284100。显然程序正准备将加密后的数据移入该地址。看来这里就是关键处了!
到DUMP区284100处看看:
00284100 55 64 00 01 54 63 A0 EF Ud.Tc_?
还记得前面的问题吗-EAX和EDI的数据是哪里来的?看到DUMP区该知道了吧:)
下面来PATH:
重新载入程序,然后bp VirtualAlloc,在01010237处断下2次后,返回,CTRL+G来到:
0028322A 25 FFFFFF7F and eax,7FFFFFFF////从此处开始PATH。
0028322F 0385 83060000 add eax,dword ptr ss:[ebp+683]
00283235 2B85 8F060000 sub eax,dword ptr ss:[ebp+68F]
0028323B 8BDE mov ebx,esi
0028323D 2BD8 sub ebx,eax
0028323F 8958 FC mov dword ptr ds:[eax-4],ebx
00283242 83C7 08 add edi,8
00283245 ^ EB DB jmp short 00283222
00283247 64:FF35 30000000 push dword ptr fs:[30]
0028324E 58 pop eax
修改为:
0028322A /E9 D11B0000 jmp 00284E00
下面是我写的憋脚Path代码:
00284E00 807F 03 01 cmp byte ptr ds:[edi+3],1////比较最高位是否为1。原因不再解释。
00284E04 75 1C jnz short 00284E22
00284E06 53 push ebx///借用一下:)
00284E07 8B47 04 mov eax,dword ptr ds:[edi+4]////加密数据之一移入EAX。
00284E0A 2B07 sub eax,dword ptr ds:[edi]///相当于0028335E处的sub eax,edi。
00284E0C F7D0 not eax///取反。
00284E0E C1C0 10 rol eax,10///循环左移。
00284E11 8B1F mov ebx,dword ptr ds:[edi]///调用地址入EBX。
00284E13 66:C743 FA FF15 mov word ptr ds:[ebx-6],15FF///加入指令CALL[XXXXXXXX]
00284E19 8943 FC mov dword ptr ds:[ebx-4],eax///正确的跳转地址移入正确的调用地址。
00284E1C 5B pop ebx///归还。
00284E1D ^ E9 20E4FFFF jmp 00283242////跳回继续。
00284E22 53 push ebx///借用一下:)
00284E23 8B1F mov ebx,dword ptr ds:[edi]///先要处理一下最高位。
00284E25 81E3 FFFFFF7F and ebx,7FFFFFFF////取消最高位。
00284E2B 891F mov dword ptr ds:[edi],ebx
00284E2D 8B47 04 mov eax,dword ptr ds:[edi+4]
00284E30 2B07 sub eax,dword ptr ds:[edi]
00284E32 F7D0 not eax
00284E34 C1C0 10 rol eax,10
00284E37 8B1F mov ebx,dword ptr ds:[edi]
00284E39 66:C743 FA FF25 mov word ptr ds:[ebx-6],25FF////加入指令JMP[XXXXXXXX]
00284E3F 8943 FC mov dword ptr ds:[ebx-4],eax
00284E42 5B pop ebx
00284E43 ^ E9 FAE3FFFF jmp 00283242////跳回继续。
二进制数据:
80 7F 03 01 75 1C 53 8B 47 04 2B 07 F7 D0 C1 C0 10 8B 1F 66 C7 43 FA FF 15 89 43 FC 5B E9 20 E4
FF FF 53 8B 1F 81 E3 FF FF FF 7F 89 1F 8B 47 04 2B 07 F7 D0 C1 C0 10 8B 1F 66 C7 43 FA FF 25 89
43 FC 5B E9 FA E3 FF FF
按上述方法PATH后就可以到入口修复入口代码并DUMP了,然后用ImportREC修复就OK了。如果将DUMP文件的最后一个区段删除再修复IAT将会失去图标,但可以正常运行。
三、查找被偷代码:
重新载入后在壳的入口处:
01010000 > 56 push esi
01010001 52 push edx
01010002 51 push ecx
01010003 53 push ebx
01010004 55 push ebp
01010005 E8 15010000 call NOTEPAD.0101011F
0101000A 3200 xor al,byte ptr ds:[eax]
此时观察寄存器数据,ESP=0006FFC4。
重复上面的步骤,在01010237处断下2次后,F8返回后,根据堆栈平衡原理,在0006FFC0处的四个字节下硬件访问双字节断点。然后F9运行。
002832B5 55 push ebp///断下!被偷代码第一行。
002832B6 8BEC mov ebp,esp///被偷代码第二行。
002832B8 EB 19 jmp short 002832D3
002832BA 83FB 02 cmp ebx,2
002832BD 75 0F jnz short 002832CE
002832BF 8BC5 mov eax,ebp
002832C1 5D pop ebp
002832C2 5B pop ebx
002832C3 59 pop ecx
002832C4 5A pop edx
找到被偷代码后就可以恢复了。
附件:pack.rar
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)