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

发布于 2024-08-08 03:52:02 字数 1196 浏览 5 评论 0原文

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

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

  1. compile main.c gcc –Wall –o main main.c
  2. 创建我自己的库 gcc –Wall –fPIC –shared –o PrintfHank.so PrintfHank.c –ldl
  3. 测试新库 LD_PRELOAD=”$mypath/PrintfHank.so” $mypath/main

但我在控制台中收到“hello world”而不是“在我自己的 printf 中”。当破解 malloc/free 函数时,这是可以的。

我以“root”身份登录系统并使用 2.6.23.1-42.fc8-i686。任何意见将不胜感激!

main.c

#include <stdio.h>

int main(void)
{
    printf("hello world\n");

    return 0;
}

PrintfHank.c

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <dlfcn.h>

static int (*orig_printf)(const char *format, ...) = NULL;

int printf(const char *format, ...)
{
 if (orig_printf == NULL)
 {
  orig_printf = (int (*)(const char *format, ...))dlsym(RTLD_NEXT, "printf");
 }

 // TODO: print desired message from caller. 
 return orig_printf("within my own printf\n");
}

I was hacking printf() of glibc in one of my project and encountered some problem. Could you please give some clues? And one of my concern is why the same solution for malloc/free works perfect!

As attached, “PrintfHank.c” contains my own solution of printf() which will be preloaded before standard library; and “main.c” just outputs a sentence using printf(). After editing two files, I issued following commands:

  1. compile main.c
    gcc –Wall –o main main.c
  2. create my own library
    gcc –Wall –fPIC –shared –o PrintfHank.so PrintfHank.c –ldl
  3. test the new library
    LD_PRELOAD=”$mypath/PrintfHank.so” $mypath/main

But I received “hello world” instead of “within my own printf” in the console. When hacking malloc/free functions, it’s okay.

I log in my system as “root” and am using 2.6.23.1-42.fc8-i686. Any comments will be highly appreciated!!

main.c

#include <stdio.h>

int main(void)
{
    printf("hello world\n");

    return 0;
}

PrintfHank.c

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <dlfcn.h>

static int (*orig_printf)(const char *format, ...) = NULL;

int printf(const char *format, ...)
{
 if (orig_printf == NULL)
 {
  orig_printf = (int (*)(const char *format, ...))dlsym(RTLD_NEXT, "printf");
 }

 // TODO: print desired message from caller. 
 return orig_printf("within my own printf\n");
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凉薄对峙 2024-08-15 03:52:02

然而,这个问题很古老:

在您的 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]

并没有实际的提到printfputs 基本上是没有格式的 printf,并且在末尾有一个自动换行符,所以这显然是 gcc 通过用 printf 替换 printf 来“帮助”的结果>放置。

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

 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]

现在我可以看到 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");
}

This question is ancient, however:

In your main.c, you've got a newline at the end and aren't using any of the formatting capability of printf.

If I look at the output of LD_DEBUG=all LD_PRELOAD=./printhack.so hello 2>&1 (I've renamed your files somewhat), then near the bottom I can see

 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]

and no actual mention of printf. puts is basically printf without the formatting and with an automatic line break at the end, so this evidently the result of gcc being "helpful" by replacing the printf with a puts.

To make your example work, I removed the \n from the printf, which gives me output like:

 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]

Now I can see that printhack.so is indeed being dragged in with its custom printf.

Alternatively, you can define a custom puts function as well:

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");
}
寄居者 2024-08-15 03:52:02

查看
1) 预处理器输出。 printf 可以更改为 smth else

gcc -E main.c

2) 有关 printf 符号和预加载的 ld_debug 信息

LD_DEBUG=help LD_PRELOAD=”$mypath/PrintfHank.so” $mypath/main
LD_DEBUG=all LD_PRELOAD=”$mypath/PrintfHank.so” $mypath/main

Check
1) preprocessor output. printf can be changed to smth else

gcc -E main.c

2) ld_debug info about printf symbol and preloading

LD_DEBUG=help LD_PRELOAD=”$mypath/PrintfHank.so” $mypath/main
LD_DEBUG=all LD_PRELOAD=”$mypath/PrintfHank.so” $mypath/main
追星践月 2024-08-15 03:52:02

更改

return orig_printf("within my own printf\n");

return (*orig_printf)("within my own printf\n");

Change

return orig_printf("within my own printf\n");

to

return (*orig_printf)("within my own printf\n");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文