使用LD_PRELOAD方法注入printf的问题 [英] Problems on injecting into printf using LD_PRELOAD method

查看:130
本文介绍了使用LD_PRELOAD方法注入printf的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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!

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

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. 编译main.c
    gcc –Wall –o main main .c

  2. 创建我自己的库
    gcc –Wall –fPIC –共享–o PrintfHank.so PrintfHank.c –ldl

  3. 测试新库
    LD_PRELOAD = $ mypath / PrintfHank.so $ mypath / main

  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

但是我在控制台中收到的是 hello world,而不是在我自己的printf中。黑客malloc / free函数时,没关系。

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

我以 root用户身份登录系统,并正在使用2.6.23.1-42.fc8-i686。

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

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");
}


推荐答案

这个问题很古老:

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

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

如果我查看 LD_DEBUG =全部LD_PRELOAD =。/ printhack.so你好2>& 1 (我已经对您的文件进行了重命名),然后在底部附近可以看到

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]

,没有实际提及 printf puts 基本上是不带格式的printf,并且末尾有自动换行符,因此这显然是gcc通过替换来帮助的结果带有 puts 的printf

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.

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

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]

现在我可以看到 printhack.so 确实被拖了

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

您也可以定义自定义 puts 函数也是如此:

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");
}

这篇关于使用LD_PRELOAD方法注入printf的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