为什么似乎并LD_ preLOAD不与厕所写工作

为什么似乎并LD_ preLOAD不与厕所写工作

问题描述:

我在玩弄LD_ preLOAD拦截的libc电话,看来写调用不会与WC拦截,但它似乎与猫的工作。这个问题的一个精简版显示如下。

I was playing around with LD_PRELOAD to intercept libc calls, it appears that the write call doesn't get intercepted with wc, though it does seem to work with cat. A stripped down version of the problem appears below.

RedHat Linux上2.6.9-42.ELsmp

RedHat Linux 2.6.9-42.ELsmp

的Makefile

writelib:
        gcc -Wall -rdynamic -fPIC -c write.c
        gcc -shared -Wl,-soname,libwrite.so -Wl,-export-dynamic -o libwrite.so write.o -ldl

为write.c:

write.c:

#include <stdio.h>
#include <string.h>
#ifndef __USE_GNU
 #define __USE_GNU
 #define __USE_GNU_DEFINED
#endif
#include <dlfcn.h>
#ifdef __USE_GNU_DEFINED
 #undef __USE_GNU
 #undef __USE_GNU_DEFINED
#endif
#include <unistd.h>
#include <stdlib.h>

static ssize_t (*libc_write)(int fd, const void *buf, size_t len);

ssize_t
write(int fd, const void *buf, size_t len)
{
    static int already;
    ssize_t ret;

    if (!already) {
            if ((libc_write = dlsym(RTLD_NEXT, "write")) == NULL) {
                    exit(1);
            }
            already = 1;
    }


    ret = (*libc_write)(fd,"LD_PRELOAD\n",11);
    return len; // not ret so cat doesn't take forever
}

输出:

prompt: make
gcc -Wall -rdynamic -fPIC -c write.c
gcc -shared -Wl,-soname,libwrite.so -Wl,-export-dynamic -o libwrite.so write.o -ldl
prompt: LD_PRELOAD=./libwrite.so /bin/cat write.c
LD_PRELOAD
prompt: LD_PRELOAD=./libwrite.so /usr/bin/wc write.c
 32  70 572 write.c

任何解释吗?

这是因为当使用厕所使用的printf ,这可能是使用任内联版本写,或它引用势必的libc ,所以不能插入。

That's because while cat uses write, wc uses printf, which is probably using either an inlined version of write, or its reference to write is bound to libc, so cannot be interposed.

这可以很容易地使用可见 ltrace

This can easily be seen using ltrace:

$ echo foo | ltrace wc 2>&1 | grep 'write\|print'
printf("%*s", 7, "1")                            = 7
printf(" %*s", 7, "1")                           = 8
printf(" %*s", 7, "4")                           = 8


$ echo foo | ltrace cat 2>&1 | grep 'write\|print'
write(1, "foo\n", 4foo