示例
外部动态库
mytest.c:
#include <stdio.h>
static void mytest_print(void)
{
printf("[%s:%d] %s\n", __FILE__, __LINE__, __FUNCTION__);
}
void mytest2(void)
{
printf("[%s:%d] %s\n", __FILE__, __LINE__, __FUNCTION__);
}
void mytest(void)
{
mytest_print();
}
编译
aarch64-linux-gnu-gcc -g -shared -fPIC mytest.c -o libmytest.so
主函数
mymain.c:
#include <stdio.h>
#include <time.h>
#include <unistd.h>
extern void mytest2(void);
extern void mytest(void);
int main(int argc, const char *argv[])
{
while (1) {
sleep(1);
mytest();
}
return 0;
}
编译
aarch64-linux-gnu-gcc -g -L. -Wl,-rpath=. mymain.c -lmytest
背景
- 在上述示例main中,通过mytest2替换mytest的调用。
原理
- 在本实例中主要利用动态库的重定位原理来,将重定位地址直接执行强制赋值操作,这样就会将原mytest的跳转地址修改为mytest2的跳转地址,完成了mytest2对mytest函数调用的替换操作。
查看a.out中的需要重定位的符号
查看0x410b18的实际值
(gdb) x /a 0x410b18
0x410b18 <mytest@got.plt>: 0x7fb7fc1820 <mytest>
(gdb) print mytest
$1 = {void (void)} 0x7fb7fc1820 <mytest>
替换过程
- 0x410b18地址对应的值为mytest对应函数的实际地址
- 只要将0x410b18地址对应的值替换为mytest2的实际地址,即可完成mytest2对mytest的替换操作
(gdb) set *0x410b18 = 0x7fb7fc17e8
(gdb) continue
替换前输出
[mytest.c:5] mytest_print
[mytest.c:5] mytest_print
替换后输出
[mytest.c:10] mytest2
[mytest.c:10] mytest2
[mytest.c:10] mytest2
[mytest.c:10] mytest2