# Homework/Project 4
**Student information:** Owen Sullivan (opsulli | C34243277)

## Introduction
For this assignment, I worked alone and thus did not divide up any of the work.

## Methodology

### target0: Overwriting a variable on the stack
For target0, I created a solution (`sol0.py`) that prints the bytes of my username (opsulli), three nul character bytes, then the bytes of "A+". This causes the `name` buffer to overflow into the `grade` buffer without causing arbitrary characters to be printed with the name, and results in the text "Hi opsulli! Your grade is A+.".

### target1: Overwriting the return address
For target1, I analyzed the executable and found the memory address of the `print_good_grade()` function, which is `0x08048c23` in the case of the executable built using my username. My solution (`sol1.py`) prints 16 arbitrary bytes, followed by that memory address, which causes the stack's return address to be pointed to the start of the `print_good_grade()` function.

### target2: Redirecting control to shellcode
For target2, I analyzed the executable after injecting only the shellcode into the `buf` buffer within the `vulnerable()` function and found the memory address where the shellcode starts (`0xfff6b8ec` in my case). Then, I modified my solution (`sol2.py`) to inject the shellcode bytes, then 59 bytes of padding to close the gap to the stack's return address pointer, then finally the memory address for the start of the shellcode.

### target3: Overwriting the return address indirectly
For target3, I analyzed the executable after injecting only the shellcode and identified the memory address of its start, similarly to target2. Then, in my solution (`sol3.py`), I experimented with injecting various lengths of padding bytes and finished by injecting both the memory address of the start of the shellcode and the memory address of the previous return pointer. When the pointer within the `vulnerable()` function is dereferenced, it causes the return address to be replaced with the memory address of the shellcode's start.

### target4: Beyond strings
For target4, I created a solution (`sol4.py`) which writes the bytes of a count value (for how many segments of data the program should read) followed by the shellcode bytes, some garbage bytes, and the memory address of where the shellcode starts in the buffer in memory. For the count, I discovered that a sufficiently large value would overflow and cause the buffer to be allocated based on the overflowed value in `read_file()` while the for loop in `read_elements()` continued writing past the buffer's size. Thus, writing a number of garbage bytes equal to the overflowed count value plus the offset from the end of the buffer to the location of the return address on the stack causes a buffer overflow that allows the return address to be overwritten.

### target5: Bypassing DEP
For target5, I analyzed the executable using GDB to find the memory addresses of the libc `system()` and `exit()` functions as well as the address of the argument `/bin/sh`. Then, I created a solution (`sol5.py`) which prints 22 bytes (the offset between the start of the buffer and the base pointer) followed by those memory addresses in order. When the program is run with the solution input, it executes `system("/bin/sh")`.