详解OD脚本的写法续之进阶篇
昨天给大家写了简单壳的脚本的写法,相信大家对一些简单壳都已经学会自己去写脚本了,至少已经能看懂脚本了吧。好,今天就继续给大家讲稍微难点的壳的脚本的写法,希望大家能好好掌握。前提是,你已经看了昨天的基础篇,并已经学会写一些简单的脚本。
废话不多说,开始今天的内容。
首先来个稍微简单点的壳的脚本的写法:MoleBox 2.x的壳
当然,我们首先还是来手脱一下这个壳。所以说,写脚本的前提是你已经学会了手脱这个壳,并且掌握了这个壳的一些脱壳的规律。
00596BD3 >E8 00000000 call Notepad.00596BD8//载入到这,F8,2次
00596BD860pushad
00596BD9E8 4F000000 call Notepad.00596C2D//2次后来到这,在ESP处下硬件访问断点
00596BDE0D 76CC70B0 or eax,B070CC76
00596BE3^ EB 81 jmp short Notepad.00596B66
00596BE56Fouts dx,dword ptr es:
00596BE637aaa
00596BE704 57 add al,57
先不要着急着运行,由于我们知道这个壳对IAT有加密,所以,我们再去OEP之前,首先得处理下IAT。
于是我们下断点:bp VirtualProtect,SHIFT+F9,中断后,取消断点,并ALT+F9返回
然后我们查找 89 01
然后把它NOP掉
因为我们知道,只要NOP掉这一句后,即可跳过壳对IAT的加密。
PS:具体的请参看脱这壳的相关文章,这里不再赘述!
处理完后,我们就F9运行
005967B158pop eax//来到这,F8走
005967B258pop eax
005967B3FFD0call eax //走到这里后,F7进去,就来到了OEP!
005967B5E8 F5CB0000 call Notepad.005A33AF
005967BACCint3
005967BBCCint3
004A2ADCE8 B6A40000 call Notepad.004ACF97 //OEP!
004A2AE1^ E9 16FEFFFF jmp Notepad.004A28FC
004A2AE6CCint3
004A2AE7CCint3
004A2AE8CCint3
004A2AE9CCint3
004A2AEACCint3
004A2AEBCCint3
004A2AECCCint3
004A2AEDCCint3
004A2AEECCint3
004A2AEFCCint3
根据上面的流程,我们就可以开始写脱壳的脚本了!
---------------------------------------------------------------------------------------------------------
////////////////////////////////////////////////////////////
/// MoleBox v2.X 脱壳脚本///
/// by 徐超(ximo) QQ:178911980 ///
/// http://www.54soft.com.cn ///
///http://www.52pojie.net ///
//////
/// 2008.7.26///
////////////////////////////////////////////////////////////
var addr //定义一个变量,用来放ESP的值
sto
sto//单步2次
mov addr,esp //把ESP的值,放变量addr中
bphws addr,"r" //下硬件访问断点
/*接着来处理IAT*/
gpa "VirtualProtect","kernel32.dll"//查找特征API,并把查找到的地址放RESULT中
bp $RESULT //对找到的地址处,下F2断点,也就是BP
run//运行
bc $RESULT //取消断点
rtu//ALT+F9返回
/*返回后,找特征加密语句,处理IAT的加密*/
find eip,#8901#//查找特征加密语句
bp $RESULT //对返回的地址处F2下断
run//运行到该处
bc $RESULT //取消断点
repl eip, #8901#, #9090#, 10 //把加密语句NOP掉,即替换为9090
/*下面就去OEP了*/
run//由于刚才已经下好了硬件断点,现在只要运行即可
bphwc addr //取消断点
sto
sto//单步走2次
sti//F7跟进,就来到了OEP了
cmt eip,"这里就是OEP!"//在EIP处,也就是现在OD停留了位置加注释
MSG "感谢使用此脚本,现在可以脱壳了" //加个对话框,给出一些提示信息
ret//结束脚本
---------------------------------------------------------------------------------------------------------
OK,这个脚本就顺利写完了。去试下效果吧,哈,一切OK!
有了写这个壳的脚本来练手,我们就再来个更强点的壳吧,哈,穿山甲上场!
当然,我们这里只给大家讲解下单进程标准壳的写法,至于其他的保护方式,大家可以自己去举一反三,自己学着写,或者,自己去网上找些脚本的资料,至少去看懂脚本的内容!
好,我们开始吧:
穿山甲标准壳的脱壳相对简单点:
1、寻找magic jump,避开IAT加密
我们CTRL+G GetModuleHandleA,查找到这里
7C80B6A1 >8BFFmov edi,edi //查找到这里
7C80B6A355push ebp
7C80B6A48BECmov ebp,esp
7C80B6A6837D 08 00cmp dword ptr ss:,0
7C80B6AA74 18 je short kernel32.7C80B6C4 //在这里我们下硬件执行断点,可以发现,是找到的地址+5
7C80B6ACFF75 08 push dword ptr ss:
7C80B6AFE8 C0290000 call kernel32.7C80E074
7C80B6B485C0test eax,eax
7C80B6B674 08 je short kernel32.7C80B6C0
然后我们SHIFT+F9运行,仔细观察堆栈窗口和寄存器窗口,找适当的时机返回
第一次:
堆栈:
000794FC/0007EC44
00079500|00B46DF3返回到 00B46DF3 来自 kernel32.GetModuleHandleA
00079504|00B5BC1CASCII "kernel32.dll"
00079508|00B5CEC4ASCII "VirtualAlloc"
0007950C|00B5FA98
00079510|7C9210EDntdll.RtlLeaveCriticalSection
寄存器:
EAX 77DCCBAC ADVAPI32.77DCCBAC
ECX 00000001
EDX EBF07409
EBX 00000000
ESP 000794FC
EBP 000794FC
ESI 7C9210ED ntdll.RtlLeaveCriticalSection
EDI 00B5FA98
EIP 7C80B6AA kernel32.7C80B6AA
第二次:
堆栈:
000794FC/0007EC44
00079500|00B46E10返回到 00B46E10 来自 kernel32.GetModuleHandleA
00079504|00B5BC1CASCII "kernel32.dll"
00079508|00B5CEB8ASCII "VirtualFree"
0007950C|00B5FA98
00079510|7C9210EDntdll.RtlLeaveCriticalSection
寄存器:
EAX 7C809A51 kernel32.VirtualAlloc
ECX 00B5CEC4 ASCII "VirtualAlloc"
EDX 00B5CED0
EBX 00000000
ESP 000794FC
EBP 000794FC
ESI 7C9210ED ntdll.RtlLeaveCriticalSection
EDI 00B5FA98
EIP 7C80B6AA kernel32.7C80B6AA
第三次:
堆栈:
00079260/00079500
00079264|00B35CE1返回到 00B35CE1 来自 kernel32.GetModuleHandleA
00079268|000793B4ASCII "kernel32.dll"
0007926C|00000000
寄存器:
EAX 000793B4 ASCII "kernel32.dll"
ECX 000793C0
EDX 000793B4 ASCII "kernel32.dll"
EBX 00000000
ESP 00079260
EBP 00079260
ESI 00000000
EDI 00B5B0F4
EIP 7C80B6AA kernel32.7C80B6AA
很明显,这里就是返回的时机了。
当然我们也找到了这么个规律,就是EAX的值为VirtualAlloc的下一次,就是我们的返回时机!
好,接着我们就取消硬件断点,ALT+F9运行
00B35CE18B0D AC40B600 mov ecx,dword ptr ds: //返回到这里
00B35CE789040Emov dword ptr ds:,eax
00B35CEAA1 AC40B600 mov eax,dword ptr ds:
00B35CEF391C06cmp dword ptr ds:,ebx
00B35CF275 16 jnz short 00B35D0A
00B35CF48D85 B4FEFFFF lea eax,dword ptr ss:
00B35CFA50push eax
00B35CFBFF15 BC62B500 call dword ptr ds: ; kernel32.LoadLibraryA
00B35D018B0D AC40B600 mov ecx,dword ptr ds:
00B35D0789040Emov dword ptr ds:,eax
00B35D0AA1 AC40B600 mov eax,dword ptr ds:
00B35D0F391C06cmp dword ptr ds:,ebx
00B35D120F84 2F010000 je 00B35E47 //这就是magic jump,改JMP吧!
00B35D1833C9xor ecx,ecx
00B35D1A8B07mov eax,dword ptr ds:
00B35D1C3918cmp dword ptr ds:,ebx
00B35D1E74 06 je short 00B35D26
00B35D2041inc ecx
00B35D2183C0 0C add eax,0C
00B35D24^ EB F6 jmp short 00B35D1C
00B35D268BD9mov ebx,ecx
00B35D28C1E3 02 shl ebx,2
处理完IAT后,我们就找OEP了!
下断点bp CreateThread,shift+f9运行,中断后取消断点,ALT+F9返回
返回后就去单步走,去OEP吧
00B4F6ABA1 E400B600 mov eax,dword ptr ds:
00B4F6B03190 88000000 xor dword ptr ds:,edx
00B4F6B6A1 E400B600 mov eax,dword ptr ds:
00B4F6BB3190 88000000 xor dword ptr ds:,edx
00B4F6C1A1 E400B600 mov eax,dword ptr ds:
00B4F6C68B88 90000000 mov ecx,dword ptr ds:
00B4F6CC3348 2C xor ecx,dword ptr ds:
00B4F6CF3348 18 xor ecx,dword ptr ds:
00B4F6D2030D FC00B600 add ecx,dword ptr ds:; sol.01000000
00B4F6D88B17mov edx,dword ptr ds:
00B4F6DA85D2test edx,edx
00B4F6DC75 1B jnz short 00B4F6F9
00B4F6DEFF77 18 push dword ptr ds:
00B4F6E1FF77 14 push dword ptr ds:
00B4F6E4FF77 10 push dword ptr ds:
00B4F6E78B90 90000000 mov edx,dword ptr ds:
00B4F6ED3350 40 xor edx,dword ptr ds:
00B4F6F03350 04 xor edx,dword ptr ds:
00B4F6F32BCAsub ecx,edx
00B4F6F5FFD1call ecx//这里F7进去,就是OEP了!
00B4F6F7EB 20 jmp short 00B4F719
00B4F6F983FA 01 cmp edx,1
00B4F6FC75 1E jnz short 00B4F71C
00B4F6FEFF77 04 push dword ptr ds:
01005F856A 70 push 70 //这里就是OEP了
01005F8768 F8120001 push sol.010012F8
01005F8CE8 DF010000 call sol.01006170
01005F9133DBxor ebx,ebx
01005F9353push ebx
01005F948B3D 98100001 mov edi,dword ptr ds: ; kernel32.GetModuleHandleA
01005F9AFFD7call edi
01005F9C66:8138 4D5Acmp word ptr ds:,5A4D
01005FA175 1F jnz short sol.01005FC2
01005FA38B48 3C mov ecx,dword ptr ds:
好,有了上面的分析,我们又可以来写脚本了!哈~
---------------------------------------------------------------------------------------------------------
////////////////////////////////////////////////////////////
/// Armadillo 3.78 - 4.xx标准单进程脱壳脚本///
/// by 徐超(ximo) QQ:178911980 ///
/// http://www.54soft.com.cn ///
///http://www.52pojie.net ///
//////
/// 2008.7.26///
////////////////////////////////////////////////////////////
var GetModuleHandleA
var VirtualAlloc
var CreateThread
var OEP //定义4个变量
MSGYN "请取消所以的断点,忽略所有异常,并添加C000001D..C000001E到异常中!"//提示运行脚本前的一些信息
cmp $RESULT, 0//比较是否点"否"或"取消"
je end//如果点"否"或"取消",就来到end处
/*做些准备工作,找到所要下的各函数的地址*/
gpa "GetModuleHandleA", "kernel32.dll"//找特征API函数GetModuleHandleA
mov GetModuleHandleA, $RESULT //把找到的地址放变量GetModuleHandleA中
add GetModuleHandleA,5//GetModuleHandleA=GetModuleHandleA+5
gpa "VirtualAlloc", "kernel32.dll"//找特征APIVirtualAlloc
mov VirtualAlloc, $RESULT //把找到的地址放变量VtrtualAlloc中
gpa "CreateThread", "kernel32.dll"//找特征APICreateThread
mov CreateThread, $RESULT //把找到的地址放变量CreateThread中
/*下断点GetModuleHandleA+5,找合适的时机返回*/
bphws GetModuleHandleA, "x" //在GetModuleHandleA+5处,下硬件执行断点
label1: //标签label1
esto//SHIFT+F9
cmp eax,VirtualAlloc//比较EAX的值是否为VirtualAlloc
jne label1//不是的话,来到标签label1,继续SHIFT+F9
esto//再SHIFT+F9,来到最佳的返回时机
bphwc GetModuleHandleA//取消此硬件断点
rtu //ALT+F9返回
/*找magic jump,并修改*/
find eip, #0F84????????#//查找magic jump的特征码,"?"为通配符
bp $RESULT//找到的地址处下断
esto//SHIFT+F9
bc $RESULT//取消断点
repl eip, #0F84????????#, #90E9????????#, 10//修改magic jump,即改为"90E9"。由于字节数不同,故NOP填充
/*寻找OEP*/
bp CreateThread //下断点bp CreateThread
run //运行
bc CreateThread //取消断点
rtu //ALT+F9返回
rtr //执行到返回,相当与CTRL+F9
sti //F7
/*例子中的特征代码:
00B4F6F32BCAsub ecx,edx
00B4F6F5FFD1call ecx
00B4F6F7EB 20 jmp short 00B4F719
*/
find eip, #2B??FF??8?#//找特征代码
mov OEP, $RESULT//把返回的值放变量OEP中
add OEP, 2//OEP=OEP+2,很明显找到地址的后2个字节就是
bp OEP//下断点
run //运行
bc OEP//取消断点
sti //F7进去,就是OEP了
cmt eip,"这里就是OEP!" //在EIP处,也就是现在OD停留了位置加注释
MSG "感谢使用此脚本,现在可以脱壳了"//加个对话框,给出一些提示信息
ret //结束脚本
end:
msg "您取消了脚本的运行!"//提示没有运行脚本
ret //结束脚本的运行
---------------------------------------------------------------------------------------------------------
哈,穿山甲的脚本就这么搞定了!测试一下效果吧,同样OK!
差不多到这里,看了这些讲解,大家对写脚本应该有个更加深刻的认识了吧!
以后的工作就是大家多多动手去实践了。
水平有限,讲的不是那么好,请大家谅解!
作者徐超,转载注明出处!谢谢合作! 晕,论坛上的显示效果和我在笔记本中写的不一样.
笔记本中写的明显整齐多了,呵呵
附件中就有完整的文章,2个脚本,以及教程中的程序! 超牛 真厉害顶啊 超哥辛苦了,讲的很好,收藏起来慢慢看。 嗯嗯!~
很厉害~!佩服死了~!
我要是女的就嫁给你!~ 这个厉害啊我下来用用
晕,终于看见了 天书 处理完IAT后,我们就找OEP了 的确很强 超人啊。。。 学习下下 [下个来试试.谢谢楼主的无私分享.