使用LD_PRELOAD方法注入printf时出现问题

Joh*_*nny 3 hook glibc code-injection

我在我的一个项目中破解了 glibc 的 printf() 并遇到了一些问题。您能提供一些线索吗?我关心的问题之一是为什么同样的 malloc/free 解决方案可以完美地工作!

\n\n

如附件所示,\xe2\x80\x9cPrintfHank.c\xe2\x80\x9d 包含我自己的 printf() 解决方案,它将在标准库之前预加载;而 \xe2\x80\x9cmain.c\xe2\x80\x9d 只是使用 printf() 输出一个句子。编辑两个文件后,我发出以下命令:

\n\n
    \n
  1. 编译 main.c\n gcc \xe2\x80\x93Wall \xe2\x80\x93o main main.c
  2. \n
  3. 创建我自己的库\n gcc \xe2\x80\x93Wall \xe2\x80\x93fPIC \xe2\x80\x93shared \xe2\x80\x93o PrintfHank.so PrintfHank.c \xe2\x80\x93ldl
  4. \n
  5. 测试新库\n LD_PRELOAD=\xe2\x80\x9d$mypath/PrintfHank.so\xe2\x80\x9d $mypath/main
  6. \n
\n\n

但我在控制台中的 printf\xe2\x80\x9d 中收到了 \xe2\x80\x9chello world\xe2\x80\x9d 而不是 \xe2\x80\x9c 。当破解 malloc/free 函数时,\xe2\x80\x99s 没问题。

\n\n

我以 \xe2\x80\x9croot\xe2\x80\x9d 身份登录系统,并使用 2.6.23.1-42.fc8-i686。任何意见将不胜感激!

\n\n

主程序

\n\n
#include <stdio.h>\n\nint main(void)\n{\n    printf("hello world\\n");\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

PrintfHank.c

\n\n
#ifndef _GNU_SOURCE\n#define _GNU_SOURCE\n#endif\n\n#include <stdio.h>\n#include <dlfcn.h>\n\nstatic int (*orig_printf)(const char *format, ...) = NULL;\n\nint printf(const char *format, ...)\n{\n if (orig_printf == NULL)\n {\n  orig_printf = (int (*)(const char *format, ...))dlsym(RTLD_NEXT, "printf");\n }\n\n // TODO: print desired message from caller. \n return orig_printf("within my own printf\\n");\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Cas*_*par 5

然而这个问题很古老:

在您的 中main.c,您的末尾有一个换行符,并且没有使用 的任何格式化功能printf

如果我查看LD_DEBUG=all LD_PRELOAD=./printhack.so hello 2>&1(我稍微重命名了你的文件)的输出,那么在底部附近我可以看到

 17246:     transferring control: ./hello
 17246:     
 17246:     symbol=puts;  lookup in file=./hello [0]
 17246:     symbol=puts;  lookup in file=./printhack.so [0]
 17246:     symbol=puts;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
 17246:     binding file ./hello [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `puts' [GLIBC_2.2.5]
Run Code Online (Sandbox Code Playgroud)

并且没有实际提及printf. puts基本上是 printf 没有格式化,并且末尾有自动换行符,所以这显然是 gcc 通过将 替换printfputs.

为了使您的示例正常工作,我\n从 中删除了printf,这给出了如下输出:

 17114:     transferring control: ./hello
 17114:     
 17114:     symbol=printf;  lookup in file=./hello [0]
 17114:     symbol=printf;  lookup in file=./printhack.so [0]
 17114:     binding file ./hello [0] to ./printhack.so [0]: normal symbol `printf' [GLIBC_2.2.5]
Run Code Online (Sandbox Code Playgroud)

现在看来,printhack.so确实是被它的风俗拖进去了printf

puts或者,您也可以定义自定义函数:

static int (*orig_puts)(const char *str) = NULL;
int puts(const char *str)
{
    if (orig_puts == NULL)
    {
        orig_puts = (int (*)(const char *str))dlsym(RTLD_NEXT, "puts");
    }

    // TODO: print desired message from caller.
    return orig_puts("within my own puts");
}
Run Code Online (Sandbox Code Playgroud)