python - 给定该函数的 RVA,如何使用 WinAppDbg 挂钩和调用现有函数?
问题描述
我正在尝试使用 WinAppDbg 为游戏编写插件,其中涉及挂钩和调用该游戏中的现有函数。经过一些逆向工程工作,我得到了一些目标函数或类方法的 RVA 和签名。但很快我发现WinAppDbg的文档只告诉我如何hook现有函数而不是调用它们。此外,通常目标函数的地址来自 Process.resolve_label,但我只有 RVA。如何将函数与它的 RVA 挂钩?谢谢!
------------------ 更新 1------------------------
为了弄清楚我要做什么,请考虑以下情况:
有一个类方法调用bool Player::attack(this, Animal *some_animal)
,some_game.exe
当我攻击任何动物时都会调用它。我想监视攻击事件,并可能随时模拟/触发攻击事件。
在检查了“some_game.pdb”文件后,我发现目标函数的 RVAPlayer::attack
即0x00678840
. 我制作了一个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 库的帮助下,挂钩也很容易,首先定义一个辅助挂钩函数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;
}
}
my_attack
然后像这样使用“RegisterStaticHook”挂钩:
void** org;
bool my_attack(void* player_this, void* animal){
...
}
RegisterStaticHook(0x00678840, my_attack, org);
我的问题是如何用 WinAppDbg 做到这一点。
解决方案
TL;DR:WinAppDbg 并不真正支持这一点,而且这样做会有点困难。请改用 Microsoft Detours。
长解释:
WinAppDbg 是一个调试器,这意味着您要修补/挂钩等的目标程序运行在与 Python 脚本不同的 Windows 进程中。它只能以 Win32 API 允许的方式与被调试的进程交互,不幸的是,没有在目标进程中执行函数的机制。
您可以通过一些工作在某种程度上模拟此功能。基本上这意味着修改寄存器和堆栈以执行挂钩函数的开头,确保堆栈中的所有指针实际上都指向进程中的有效内存,并可能分配一些蹦床代码以允许 WinAppDbg 在函数执行后中断执行已经回来了。由于架构差异,这对于 32 位和 64 位都必须重新完成。这基本上就是像 GDB 这样的调试器所做的。
另一方面,Detours 通过将 DLL 直接注入您要定位的进程的内存来工作 - 因此执行代码轻而易举,因为您不必处理奇怪的 Win32 API 调用或跨进程映射内存。它也快了很多。但是你必须用 C 而不是 Python 编写代码。
推荐阅读
- php - 在codeigniter php中提交表单后不清除数据
- asp.net-core - CentOS 7 上带有 GDI+ 的 ASP.NET Core 3.0
- scala - 使用 Intellij IDEA 在 Maven 中使用 Scala 的 Spark 工作流和调度框架
- javascript - 如何在 Bootstrap 轮播的下一个/上一个单击时加载 JSP 页面
- c# - 尝试显示 umbraco 文件夹中的图像时出错
- angular - Angular:访问投影的 FormGroup
- elasticsearch - 如何将文档特征信息(从其他来源提取)添加到现有的弹性搜索索引?
- r - 逐对计算行相似性百分比并将其添加为新列
- mysql - JOIN 语句的 SQL 问题(来自 1 个表的多个结果)
- android - 如何在 Android 中从 JSONObject 生成 PDF?