8

Yes, quite a few similar questions exist already (5037601, 19166698, 4855162, 14505995, 5052648, 13409508, 7745146, 7459630; sorry, not enough rep for more than 2 links), and yes, there are some nice articles explaining this kind of thing (click, click, http ://codearcana.com/posts/2013/05/02/introduction-to-format-string-exploits.html). I've read them and I think I get the general idea, but I still fail at succesfully exploiting the easiest training toy example that I could think of.

#include <stdio.h>

void f(char* a)
{
    printf("a: %p\n", &a);
    printf(a);
    return;
}

void main(int argc, char** argv)
{
    f(argv[1]); //please ignore the lack of any check
    return;
}

Yes, the stack is executable and yes, memory layout randomisation is disabled. Each execution gives me the same address of a. I can feed it for instance $ ruby -e 'print "AAAA"+("%08x."*16)', and that results in:

a: 0xbfffece0
AAAAbfffece0.bfffecf0.b7fd7ff4.00000000.00000000.bffffcf8.080484b0.bfffecf0.00000fff.b7fd8420.00000000.41414141.78383025.3830252e.30252e78.252e7838.

So now I can see where my input ends up in memory. I can write a value to the stack with $ ruby -e 'print "12345%n"+("%08x."*16)', which results in this:

a: 0xbfffece0
12345bfffecf0.b7fd7ff4.00000000.00000000.bffffcf8.080484b0.00000005.00000fff.b7fd8420.00000000.34333231.256e2535.2e783830.78383025.3830252e.30252e78.

Obviously, my ultimate goal would presumably be something like <something><NOPs><shellcode>, where <something> overwrites the return address of f so that the program will jump into the NOP sled and execute the shellcode. But the address of the saved return address seems to depend on my input now, right? Something similar to 0xbfffece0 - len(input) - 12, assuming a 12-byte prologue? Perhaps this example is not the easiest after all...

I'm getting confused. Any ideas?

AstroCB
  • 12,337
  • 20
  • 57
  • 73
Bla Blaat
  • 143
  • 1
  • 1
  • 7
  • Indeed, since arguments to `printf` will be pushed on the stack, the address of the return address is changing according to your input. Your format string must, then, "consume" as many bytes as itself, plus everything else up to the return address. – Michael Foukarakis Jan 16 '14 at 13:24
  • Could you perhaps give a concrete example, assuming for instance a 50-byte shellcode and no NOPs? – Bla Blaat Jan 16 '14 at 13:31
  • http://stackoverflow.com/questions/7459630/how-can-a-format-string-vulnerability-be-exploited – w s Jan 22 '14 at 15:52
  • Yeah, I know, I already read that one and wanted to link to it above... – Bla Blaat Jan 23 '14 at 11:57

2 Answers2

2

Another idea is to use the dollar sign: %<distance>$n.

Quoting from Linux's printf manpage:

One can also specify explicitly which argument is taken, at each place where an argument is required, by writing "%m$". Where the decimal integer m denotes the position in the argument list of the desired argument, indexed starting from 1. Source

Example: %5$n would write to the 5th address from the top of the stack.

multithr3at3d
  • 510
  • 1
  • 5
  • 14
Aneesh Dogra
  • 740
  • 5
  • 30
1

I suggest you use a long string of '%08x' format characters to figure out the correct '%n' value in the input such that it overwrites the return address.

12345%n%08x%08x%08x%08x........%08x%08x

Next you can modify your input replacing a part of the'%08x' string with NOP sled + shellcode keeping the length of the input same.

12345%n\x90\x90\x90\x90...\x90\x90SHELLCODE

(Modify %n format specifier above as required to write a correct value)

This will ensure the size of the input and hence the location of the saved return address remains the same.

pank4j
  • 451
  • 4
  • 7