C:转换函数指针以编辑可执行代码

标签 c

假设如下代码:

int f1(int x, int y);

int main(void) {
    printf("%d", f1(2,3));
    char* x = (char*)&f1;
    //edit the stuff here?
    printf("%d", f1(2,3));
    return 0;
}

int f1(int x, int y){
    return x*y;
}

现在,尽管事实上这真的很愚蠢而且您永远不会实际上这样做,但您会怎么做呢?如果我想让这个函数将两个数字相加,而不是相减,或者甚至做一些更复杂的事情,我应该采取什么步骤?我如何找出正确的机器代码以获得所需的结果?

最佳答案

虽然这并非不可能,但通常是不切实际的,因为存在重大障碍,包括:

  • 包含机器指令的内存通常标记为不可写,因此您必须先更改保护设置才能更改。 (在 Unix 系统上,查看 mprotect。)
  • 需要进行的更改取决于架构——每个处理器架构都有自己的指令和这些指令的编码。您必须弄清楚要编写哪些新指令以及如何对它们进行编码。
  • 有一种广泛使用的软件可以对指令进行编码,即汇编程序。要即时将指令转换为编码,可以在程序中嵌入汇编器或在另一个进程中调用汇编器。然后就是如何从汇编程序的输出(目标文件)中提取指令的问题。汇编程序也可以以普通方式用于准备给定的指令序列,而不是在正在运行的程序中即时使用。
  • 刚被汇编程序编码后的指令通常以中间形式表示,其中对内存中特定位置的引用要么是符号性的,要么是相对于某些引用点的。在将它们放入正在运行的程序之前,必须将这些引用解析为程序中的实际地址。
  • 一旦您知道要在函数中替换哪些指令,就会出现这样的问题,即它们可能比要替换的指令大,所以它们不适合。然后您需要一个解决方法,例如为您的指令找到一个替代位置,而不是将您的指令放在函数中,而是放入一条跳转到您的指令的小指令。请注意,您用于指令的内存必须标记为可执行。
  • 更改主内存后,指令缓存可能保存指令的旧副本,因此您需要刷新指令缓存。

从减法到加法的简单更改可以通过找到相关的减法指令、更改内存保护、在减法上写入加法指令以及刷新指令缓存来完成。除此之外的任何事情都会更加复杂。

关于C:转换函数指针以编辑可执行代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54891800/

相关文章:

c - 使用 soxr 和 libsndfile 重新采样 PCM 文件数据会崩溃

c - 在汇编程序中,为什么寄存器的使用在加法和减法之间有所不同?

c - 我的代码中是否有任何未初始化的值?

c - 当内存不足时,如何防止变长数组崩溃?

c - 如何在 switch 与 integer using 中使用枚举

c - C 中动态的、大小不可预测的数组

c - 将结构传递给函数并将值存储在结构的元素中

"#pragma omp parallel for "可以在循环内使用吗?

c - 在内存中执行机器代码

c - 消息队列多接收者实现