用OllyDbg 1.10 手脱 chap708.exe之Mission Impassable?(OS:98/XP)
98环境:
说明:(失败之处,不解之处还请赐教!)
无需隐藏OD,你要隐我也没意见^o^,OD设置忽略所有异常,平台只要你的平台能运行OD就行了;
异常无特别说明,Shift+F9通过就行了!看到的nop指令一般是垃圾指令,你看到的4xxxxx不一定是程序空间(参看内存窗口你就知道)
跟踪得知在call dword ptr ds:[eax-C]异常前已经加密处理了Iat,所以……
入口不贴了,重来,int3和内存异常不忽略,F9运行来到int3断点命令中中断:
00467B28 CC int3 ; // int3中断命令
00467B29 EB 02 jmp short 00467B2D ; // 中断于此
00467B2B - E9 025DEB02 jmp 0331D832
00467B30 - E9 FF33C05A jmp 5B06AF34
00467B35 59 pop ecx
00467B36 59 pop ecx
00467B37 64:8910 mov dword ptr fs:[eax],edx
00467B3A EB 0A jmp short 00467B46
00467B3C ^ E9 1305FFFF jmp 00458054
Ctrl+B 搜索进二进制串:ABEBDC61,搜到后将“stos dword ptr es:[edi]”改为Nop指令,是不是很简单……
00477B13 AB stos dword ptr es:[edi] //Iat加密处理,Nop去(解压码默认是98的AIP)
00477B14 ^ EB DC jmp short 00477AF2
00477B16 61 popad //此处下F2断点并Shift+F9到达,iat已经是清白之身,不曾被人沾污!
00477B17 837D 08 00 cmp dword ptr ss:[ebp+8],0
00477B1B 75 09 jnz short 00477B26
00477B1D 33C0 xor eax,eax
Shift+F9运行来到壳的空间的异常处:
0046D280 52 push edx
0046D281 51 push ecx
0046D282 53 push ebx
0046D283 FF50 F4 call dword ptr ds:[eax-C] ; // 这里发生第1次异常:读取[fffffff4]
0046D286 31D2 xor edx,edx
0046D288 8D4C24 10 lea ecx,dword ptr ss:[esp+10]
0046D28C 64:8B1A mov ebx,dword ptr fs:[edx]
0046D28F 8919 mov dword ptr ds:[ecx],ebx
0046D291 8969 08 mov dword ptr ds:[ecx+8],ebp
0046D294 C741 04 A5D24600 mov dword ptr ds:[ecx+4],46D2A5
0046D29B 8941 0C mov dword ptr ds:[ecx+C],eax
0046D29E 64:890A mov dword ptr fs:[edx],ecx
0046D2A1 5B pop ebx
0046D2A2 59 pop ecx
0046D2A3 5A pop edx
0046D2A4 C3 retn
0047CB60 55 push ebp
0047CB61 68 89CB4700 push 47CB89
0047CB66 64:FF30 push dword ptr fs:[eax]
0047CB69 64:8920 mov dword ptr fs:[eax],esp
0047CB6C 33C9 xor ecx,ecx
0047CB6E B2 01 mov dl,1
0047CB70 B8 20EE4600 mov eax,46EE20
0047CB75 E8 AE3CFFFF call 00470828
0047CB7A E8 6D0AFFFF call 0046D5EC
0047CB7F 33C0 xor eax,eax ; // 第2次异常:0EEDFACE
0047CB81 5A pop edx
0047CB82 59 pop ecx
0047CB83 59 pop ecx
0047CB84 64:8910 mov dword ptr fs:[eax],edx
0047CB87 EB 0A jmp short 0047CB93
0047CB95 55 push ebp
0047CB96 68 BECB4700 push 47CBBE
0047CB9B 64:FF30 push dword ptr fs:[eax]
0047CB9E 64:8920 mov dword ptr fs:[eax],esp
0047CBA1 33C9 xor ecx,ecx
0047CBA3 B2 01 mov dl,1
0047CBA5 B8 20EE4600 mov eax,46EE20
0047CBAA E8 793CFFFF call 00470828
0047CBAF E8 380AFFFF call 0046D5EC
0047CBB4 33C0 xor eax,eax ; // 第3次异常:0EEDFACE
0047CBB6 5A pop edx
0047CBB7 59 pop ecx
0047CBB8 59 pop ecx
0047CBB9 64:8910 mov dword ptr fs:[eax],edx
0047CBBC EB 0A jmp short 0047CBC8
0047CBF7 55 push ebp
0047CBF8 68 20CC4700 push 47CC20 // seh
0047CBFD 64:FF30 push dword ptr fs:[eax]
0047CC00 64:8920 mov dword ptr fs:[eax],esp
0047CC03 33C9 xor ecx,ecx
0047CC05 B2 01 mov dl,1
0047CC07 B8 20EE4600 mov eax,46EE20
0047CC0C E8 173CFFFF call 00470828
0047CC11 E8 D609FFFF call 0046D5EC
0047CC16 33C0 xor eax,eax ; // 第4次异常:0EEDFACE,可能算是最后一个异常吧(至少我这里是)
0047CC18 5A pop edx
0047CC19 59 pop ecx
0047CC1A 59 pop ecx
0047CC1B 64:8910 mov dword ptr fs:[eax],edx
0047CC1E EB 0A jmp short 0047CC2A
到达第4个异常时向下不远处找popad和jmp指令,like this:
0048380A 61 popad ; // 这里eax将会看到OEP,下F2断点,Shift+F9通过断于此,下面不远处就是返回OEP!
0048380B EB 01 jmp short 0048380E ; // 以下都是垃圾指令
0048380D E8 50EB02E9 call E94B2362
00483812 17 pop ss
00483813 E8 02000000 call 0048381A
00483818 90 nop ; // // 为了看到下面的正确指令,NOP掉两个字节
00483819 90 nop
0048381A 58 pop eax ; // 垃圾指令结束
0048381B 803D 00AA4800 00 cmp byte ptr ds:[48AA00],0 ; // 比较是否返回OEP标志!正确点是是否显示Nag提示!
00483822 74 23 je short 00483847
00483824 5B pop ebx
00483825 6A 10 push 10
00483827 B8 CE994800 mov eax,4899CE
0048382C 83C0 0A add eax,0A
0048382F 8B00 mov eax,dword ptr ds:[eax]
00483831 50 push eax
00483832 B8 DE994800 mov eax,4899DE
00483837 83E8 0A sub eax,0A
0048383A 8B00 mov eax,dword ptr ds:[eax]
0048383C 50 push eax
0048383D 6A 00 push 0
0048383F B8 59594700 mov eax,475959
00483844 48 dec eax
00483845 53 push ebx
00483846 50 push eax
00483847 C3 retn ; // 返回OEP
retn单步后到了OEP: 4010cc还不快拿工具DUMP,用ImportREC "GET Iat" 全部有效,fix it!
Mission Impassable?就此完成,其实写文章比脱壳还要麻烦麻烦麻烦……^_^ ^_^
附:
在 call 00467BA8 里单步不知到哪或call后断点会令你无法到达正确的OEP:
0047716A /EB 0A jmp short 00477176
0047716C ^|E9 9B07FFFF jmp 0046790C
00477171 |E8 320AFFFF call 00467BA8 ; // 这里有trick: 令你无法到达正确的OEP,小弟不才,请高手解释……
00477176 \8B45 F4 mov eax,dword ptr ss:[ebp-C]
00477179 0145 F8 add dword ptr ss:[ebp-8],eax ; // 计算出正确的OEP!
0047717C 833D 9CE34700 00 cmp dword ptr ds:[47E39C],0
00477183 0F9405 A0E34700 sete byte ptr ds:[47E3A0]
0047718A EB 01 jmp short 0047718D
0047718C 90 nop
0047718D 8B65 FC mov esp,dword ptr ss:[ebp-4] ; // 关键地方: [ebp-4]一定要等于esp或Nop掉它,否则跟到这OEP没门!
00477190 EB 01 jmp short 00477193
00477192 90 nop
00477193 8B45 F8 mov eax,dword ptr ss:[ebp-8]
00477196 EB 02 jmp short 0047719A
00477198 90 nop
00477199 90 nop
0047719A 8B1D 90D34700 mov ebx,dword ptr ds:[47D390]
004771A0 EB 01 jmp short 004771A3
004771A2 90 nop
004771A3 89041C mov dword ptr ss:[esp+ebx],eax
004771A6 EB 02 jmp short 004771AA
004771A8 90 nop
004771A9 90 nop
004771AA 61 popad
004771AB 90 nop
004771AC 90 nop
004771AD 90 nop
004771AE 90 nop
004771AF 90 nop
004771B0 90 nop
004771B1 90 nop
004771B2 90 nop
004771B3 90 nop
004771B4 90 nop
004771B5 90 nop
004771B6 90 nop
004771B7 90 nop
004771B8 90 nop
004771B9 90 nop
004771BA 90 nop
004771BB 803D A0E34700 00 cmp byte ptr ds:[47E3A0],0 ; // 比较是否返回OEP标志!正确点是是否显示Nag提示!
XP环境:
bp GetModuleHandleA 3次运行中断点后,取消断点,Alt+F9返回到用户代码
001A5E3A FF95 B4314400 call dword ptr ss:[ebp+4431B4] ; kernel32.GetModuleHandleA
001A5E40 85C0 test eax,eax ; 返回到这
001A5E42 75 07 jnz short 001A5E4B
001A5E44 53 push ebx
001A5E45 FF95 B8314400 call dword ptr ss:[ebp+4431B8]
……
001A5F55 61 popad
001A5F56 75 08 jnz short 001A5F60
001A5F58 B8 01000000 mov eax,1
001A5F5D C2 0C00 retn 0C
001A5F60 68 00000000 push 0
001A5F65 C3 retn //上面到这是aspack的解压,F4运行到这
我这里上面的retn 是00197FCC
00197FCC 55 push ebp //F7单步到这
00197FCD 8BEC mov ebp,esp
00197FCF 83C4 F4 add esp,-0C
00197FD2 E8 6DFBFEFF call 00187B44
00197FD7 ^ 0F85 8F09FFFF jnz 0018896C
00197FDD E8 460EFFFF call 00188E28
00197FE2 E8 4537FFFF call 0018B72C
00197FE7 E8 1C55FFFF call 0018D508
00197FEC E8 A3AAFFFF call 00192A94
00197FF1 E8 7609FFFF call 0018896C
00197FF6 8BE5 mov esp,ebp
00197FF8 5D pop ebp
00197FF9 C2 0C00 retn 0C
00197FFC 0D F0ADBA0D or eax,0DBAADF0 //你看到了吗?从这里到下面一直延伸相同的“垃圾”
00198001 F0:AD lock lods dword ptr ds:[esi] ; 锁定前缀是不允许的
00198003 BA 0DF0ADBA mov edx,BAADF00D //就是它
00198008 0D F0ADBA0D or eax,0DBAADF0
cpu窗口往上滚动到顶部,运行脚本“垃圾铲除脚本”--replace code.txt,按说明运行使用。
小心你的CPU,我这里弱机要等10多秒左右,期间是忙中,失去响应,是正常现象^_^
待脚本完成报告时,一看count == 281D,还真多呀!
我们此时再看:
00197FCC 55 push ebp
00197FCD 8BEC mov ebp,esp
00197FCF 83C4 F4 add esp,-0C
00197FD2 E8 6DFBFEFF call 00187B44
00197FD7 ^ 0F85 8F09FFFF jnz 0018896C
00197FDD E8 460EFFFF call 00188E28
00197FE2 E8 4537FFFF call 0018B72C
00197FE7 E8 1C55FFFF call 0018D508
00197FEC E8 A3AAFFFF call 00192A94
00197FF1 E8 7609FFFF call 0018896C
00197FF6 8BE5 mov esp,ebp
00197FF8 5D pop ebp
00197FF9 C2 0C00 retn 0C
00197FFC 0000 add byte ptr ds:[eax],al
00197FFE 0000 add byte ptr ds:[eax],al
00198000 0000 add byte ptr ds:[eax],al
00198002 0000 add byte ptr ds:[eax],al
00198004 0000 add byte ptr ds:[eax],al
现在正常了,异常没再死敲敲地非法EIP了,可以通过异常正常运行!
iat修复不可按我98的方式进行(抵达入口可以)-- 有点难度,留给大家练练玩玩,只是异常0EEDFACE的位置不同而已,另外垃圾来源好像程序未运行前就存在某region,不知为何存在的,高手指点,ByteBye!
脚本:
// replace code.txt
var addr
var count
mov count,0
ask "Please input address for replace:" //输入cpu窗口顶部地址
cmp $RESULT,0
je exit
mov addr,$RESULT
loop:
find addr, #0DF0ADBA# //你机器看到的垃圾代码
cmp $RESULT,0
je exit
mov [$RESULT],0
inc count
jmp loop
exit:
msg "Finished to Replace Job!"
log "清除垃圾代码统计数量在count:"
log count
ret
:D :D :D
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!