示例
主程序动态链接库
// 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)
{
mytest2();
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
被注入的动态库
// mytest2.c:
#include <stdio.h>
static void mytest3(void)
{
printf("[%s:%d]This is a injection procedure!\n", __FILE__, __LINE__);
}
编译
aarch64-linux-gnu-gcc -g -shared -fPIC mytest2.c -o libmytest2.so
背景
- 在上述主函数main中调用了mytest函数,在动态库libmytest.so中的mytest中调用了mytest2函数,在此处将mytest中所调用的mytest2函数替换为另一个外部动态库libmytest2.so中的mytest3函数。
原理
- 此处依然利用动态库的重定位原理,将mytest2对应的重定位地址的值强制修改为mytest3函数的地址即可完成mytest3对mytest2的替换操作。
操作步骤
查看重定位地址(aarch64-linux-gnu-readelf -r libmytest.so)
Relocation section '.rela.plt' at offset 0x5e8 contains 4 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000010ad0 000500000402 R_AARCH64_JUMP_SL 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0
000000010ad8 000a00000402 R_AARCH64_JUMP_SL 0000000000000000 __gmon_start__ + 0
000000010ae0 001100000402 R_AARCH64_JUMP_SL 0000000000000000 printf@GLIBC_2.17 + 0
000000010ae8 001300000402 R_AARCH64_JUMP_SL 0000000000000808 mytest2 + 0
- 从上述结果可知mytest2的重定位地址为:0x10ae8
- 0x10ae8表示mytest2在libmytest.so ELF文件中的偏移地址
- 当libmytest.so被加载到进程空间后,mytest2的重定位地址为:页偏移基址 + 0x10ae8
计算mytest2的重定位地址
0x7fb7fc1000 0x7fb7fc2000 0x1000 0x0 /data/libmytest.so
0x7fb7fc2000 0x7fb7fd1000 0xf000 0x1000 /data/libmytest.so
0x7fb7fd1000 0x7fb7fd2000 0x1000 0x0 /data/libmytest.so
导入动态库libmytest2.so
(gdb) call (void *)__libc_dlopen_mode("./libmytest2.so", 2)
$2 = (void *) 0x411440
(gdb) print mytest3
$3 = {void (void)} 0x7fb7e65720 <mytest3>
mytest3替换mytest2函数
(gdb) print mytest3
$3 = {void (void)} 0x7fb7e65720 <mytest3>
(gdb) set *0x7fb7fd1ae8 = 0x7fb7e65720
(gdb) continue
结果展示
替换前
[mytest.c:10] mytest2
[mytest.c:5] mytest_print
[mytest.c:10] mytest2
[mytest.c:5] mytest_print
[mytest.c:10] mytest2
[mytest.c:5] mytest_print
[mytest.c:10] mytest2
[mytest.c:5] mytest_print
[mytest.c:10] mytest2
[mytest.c:5] mytest_print
[mytest.c:10] mytest2
[mytest.c:5] mytest_print
替换后
[mytest2.c:5]This is a injection procedure!
[mytest.c:5] mytest_print
[mytest2.c:5]This is a injection procedure!
[mytest.c:5] mytest_print
[mytest2.c:5]This is a injection procedure!
[mytest.c:5] mytest_print
[mytest2.c:5]This is a injection procedure!
[mytest.c:5] mytest_print