简单来说,我们有两个类似的函数:
void f1()
{
printf("%d", 123);
}
void f2()
{
printf("%d", 124);
}
现在我们在main中调用f1,它会打印123。编译时,反汇编f1
可能是这样的:
08048424 <f1>:
8048424: 55 push %ebp
8048425: 89 e5 mov %esp,%ebp
8048427: 83 ec 18 sub $0x18,%esp
804842a: b8 40 86 04 08 mov $0x8048640,%eax
804842f: c7 44 24 04 7b 00 00 movl $0x7b,0x4(%esp)
8048436: 00
8048437: 89 04 24 mov %eax,(%esp)
804843a: e8 05 ff ff ff call 8048344 <printf@plt>
804843f: c9 leave
8048440: c3 ret
f2 的机器码与 f1 类似。
现在我想在运行时用f2的机器码替换f1。我使用 memcpy(f1, f2, SIZE_OF_F2_MACHINE_CODE)。
当然,问题来了——段错误。
现在我想知道是否有解决方案可以解决这个问题。这是一个常见的C程序。
据我所知,我们可以使用下面的代码在Linux内核中设置页面可写:
int set_page_rw(long unsigned int addr)
{
unsigned int level;
pte_t *pte = lookup_address(addr, &level);
if(pte->pte & ~_PAGE_RW)
pte->pte |= _PAGE_RW
}
但它不适用于普通的 Linux C 程序。那么什么有效呢?