Skip to content

Latest commit

 

History

History
129 lines (76 loc) · 5.85 KB

assignment5.md

File metadata and controls

129 lines (76 loc) · 5.85 KB

Assignment 5

Compiling

When compiling any program use the following command

gcc -ggdb -fno-stack-protector -no-pie -m32 -z execstack [PROGRAM].c -o [PROGRAM]

This will disable the dark magic behind the gcc.

2. Buffer Overflows

To understand what a buffer overflow read this and watch this video.

2.1 Change the return address

Assuming you have read the above, the stack for overflow_function should be something like

bottom                                         top
of                                             of
mem     |   [buffer] [SFP] [RET] [*str]      | mem    
        |   [   20B] [ 4B] [ 4B] [  4B]      |

Compile the code and run gdb overflow. Using disas overflow_function, its observable that the compiler allocated 40 Bytes instead of 32 Bytes. (Why? No idea, something to do with the way it allocs memory)

0x0804843e <+3>:    sub    $0x28,%esp

Using a big_string of 32 Bytes, the program crashes, as it should since its trying to access memory passed 20 Bytes to write on it. Yet it does not write 'AAAAA' to the RET address. Using 36 Bytes, it will fully write the RET address, which is visible when you run the program in gdb. (Why? No idea)

2.2 Buffer overflow in stack

Compile vuln.c, then change the ownership to root

sudo chown root vuln

and give it root privileges

chmod 4755 vuln

('4' activates SUID - Set owner User ID up on execution). What this last command does is give temporary permissions to a user to run a program/file with the permissions of the file owner (root) rather that the user who runs it. Furtherly, this will allow you to use a shell as root and fuck up the whole machine.

Compile and run exploit.c. Its really hard to discover where the return address is pointing to and modify that position content. So instead the objective is to overwrite the return address with the address of the buffer. And in buffer add the malicious code we want to execute!

Looking at exploit.c:

  1. We try to find the address of where vuln.c buffer will be. This is done by finding out where out current stack pointer is and subtracting it an offset. Multiple attempts will be needed to get the offset right.

  2. We allocate our malicious buffer on the heap! So it doesn't interfere with the rest. 600 Bytes are allocated to make sure it reaches the return address, since vuln.c buffer is 500 Bytes.

  3. We fill the entire malicious buffer with the desired return address (aka one address that we think is where the vuln.c buffer can be).

  4. We write around 200 Bytes of NOPs (each NOP is 1 Byte and its code is \x90) to the beggining of malicious buffer. The NOPs allow us to slide from byte to byte in the stack. It's needed because we arent entirely sure where the vuln.c buffer starts, so we don't want to put the malicious code right at the beggining, the NOPs will slide us to it.

  5. We add the malicious code (about 46 Bytes) that consist on execve() to open a shell and exit() because in case execve() fails, we don't want the program fetching instructions from the stack, which may contain random data.

  6. We finalize by putting '\0' at the end of the buffer so stcpy() stops writing.

So our malicious buffer and stack will be something like

buffer[600]:  | NOPx200 | Shellcode     | RETx~350        | '\0'         |
stack:        | vuln.c Buffer[500]      | SPF | RET | *bf | ............ |

If everything works, it will open a shell as root.

2.3 Buffer overflow in stack using perl

This does exactly the same as before in one line and using perl... Notice that you need to get the return address and put it little Endian due to intel CPU.

"\x3c\xed\xff\xbf"x88

88 Bytes of this should be enough to reach the return address.

2.4 Buffer overflow in stack using env variables

Read the "Small Bufffer Overflows" section of the link given if you haven't yet.

When the buffer is too small, instead of putting the shellcode in it, we overwrite it with the address of environment variables in which we will store our shellcode.

Give root priviliges to vuln2 like before.

"The environment variables are stored in the top of the stack when the program is started." - So starting on the top "0xbffffffa", below the program execution, should be the shellcode.

ret = 0xbffffffa - strlen(shellcode) - strlen("./vuln2");
| ... | ->shellcode | "./vuln2" | 0xbffffffa

Using a 40 Bytes malicious buffer, we overwrite the the 4 Byte buffer of vuln2.c with the address of the shellcode (env variable), this should be more than enough to reach the ret address.

Compile and execute ./env_exploit where all of this is done, and should be working.

For the perl version, export the variable SHELLCODE by doing source env_exploit.txt. We now have to find the address of the variable, for that use gdb with a breakpoint in main b main. Do x/20s $esp and ENTER till you find the SHELLCODE address. Should be something like

0xbffffa64: "SHELLCODE=", '\220' <repeats 100 times>, ...

Write a bash script using perl to print this address 10 times as an argument for vuln2. Notice that the word "SHELLCODE=" has its own space in stack too, so we need to sum its length to get the exact address. The word has 12 chars, 12 bytes. In hex the address should be 0xbffffa70 and the script:

./vuln2 `perl -e 'print "\x70\xfa\xff\xbf"x10'`