自写自用的调试分析工具 udbg

自己利用业余时间写了很长时间了,核心功能使用rust开发,上层逻辑使用lua开发,不敢说比现有的调试器更好用,主要是方便我自己用来做一些自动化调试分析的事情

  • 项目地址: https://gitee.com/udbg/udbg
  • 文档地址: https://udbg.github.io/udbg/index.html

release页面下载dist.zip解压到本地即可使用,路径中不要包含Unicode字符

要介绍的内容有点多,文档还在完善中...

设计理念

  • 尽可能支持更多的调试/分析场景
    • Windows:标准调试器
    • Windows:VEH调试器
    • 非侵入式调试、进程信息查看
    • WinDbg 调试引擎:可用于分析dmp、内核调试
    • [ ] ARK工具、内核信息查看
    • [ ] 跨平台:支持linux、android
  • 方便地编写扩展
    • udbg本身使用lua编写了大部分上层逻辑
    • 提供了大量lua接口,支持libffi
    • 提供原生的Rust接口,编写高性能的扩展
  • 界面/核心分离,可进行远程分析/调试
  • CUI && GUI 双界面: CUI便于和其他第三方编辑器集成、GUI便于展示更多数据
  • 功能抽象、分层,跨平台:既保留各平台的共性,降低学习成本,也允许差异化定制,实现平台特定的功能

启动调试器

主要是命令行启动

  • udbg 启动udbg,并显示主窗口,相当于在资源管理器中双击udbg.exe进行启动
  • udbg -W 无窗口启动udbg,在命令行中调试
  • udbg -e test.lua 启动udbg并执行 test.lua 脚本
  • udbg -e test.lua --watch 监控 test.lua 脚本改动并自动执行
  • udbg notepad.exe (默认的调试引擎) 创建并调试 notepad.exe
  • udbg -a notepad.exe (默认的调试引擎) 附加到 notepad.exe
  • udbg -A spy notepad.exe 通过spy调试引擎 创建并调试 notepad.exe
  • udbg -A spy -a notepad.exe 通过spy调试引擎 附加到 notepad.exe
  • udbg -r localhost:2333 连接到udbg-server,并启动,后面可跟上面所有的参数,参考 远程调试

完整的命令行语法如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

udbg 0.1.0

metaworm

USAGE:

    udbg.exe [FLAGS] [OPTIONS] [--] [ARGS]

FLAGS:

    -a, --attach       Attach target

    -h, --help         Prints help information

    -W, --no-window    Dont show the main window

    -o, --open         Open the target, not attach

    -p, --pid          Target as pid

        --version      Prints version information

    -V, --verbose      Show the verbose info

    -w, --watch        Watch the executed lua script

OPTIONS:

    -A, --adaptor <adaptor>          Specify the adaptor [default: ]

    -r, --remote <address:port>      Connect to udbg server, with cui [env: UDBG_SERVER=]

        --cwd <directory>            Set CWD for target

    -e, --execute <lua path>         Execute lua script

    -c, --config <udbg config>...    Set the __config

ARGS:

    <target-path>    Create debug target

    <args>...        Shell Arguments to target

软件截图

图片描述

脚本自动执行

  1. 最直接的方法是通过命令行启动udbg -e test.lua --watch指定运行一个脚本并监控其改动,然后自动执行
  2. 可以在udbg.exe所在目录下创建config/autorun/目录,autorun目录下的lua脚本发生改动时都会自动执行

断点

设置断点最简单的方法是在反汇编视图中,选择对应汇编语句,按F2

但如果想设置更复杂的断点需要使用bp命令,列几个常用的断点设置示例

  • 常规断点 bp CreateFileW 在 CreateFileW 函数处下断点
  • 日志断点 bp CreateFileW wstr(reg[1]) 在 CreateFileW 函数处下断点,并显示第一个参数
    • 其中wstr(reg[1])是一个lua表达式,表示需要记录的内容,reg[1]表示当前架构下标准调用约定的第一个参数(x64下相当于reg.rcx),可跟多个表达式比如 bp CreateFileW wstr(reg[1]) reg.rdx
    • 如果想过滤需要记录的日志,可加-f参数+lua表达式,比如 bp CreateFileW wstr(reg[1]) -f v1:find'log.txt'可以过滤带有log.txt的路径,其中v1表示CreateFileW后面的表达式列表里的第一个表达式的值
  • 条件断点 bp CreateFileW wstr(reg[1]) -c v1:find'log.txt' 当CreateFileW的第一个参数路径包含 log.txt 时断下
  • 硬件断点 bp CreateFileW -t e1 临时(一次性)断点 bp CreateFileW --temp

bp命令的完整帮助 bp -h

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

bp                                        设置断点

    <address>       (string)              断点地址

    <vars...>       (optional string)     变量列表

    -n, --name        (optional string)   断点名称

    -c, --cond        (optional string)   中断条件

    -l, --log         (optional string)   日志表达式

    -f, --filter      (optional string)   日志条件

    -s, --statistics  (optional string)   统计表达式

    -t, --type        (optional bp_type)  断点类型(e|w|a)(1|2|4|8)

    --tid             (optional number)   命中线程

    --temp                                临时断点

    --symbol                              转换为符号

    --hex                                 十六进制显示

    --caller                              显示调用者

    -m, --module                          模块加载断点

