如何使用WinAppDbg挂钩并调用给定RVA的现有功能?

问题描述 投票:1回答:1

我正在尝试使用WinAppDbg编写游戏插件,这涉及到钩子并调用该游戏中的现有功能。经过一些反向工程后,我得到了一些目标函数或类方法的RVA和签名。但是很快我发现WinAppDbg的文档仅告诉我如何挂钩现有函数而不是调用它们。此外,通常目标函数的地址是从Process.resolve_label获取的,但是我只有RVA。如何将函数与其RVA挂钩?谢谢!

------------------更新1 -----------------------

为了清楚说明我要做什么,请考虑以下情况:

bool Player::attack(this, Animal *some_animal)中有一个称为some_game.exe的类方法,当我攻击任何动物时都会调用该方法。我想监视攻击事件,并可能随时模拟/触发攻击事件。

[检查完'some_game.pdb'文件后,我发现目标函数的RVA即Player::attack0x00678840。我制作了一个myplugin.dll文件,该文件将在游戏过程中注入。

然后像这样在myplugin.dll中调用此函数非常简单

#include <windows.h>

auto module_addr = reinterpret_cast<unsigned int>(GetModuleHandle(NULL));
attack_func = reinterpret_cast<void(*)(void*, void*)>(0x00678840+module_addr);
attack_func(...)

[通过首先定义一个辅助钩子函数Microsoft Detours library,钩子也很容易在void RegisterStaticHook(RVA sym, void* hook, void** org);的帮助下:

#include <windows.h>
// Detours
#include <detours/detours.h>

typedef uint64_t VA;
typedef unsigned int RVA;

template<typename Type>
using Ptr = Type*;

enum class HookErrorCode {
    ERR_SUCCESS,
    ERR_TRANSACTION_BEGIN,
    ERR_UPDATE_THREAD,
    ERR_ATTACH,
    ERR_DETACH,
    ERR_TRANSACTION_COMMIT
};
template<typename T = Ptr<void>>
auto Hook(Ptr<T> p, T f) {
    int error = DetourTransactionBegin();
    if (error != NO_ERROR) {
        return HookErrorCode::ERR_TRANSACTION_BEGIN;
    }
    error = DetourUpdateThread(GetCurrentThread());
    if (error != NO_ERROR) {
        return HookErrorCode::ERR_UPDATE_THREAD;
    }
    error = DetourAttach(
        reinterpret_cast<Ptr<PVOID>>(p),
        reinterpret_cast<PVOID>(f)
    );
    if (error != NO_ERROR) {
        return HookErrorCode::ERR_ATTACH;
    }
    error = DetourTransactionCommit();
    if (error != NO_ERROR) {
        return HookErrorCode::ERR_TRANSACTION_COMMIT;
    }
    return HookErrorCode::ERR_SUCCESS;
}

void RegisterStaticHook(RVA sym, void* hook, void** org) {
    auto base = reinterpret_cast<VA>(GetModuleHandle(NULL));
    *org = reinterpret_cast<void*>(base + sym);
    auto ret = Hook<void*>(org, hook);
    if (ret != HookErrorCode::ERR_SUCCESS) {
        std::cout << "[Error] ";
        switch (ret) {
        case HookErrorCode::ERR_TRANSACTION_BEGIN:
            std::cout << "DetourTransactionBegin";
            break;
        case HookErrorCode::ERR_UPDATE_THREAD:
            std::cout << "DetourUpdateThread";
            break;
        case HookErrorCode::ERR_ATTACH:
            std::cout << "DetourAttach";
            break;
        case HookErrorCode::ERR_DETACH:
            std::cout << "DetourDetach";
            break;
        case HookErrorCode::ERR_TRANSACTION_COMMIT:
            std::cout << "DetourTransactionCommit";
            break;
        default:
            break;
        }
        std::cout << "failed!" << std::endl;
    }
}

然后用[RegisterStaticHook]钩住my_attack

void** org;
bool my_attack(void* player_this, void* animal){
...
}

RegisterStaticHook(0x00678840, my_attack, org);

我的问题是如何使用WinAppDbg。

python debugging reverse-engineering
1个回答
0
投票

TL; DR:WinAppDbg并不真正支持此功能,这样做有点困难。请改用Microsoft Detours。

详细说明:

WinAppDbg是调试器,这意味着要修补/挂钩等的目标程序正在与Python脚本不同的Windows进程中运行。它只能以Win32 API允许的方式与调试过的进程进行交互,不幸的是,没有在目标进程中执行功能的机制。

您可以通过一些工作来模拟此功能。基本上,这意味着要修改寄存器和堆栈以执行钩子函数的开头,确保堆栈中的所有指针实际上都指向该进程中的有效内存,并可能分配一些蹦床代码以使WinAppDbg一旦该函数中断执行已经回来了。由于体系结构的差异,必须对32位和64位都重新进行一次此操作。这基本上就是像GDB这样的调试器所做的。

另一方面,Detours的工作原理是将DLL直接注入到您要定位的进程的内存中-因此执行代码很容易,因为您不必处理怪异的Win32 API调用或映射内存流程。这也快得多了。但是您将不得不使用C而不是Python进行编码。

© www.soinside.com 2019 - 2024. All rights reserved.