简单来说,我们有两个类似的功能:
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程序中不起作用.什么有用?
解决方法:
不要覆盖该过程,而是覆盖符号表中的符号引用.这确实需要动态联系.或者你可以通过调用另一个函数来覆盖函数的调用,但是像NX位这样的东西可能会阻挡你.自修改代码通常不受欢迎.