C:逐字节覆盖另一个函数

phi*_*mue 6 c byte function

我们假设我有一个功能:

int f1(int x){
 // some more or less complicated operations on x
 return x;
}
Run Code Online (Sandbox Code Playgroud)

而且我有另一个功能

int f2(int x){
 // we simply return x
 return x;
}
Run Code Online (Sandbox Code Playgroud)

我希望能够做类似以下的事情:

char* _f1 = (char*)f1;
char* _f2 = (char*)f2;
int i;
for (i=0; i<FUN_LENGTH; ++i){
 f1[i] = f2[i];
}
Run Code Online (Sandbox Code Playgroud)

即我想解释f1f2作为原始字节数组和" f1逐字节覆盖",因此,替换它f2.

我知道通常可调用的代码是写保护的,但是,在我的特定情况下,您可以简单地覆盖所在的内存位置f1.也就是说,我可以将字节复制到f1,但之后,如果我调用f1,整个事情就会崩溃.

那么,我的方法原则上可行吗?或者是否有一些我需要考虑的机器/实现/任何依赖性问题?

Gre*_*ill 8

f1机器jump指令的前几个字节替换为开头更容易f2.这样,您就不必处理任何可能的代码重定位问题.

此外,有关函数占用的字节数(FUN_LENGTH在您的问题中)的信息通常在运行时不可用.使用a jump也可以避免这个问题.

对于x86,您需要的相对跳转指令操作码E9(根据此处).这是一个32位的相对跳转,这意味着你需要计算f2和之间的相对偏移量f1.这段代码可能会这样做:

int offset = (int)f2 - ((int)f1 + 5); // 5 bytes for size of instruction
char *pf1 = (char *)f1;
pf1[0] = 0xe9;
pf1[1] = offset & 0xff;
pf1[2] = (offset >> 8) & 0xff;
pf1[3] = (offset >> 16) & 0xff;
pf1[4] = (offset >> 24) & 0xff;
Run Code Online (Sandbox Code Playgroud)

偏移量取自JMP指令的末尾,这就是为什么f1在偏移量计算中将5添加到地址的原因.

使用汇编级调试器逐步执行结果是一个好主意,以确保您正在查找正确的字节.当然,这一切都不符合标准,所以如果它打破了你就可以保留两件.