Defining a shim printf
to dump memory around the pointer it is passed is not a difficult task:
#include <stdio.h>
void dump(const char *data) {
fwrite(data - 32, 1, 64, stdout);
}
int printf(const char *data, ...) {
dump(data);
}
Compile with:
gcc -c -fPIC print.c -o print.o
ld -shared -o libprint.so print.o
and now you can LD_PRELOAD=./libprint.so ./program
and get the key. Or you could... You have a few separate problems here.
GCC at least optimizes a printf
with no placeholders in the format string to a puts
. So what gets called by your program is not printf
. Well, let's shim puts
too:
int puts(const char *data) {
dump(data);
}
now you get the dump on screen:
..............Hey........
so it's working. But there's no trace of the key. Why?
Because text
is a local variable (array) and "Hey\n"
is a constant string. So text
is allocated on the stack and "Hey\n"
in the constant pool, which is not exactly "next to it". Your assumption is wrong. If you modify the program as:
#include <stdio.h>
#include <strings.h>
int main(int ac, char **av)
{
char text[] = "PASS_KEY";
char format[] = "Hey\n";
printf(format);
return 0;
}
which, incidentally, is a thing you WOULD THINK TWICE BEFORE DOING because using non-constant format strings for printf
is B.A.D. in most cases, it will work:
............Hey
PASS_KEY.
Success!