问题
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:
- compile main.c gcc –Wall –o main main.c
- create my own library gcc –Wall –fPIC –shared –o PrintfHank.so PrintfHank.c –ldl
- 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");
}
回答1:
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");
}
回答2:
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
回答3:
Change
return orig_printf("within my own printf\n");
to
return (*orig_printf)("within my own printf\n");
来源:https://stackoverflow.com/questions/1576689/problems-on-injecting-into-printf-using-ld-preload-method