bas*_*sin 3 c linux shared-libraries
好的我明白了.当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;
}
Run Code Online (Sandbox Code Playgroud)
test.c:
#include <unistd.h>
int main(int argc, char *argv[]) {
write(1,"abc\n",4);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
_
$ 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
Run Code Online (Sandbox Code Playgroud)
upd:根据ensc,它与符号版本有关.
链接./test需要改变什么才能像bash一样失败?我的意思是,使用相同的.so文件命令:$ LD_PRELOAD=./libtest.so ./test将打印"abc",因为test它将绑定到writeglibc中的版本.
我也正在尝试相反的方法 - 使用版本化的.so文件write.version.script:
GLIBC_2.2.5 {
write;
};
Run Code Online (Sandbox Code Playgroud)
但我的图书馆仍然无法拦截writebash
$ gcc -g -O0 -fPIC -shared -Wl,--version-script=./version.script -o libtest.so libtest.c
$ LD_PRELOAD=./libtest.so bash -c 'echo abc'
abc
Run Code Online (Sandbox Code Playgroud)
当您查看使用过的符号时,您可能会看到版本化符号用于write:
$ readelf -a test | grep write
48: 0000000000000000 0 FUNC GLOBAL DEFAULT UND write@@GLIBC_2.2.5
Run Code Online (Sandbox Code Playgroud)
您必须编写带有VERSION部分的链接描述文件(info ld - >"Version command").
你的情况(操纵bash行为)更复杂,因为bash调用printf(3),而printf(3)又使用了libc的一些内部函数.当你运气好并且调用弱内部函数时(afais,只有'__write'),你可以在库中重载它.
否则,你必须覆盖bash调用的printf(); 你可以用'ltrace'找到它; 例如:
$ ltrace bash -c 'echo abc'
__printf_chk(1, "%s", "abc") = 3
_IO_putc('\n', 0x7fc5eeac3420abc
Run Code Online (Sandbox Code Playgroud)
或者通过设置LD_DEBUG( - > man ld.so)