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 |
|