4

好的我明白了。当另一个 libc 函数调用它时,您不能用 LD_PRELOAD 覆盖一个 libc 函数。


我在玩 Dante socksifier,发现它不适用于 bash /dev/udp FD。然后我用这个函数写了一个简单的 .so 文件write,它也不适用于 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会绑定到writeglibc 中的版本。

我也在尝试相反的方法 - 使用版本化的 .so 文件制作 .so 文件writeversion.script

GLIBC_2.2.5 {
    write;
};

但我的图书馆仍然无法write在 bash中拦截

$ gcc -g -O0 -fPIC -shared -Wl,--version-script=./version.script -o libtest.so libtest.c
$ LD_PRELOAD=./libtest.so bash -c 'echo abc'
abc
4

1 回答 1

7

当您查看使用的符号时,您可能会看到版本化符号用于write

$ readelf -a test | grep write
48: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND write@@GLIBC_2.2.5

您必须编写一个带有 VERSION 部分的链接描述文件(info ld -> "Version command")。

您的案例(操纵 bash 行为)更复杂,因为 bash 调用 printf(3) ,而后者又使用了 libc 的一些内部函数。当你运气好并且调用了一个弱内部函数(afais,只有'__write'),你可以在你的库中重载它。

否则,您必须覆盖 bash 调用的 printf();你可以用'ltrace'找到它;例如:

$ ltrace  bash -c 'echo abc'
__printf_chk(1, "%s", "abc")                                  = 3
_IO_putc('\n', 0x7fc5eeac3420abc

或通过设置 LD_DEBUG (--> man ld.so)

于 2013-10-26T12:21:04.653 回答