0

I have this code:

#include <stdio.h>
#include <strings.h>

int main(int ac, char **av)
{
  char text[] = "PASS_KEY";

  printf("Hey\n");
  return 0;
}

I know those strings are literally next one to one in memory. How can I redefine printf with LD_Preload to read text?

unwind
  • 391,730
  • 64
  • 469
  • 606
Enguerrand
  • 168
  • 4
  • 14

1 Answers1

2

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!

Stefano Sanfilippo
  • 32,265
  • 7
  • 79
  • 80