我已经成功地用DLL注入钩住了受害者应用程序。 现在,我需要调用受害者进程的未导出单例函数。 这可能吗,我该怎么办?
虽然我有受害者进程的目标文件等,但是我无法重建/部署新版本,所以我不能只创建具有导出链接的函数。
我在挂钩过程中尝试过代码:
#include "VictimSingleton.h"
//...
void SomeFuncInHook()
{
VictimSingleton *vs = VictimSingleton::Get();
vs->DoThing();
}
内部实现Get()的方式如下:
VictimSingleton* VictimSingleton::Get()
{
static VictimSingleton singleton;
return &singleton;
}
预期结果:当从我的钩子或受害者进程中调用时,VictimSingleton :: Get()返回相同的地址。
实际结果: Get返回的指针在有效的同时指向与受害者进程所使用的指针不同的VictimSingleton。
我猜这是因为它是两个单独的翻译单元,所以当从我的钩子进程中调用时,它会创建不同版本的单例。
答案 0 :(得分:1)
如果未导出函数,则说明您没有PDB并且未嵌入调试符号,那么首先必须使用反汇编程序(例如IDA Pro)找到该函数。如果它是一个虚拟函数,则找到它会容易得多,因为您可以使用IDA插件(例如Class Informer)公开运行时类型信息,这将为您提供所有vtable函数的列表。
一旦有了函数的地址,就需要颠倒它的调用约定及其参数。这很可能是__thiscall函数,因为它是成员函数。
接下来,为了调用成员函数,您需要一个类实例作为this指针传递。为此,您还可以找到该类的构造函数并使用它的返回值作为实例来调用它。
接下来,您需要调用该函数。要调用__thiscall函数,您实际上将其称为__fastcall,并将作为this指针创建的对象的地址作为第一个参数传递,将第二个变量的0传递,然后是实际的函数参数。
第二个参数为零,因为__fastcall期望在EDX中传递一个变量。
Typedef函数指针原型,创建此函数指针的实例,为其分配函数地址,然后调用它。
typedef void(__fastcall* fFunc)(void* thisptr, void* not_edx, float arg1, int arg2);
fFunc Func = (fFunc)0xDEADC0DE; //address of function
Func(objectPtr, 0, 1.0f, 2);