主程序: メインプログラム
子程序: プログラム
程序段: プログラム
执行程序: プログラム执行
程序号: プログラムコード
程序运行过程中,出现报警。:プログラム実行中エラー
【使用工具】 OllyDbg,PEid,LoadPE【破解平台】 Win2K+SP4
【软件名称】 大嘴日语 5.0
【软件简介】 大嘴日语 融合了【逆向学习法】和【疯狂英语】这两种有效的英语学习方法的精髓,
并加以创新,集日语的【听、说、读、写、背、查】功能于一身, 解决了困扰国人的学习日语难的问题。
是一款集日语口语、日语背单词综合教育软件。
【加壳方式】 EXEStealth 2.75a + ASPack + UPX
开始调试前,最好把OLLYDBG.EXE改名为CMD.EXE因为壳里面有些代码是检测父进程的,如下:
0123CCA0813F 434D442E cmp dword ptr ds:[edi],2E444D43 [EDI]是检测父程序名字, 0x43,0x4D,0x44,0x2E的ASCII字符是"CMD."
0123CCA674 3B je short BmJapane.0123CCE3 父程序不是CMD.EXE,就不跳,接着就OVER了 修改ZF寄存器为1
0123CCA890 nop
0123CCA990 nop
0123CCAA90 nop
0123CCAB90 nop
0123CCAC83EE 0C sub esi,0C
0123CCAFAD lods dword ptr ds:[esi]
0123CCB00306add eax,dword ptr ds:[esi]
0123CCB20346 04 add eax,dword ptr ds:[esi+4]
0123CCB58BD8mov ebx,eax
0123CCB78DB5 A1194100 lea esi,dword ptr ss:[ebp+4119A1]
0123CCBDAD lods dword ptr ds:[esi]
0123CCBE0BC0or eax,eax
0123CCC074 0E je short BmJapane.0123CCD0
0123CCC290 nop
0123CCC390 nop
0123CCC490 nop
0123CCC590 nop
0123CCC62BC3sub eax,ebx
0123CCC874 19 je short BmJapane.0123CCE3
0123CCCA90 nop
0123CCCB90 nop
0123CCCC90 nop
0123CCCD90 nop
0123CCCE ^ EB ED jmp short BmJapane.0123CCBD
0123CCD0B8 90010000 mov eax,190
0123CCD5E8 C6EFFFFF call BmJapane.0123BCA0
0123CCDA8DBD 69324000 lea edi,dword ptr ss:[ebp+403269]
0123CCE003F8add edi,eax
0123CCE2AB stos dword ptr es:[edi] 若是前面不跳的话,到这里调试器就会无法处理异常,进程退出
0123CCE3FFB5 30FE4000 push dword ptr ss:[ebp+40FE30] 跳到这里
0123CCE950 push eax
另把同目录下的Config.ini文件备份一个,当出来说文件不完整要重新安装程序的时候
把备份文件覆盖了Config文件就行了
---------------------------------------------------------------------------------------------------------
用OD载入程序,停在这里:(第一层壳 EXEStealth)
0124A060 >/EB 58 jmp short BmJapane.0124A0BA
0124A062 |53 push ebx
0124A063 |68 61726577 push 77657261
0124A068 |61 popad
0124A069 |72 65 jb short BmJapane.0124A0D0
忽略除内存异常外的所有异常,经过5个内存异常(按4次Shift+F9)后来到这里:
0078700D64:8925 0000000>mov dword ptr fs:[0],esp
0078701433C0xor eax,eax
007870168908mov dword ptr ds:[eax],ecx 内存异常
007870180000add byte ptr ds:[eax],al
0078701A0000add byte ptr ds:[eax],al
此时的堆栈是:
0012FFBC FFFFFFFF End of SEH chain
0012FFC0 00D9DAA8 SE handler
0012FFC4 7C4E87F5 RETURN to kernel32.7C4E87F5
0012FFC8 005616A8 BmJapane.005616A8
在D9DAA8上下断点,按Shift+F9
00D9DAA8B8 A7C8D9F0 mov eax,F0D9C8A7
00D9DAAD8D88 24120010 lea ecx,dword ptr ds:[eax+10001224]
00D9DAB38941 01 mov dword ptr ds:[ecx+1],eax
00D9DAB68B5424 04 mov edx,dword ptr ss:[esp+4]
00D9DABA8B52 0C mov edx,dword ptr ds:[edx+C]
00D9DABDC602 E9 mov byte ptr ds:[edx],0E9
00D9DAC083C2 05 add edx,5
00D9DAC32BCAsub ecx,edx
00D9DAC5894A FC mov dword ptr ds:[edx-4],ecx
00D9DAC833C0xor eax,eax
00D9DACAC3 retn
走到RETN后,看原地址的代码:
0078700D64:8925 0000000>mov dword ptr fs:[0],esp
0078701433C0xor eax,eax
00787016 - E9 B06A6100 jmp BmJapane.00D9DACB在这里下断点,程序断在这里,然后把标志寄存器的TP置0,继续运行
0078701B0000add byte ptr ds:[eax],al
0078701D0000add byte ptr ds:[eax],al
00D9DACAC3 retn
00D9DACBB8 A7C8D9F0 mov eax,F0D9C8A7 原来跳到这里了
00D9DAD064:8F05 0000000>pop dword ptr fs:[0]
00D9DAD783C4 04 add esp,4
00D9DADA55 push ebp
00D9DADB53 push ebx
00D9DADC51 push ecx
00D9DADD57 push edi
00D9DADE56 push esi
00D9DADF52 push edx
00D9DAE08D98 DD110010 lea ebx,dword ptr ds:[eax+100011DD]
一直走到这里:
00D9DB705E pop esi
00D9DB715F pop edi
00D9DB7259 pop ecx
00D9DB735B pop ebx
00D9DB745D pop ebp
00D9DB75 - FFE0jmp eax EAX=B55001
---------------------------------------------------------------------------------------------------------
又跳到下一层去了,貌似是ASPack壳
00B5500160 pushad
00B55002E8 03000000 call BmJapane.00B5500A
00B55007 - E9 EB045D45 jmp 461254F7
00B5500C55 push ebp
00B5500DC3 retn
00B5500EE8 01000000 call BmJapane.00B55014
00B55013EB 5D jmp short BmJapane.00B55072
直接用Ctrl+S来找popad
来到这里:
00B553A98985 A8030000 mov dword ptr ss:[ebp+3A8],eax
00B553AF61 popad
00B553B075 08 jnz short BmJapane.00B553BA
00B553B2B8 01000000 mov eax,1
00B553B7C2 0C00 retn 0C
00B553BA68 00000000 push 0 运行到这里会变成push 90fc10
00B553BFC3 retn
---------------------------------------------------------------------------------------------------------
到达下一层壳,是UPX壳
0090FC1060 pushad
0090FC11BE 00707800 mov esi,BmJapane.00787000
0090FC168DBE 00A0C7FF lea edi,dword ptr ds:[esi+FFC7A000]
0090FC1C57 push edi
0090FC1D83CD FF or ebp,FFFFFFFF
0090FC20EB 10 jmp short BmJapane.0090FC32
0090FC2290 nop
0090FC2390 nop
0090FC2490 nop
0090FC2590 nop
0090FC2690 nop
0090FC2790 nop
0090FC288A06mov al,byte ptr ds:[esi]
0090FC2A46 inc esi
0090FC2B8807mov byte ptr ds:[edi],al
0090FC2D47 inc edi
0090FC2E01DBadd ebx,ebx
0090FC3075 07 jnz short BmJapane.0090FC39
同样往下找popad,找到如下:
0090FD9B66:8B07 mov ax,word ptr ds:[edi]
0090FD9E83C7 02 add edi,2
0090FDA1 ^ EB E2 jmp short BmJapane.0090FD85
0090FDA361 popad
0090FDA4 ^ E9 8B1DD7FF jmp BmJapane.00681B34
---------------------------------------------------------------------------------------------------------
到达程序的OPE了,用OllDump把程序DUMP出来,用LordPE来DUMP也行,不过要用IR修复一下IAT
00681B3455 push ebp
00681B358BECmov ebp,esp
00681B3783C4 F0 add esp,-10
00681B3A53 push ebx
00681B3BB8 9C146800 mov eax,BmJapane.0068149C
00681B40E8 175DD8FF call BmJapane.0040785C
00681B458B1D D0906800 mov ebx,dword ptr ds:[6890D0]BmJapane.0068AC18
00681B4B8B03mov eax,dword ptr ds:[ebx]
00681B4DE8 CE22E1FF call BmJapane.00493E20
00681B528B03mov eax,dword ptr ds:[ebx]
00681B54BA 7C1E6800 mov edx,BmJapane.00681E7C
00681B59E8 AA1EE1FF call BmJapane.00493A08
00681B5E8B0Bmov ecx,dword ptr ds:[ebx]
---------------------------------------------------------------------------------------------------------
运行一下,程序报错
"Access violation at address 1000100A. Read of address 1000100A."
用LordPE看看内存空间:
ListView的Item总数: 26
-------------------------
Path ImageBase ImageSize
-------------------------------------------------------------------------------
d:\bmjapanese\bmjapanese.exe 00400000 00001000
c:\winnt\system32\ntdll.dll 77F80000 0007B000
c:\winnt\system32\kernel32.dll 7C4E0000 000B9000
c:\winnt\system32\user32.dll 77E10000 00065000
c:\winnt\system32\gdi32.dll 77F40000 0003C000
c:\winnt\system32\imm32.dll 75E60000 0001A000
c:\winnt\system32\advapi32.dll 7C2D0000 00062000
c:\winnt\system32\rpcrt4.dll 77D30000 00071000
d:\bmjapanese\data\data.dat 10000000 00037000
c:\winnt\system32\comctl32.dll 71710000 00084000
c:\winnt\system32\comdlg32.dll 76B30000 0003E000
c:\winnt\system32\shlwapi.dll70BD0000 00065000
c:\winnt\system32\msvcrt.dll 78000000 00045000
c:\winnt\system32\shell32.dll782F0000 00248000
c:\winnt\system32\hhctrl.ocx 5D300000 00080000
c:\winnt\system32\ole32.dll 77A50000 000F7000
c:\winnt\system32\oleaut32.dll 779B0000 0009B000
c:\winnt\system32\msacm32.dll77410000 00013000
c:\winnt\system32\winmm.dll 77570000 00030000
c:\winnt\system32\version.dll77820000 00007000
c:\winnt\system32\lz32.dll 759B0000 00006000
c:\winnt\system32\winspool.drv 77800000 0001E000
c:\winnt\system32\mpr.dll76620000 00011000
c:\winnt\system32\wsock32.dll75050000 00008000
c:\winnt\system32\ws2_32.dll 75030000 00014000
c:\winnt\system32\ws2help.dll75020000 00008000
地址是data.dat的空间,用PEID一查,是个ASPack壳的DLL文件,查输出表,只有两个函数,
分别是HDSerialNumRead和WEP
还差一个DLL没有LOAD进去,当然会出错了.
重新载入原文件,下LoadLibraryA断点,经过几次后,断在这里:
0124087353 push ebx
01240874FF95 94E24100 call dword ptr ss:[ebp+41E294] LoadLibraryA .dat\data\data.dat
0124087A0BC0or eax,eax
0124087C75 34 jnz short BmJapane.012408B2
然后来到这里:
0124094153 push ebx
01240942FFB5 17FC4000 push dword ptr ss:[ebp+40FC17]
01240948FF95 8CE24100 call dword ptr ss:[ebp+41E28C] kernel32.GetProcAddress
0124094E3B9D 1FFC4000 cmp ebx,dword ptr ss:[ebp+40FC1F]
得到HDSerialNumRead的地址
用Alt+M,打开内存镜像,
在10001000处按F2下断点,取消刚才的LoadLibraryA断点,按F9,来到这里
10001003CC int3
10001004CC int3
10001005E9 66010000 jmp data.10001170
1000100A > E9 310B0000 jmp data.10001B40 -|jmp
1000100F > E9 3C0C0000 jmp data.10001C50
10001014E9 C7030000 jmp data.100013E0
10001019E9 52000000 jmp data.10001070
1000101EE9 0D020000 jmp data.10001230
10001023E9 78080000 jmp data.100018A0
10001028E9 93020000 jmp data.100012C0
1000102DE9 BE040000 jmp data.100014F0
10001032E9 89070000 jmp data.100017C0
10001037CC int3
10001038CC int3
----------------------------------------------------|
10001B4055 push ebp
10001B418BECmov ebp,esp
10001B4381EC D4070000 sub esp,7D4
10001B4953 push ebx
10001B4A56 push esi
按CTRL+F9,然后返回主程序:
0059C5678D45 C4 lea eax,dword ptr ss:[ebp-3C]
0059C56AE8 518AE6FF call BmJapane.00404FC0
0059C56FE8 D0F1FFFF call BmJapane.0059B744 jmp to data.HDSerialNumRead
0059C5748BD0mov edx,eax
0059C5768D45 C4 lea eax,dword ptr ss:[ebp-3C]
原来CALL 59B744是data.HDSerialNumRead的函数的地址CALL,直接到上面看看:
0059B744 - FF25 2CCC6800 jmp dword ptr ds:[68CC2C]data.HDSerialNumRead
嗯,只要把68CC20填充为正确的地址就可以了
用OD载入DUMP出来的程序,下断点LoadLibraryA,程序中断后按Alt+F9返回用户代码:
0047E97B /0F85 EE000000 jnz oll.0047EA6F
0047E981 |68 ACEA4700 push oll.0047EAACASCII "imm32.dll"
0047E986 |E8 D594F8FF call <jmp.&kernel32.LoadLibraryA>
0047E98B |A3 88326800 mov dword ptr ds:[683288],eaxIMM32.75E60000
0047E990 |833D 88326800 0>cmp dword ptr ds:[683288],0
0047E997 |0F84 D2000000 je oll.0047EA6F
往下找代码,找到出口处:
0047EA8D5B pop ebx USER32.77E10000
0047EA8E59 pop ecx
0047EA8F5D pop ebp
0047EA90C3 retn
0047EA910000add byte ptr ds:[eax],al
找一个地方加上自己的代码:
区块ExeS已经不用了,正好用来写代码:
注:LoadLibraryA的CALL是"call 00407E60" GetProcAddress的CALL是"call 00407D50"
情况不同者要相应作出修改.
0047EA8D - E9 6EB5DC00 jmp oll.0124A000
0047EA92C3 retn
0124A00068 30A02401 push oll.0124A030ASCII ".\data\Data.dat"
0124A005E8 56DE1BFF call <jmp.&kernel32.LoadLibraryA>
0124A00A68 40A02401 push oll.0124A040ASCII "HDSerialNumRead"
0124A00F50 push eax EAX是LoadLibraryA后的DLL句柄
0124A010E8 3BDD1BFF call <jmp.&kernel32.GetProcAddress>
0124A015A3 2CCC6800 mov dword ptr ds:[68CC2C],eax
0124A01A5B pop ebx
0124A01B59 pop ecx
0124A01C5D pop ebp
0124A01D90 nop
0124A01E - E9 6F4A23FF jmp oll.0047EA92
0124A02390 nop
---------------------------------------------------------------------------------------------------------
去程序的ANTI代码
0067D1E9 ^\EB CE jmp short dumped.0067D1B9
0067D1EBE8 80C4E4FF call dumped.004C9670
0067D1F068 FFFF0000 push 0FFFF
0067D1F56A 0D push 0D
0067D1F7E8 7CB2D8FF call <jmp.&user32.ExitWindowsEx>关机了~
0067D1FCE9 CD060000 jmp dumped.0067D8CE
这样危险的API当然不能让程序乱用的,要它指向自己的代码,直接在IAT里面改:
0067D1F7E8 7CB2D8FF call <jmp.&user32.ExitWindowsEx>本来是 call 00408478
去408478上看看:
00408478 - FF25 50C96800 jmp dword ptr ds:[<&user32.ExitWindowsEx>user32.ExitWindowsEx
自己写的代码:
0124A00083C4 0C add esp,0C
0124A003FF7424 F4 push dword ptr ss:[esp-C]还原调用CALL以后RETN的地址
0124A007C3 retn
更改IAT表:
00408478 - E9 831BE400 jmp exit_fix.0124A000
0040847D90 nop
运行,程序OK,....
脱壳完成
后记,EXEStealth的IAT还原部分,比较有趣:
00FDE5358B07mov eax,dword ptr ds:[edi] EDI是加密函数名结构(可以这样说)的基地址
00FDE53709C0or eax,eax
00FDE53974 3C je short BmJapane.00FDE577 IAT表是否填充完成,完成的话跳
00FDE53B8B5F 04 mov ebx,dword ptr ds:[edi+4]
00FDE53E8D8430 BC43BE00 lea eax,dword ptr ds:[eax+esi+BE43BC]
00FDE54501F3add ebx,esi
00FDE54750 push eax
00FDE54883C7 08 add edi,8函数名结构基地址+8byte,指向第3项
00FDE54BFF96 1045BE00 call dword ptr ds:[esi+BE4510] LoadLibraryA
00FDE55195 xchg eax,ebp
00FDE5528A07mov al,byte ptr ds:[edi] 读取第3项数值
00FDE55447 inc edi 函数名结构基地址+1,指向第4项,即函数名
00FDE55508C0or al,al 看AL(函数名第3项)是否为空
00FDE557 ^ 74 DC je short BmJapane.00FDE535
00FDE55989F9mov ecx,edi 读取函数名,放入ECX里面
00FDE55B57 push edi 函数名
00FDE55C48 dec eax
00FDE55DF2:AE repne scas byte ptr es:[edi] 这条指令作用实际上是计算下一个函数的基地址
00FDE55F55 push ebp
00FDE560FF96 1445BE00 call dword ptr ds:[esi+BE4514] GetProcAddress
00FDE56609C0or eax,eax
00FDE56874 07 je short BmJapane.00FDE571 正常情况下不会跳下去的,这里是处理无法取得函数地址的情况
00FDE56A8903mov dword ptr ds:[ebx],eax 取得地址后填充到[ebx]里面(IAT表)
00FDE56C83C3 04 add ebx,4IAT表地址+4bytes
00FDE56F ^ EB E1 jmp short BmJapane.00FDE552
以下是其中一个函数的函数结构,与上面联系的:
35 02 00 00 24 B9 99 00 01 61 63 6D 4D 65 74 72 5..$箼.acmMetr
|----1----| |----2----| 3 |----4-----
69 63 73 ics
------|
1->用lea eax,dword ptr ds:[eax+esi+BE43BC]来标志该函数是哪个DLL文件里面的,把DLL文件的地址传给EAX
2->这部分加上基地址(401000)后用为填充程序IAT表的地址
3->标识函数所在的DLL是否与前一个函数的DLL相同
4->函数名
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)