如何从DLL注入进程的受害者进程调用静态库静态类成员函数

时间:2019-04-29 13:32:36

标签: c++ static-libraries dll-injection

我已经成功地用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。

我猜这是因为它是两个单独的翻译单元,所以当从我的钩子进程中调用时,它会创建不同版本的单例。

1 个答案:

答案 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);