DeepSec 2013 Workshop: Hands On Exploit Development (Part 2)
Unless you buy ready-made exploits or do security research (you know, the tedious task of testing systems and code, findings bugs and assessing their impact) you may wonder where they come from. To show you how to exploit a vulnerability and how to get to an exploit, we have asked Georgia Weidman for an example. She will be conducting the Hands On Exploit Development training.
Early in my infosec education I took a class with a lab portion systems with known vulnerabilities. One system that I had difficulty exploiting was a Windows 7 host with HP Power Manager 4.2.6 which is subject to CVE-2009-2685. There is no Metasploit Module for this issue, but I was able to find some public exploit code on Exploit-db. The exploit calls out explicitly that it has been tested on Windows 2003 SP2 English and Windows XP SP2 English. I was faced with Windows 7 SP1 English. I had previously encountered exercises where I needed to port an exploit from one Windows platform to another. I needed to find the return address used to hijack the EIP register in the stack based buffer overflow on the new platform and change the memory address in the exploit accordingly.
The exploit calls out the details of the return address in a comment as shown here:
RET = “\xCF\xBC\x08\x76” # 7608BCCF JMP ESP MSVCP60.dll
This is helpful. We know we are looking for a JMP ESP (or redirect execution to the memory address in the ESP register). There is no Windows library called MSVCP60.dll, so one must assume that this is a library included with the HP Power Manager software. Thus we may not need to change this value at all. Though Windows libraries will move around in memory from platform to platform, the third party program and its libraries should not.
Of course the move from Windows XP or Windows 2003 to Windows 7 comes with additional security features that must be taken into account when developing exploits, namely Data Execution Prevention (DEP) and Address Space Layout Randomization (ASLR). DEP is designed to stop attacks where memory corruption is used to dump shellcode (or instructions to be executed) onto the stack (or in some cases the heap) and then redirecting execution to them. DEP marks memory regions that contain data rather than executable instructions as non-executable. As such if we try to execute shellcode from a non-executable memory region, the attack will fail, and our shellcode will not be executed. By default on Windows 7 DEP is turned on for “essential Windows programs and services only.” Thus DEP should not affect our HP Power Manager exploit at all.
Likewise ASLR randomizes the memory location of Windows libraries. Rather than being in the same place on every Windows XP SP2 system, USER32.dll etc will change memory locations at every reboot. This stops attacks from hardcoding memory addresses for the return address to a JMP ESP (or other attacker controlled register) instruction, as the memory locations will change. Luckily, our exploit references a JMP ESP in a HP Power Manager library. Though, all Windows libraries in Windows 7 will use ASLR, there is no requirement that third party programs use it. Even today maybe new programs don’t use ASLR, so it is likely that ASLR will not affect our exploit either.
The last consideration for porting the exploit to meet our needs is the shellcode. It is a good policy to regenerate shellcode in public exploits. The shellcode in the public exploit claims to be a bind shell on port 4444 generated by Metasploit. It even tells us the resulting length (709 bytes) and the bad character list the authors used to generate it (\x00\x3a\x26\x3f\x25\x23\x20\x0a\x0d\x2f\x2b\x0b\x5c\x3d\x3b\x2d\x2c\x2e\x24\x25\x1a) to help us create our own shellcode to fit in the exploit. This payload would work fine in my penetration testing practice lab environment. Thus it is possible that the exploit we found will work out of the box on our Windows 7 SP1 target.
There was one other thing that stuck out as I was reading through the exploit. At the beginning of the included shellcode there was the string n00bn00b. At first glance I thought this was put in to stop users from just downloading and running the code to get a shell without reading through it. My exploit development skills were limited to a simple stack based buffer overflow example from the course. I had not yet heard of an egghunter, or a small payload that searches memory for a string and the shellcode that comes after. A technical whitepaper on the subject can be downloaded here. The n00bn00b is the egg used. The small EH payload will search memory for the value n00b. If it finds it, it will see if another instance of n00b is right next to it (to keep the egghunter from finding itself). If so, the egghunter will have found the shellcode in memory and will redirect execution to it accordingly.
The public exploit includes the egghunter (variable EH) as part of the Login parameter where execution is hijacked and redirected to ESP. The main shellcode is included in the HTTP request to the server in the User-Agent parameter (line 96 of the exploit). Though it is hard to say for sure without analyzing the program in a debugger, chances are exploit hijacks execution and redirects it to ESP where there is not enough space for a typical payload such as a bind shell or Metasploit’s Meterpreter. However, the User-Agent part of the request is in memory somewhere, so we can use a small egghunter payload to find it and redirect execution to it.
Thus with a reasonable understanding of the public exploit and reason to believe that it would work despite the platform change, I ran the exploit, and it failed. But I wasn’t about to give up, so I set out to build a working exploit from scratch if I had to, despite the fact that I had never encountered an egghunter before. First things first however. If I was going to fix the exploit I needed a copy of the vulnerable software. The Exploit-db entry has N/A for the Vulnerable App field, a bad sign. I Googled around for the old version but had no luck. I eventually found HP Power Manager 4.2.6 with the help of a colleague who introduced me to Wayback Machine from the Internet Archive.
I installed HP Power Manager on a Windows 7 SP1 virtual machine. Even though I don’t have any SCADA devices to attach, the webserver will start up. I used Ollydbg for debugging. Since I was using a Windows 7 target I needed to run Ollydbg as Administrator to have access to all its functionality. I attached to the vulnerable in Ollydbg by going to File->Attach and highlighting DevManBe.exe and clicking the Attach button. One weird thing about the HP Power Manager is that it periodically throws an exception in the debugger. I had to pass an exception to the program with Shift-F9 to allow the program to continue to run.
By sending the exploit I was able to see the crash in Ollydbg. The program did indeed crash without opening a command shell on port 4444 as the exploit comments indicated that it would. The program crashed with an access violation when reading C76000D2. This access violation is a little bit different than the ones I was used to seeing in my limited experience writing exploits. Typically I saw a crash when I was developing exploits before I had found a return address or created shellcode. I first send a long string of A’s and the program crashes with an access violation when executing 41414141 (41 is hex for A). This indicates that I control EIP and I move on through the steps of developing an exploit: finding an attacker controlled register, finding a return address to get to it, generating shellcode, etc. Our exploit is theoretically finished with all of those steps finished, so it is not surprising that we do not see such a crash. In this case it is not the memory address that is being executed that is out of bounds. We are instead trying to read from a memory address that is not mapped to our process. Looking at the instructions in the top left pane of Ollydbg, we see that the instruction is trying to read from the memory address in ESI register, which we see in the top right register holds the value C76000D2.
This left me with a few questions, for example where the hell are we? Has my return address been executed? Is my shellcode in memory somewhere? Did the egghunter find it? Why did I end up reading from a location that isn’t mapped to my process?
I set out to answer one question at a time. As it turns out HP Power Manager is one of only a few Windows programs I have ever seen restart nicely in Ollydbg. Most of the time I need to detach from the process and restart it manually, but here I could go to Debug->Restart and click the blue Play button to run the program.
To see if our return address, the JMP ESP in MSVCP60.dll, is being executed before the crash I set a breakpoint on the memory address 7608BCCF. I opened the executable modules pane by clicking on the E. I choose MSVCP60.dll from the list. Then I right clicked on the instructions pane and chose Go To->Expression. I searched for the memory address and then hit F2 to set a breakpoint as shown in Figure 2.
I then ran the public exploit code again. Execution paused at my breakpoint. The return address is being executed as shown in Figure 3.As shown in Figure 3 in the stack pane in the bottom right, I saw the contents of ESP that will be executed next after the JMP ESP at the breakpoint. There are the NOPs followed by the egghunter. So the egghunter is being executed.
My next question is, is the egg followed by the shellcode actually in memory somewhere to be found by the egghunter? I went to View->Memory to see all the mapped memory regions. I right clicked on the memory pane and chose Search. I searched for an instance of the ASCII string n00bn00b as shown in Figure 4.
The search found the n00bn00b followed by the shellcode. I took note of the memory address and compared it to the crash in Figure 1. It seems we crashed just a few instructions down from the start of the shellcode. The egghunter is working, finding the shellcode and redirecting execution to it. The problem is definitely in the shellcode. Just to be sure, I tried the exploit again on Windows XP SP2, one of the verified targets in the exploit, and had the same result.
There is a long list of bad characters included in the comments of the exploit. Perhaps the authors missed one? Just to be sure I replaced the shellcode with the full hexadecimal character set:
As it turns out there are no bad characters that must be avoided in the shellcode, not even the null byte. I wasn’t sure where the original authors got their list. It’s not unheard of for public exploit writers to put in shellcode that doesn’t work or is otherwise incorrect. For one this makes it harder for unskilled attackers to just take public exploit code designed for pentesters and to use it for evil. Perhaps that is the case here. A next step in this exercise would be to analyze the original shellcode to discover the problem or what it really does.
I created a variable shell2 = “n00bn00b” + barchars in the exploit. Then I changed the User-Agent string to shell2 in the exploit string (replaced SHELL with shell2 at line 107).
Based on what characters do not appear in memory when I ran the exploit again, I could tell what characters needed to be avoided when regenerating the shellcode. I ran the exploit again, paused at the breakpoint, and searched memory for n00bn00b to find the dummy shellcode. As shown in Figure 5 the entire badchars string appears in memory.
I generated new shellcode with Msfvenom. I used the same Windows bind shell payload and left the LPORT option as the default 4444.
root@kali:~# msfvenom -p windows/shell_bind_tcp -f py
I copied the generated shellcode (buf variable) into my exploit. I changed the first line of the generated shellcode for buf = “” to buf=”n00bn00b” to tack on the egg at the beginning of the shellocde. I then changed the User-Agent string from shell2 to buf (line 107).
When I ran the finished exploit against a restarted HP Power Manager, this time the payload executed and I was able to get a shell on the target system. The only problem with this exploit was the included shellcode. I didn’t know it at the time, but it is always a good policy to regenerate shellcode in public exploits even if what it claims to do will work for your purposes. There is nothing to stop exploit developers from creating malicious shellcode that does something else to the target such as deleting the harddrive, or the shellcode may just not work, as we saw here.
In the DeepSec course we will look at building this exploit from scratch as well as converting it into a Metasploit module.
So you see that developing exploits requires some skill and experience. The workshop is a great way to start, and it helps to understand what attackers do to get a foothold in your internal networks and systems.