【问题标题】:Hooking non-virtual class member function挂钩非虚拟类成员函数
【发布时间】:2014-01-17 22:18:13
【问题描述】:

我设法挂钩了我想要的所有东西(API 函数、虚拟方法、“标准”函数),但我想知道如何挂钩 非虚拟 类成员函数(方法)。 要挂钩虚拟方法,您只需要获取 VTable 并对其进行修补(或复制、修改并更改 VPointer)。但是,当方法是NOT virtual时,没有VTable。

首先,我怎样才能从 name 中获取我想要挂钩的方法的地址?我不能使用GetProcAddress(),因为该函数没有导出。唯一的方法似乎是在内存中搜索与函数对应的字节模式。 那么,一旦我得到了地址,我该如何挂钩呢?使用基本方法 (JMP)?如果我只想挂钩一个实例怎么办?我想我会检查我的挂钩函数:如果它是正确的实例,那么就做必须做的事情,否则只执行它而不做任何其他事情。

实际上我正在寻找更好的解决方案,因为我认为上面的解决方案可行,但它们不是很“整洁”,是吗?

谢谢。

【问题讨论】:

  • 我不太了解WinAPI,但您可以使用&ClassName::member_name 语法获取成员函数的地址。
  • 假设ClassName 不是我可以在我的DLL 中#include 的库的一部分(我想注入它),而是它是在我想挂钩的程序中定义的一个类:我可以'不要在我的DLL中写&ClassName:member_name,我会得到一个编译错误。

标签: c++ windows hook


【解决方案1】:

大多数时候根本不可能转移静态解析的函数。您是否听说过这种称为 inlining 的优化?即使没有发生这种情况,COMDAT 折叠也会使您无法隔离您感兴趣的功能。

强烈推荐阅读:Raymond Chen's "Why does the debugger show me the wrong function?"

【讨论】:

  • “静态解析函数”是什么意思?是的,我忘记了内联......你是对的,这可能是有问题的。至于 COMDAT 折叠,假设该函数在程序中被引用,因此它没有被链接器删除(我不会挂钩未使用的函数?)。那么如果这个函数没有被内联,你将如何继续挂钩呢?
  • @GuiTeK:静态解析意味着编译器在编译时准确地决定(解析)什么函数被调用。这包括对命名非虚拟函数的所有调用。虚函数和通过函数指针的调用可能是静态解析或动态解析的,这取决于编译器是否能找出确切的类型。
  • 另外,通过 COMDAT 折叠,我的意思是包含相同指令的函数(在 C++ 中发生的频率比您最初想象的要多,例如所有读取并返回整数的 getter 存储 8 个字节到无论对象的实际类型如何,对象倾向于产生完全相同的机器代码)然后这些函数被映射到可执行文件中的相同位置。见stackoverflow.com/questions/15168924/… 然后考虑替换共享单个实现的功能之一的问题。
猜你喜欢
  • 2014-01-04
  • 2012-09-27
  • 1970-01-01
  • 2018-03-18
  • 2010-11-14
  • 2010-09-21
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多