如果需要了解bp命令的详细实现方式,参考script/udbg/command/bp.lua

自定义断点回调

通过脚本定制更复杂的断点处理逻辑

1

2

3

4

5

6

7

8

9

10

11

12

add_bp('kernel32!CreateFileW', function()

    local path = read_wstring(reg.rcx)

    log('[CreateFileW]', path)

    if path:find 'xxx' then

        -- 返回true表示这个断点会中断给用户处理

        return true

    end

    -- 在调用 CreateFileW 的返回点处设置断点

    add_bp(reg.rsp, function()

        log('[CreateFileW]''return', reg.rax)

    end, {temp = true, type = 'table'})

end)

堆栈回溯

除了堆栈视图,还可以使用dp -r rsp来查看堆栈;udbg目前未实现基于符号的堆栈回溯,dp -r本质上是暴力搜索堆栈上的返回地址

模块符号

udbg自带的调试引擎支持加载pdb符号,可在配置文件中通过__config.symbol_cache = 'D:/Symbols来指定pdb符号所在的目录,目录结构和windbg的符号缓存目录一致,可以在windbg里下载系统所需要的符号

udbg首先会根据dll/exe里的pdb路径去加载符号,如果没有的话再寻找dll所在目录下的同名pdb,如果也没有就会去符号缓存目录中加载

如果想给一个模块手动指定pdb路径,可以使用命令 load-symbol xx.dll D:\xx.pdb

也可以在配置文件中写脚本来自动加载

1

2

3

4

5

function uevent.on.module_load(m)

    if m.base == PA 'xx.dll' then

        m:load_symbol [[D:\xx.pdb]]

    end

end

内存读写

  • 直接在内存视图中查看
    • Ctrl+1 Ctrl+2 Ctrl+3 Ctrl+4 分别切换BYTE WORD DWORD QWORD显示
    • Ctrl+F切换float显示
    • Ctrl+D切换double显示
    • Ctrl+G可以输入地址表达式并跳转到对应地址
  • mem <address> 命令在内存视图中 跳转到对应的地址表达式 mem ntdll.dll mem [[0x403000]+0x10]
  • e 命令编辑内存
  • Lua函数 {read|write}_{u8|u16|u32|u64|ptr|float|double}

异常处理

相关配置

  • __config.ignore_all_exception = false 是否忽略所有异常

处理异常事件

可以通过脚本配置更复杂的异常处理

1

2

3

4

5

6

7

8

function uevent.on.exception(tid, code, first)

    if code == STATUS_CPP_EH_EXCEPTION then

        return 'run'

    end

    if reg.rip == 0 then

        return 'run'

    end

end

单步跟踪

在目标断下时,可以通过如下脚本来启动一个单步跟踪过程

1

2

3

4

5

6

7

8

9

-- 单步跟踪1000步并输出每一步的汇编语句

local count = 1000

local disasm = disasm

ui.continue('step', function()

    count = count - 1

    local pc = reg._pc

    log(hex(pc), disasm(pc).string)

    return count == 0

end)

配置脚本

  • udbg所在目录下的config目录为配置目录,可以通过同步盘同步配置,软连接到config
  • config目录本身也会被加到lua的模块搜索路径里
  • config下的client.lua为第一个被执行的配置脚本,主要用于定制一些跟客户端UI相关的配置,配置脚本示例如下

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    -- 指定其他插件/配置路径

    plugins = {

        {path = [[D:\Plugin1]]},

        {path = [[D:\Plugin2]]},

    }

    -- 指定启动编辑器的命令

    --   默认是 notepad

    edit_cmd = 'notepad.exe %1'

    --   如果安装了vscode,建议改为 vscode

    edit_cmd = 'code %1'

    -- 远程地址映射

    --   配置了此项可在命令行中用键名代替对应的地址端口

    --   比如: udbg -r vmware C:\Windows\notepad.exe

    remote_map = {

        ['local'= '127.0.0.1:2333',

        local1 = '127.0.0.1:2334',

        local2 = '127.0.0.1:2335',

        vmware = '192.168.1.239:2333',

    }

  • config下的udbg/plugin/init.lua会在调试器初始化时被执行,可以做一些跟调试器相关的配置,比如

    1

    2

    3

    4

    5

    6

    7

    8

    -- 忽略初始断点(不中断给用户)

    __config.ignore_initbp = true

    -- 初始断点事件触发时自动下断点

    function uevent.on.init_bp()

        if udbg.target.path:find 'notepad' then

            ucmd 'bp kernel32!CreateFileW'

        end

    end

    注意,执行client.luaudbg/plugin/init.lua的是两个不同的lua虚拟机,前者是给客户端UI使用的,后者是给调试器核心使用的

  • autorun/目录下的lua脚本发生改动时,会被(调试器的lua虚拟机)自动执行

远程调试

  1. 启动udbg服务:将udbg-server.exe lua54.dll uspy.dll 三个文件拷到目标机器上,然后管理员权限运行udbg-server.exe
  2. 通过udbg -r 目标机器地址:端口连接到udbg服务进行调试,比如udbg -r 192.168.1.239:2333 C:\Windows\notepad.exe
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值