Проблемы с инъекцией в printf методом LD_PRELOAD

Я взламывал printf() glibc в одном из своих проектов и столкнулся с проблемой. Не могли бы вы дать некоторые подсказки? И меня беспокоит то, почему то же самое решение для malloc/free работает идеально!

Как прилагается, «PrintfHank.c» содержит мое собственное решение printf(), которое будет предварительно загружено перед стандартной библиотекой; а «main.c» просто выводит предложение с помощью printf(). После редактирования двух файлов я выполнил следующие команды:

  1. скомпилировать 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» вместо «in my own 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");
}

person Johnny    schedule 16.10.2009    source источник


Ответы (3)


Однако этот вопрос древний:

В вашем 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]

и никакого фактического упоминания о printf. puts в основном является printf без форматирования и с автоматическим разрывом строки в конце, так что это, очевидно, результат того, что gcc «полезно» заменить printf на puts.

Чтобы ваш пример работал, я удалил \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]

Теперь я вижу, что 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");
}
person Caspar    schedule 10.03.2016
comment
Есть ли способ отключить gcc от изменения функции printf() на puts()? - person bawejakunal; 10.04.2017

Проверьте 1) вывод препроцессора. printf можно изменить на что-то еще

gcc -E main.c

2) ld_debug информация о символе printf и предварительной загрузке

LD_DEBUG=help LD_PRELOAD=”$mypath/PrintfHank.so” $mypath/main
LD_DEBUG=all LD_PRELOAD=”$mypath/PrintfHank.so” $mypath/main
person osgx    schedule 31.03.2010

Сдача

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

to

return (*orig_printf)("within my own printf\n");
person Ricardo Cristian Ramirez    schedule 07.12.2012