是否有用于操作x86 / x64机器代码的C库?具体来说,我想在运行时修改程序地址空间中的函数。
例如,我有函数foo
和bar
,我有其内部工作的来源或知识,但无法重新编译它们所在的库,我有我自己写的函数baz
。现在,我希望能够说出以下内容:“在函数foo
中,找到对bar
的调用,并在其前面注入baz
的说明”。该工具必须相应地调整程序中的所有相关地址。
我知道所有的零碎都存在,例如,有工具可以进行热修补功能。我想由于优化等原因会对可能的内容有一些限制,但基本功能应该是可能的。我找不到这样的东西,有没有人有链接?
答案 0 :(得分:3)
这被称为“自我修改代码”(参见wikipedia),它曾经在80年代和90年代初很流行。然而,特别是在机器代码和ASM中,它几乎作为现代语言的方法而消失,因为它非常脆弱。托管语言试图提供更安全的模型,因为它也是缓冲区溢出攻击的基础。
请记住,您的代码页可能被标记为只读或写时复制,并且您可能会在许多现代操作系统上获得访问冲突,但如果内存为我服务,则需要获取内存的基本原则变量或函数的地址,您需要对该位置生成的代码和/或堆栈布局有非常具体的了解。
这里有一些让你入门的链接;
具体来说,在您的情况下,我不会通过插入操作来修改foo
,然后尝试调整所有代码,您需要做的就是更改{{1} }地址jump
通过中间人。这被称为bar
。这样做的好处是,将跳转地址从一个地址修改为另一个地址要脆弱得多,因为它不会改变原始函数的结构,只是一个数字。事实上,相比之下它是微不足道的。
在Thunk
中,您可以在调用真实函数之前和之后执行您喜欢的任何操作。如果您已经在相同的地址空间并且加载了thunk代码,那么您就回家了。
如果您使用的是Windows,则可能还需要查看Detours.
答案 1 :(得分:1)
如果您正在使用gcc
并且想要替换整个函数,则可以使用-Wl,wrap,functionName
开关重定向,包装函数:https://stackoverflow.com/a/617606/111160。
然后,只要代码想要访问,请调用functionName
它运行您提供的__wrap_functionName
。您仍然可以使用__real_functionName
访问原始文件。
如果您想在每次致电baz
之前执行某些操作,请让__wrap_baz
执行此操作,然后再致电__real_baz
。