进程注入场景下无对应lib文件如何将类函数调用链接到进程已加载模块
提问内容
我当前的需求是向目标进程注入后调用该进程内已加载的模块,这一步通过调用GetProcAddress()按需获取单个函数就可以直接实现。
但我还需要使用第三方API文件,这些文件包含可用于发起各类API调用的类,将其导入我的项目尝试编译时,出现了LNK2019 unresolved external symbol报错。该报错的原因是我没有导入对应的lib文件,而我目前无法获取到这些lib文件,因此想要直接使用注入目标进程中已加载的对应模块。
我暂时找不到将这两个需求结合的实现方法,请问如何才能将类文件中的各类函数调用链接到进程内已加载的模块?如果该方案不可行,应该采用什么替代思路?
编辑:已修正关于lib文件的相关表述
解决方案
直接绑定进程内已加载模块的可行方法
如果你手里的第三方头文件类定义和目标进程中加载的模块编译时的定义完全一致(包括成员顺序、内存对齐、调用约定、虚函数表顺序),可以通过两种方式实现免lib链接:
- 手动生成伪lib文件
你不需要拿到官方的lib文件,只需要梳理出所有你用到的导出函数的完整修饰名,编写一个.def文件,格式如下:
LIBRARY 目标第三方模块的文件名.dll EXPORTS 你用到的函数1修饰名 @1 你用到的函数2修饰名 @2 ... 其他你需要的函数
之后用VS自带的lib /def:你的def文件路径 /out:生成的lib文件名.lib /machine:x86(或者x64对应你的架构)命令生成伪lib文件,项目链接时引入这个lib即可解决LNK2019报错。运行时由于目标进程已经提前加载了对应模块,系统会直接绑定到进程内已加载的模块地址,不需要额外加载dll。
2. 代理类转发调用
不想生成伪lib的话,可以自己编写代理类:
- 注入后首先调用
GetModuleHandle(第三方模块名)获取进程内已加载的模块句柄,再通过GetProcAddress()拿到所有你需要用到的类成员函数、全局函数的地址,定义对应调用约定的函数指针存储这些地址。 - 重写头文件中的类,将所有成员函数的实现改为调用对应函数指针,主动传递this指针和参数即可。如果是纯虚类,直接用头文件定义转换实例指针即可,无需额外处理,虚表会直接指向模块内已有的实现。
方案不可行时的替代思路
如果无法获取到完整的函数修饰名、或者类未导出、类定义和目标模块不匹配:
- 放弃直接使用第三方头文件的类调用,自己封装所有API调用逻辑,全部通过
GetProcAddress()拿到的函数指针发起调用,只需要匹配调用约定和参数顺序即可,不需要处理链接问题。 - 如果是COM组件类,直接用COM的标准接口调用逻辑,不需要链接lib,调用
CoCreateInstance即可拿到实例指针,直接用头文件的接口定义调用即可。
注意事项
- 所有类、结构体的定义必须和目标模块编译时的定义完全对齐,否则会出现内存访问错误、调用栈不平衡等崩溃问题。
- 32位和64位程序的函数修饰名规则、调用约定存在差异,需要对应目标进程的架构处理。
内容的提问来源于stack exchange,提问作者piper123
相关产品推荐
相关产品推荐

