Search code examples
cstringsecurityunixexploit

Format String Exploit, unexpected result


I'm trying to implement simple example of Format String Vulnerability in C on 64-bits Linux. Here is my source code:

void not_called() {
    printf("Exploited\n");
}

int main(int argc, char **argv) {

    // Buffer overflow vulnerability
    char buffer[256];
    gets(buffer);

    // User may input the format string
    printf(buffer);
}

I input the following string to program

AAAABBBB-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x

And the result is

AAAABBBB-8608002c-f458fe00-fbad2288-78252d78-252d7825-5e5c51a8-0-41414141-2d78252d-78252d78-252d7825-2d78252d

I can spot the AAAA as 41414141 but not the BBBB following as I would expect, as it's integral part of the same input string in the buffer.

Is this some sort of protection mechanism or am I misinterpreting something? My goal is to overwrite return address, and I need to read 8 bytes (AAAABBBB) as I'm working on 64-bits machine.

Pseudo-code for exploit string would look something like this

RETRNPTR%[decimal address of not_called - 8]u%[offset of RETRNPTR]$n

RETRNPTR is the address of memory storing the return address in the current stack frame.

So my biggest concern is, 8 bytes of RETRNPTR doesn't seem to be continuously in memory as I would expect. Second concern is, %n is int-pointer, meaning only 4 bytes are written. I'm also confused, where those values preceding the AAAA are coming from.


Solution

  • First of all, you're asking about code that has undefined behaviour; the behaviour of the code indeed should for the most of the part considered undefined by a casual C programmer.

    Now, as to why you do not see BBBB. I presume it is because you're running this program on x86-64 system. There the calling convention is to do 64-bit pushes for the values that go on stack; However %x prints a 32-bit int; the 32 least significant bits of 64-bit stack value. To print 64-bit long values use %lx.

    (Also, on System-V API for x86-64 the 6 first integer/pointer arguments do not go on stack at all; they're in RDI, RSI, RDX, RCX, R8, and R9 registers).

    For example I entered:

    AAAABBBB %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx
    

    and got output

    AAAABBBB 7f7c0a88f030 7f7c0a66b980 7f7c0a669980 7f7c0a88f031 786c2520786c2520 7ffc1456b6f8
    100000000 4242424241414141 786c2520786c2520 786c2520786c2520