KuNgBiM的UnPaCkIt脱壳
附件:pack.rar

 
     日期: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

找到被偷代码后就可以恢复了。