3

是否有任何用于操作 x86 / x64 机器代码的 C 库?具体来说,我想在运行时修改程序地址空间中的一个函数。

例如,我有函数fooand bar,我有它们内部工作的来源或知识,但无法重新编译它们所在的库,并且我有baz我自己编写的函数。现在我想能够说这样的话:“在函数foo中,找到对 的调用,并在它前面bar注入指令”。baz该工具必须相应地调整程序中的所有相关地址。

我知道所有的点点滴滴都存在,例如有一些工具可以对功能进行热补丁。我想由于优化等原因,可能会有一些限制,但基本功能应该是可能的。我找不到类似的东西,有人有链接吗?

4

2 回答 2

3

This is known as 'self modifying code' (see wikipedia) and it used to be quite trendy in the 80s and early 90s. Particularly in machine code and ASM, however, it pretty much died out as an approach with modern languages because it's pretty fragile. Managed languages attempted to provide a more secure model as it was also the basis for a buffer-overrun attack.

Bearing in mind your code pages may be marked as read-only or copy-on-write and you might get access violation on many modern OS's, but if memory serves me, the basic principle you need to get hold of a memory address of a variable, or function, and you need to have quite specific knowledge about the code generated and/or stack layout at that location.

Here's some links to get you started;

  1. How to write self-modifying code in x86 assembly
  2. Self-modifying code for debug tracing in quasi-C

Specifically, in your case, I wouldn't modify foo by inserting operations and then trying to adjust all the code, all you need to do is change the jump address to bar to go through an intermediary. This is known as a Thunk. The advantage of doing it this way is that it's much less fragile to modify a jump address from one to another because it doesn't change the structure of the original function, just a number. In fact it's trivial by comparison.

In your thunk you can do whatever operations you like before and after you call the real function. If you're already in the same address space and your thunk code is loaded you're home.

If you're on Windows, you might also want to take a look at Detours.

于 2013-04-27T23:15:10.263 回答
1

If you're using gcc and you want to substitute a whole function, you can redirect, wrap a function using a -Wl,wrap,functionName switch : https://stackoverflow.com/a/617606/111160 .

Then anytime the code wants to access, call functionName it runs __wrap_functionName which you provide. You can still access the original with __real_functionName.

If you want to perform some actions before each call to baz, make your __wrap_baz do that actions and call __real_baz afterwards.

于 2013-04-27T23:18:12.950 回答