Brainstorm was one of the first buffer overflow boxes I managed to root on a CTF platform after learning the basics. It’s not hard if you understand the process, but it’s a good challenge nonetheless. I’ll start by scanning the machine and find FTP open with anonymous login. I’ll also find a chatserver running on port 9999, and a copy of that executable in the FTP. Then, after doing some offline exploit development, I’ll have a working buffer overflow that I can then run against the remote machine to gain Administrator access.
Recon
As per usual, we always check what ports are open with nmap:
We find 3 open ports, one of which (9999), is running some mystery service.
FTP
When FTP is open, it’s always worth checking for Anonymous login, which we are able to use.
We find a chatserver directory, containing a chatserver.exe and an essfunc.dll (which I can only assume has to be used by the chatserver program). I’m going to go ahead and download these on to my machine using binary in FTP.
Port 9999 - Chatserver
Based on our FTP findings and the nmap scan, we can guess that the chatserver is probably running on port 9999. We can interact with the port using netcat and see what’s up. It is at this point I accidentally broke the machine so I had to redeploy, so the machine’s ip will look different.
It just seems like a chatserver with no one to talk to ;-;. We can try to see if we can crash the program with an absurdly sized inputs. We find that we can’t actually overflow the username input, but we can crash the program if we put too large of an input (I’ll spare you the output since it’s 2000+ A’s).
Exploit Developement
Rather than shoot blindly at the program, I’ll see if I can exploit it locally on a Windows VM, and then execute it on the real thing, by analyzing the program using Immunity Debugger. When I do basic stack overflows, I like using the template scripts from Tib3rius.
I’m not going to explain how to do a buffer overflow for people who know nothing about it (maybe for a later post), but I’ll link some people who can explain it at the bottom of this writeup.
The process I use:
Identify the part of the program we can overflow (FOUND!)
Use Immunity Debugger and Mona to find the offset
Find bad characters and the right module (using Mona)
Verify the exploit works locally and then test it against the real thing.
Assume for all of these steps I’m running the vulnerable executable through Immunity Debugger because providing all of those screenshots is a little excessive.
Installing Mona
Mona is a great plugin for Immunity Debugger that you can use to automate some of the more cumbersome parts of exploit development. You can find the plugin here. To install, just drag and drop mona.py into the PyCommands folder where the Immunity Debugger files are.
Finding the Offset
As of the writing of this article, the pattern_create.rb can now be used with /usr/bin/msf-pattern_create in Kali Linux. I’ll use this tool to generate a cyclic string that I can then use to locate the EIP.
Before I stick it in my exploit script, I have to modify it so that I can first submit a username, then the buffer.
I’m going to put the generated pattern into the exploit and see what Immunity Debugger has to say about it.
As you can see, the pointers in the program are completely overwritten, meaning that the program has no idea where to point next. Using this data, we can use a plugin called Mona to show us the offset. Entering !mona findmsp -distance 3000 will show us the following:
We find that the EIP is offset by 2012 bytes, which we can add to our exploit.
Find Bad Characters
Right now, our exploit should look like this:
Sometimes, programs interpret specific characters to serve a specific function, so we cannot use these in our shell code. Before jumping to grabbing the JMP ESP instuction and inserting shellcode, we need to find these bad characters. I’ll steal a list of hex characters from here and stick it in my code after the retn variable.
I’m also going to ask mona to do the same using !mona bytearray -cpb "\x00", so I can have mona check the bad characters for me. I’ll run the exploit again, and check for what bad characters might be using !mona -f C:\Share\bytearray.bin -a 00DCEEA8
Here, we see that there are no bad characters, so all we have to do is find the right module and the correct instruction pointer.
Getting the Rest
I see this module step skipped a lot in other tutorials and writeups because it isn’t that important, but I still think it’s worth the check. If a binary/executable is statically compiled, feel free to skip this. But, since our executable pull from a dll (and other programs could pull from multiple), we might want to double check exactly where in memory we can attack. I can look at the different libraries using !mona modules.
Here, we’re looking for a module that has all memory protections set to false, which essfunc.dll does. Our next step is to find the JMP ESP pointer that we can use to point back to our shell code, so we can get a shell. We can list instructions that are in essfunc.dll using the following command: !mona find -s "\xff\xe4" -m essfunc.dll (FF E4 is the JMP ESP instruction in hex).
If we had bad characters, we’d want to find a pointer that did not contain a bad character. However, since that isn’t a problem we can grab the first address 0x625014df, and put it in our exploit. Since Windows is little endian (which is some CS stuff that’s outside of the scope of this writeup), we need to provide this in reverse order. Our exploit should now look like this:
Verifying it Works
There’s one last step before we’re ready to roll. We will use msfvenom to generate the shellcode like so:
Since I’m testing on a local VM, I’ll have to regenerate this shell code when I go to do it on the real machine. Regardless, our final exploit should look similar to this:
I’ll start a listener on port 443 using netcat, run the chatserver.exe on my Windows VM as Administrator, and run the exploit.
Note: I did turn off Windows Defender and the firewall for this. Anti-virus is a little annoying sometimes.
Shell as Administrator
All we have to do, after replacing the shell code, is point our exploit at the actual target.