在运行时重定向 c 函数并调用原始函数

Posted

技术标签:

【中文标题】在运行时重定向 c 函数并调用原始函数【英文标题】:redirecting a c function at runtime and calling the original function 【发布时间】:2013-02-25 23:14:34 【问题描述】:

我的程序通过将 jmp 指令写入函数的前几个字节(仅 i386)将一个函数重定向到另一个函数。它按预期工作,但这意味着我不能再调用原始函数,因为它总是会跳转到新函数。

我能想到两种可能的解决方法:

    新建函数,覆盖目标函数的jmp指令并调用。之后该函数写回 jmp 指令。 但我不确定如何传递参数,因为它们可以有任意数量。我想知道目标函数是否可以在其他地方跳转并跳过写回 jmp 指令(比如 throw catch?)。

    创建一个新函数来执行我用 jmp 指令覆盖的代码。但我不能确定覆盖的数据是完整的指令。我必须知道要复制多少字节才能获得完整的说明。

所以,最后,我的问题:

    还有其他我没想到的方法吗?

    如何找到指令的大小?我已经查看了 binutils 并找到了 this 但我不知道如何解释它。

这是一个示例:

mov, 2, 0xa0, None, 1, Cpu64, D|W|CheckRegSize|No_sSuf|No_ldSuf,  Disp64|Unspecified|Byte|Word|Dword|Qword, Acc|Byte|Word|Dword|Qword 

第 2 列显示操作数 (2),最后一列包含有关操作数的信息,以逗号分隔

我还发现这个问题几乎相同,但我不能确定这 7 个字节是否包含完整的指令。 Writing a Trampoline Function

感谢任何帮助!谢谢。

【问题讨论】:

您是否正在尝试做一些用函数指针无法做到的更简单(和更便携)的事情? 我无法控制调用该函数的代码,所以,没有。我不能用函数指针来做。 也许您应该针对您的问题提供更多信息,以便我们了解您选择此解决方案的原因。然后我们可以帮助您或提出更好的建议。 我使用 hotpatch (github.com/vikasnkumar/hotpatch) 在正在运行的进程中加载​​共享库,现在我想将程序使用的函数重定向到共享库中的函数。 【参考方案1】:

Sebastian,您可以使用 hotpatch 中的 exe_load_symbols() 函数来获取符号列表及其在现有 exe 中的位置,然后查看是否可以在内存中覆盖它。我还没有尝试过。您也可以使用 LD_PRELOAD 环境变量来代替热补丁。

--维卡斯

【讨论】:

【参考方案2】:

这样的事情怎么样:

假设这是原始函数:

Instruction1
Instruction2
Instruction3
...
RET

将其转换为:

JMP new_stuff
old:
Instruction2
Instruction3
...
RET
...
new_stuff:
CMP call_my_function,0
JNZ my_function
Instruction1
JMP old
my_function:
...

当然,您必须考虑原始指令的大小(例如,您可以通过使用 objdump 反汇编来发现),以便第一个 JMP 完美匹配(使用 NOP 填充s 如果JMP 比原始指令短)。

【讨论】:

感谢您的帮助。获得原始指令的大小似乎非常困难。我不能使用 objdump,因为我必须知道函数的名称或二进制文件中的地址。进程中的地址和二进制文件中的地址可能不同。编辑:我尝试使用 libopcodes,但失败得很惨。

以上是关于在运行时重定向 c 函数并调用原始函数的主要内容,如果未能解决你的问题,请参考以下文章

RouterBrowser 不会在刷新时重定向到默认页面

.NET 实现启动时重定向程序运行路径及 Windows 服务运行模式部署

Google OAuth Api 未在登录时重定向

滚动时重定向到*新页面* - 如何添加时间延迟?

防止表单提交重定向

收集启动函数