我想知道如何将调用切换到可执行文件(在我的情况下为.exe)中另一个函数的调用
这是我尝试使用的代码
#include <stdio.h>
void hello()
{
printf("Hello world!");
}
void investigate()
{
printf("Investigate all the things!");
}
main()
{
hello();
}
一旦我用gcc编译了上面的代码并获得了可执行文件(.exe),我想将“ hello”调用切换为“ investigate”。
-编辑-
我的环境:Windows 10(64位),使用gcc / g ++ 4.8.1的mingw
-编辑2-
我对Linux的回答(任何Ubuntu,OpenSuse和任何体系结构)都很好,因为对我来说,有一个概念证明非常重要。
答案 0 :(得分:2)
假设编译器没有完全省略死函数,没有内联函数并且调用不会通过PLT,那么一旦编译了可执行文件,就可以简单地编辑调用指令。
请注意,这两个函数必须是“兼容的”,兼容性的概念是模糊的,这意味着“新函数必须至少满足编译器在调用旧函数时所做的相同假设”。
ABI当然是这样的假设之一,但可能不是唯一的假设。
如果编译器省略了死函数,则无法切换该函数(缺少一个)。
如果编译器内联了该调用,则无法切换该函数(没有调用)。您可以对编译器进行操作并在调用站点(在C源代码中)重写代码,这称为修补。
如果编译器使用PLT,则需要更改PLT存根使用的GOT条目。您可能需要稍微记录一下自己,但更改链接的过程实际上是PLT机械的功能。
如果您的编译器没有执行任何操作,那么在没有启用优化的情况下,对于这样一个简单的源应该是这种情况,您可以使用objdump -d <file>
查找调用位置和新函数的地址:>
000000000040051d <hello>:
40051d: 55 push %rbp
40051e: 48 89 e5 mov %rsp,%rbp
400521: bf f0 05 40 00 mov $0x4005f0,%edi
400526: b8 00 00 00 00 mov $0x0,%eax
40052b: e8 d0 fe ff ff callq 400400 <printf@plt>
400530: 5d pop %rbp
400531: c3 retq
0000000000400532 <investigate>:
400532: 55 push %rbp
400533: 48 89 e5 mov %rsp,%rbp
400536: bf fd 05 40 00 mov $0x4005fd,%edi
40053b: b8 00 00 00 00 mov $0x0,%eax
400540: e8 bb fe ff ff callq 400400 <printf@plt>
400545: 5d pop %rbp
400546: c3 retq
0000000000400547 <main>:
400547: 55 push %rbp
400548: 48 89 e5 mov %rsp,%rbp
40054b: b8 00 00 00 00 mov $0x0,%eax
400550: e8 c8 ff ff ff callq 40051d <hello>
400555: b8 00 00 00 00 mov $0x0,%eax
40055a: 5d pop %rbp
40055b: c3 retq
40055c: 0f 1f 40 00 nopl 0x0(%rax)
然后使用目标地址和call
指令结束后的地址之间的差值来更改call
指令的立即数(原点只要是两个地址都一样)。
Target = 400532
After the end of call = 400555
Difference = 400532 - 400555 = -23 = 0xFFFFFFDD
Change from:
400550: e8 c8 ff ff ff
to:
400550: e8 dd ff ff ff
请注意,立即数是小端的。
您可以使用hexeditor编辑代码,找到偏移量到文件中,您可以使用elf阅读器并进行一些数学运算,也可以简单地搜索调用指令的字节(也请检查周围的字节)请务必致电)。
编辑后,二进制文件已被修补:
0000000000400532 <investigate>:
400532: 55 push %rbp
400533: 48 89 e5 mov %rsp,%rbp
400536: bf fd 05 40 00 mov $0x4005fd,%edi
40053b: b8 00 00 00 00 mov $0x0,%eax
400540: e8 bb fe ff ff callq 400400 <printf@plt>
400545: 5d pop %rbp
400546: c3 retq
0000000000400547 <main>:
400547: 55 push %rbp
400548: 48 89 e5 mov %rsp,%rbp
40054b: b8 00 00 00 00 mov $0x0,%eax
400550: e8 dd ff ff ff callq 400532 <investigate>
400555: b8 00 00 00 00 mov $0x0,%eax
40055a: 5d pop %rbp
40055b: c3 retq