C++中向Hook函数返回值传递自定义监听器类对象是否可行?
核心问题原因
- 类布局不匹配:你自定义的
MyListener和目标程序的IListener虚函数表结构完全不一致。通常C++带I前缀的接口类都是纯虚类,虚函数的声明顺序、每个函数的签名、调用约定都是固定的,你自己写的GetTypeOfEvent、OnEventHappening的顺序、参数、调用约定如果和目标侧IListener定义不一样,目标程序调用回调时会执行错误的内存地址,自然不会触发你的打印逻辑。 - 注册函数是你自己写的空实现:你声明了
RandomEventListener的RegisterToEvent之后自己写了个空函数体,你代码里调用的根本不是目标程序EventsForMe.dll里的真实注册逻辑,等于你根本没把监听器注册到目标的事件系统里。 - 函数获取与调用逻辑错误:你用
GetProcAddress拿到了GetEventReg的地址却没有调用,反而去获取了不存在的connect导出函数赋值给orig,后续调用orig.RegisterToEvent的逻辑完全不成立,你应该先调用GetEventReg拿到目标侧返回的RandomEventListener实例,再调用实例的真实注册方法。 - 调用约定缺失:C++非静态成员函数的默认调用约定是
__thiscall,你没有在自定义类的成员函数上显式声明匹配的调用约定,目标程序触发回调时参数传递(包括this指针)会完全错乱,你现在程序没有崩溃纯属巧合。
可行性说明
从注入DLL向被注入程序传递类对象作为监听器是可行的,但前提是你自定义的类必须和目标侧的接口类内存布局、虚表顺序、函数签名、调用约定完全一致,和Hook是否需要引入原有代码无关,这种二进制层面的交互必须严格对齐结构定义。
修复方向
- 先逆向分析目标侧
IListener的完整定义,确认虚函数的数量、顺序、每个函数的参数列表、返回值、调用约定,你的MyListener必须按照完全相同的顺序声明虚函数,签名和调用约定完全匹配。 - 删除你自己实现的
RandomEventListener::RegisterToEvent空实现,改用函数指针的方式调用目标实例的成员函数,成员函数指针需要显式指定__thiscall调用约定,同时手动传递实例的this指针作为第一个参数。 - 正确调用
GetEventReg拿到真实的RandomEventListener实例,再调用实例的RegisterToEvent方法完成监听器注册。 - 给你自定义
MyListener的所有虚函数加上__stdcall或者__thiscall修饰,和目标侧保持一致。
内容的提问来源于stack exchange,提问作者Malte
相关产品推荐
相关产品推荐

