LD_PRELOAD tips
很多程序都需要链接共享库才能运行, 链接共享库默认会从系统/usr/lib
目录中查找, 然后链接.so
文件。而且对于同名函数, 只会识别最先出现的那一个。指定LD_PRELOAD
变量就能让链接器先去找LD_PRELOAD
指定的路径再去找默认路径, 从而实现对函数劫持。
详见man ld.so
实验例子
我们可以通过strace
查看一个程序执行过程中使用到的系统调用。再配合上man 2
就可以查看系统调用的详细信息, 以便后续覆盖。
来一个经典的篡改whoami
使用strace
查看whoami
的调用。可以看到调用了geteuid
, 使用man 2 geteuid
查看详情来做点伪造uid_t geteuid(void)
可见返回的是一个用户id。
1 | $ strace whoami |
使用cat /etc/passwd
看看都有哪些uid
1 | $ cat /etc/passwd |
那么可以简单返回个int, 然后gcc --shared -fPIC a.c -o a.so
编译.so
动态库
1 | // a.c |
在whoami
程序前使用LD_PRELOAD
环境变量LD_PRELOAD=$(pwd)/a.so whoami
, 可以看到返回root
, 而我们现在并非root用户。
进一步的, 可以使用ldd
命令查看运行都要链接哪些库。可以看到差异
1 | $ ldd $(which whoami) |
伪造后怎么再去调用原来的?
使用<dlfcn.h>
中的dlsym(RTLD_NEXT, "name")
。RTLD_NEXT
会找下一个出现的,返回函数指针, 从而实现对原始函数的调用。
使用dlcn.h
需要引用dl库-ldl
。gcc --shared -fPIC -ldl a.c -o a.so
1 |
|