Format String Attack
Asked Answered
P

1

6

I have a small C program to be exploited. And I also understood the logic behind the attack to be performed. However, as much as I try, it is just not working for me.

#include <stdio.h>
#include <stdlib.h>

#define SECRET1 0x44
#define SECRET2 0x55

int main(int argc, char *argv[]) {
  char user_input[100];
  int *secret;
  int int_input;
  int a, b, c, d; /* other variables, not used here.*/

  /* The secret value is stored on the heap */
  secret = (int *) malloc(2*sizeof(int));

  /* getting the secret */
  secret[0] = SECRET1; secret[1] = SECRET2;

  printf("Please enter a decimal integer\n");
  scanf("%d", &int_input);  /* getting an input from user */
  printf("Please enter a string\n");
  scanf("%s", user_input); /* getting a string from user */

  printf(user_input);
  printf("\n");

  /* Verify whether your attack is successful */
  printf("The original secrets: 0x%x -- 0x%x\n", SECRET1, SECRET2);
  printf("The new secrets:      0x%x -- 0x%x\n", secret[0], secret[1]);
  return 0;
}

I just need to print the address and value of secret[0] using the format string "printf(user_input);"

I have tried giving something like "\x6e\xaf\xff\xff%x%x%x%x%s". but it is not working. Any suggestions will be appreciated. Thanks a lot.

Pilose answered 16/11, 2012 at 2:27 Comment(1)
If you want to print the address of something, you should probably use the addressof operator, &.Horoscope
R
8

This looks like an exercise for a class, so I'll provide some pointers, but no the actual solution.

You are attempting to exploit this program, by providing untrusted input. There are two fairly obvious bugs here; one is the scanf() using %s, as you can overflow the buffer and overwrite the stack. The other is a format-string vulnerability. Overwriting the stack probably wouldn't let you do anything interesting until the function returned. Based on the "verify whether your attack is successful" section, you probably want to exploit the vulnerability before then, so I'm guessing it's supposed to be a format string vulnerability.

Based on the verification section, you are expected to overwrite the memory pointed to by secret. The only way of causing printf to write to a controlled location in memory is to use the %n format specifier, which writes the given pointer.

Now the trick is to figure out how to walk up the stack until we find the appropriate pointer. Conveniently, there's a user-controlled integer right before the pointer on the stack. So, we enter a number with an easy to spot pattern (maybe 65535, which is ffff in hex), and use a format string with a lot of %xs to see what's on the stack. Once we find that, the next thing on the stack should be the pointer.

Hmm. I just tried this, and it turns out that it's not quite so simple. The exact layout of the stack frame isn't actually related to the order of declarations; and it differs between different systems for me. Instead, I had to use a lot of %lxs, along with a well-known string at the beginning, and add a line to print out the actual pointer, so I would know when I found it. Then replace the corresponding %lx with the %n to write through that pointer. It may be easiest to just try 20 or so %lxs, and substitute each one by one with %n, until you have managed to overwrite that pointer.

Anyhow, hope that's enough to get you started. Let me know if you have any questions.

Rasberry answered 16/11, 2012 at 5:10 Comment(6)
In fact, on x86_64 there are enough registers that if you compile with O2 or O3 there may not be anything on the stack except the buffer.Schreck
Also, unused variables may be optimized away by the compiler, so the actual setup of the stack might not be that you expect.Anemone
Thanks a lot for your inputs. I get repeated addresses when I give %1x many times which is confusing me. I understand that on the stack (high to low) variables are stored in the order, user_input, secret, int_input. So if I give %1x 8 times, I should be able to point to &int_input. secret = 0xbffffa5c, user_input = bffffa60, int_input = bffffa58 Please enter a decimal integer 1 Please enter a string %1x%1x%1x%1x%1x%1x%1x%1x bffffa60bffffa60bffffa584002c8a440021000400212d810 The original secrets: 0x44 -- 0x55 The new secrets: 0x44 -- 0x55Pilose
@BrianCampbell Also, since scanf is used like this, scanf("%s", user_input);... and I provide input as \x5c\xfa\xff\xbf, all values of the input are converted to hex of their ASCII and being stored on stack. 0xbffffa58: 0x01 0x00 0x00 0x00 0xd8 0x99 0x04 0x08 0xbffffa60: 0x5c 0x78 0x35 0x63 0x5c 0x78 0x66 0x61 0xbffffa68: 0x5c 0x78 0x66 0x66 0x5c 0x78 0x62 0x66 Can you please give an example how exactly should I give my input to exploit?Pilose
Thanks for all the comments . I could get the solution.Pilose
I understand that on the heap secret[1] is stored after secret[0]. With the attack, I was able to print values of secret[0] and change its value also. Is there any way I can access secret[1] using format string attack?Pilose

© 2022 - 2024 — McMap. All rights reserved.