前言
本文论证了以下结论
- 类函数本质就是普通函数,第一个参数是类实例
func(cls*, ...)
- 函数地址就是模块地址(
GetModuleHandle
)+ 偏移量(dumpbin /exports dll.dll
)得到- 不包括虚函数,虚函数地址需要通过虚表获取
- 如果你可以获取到某个类实例地址,那么通过
GetModuleHandle
+GetProcAddress
的方式可以调用第三方程序的方法
dll.h
#ifndef FUNC_ADDRESS_DLL_H
#define FUNC_ADDRESS_DLL_H
#ifdef DLL_EXPORTS
# define DLL_API __declspec(dllexport)
#else
# define DLL_API __declspec(dllimport)
#endif // DLL_EXPORTS
class DLL_API Dll
{
public:
Dll();
int add_a(int a, int b);
};
int DLL_API add_b(int a, int b);
extern "C" int DLL_API add_c(int a, int b);
#endif // !FUNC_ADDRESS_DLL_H
dll.cpp
#define DLL_EXPORTS
#include "dll.h"
#include <iostream>
Dll::Dll()
{
}
int Dll::add_a(int a, int b)
{
std::cout << "this = " << this << std::endl;
return a + b;
}
int add_b(int a, int b)
{
return a + b;
}
int add_c(int a, int b)
{
return a + b;
}
main.cpp
#include "dll.h"
#include <iostream>
#include <Windows.h>
using namespace std;
typedef int(*AddFunc)(int a, int b);
typedef int(*HackFunc)(Dll *, int a, int b);
int main()
{
Dll dll;
union
{
void *pv;
int(Dll::* pfn)(int, int);
int(*fn) (Dll *, int a, int b);
} u;
u.pfn = &Dll::add_a;
cout << "Dll::add_a = " << &Dll::add_a << ", u.pv = " << u.pv << endl;
cout << "u.fn(nullptr, 10, 20) = " << u.fn(nullptr, 10, 20) << endl;
cout << "u.fn(dll, 10, 20) = " << u.fn(&dll, 10, 20) << endl;
cout << "(dll.*u.pfn)(10, 20) = " << (dll.*u.pfn)(10, 20) << endl;
int a = dll.add_a(10, 20);
cout << "Dll::add_a(20, 30)[" << &Dll::add_a << "] = " << a << endl;
int b = add_b(10, 20);
cout << "add_b(10, 20)[" << &add_b << "] = " << b << endl;
int c = add_c(10, 20);
cout << "add_c(10, 20)[" << &add_c << "] = " << c << endl;
HMODULE hmod = GetModuleHandleA("dll.dll");
cout << "hmod: " << hmod << endl;
AddFunc proc = (AddFunc)GetProcAddress(hmod, "add_c");
if (proc)
{
cout << "dynamic add_b(10, 20) = " << proc(10, 20) << endl;
}
return 0;
}
运行结果
Dll::add_a = 1, u.pv = 00007FFCA42E1073
this = 0000000000000000
u.fn(nullptr, 10, 20) = 30
this = 00000010975DF7D4
u.fn(dll, 10, 20) = 30
this = 00000010975DF7D4
(dll.*u.pfn)(10, 20) = 30
this = 00000010975DF7D4
Dll::add_a(20, 30)[1] = 30
add_b(10, 20)[00007FFCA42E102D] = 30
add_c(10, 20)[00007FFCA42E100A] = 30
hmod: 00007FFCA42E0000
dynamic add_b(10, 20) = 30
dumpbin /exports dll.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30133.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file dll.dll
File Type: DLL
Section contains the following exports for dll.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
6 number of functions
6 number of names
ordinal hint RVA name
1 0 00001136 ??0Dll@@QEAA@XZ = @ILT+305(??0Dll@@QEAA@XZ)
2 1 0000113B ??4Dll@@QEAAAEAV0@$$QEAV0@@Z = @ILT+310(??4Dll@@QEAAAEAV0@$$QEAV0@@Z)
3 2 000010A0 ??4Dll@@QEAAAEAV0@AEBV0@@Z = @ILT+155(??4Dll@@QEAAAEAV0@AEBV0@@Z)
4 3 00001073 ?add_a@Dll@@QEAAHHH@Z = @ILT+110(?add_a@Dll@@QEAAHHH@Z)
5 4 0000102D ?add_b@@YAHHH@Z = @ILT+40(?add_b@@YAHHH@Z)
6 5 0000100A add_c = @ILT+5(add_c)
Summary
1000 .00cfg
1000 .data
2000 .idata
1000 .pdata
3000 .rdata
1000 .reloc
1000 .rsrc
9000 .text