How to perform a specific buffer overflow bypassing a length check

0

I'm trying to perform a bufferoverflow so that a variable (type) has a specific value in it. I struggle with the strlen & check for my input.

I tried using something like: 'AAAAA\x00AAA...A\x00\xbc\xd4\xb9' for tricking the strlen check that my input is just 5 A's long. But something strips my \x00 always with the message:

-bash: Warnung: command substitution: ignored null byte in input

So i went to make a way bigger input and have an Integer overflow so that the short where the length is saved to is too big and gets below 32700... But that didnt seem to work either.

My inputs are constructed as follow:

./challenge `python -c "print 'A'*30000 + '\x00' + 'A'*10000" + '\xXX\xXX\xXX\xXX'`

(for \xXX my desired inputs)

or

./challenge `python programm.py`

I am also using gdb for the analysis of the memory. But i cant find the correct way to use it...

The code for my task is:

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

int main(int argc, char *argv[])
{
    int type = 0xdeadbeef;
    char buf[32700];
    short len;

    if (argc < 2)
        return -1;

    len = strlen(argv[1]);
    if (len > 32700) {
        printf("Too long\n");
        return -1;
    }

    strcpy(buf, argv[1]);

    if (type == 0x00b1c2d3) {
        printf("Success\n");
    } else {
        printf("Try again\n");
    }

    exit(0);
}

Any other ideas (or a 'solution') for this problem? I am trying so hard now since days. Also i didn't have anything todo with C (especially memory analysis, gdb and all of that) for years, so it's extra hard for me to understand some things.

c
gdb
buffer-overflow
strlen
asked on Stack Overflow Jun 30, 2019 by Mechamod • edited Jun 30, 2019 by Mechamod

1 Answer

2

The issue in the code is that the length len, which is calculated using strlen(), is a short. This means it's a 16-bit value. Since strlen() returns a size_t, which is a 64-bit value on my x86_64 system, only the bottom 16 bits will be stored in the len variable.

So, on first glance you can submit anything longer than 65,535 bytes, overflow that short int, and store just the lower 16-bits. But there's another issue to note. The len variable is a signed short integer. This means that it stores values from [-32768,32767], whereas a size_t is an unsigned value. So when strlen() returns its value, lengths that have the highest bit set (anything over 32,767 bytes) will become negative numbers.

Here's an example gdb session illustrating this:

(gdb) break 22
Breakpoint 1 at 0x829: file challenge.c, line 22.
(gdb) run `ruby -e 'print("A"*32768)'`
Starting program: /home/josh/foo/challenge `ruby -e 'print("A"*32768)'`

Breakpoint 1, main (argc=2, argv=0x7fffffff6338) at challenge.c:22
22          if (type == 0x00b1c2d3) {
(gdb) p len
$1 = -32768
(gdb) x/64bx $rsp
0x7ffffffee260: 0x38    0x63    0xff    0xff    0xff    0x7f    0x00    0x00
0x7ffffffee268: 0x00    0x00    0x00    0x00    0x02    0x00    0x00    0x00
0x7ffffffee270: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x7ffffffee278: 0x00    0x00    0x00    0x80    0xef    0xbe    0xad    0xde
0x7ffffffee280: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffffffee288: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffffffee290: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffffffee298: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
(gdb) 

See how the bytes at 0x7ffffffee27a are 0x00 0x80? That's -32768 to a short int, so the length is perceived to be negative (well under 32,700!).

I also included some extra info in the memory dump there, so you can see that the type field immediately succeeds the len field in memory, followed finally by the buf array (which contains my 32768 As!). Note that only certain lengths of input will work -- those that appear negative, or overflow to a value less than 32,700 when truncated to 16 bits.

This doesn't solve the entire challenge, but at least should give you a good start to understanding what you can control. Note also that there is data above the buf array, such as where rbp points, your saved return pointer, etc. Depending on how you are compiling this (e.g., with or without stack canaries, etc.), there might be some more things for you to solve along the way.

answered on Stack Overflow Jun 30, 2019 by Josh5tone • edited Jun 30, 2019 by Josh5tone

User contributions licensed under CC BY-SA 3.0