C++ DLL代理指定修饰名导出实现调用拦截及相关问题咨询
问题1解决:汇编跳转参数传递与返回值处理
你不需要手动处理参数和返回值,只要将包装函数声明为__declspec(naked),函数内部不修改栈和寄存器直接跳转即可,调用约定的处理逻辑由原函数自行实现:
- 针对
__cdecl调用约定的静态成员函数,栈参数由调用方维护,直接跳转不会破坏栈结构 - 针对
__thiscall调用约定的普通成员函数,ecx寄存器存储的this指针、栈上存储的参数都会原封不动传递给原函数,原函数执行完成后的返回值会存储在eax寄存器中,直接返回给上层调用方
示例代码如下:
class CRfebUsbApp { public: #pragma comment(linker, "/export:?GetInstance@CRfebUsbApp@@SAPAV1@XZ=?GetInstance@CRfebUsbApp@@SAPAV1@XZ") __declspec(naked) static CRfebUsbApp* __cdecl GetInstance(); #pragma comment(linker, "/export:?CmtReadRegs@CRfebUsbApp@@QAEEEQAEG@Z=?CmtReadRegs@CRfebUsbApp@@QAEEEQAEG@Z") __declspec(naked) unsigned char __thiscall CmtReadRegs(unsigned char, unsigned char* const, unsigned short); private: }; // 全局提前加载好的原函数地址 static FARPROC getInstance, cmtReadRegs; __declspec(naked) CRfebUsbApp* __cdecl CRfebUsbApp::GetInstance(void) { _asm { // 如需添加日志逻辑,此处先push所有用到的寄存器保存现场,日志执行完pop恢复再跳转 jmp [getInstance] } } __declspec(naked) unsigned char __thiscall CRfebUsbApp::CmtReadRegs(unsigned char, unsigned char* const, unsigned short) { _asm { // 如需添加日志逻辑,此处先push所有用到的寄存器保存现场,日志执行完pop恢复再跳转 jmp [cmtReadRegs] } }
问题2解决:批量封装60+导出函数
可以通过宏定义+脚本预生成的方式完全避免重复手动编码:
- 先通过
dumpbin /exports OriginalDll.dll命令导出原DLL所有的修饰名、序号、调用约定列表,整理为统一的配置表 - 选择以下两种方式之一批量生成代码:
- 宏批量生成:定义通用包装宏,每个函数只需要一行代码生成完整逻辑:
// 通用包装宏定义 #define DEFINE_WRAP(raw_func_name, mangled_name, func_ptr, ret_type, call_conv, ...) \ #pragma comment(linker, "/export:" #mangled_name "=" #mangled_name) \ __declspec(naked) ret_type call_conv CRfebUsbApp::raw_func_name(__VA_ARGS__) { \ _asm { jmp [func_ptr] } \ } // 批量声明原函数指针 static FARPROC getInstance, cmtReadRegs /* 剩余所有函数指针依次声明 */; // 批量生成包装函数,每个函数只需要一行 DEFINE_WRAP(GetInstance, ?GetInstance@CRfebUsbApp@@SAPAV1@XZ, getInstance, CRfebUsbApp*, __cdecl, void) DEFINE_WRAP(CmtReadRegs, ?CmtReadRegs@CRfebUsbApp@@QAEEEQAEG@Z, cmtReadRegs, unsigned char, __thiscall, unsigned char, unsigned char* const, unsigned short) // 剩余60+函数按格式补全即可
- 脚本自动生成:写简单的Python/JS脚本读取dumpbin的输出结果,自动生成所有函数的声明、指针定义、包装代码,完全不需要手动填写。
也可以用模块定义文件(.def)统一管理所有导出项,不需要逐个添加编译指令:
EXPORTS ?GetInstance@CRfebUsbApp@@SAPAV1@XZ=?GetInstance@CRfebUsbApp@@SAPAV1@XZ @1 ?CmtReadRegs@CRfebUsbApp@@QAEEEQAEG@Z=?CmtReadRegs@CRfebUsbApp@@QAEEEQAEG@Z @2 ; 其他导出项按序号依次添加即可
内容的提问来源于stack exchange,提问作者Marco Arigliani
相关产品推荐
相关产品推荐

