首页
社区
课程
招聘
[分享]udbg在目标进程内动态Hook、执行任意函数
发表于: 2021-5-16 18:35 9833

[分享]udbg在目标进程内动态Hook、执行任意函数

2021-5-16 18:35
9833

通过spy调试引擎附加到notepad进程

PS D:\dist> notepad.exe
PS D:\dist> .\udbg.exe -A spy -a notepad.exe

在udbg内执行.edit temp命令,会自动在script/autorun目录下打开(创建)temp.lua文件,并监控其写入,然后自动执行

udbg版本:https://gitee.com/udbg/udbg/releases/v0.1.0-nightly

udbg的spy调试引擎,会向目标进程内注入一个模块,然后使用封装好的udbg.uspy模块可以在目标进程内执行lua脚本,然后通过uspy提供的lua接口完成Hook任意函数、调用任意函数的任务

在目标进程内执行lua代码的基本用法如下

后面的示例脚本没有特殊说明,默认都是通过uspy(function() ... end)在目标进程内进行调用的

基本用法

Hook并进行参数替换

Hook并调用原函数、阻止原函数继续执行

上述Hook示例中,对 MessageBoxA 函数的调用就是一个无类型调用的例子

libffi.fn函数直接传入一个整数(C函数地址),返回一个无类型的函数对象,无类型的函数对象会根据传入的lua参数类型自动为每个C参数分配类型,映射规则如下

无类型的调用在于写起来非常简单,能够覆盖大部分应用场景,但有些时候还是需要知道明确的函数参数才能成功调用一些函数,比如涉及到浮点数的函数、非标准的调用约定等情况

声明函数类型需要指定函数的返回值类型和参数类型 libffi.fn(returnType, {argsType...}),支持的类型如下

指定x86调用约定: TODO

示例如下

有些函数只能在某些特定线程中调用,一般是UI主线程,可以Hook GetMessageW PeekMessageW之类的函数,Hook触发时,脚本则是在UI线程中调用的,然后通过libffi去调用想测试的函数

udbg本身功能也使用了很多libffi调用,比如 script/win/api.lua script/win/win.lua

 
local uspy = require "udbg.uspy"
local s = 'hello'
uspy(function()
    log(s, 'world')
end)
local uspy = require "udbg.uspy"
local s = 'hello'
uspy(function()
    log(s, 'world')
end)
local uspy = require "udbg.uspy"
local CreateFileW = PA 'kernelbase!CreateFileW'
 
uspy(function()
    local libffi = require 'libffi'
    local api = require 'win.api'
    -- Hook CreateFileW 函数,并打印第一个参数
    inline_hook(CreateFileW, function(args)
        local path = libffi.read_pack(args[1], 'w')
        log('CreateFileW', path)
    end)
end)
local uspy = require "udbg.uspy"
local CreateFileW = PA 'kernelbase!CreateFileW'
 
uspy(function()
    local libffi = require 'libffi'
    local api = require 'win.api'
    -- Hook CreateFileW 函数,并打印第一个参数
    inline_hook(CreateFileW, function(args)
        local path = libffi.read_pack(args[1], 'w')
        log('CreateFileW', path)
    end)
end)
inline_hook(CreateFileW, function(args)
    -- args[1] 在x64下相当于 args.rcx
    local path = libffi.read_pack(args[1], 'w')
    log('CreateFileW', path)
    if path:find 'a.txt$' then
        path = path:gsub('a.txt$', 'b.txt')
        log('[redirect]', 'a.txt', '->', path)
        args[1] = topointer(path:to_utf16())
    end
end)
inline_hook(CreateFileW, function(args)
    -- args[1] 在x64下相当于 args.rcx
    local path = libffi.read_pack(args[1], 'w')
    log('CreateFileW', path)
    if path:find 'a.txt$' then
        path = path:gsub('a.txt$', 'b.txt')
        log('[redirect]', 'a.txt', '->', path)
        args[1] = topointer(path:to_utf16())
    end
end)
local MessageBoxA = api.GetProcAddress(api.LoadLibraryA('user32'), 'MessageBoxA')
inline_hook(MessageBoxA, function(args)
    -- 手动调用原函数
    libffi.fn(args.trampoline)(0, 'LALALA', 'AAAAAA', 0)
    -- 返回后不再调用原函数
    args 'reject'
end)
local msgbox = libffi.fn(MessageBoxA)
msgbox(0, 'ABC', 'DEF', 0)
local MessageBoxA = api.GetProcAddress(api.LoadLibraryA('user32'), 'MessageBoxA')
inline_hook(MessageBoxA, function(args)
    -- 手动调用原函数
    libffi.fn(args.trampoline)(0, 'LALALA', 'AAAAAA', 0)
    -- 返回后不再调用原函数
    args 'reject'
end)
local msgbox = libffi.fn(MessageBoxA)

[招生]系统0day安全班,企业级设备固件漏洞挖掘,Linux平台漏洞挖掘!

收藏
免费 2
支持
分享
最新回复 (3)
雪    币: 484
活跃值: (2843)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
挺好的,但是这个跟frida相比,有什么更爽的地方吗?
2021-5-18 14:42
0
雪    币: 414
活跃值: (1731)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
saloyun 挺好的,但是这个跟frida相比,有什么更爽的地方吗?
功能上没有比frida更多,主要是有GUI,语言用的lua,还有可以多线程执行lua(这个不知道frida有没有),看个人口味吧
2021-5-18 18:58
0
雪    币: 1935
活跃值: (4185)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
好项目
2021-5-19 13:03
0
游客
登录 | 注册 方可回帖
返回
//