• X86逆向15:OD脚本的编写技巧


    本章节我们将学习OD脚本的使用与编写技巧,脚本有啥用呢?脚本的用处非常的大,比如我们要对按钮事件进行批量下断点,此时使用自动化脚本将大大减小我们的工作量,再比如有些比较简单的压缩壳需要脱壳,此时我们也可以写出属于自己的脱壳脚本,以后遇到了对应的壳就可以使用对应脚本快速的搞定,好了废话不多说,开始进入今天的正题吧。

    ------------------------------------------------------------
    本章难度:★☆☆☆☆☆☆☆☆☆
    课程课件:CM_15.zip
    ------------------------------------------------------------

    Delphi/BC++ 批量下断脚本

    脚本代码,保存为 Delphi.osc

    var Addr                      // 局部变量
    mov Addr,401000               // 指定地址为401000
    
    loop:
    	find Addr,#740E8BD38B83????????FF93????????#     // 查找特征码,并将地址放入RESULT(00401000)
    	cmp $RESULT,0                                    // 如果为0则直接跳出循环
    	je Exit
    	add $RESULT,0A                                   // 相加 (00401000+0A=0040100A)
    	bp $RESULT                                       // 下断
    	add $RESULT,1                                    // 每次递增1
    	mov Addr,$RESULT                                 // 将地址赋给Addr
    jmp loop
    Exit:
    ret
    

    1.OD直接载入CM课件中的【Project1.exe】这是一个Delphi写的测试程序,此时我们运行这个程序,会看到有三个按钮。

    2.回到OD反汇编窗口,点击【右键】,运行脚本打开,选择我们上方保存下来的脚本文件。

    3.选择好脚本以后,我们点击重新载入程序,然后按下【Alt +B】会看到所有的断点已经下好了,这个程序很小所以就这么几个。

    4.运行程序点击,弹窗按钮,程序会断下,直接【F7】进入CALL的内部就能看到按钮的核心代码了。

    VB6.0 批量下断脚本

    脚本代码,保存为 VB6.osc

    var Addr
    mov Addr,401000
    
    loop:
    	find Addr,#816C2404??000000#
    	cmp $RESULT,0
    	je Exit
    	add $RESULT,08
    	bp $RESULT
    	add $RESULT,1
    	mov Addr,$RESULT
    jmp loop
    Exit:
    

    1.OD直接载入CM课件中的【VB6.exe】这是一个VB写的测试程序,我们运行这个程序。

    2.回到OD反汇编窗口,点击【右键】,运行脚本打开,选择我们上方保存下来的脚本文件。

    3.选择好脚本以后,我们点击重新载入程序,然后按下【Alt +B】会看到所有的断点已经下好了,这个程序很小所以就这么几个。

    4.运行程序点击,弹窗按钮,程序会断下,直接【F8】进入CALL的内部就能看到按钮的核心代码了。

    易语言 批量下断脚本

    脚本代码,保存为 易语言.osc

    var Addr
    mov Addr,401000
    
    loop:
    	find Addr,#FF55FC5F5E#
    	cmp $RESULT,0
    	je Exit
    	bp $RESULT
    	add $RESULT,1
    	mov Addr,$RESULT
    jmp loop
    Exit:
    ret
    

    1.OD直接载入CM课件中的【易语言.exe】这是一个易语言写的测试程序,我们运行这个程序。

    2.回到OD反汇编窗口,点击【右键】,运行脚本打开,选择我们上方保存下来的脚本文件。

    3.选择好脚本以后,我们点击重新载入程序,然后按下【Alt +B】会看到所有的断点已经下好了,这个程序很小所以就这么几个。

    4.运行程序点击,弹窗按钮,程序会断下,直接【F7】进入CALL的内部就能看到按钮的核心代码了。

    VC++6.0/MFC 手动下断点

    VC6的特征比较特殊,这里我们只能手动下断了

    1.OD直接载入CM课件中的【VC++.exe】这是一个易语言写的测试程序,我们运行这个程序。

    2.按下【Ctrl +F】按钮,输入命令【sub eax,0a】,会搜索到如下代码,我们选中【sub eax,0a】的下面一条指令处回车。

    3.程序会跳转到如下位置,我们在跳转后的【00416043】处下断点,VC6只有这一处。

    4.回到程序,我们点击【注册按钮】然后程序会断在CALL的位置上,我们直接【F7】进入到CALL的内部,然后在按下两次【F8】

    最后就是VC++的按钮事件核心代码。

    几个常用的脱壳脚本

    我们使用CM_14.zip里面加过壳的案例。

    1.脱 Aspack 脚本

    // 脱 Aspack 壳的脚本
    findop eip,#61#         // 查找popad
    bphws $RESULT,"x"       // 返回查找到的地址,下硬件执行断点 
    run                     // 运行
    bphws $RESULT           // 取消硬件断点
    sto                     // 单步F8
    sto
    sto
    sto
    cmt eip,"已经找到了"    // 添加注释
    ret

    2.脱 UPX 脚本

    // 脱 UPX 脚本
    
    var addr              // 定义一个变量addr 
    sto                   // 单步,也就是F8 
    mov addr,esp          // 把此处ESP的地址给变量addr 
    bphws addr,"r"        // 下硬件读取断点,也就是硬件访问断点 
    run                   // 运行,也就是F9 
    BPHWC addr            // 取消断点 
    sto                   // 单步,也就是F8 
    find eip,#83EC80#     // 查找特征加密语句
    bp $RESULT            // 对返回的地址处F2下断
    run                   // 运行到该处
    sto                   // 单步F8两次
    sto
    
    cmt eip,"这里就是OEP" // 脱壳完成
    ret                   // 结束脚本
    

    3.下方的两个脚本为转载脚本,一个是脱MoleBox另一个是脱穿山甲

    MoleBox v2.X 脱壳脚本
    
    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停留了位置加注释
    ret//结束脚本
    
    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停留了位置加注释
    ret //结束脚本
    
    end:
    msg "您取消了脚本的运行!"//提示没有运行脚本
    ret //结束脚本的运行
  • 相关阅读:
    【LoadRunner-Vuser Generator】录制脚本设置Recording Options
    【LoadRunner-内部结构】
    【LoadRunner-工作过程】
    单片机上内存管理(重定义malloc free)的实现
    stm32模块的初始化顺序要求的更改设值
    [CAN波形分析] 一次CAN波形分析之旅
    w5500调试小记
    keil mdk中save和load指令,在调试中比较有用,以及hex格式的学习
    PHP启用session后抛 session_start(): open(/var/lib/php/session/sess_... 的解决办法
    brew 方式安装的php,关闭与重启----mac启动,关闭php-fpm方式
  • 原文地址:https://www.cnblogs.com/LyShark/p/11197005.html
Copyright © 2020-2023  润新知