Overwrite return address simple format string exploit
Asked Answered
V

2

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?

Vachil answered 16/1, 2014 at 12:49 Comment(4)
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.Wilmington
Could you perhaps give a concrete example, assuming for instance a 50-byte shellcode and no NOPs?Vachil
#7460130Painty
Yeah, I know, I already read that one and wanted to link to it above...Vachil
E
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.

Engender answered 4/11, 2015 at 10:46 Comment(0)
A
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.

Airboat answered 3/2, 2014 at 8:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.