好的,我明白了。当libc函数被另一个libc函数调用时,你不能用LD_PRELOAD覆盖它。
我正在玩Dante socksifier,并注意到它不能与bash / dev / udp FD一起使用。然后我用write
函数编写了一个简单的.so文件,它也不能与bash一起使用:
libtest.c
:
#include <unistd.h>
ssize_t write(int fildes, const void *buf, size_t nbyte)
{
return nbyte;
}
test.c
:
#include <unistd.h>
int main(int argc, char *argv[]) {
write(1,"abc\n",4);
return 0;
}
_
$ gcc -g -O0 -fPIC -shared -o libtest.so libtest.c
$ gcc -g -O0 -o test test.c
$ ./test
abc
$ LD_PRELOAD=./libtest.so ./test
$ LD_PRELOAD=./libtest.so bash -c 'echo abc'
abc
upd:根据ensc,它与符号版本有关。
链接./test需要更改什么才能像bash那样失败?我的意思是,使用相同的.so文件命令:$ LD_PRELOAD=./libtest.so ./test
将打印“abc”,因为test
将绑定到glibc中的版本化write
。
我也在尝试相反的方法 - 使用版本化的write
创建一个.so文件。 version.script
:
GLIBC_2.2.5 {
write;
};
但我的图书馆仍无法拦截bash中的write
$ gcc -g -O0 -fPIC -shared -Wl,--version-script=./version.script -o libtest.so libtest.c
$ LD_PRELOAD=./libtest.so bash -c 'echo abc'
abc
答案 0 :(得分:5)
当您查看使用过的符号时,您可能会看到版本化符号用于write
:
$ readelf -a test | grep write
48: 0000000000000000 0 FUNC GLOBAL DEFAULT UND write@@GLIBC_2.2.5
您必须编写带有VERSION部分的链接描述文件(info ld - &gt;“版本命令”)。
你的情况(操纵bash行为)更复杂,因为bash调用printf(3),而printf(3)又使用了libc的一些内部函数。当你运气好并且调用弱内部函数时(afais,只有'__write'),你可以在库中重载它。
否则,你必须覆盖bash调用的printf();你可以用'ltrace'找到它; e.g:
$ ltrace bash -c 'echo abc'
__printf_chk(1, "%s", "abc") = 3
_IO_putc('\n', 0x7fc5eeac3420abc
或通过设置LD_DEBUG( - &gt; man ld.so)