I work in Charleston as a red team operator. Tend to be long term operations. Because of increased defensive mechanisms we’ve started looking at additional ways to move laterally through a compromised network.
Using whatever backdoors, RATs, etc, pop open a shell and start looking around. The level of access you have on the box you are on will determine how many of these things you can get. If you are assessing an enterprise, good chance that the applications will be installed on a number of other systems.
Match the PIDs of processes listening to the binaries using tasklist .
If it’s a service, sc query and sc qc are also useful in tracking down the location without having to search manually for the binary.
Same process applies to linux.
Depending on what’s available to you, you might only be able to perform static analysis. If this is the case the only thing you really need is the application binary. Hexrays decompiler.
Biggest question I get when asked about how to begin searching for bugs in software, is where to start looking. Start looking at the entry points into the application. Check all parsing and sanitization routines for data coming into the application from the outside.
Most buffer overruns occur around some sort of copy functions. Analyze any occurrences of these that are being used on incoming or controlled data. Check bounds checking around these functions and custom copy routines. Check if you control the indexes of any copies into memory or the sizes of memory copies.
If you have the ability to setup a test environment and perform static analysis, some of these tools will help track down necessary files. Run some of these useful tools to enumerate what files you need off of the system. Either download them from the compromised machine or locate them offline.
Whenever using sysinternals utilities remember to add the /accepteula otherwise a popup will come up asking for confirmation
The dumps created by procdump.exe can be loaded into Windbg. File-> Open Crash Dump. Allows you to check whether runtime libraries are the same as your test environment. Check if any other mitigations are in place such as HIPS. (EMET, HBSS)
If you have the ability to start and stop the process without adverse effect but don’t have the ability to debug it, you can turn on crash dump capabilities.
https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181%28v=vs.85%29.aspx
Linux – set size of core dump to unlimited
Core dumps can be loaded into gdb in a test environment.
As described in the previous slides, we identify a service running on a compromised system and track down the running binary.
Since we know this application is running as a service listening on port 8080, let’s start our analysis by finding usages of the function “recv” from the winsock imported library. The code following this receive will likely be the parsing functions for whatever data was sent to the application over a socket connection. We found 2 usages of the recv function, in what appear to be a recv for a header, followed by a recv for the data. Showing the decompiled version here for easier readability.
As presumed, the calling function of the recv wrapper function, switches based on the command type, and parses the particular message.
Much reversing later… I come across the parsing function for msg type 239 (actually 238 because the parsing code adds 1). We have a loop that iterates over a user-supplied string, that is formatted as an integer array. Inside the loop, a call is made to “char_to_long_buggy”, which converts the next number in our string to a long, and then sets the return value to the next index in our integer array on the stack. As can be seen here, the loop iterates until the number returned from “char_to_long_buggy” is zero. The problem is there is no bounds checking on this loop to ensure that the number of user-supplied integers does not exceed the size of the integer array to hold them. At this point, I have enough to warrant setting up a test environment to confirm whether or not this is an exploitable vulnerability.
Run SysInternals ListDlls.exe and Handle.exe on the PID retrieved from the other utilities. No additional third party libraries are loaded, (other than McAfee HBSS). Glean information from the log file. Let’s us know that most of the necessary files are in the AHLTA Data directory.
Run SysInternals ListDlls.exe and Handle.exe on the PID retrieved from the other utilities. No additional third party libraries are loaded, (other than McAfee HBSS). Glean information from the log file. Let’s us know that most of the necessary files are in the AHLTA Data directory.
Run SysInternals ListDlls.exe and Handle.exe on the PID retrieved from the other utilities. No additional third party libraries are loaded, (other than McAfee HBSS). Glean information from the log file. Let’s us know that most of the necessary files are in the AHLTA Data directory.
Since this particular binary is a service let’s also grab the registry information for the service so we can setup the same way in our test lab.
Registry information for services resides at "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services“ add /s to query recursively.
Setup as nearly an identical environment as your target. Operating system, dependencies, service registration. This is so we don’t have to test on live systems.
Using the files and information I gleaned from the compromised system, I setup my test environment. I replicated the directory structure, added the medcinserv application as a service, started the service, and attached to it using Immunity Debugger. File -> Attach. Using my disassembly as a reference, I set a breakpoint at address 0x0425E80, the function that contains the stack overflow.
Using the files and information I gleaned from the compromised system, I setup my test environment. I replicated the directory structure, added the medcinserv application as a service, started the service, and attached to it using Immunity Debugger. File -> Attach. Using my disassembly as a reference, I set a breakpoint at address 0x0425E80, the function that contains the stack overflow.
From the IDA disassembly around the recv function calls, we saw that the protocol is structured like follows.
Using your favorite language, start coding up the boiler plate code necessary to connect to a socket and send raw bytes.
Setup socket code and the correct protocol format.
As mentioned on slide 14, the bug involves overflowing a statically allocated integer array.
When we execute or script we should trigger an access violation in our debugging as can be seen here. Our EIP ( Effective Instruction Pointer ) has been overwritten with one of the 1’s we supplied in our script, so we have verified that our bug exists and can be reached. This is the register that points to the next address to be executed.
Now that we know we control EIP, we need to see what protections are in place so we can start planning what needs to be done to construct a reliable exploit. We can use the “modules” function in Corelan’s mona.py script to identify what libraries have been loaded and what compile time protections they have. From the output here, we can see that the medcinserv binary was not compiled with any protections. This means we literally need one “JMP ESP” or PUSH ESP, RET” instruction to gain control of execution. This is assuming that the system wide DEP settings are not set to Always On, which with Windows 7 is Opt-In by default. To makes things more interesting we’ll assume the system is Always-On and we have to bypass DEP and ASLR.
The ability to put NULL bytes in our buffer is imperative since we will need to use addresses from our binary for the ROP chain, used to bypass DEP.
Using mona.py we have generated the necessary gadgets to call VirtualAlloc.
Unfortunately, the address to VirtualAlloc was not found in our binary’s import table.
To make the exploit more reliable across different versions of kernel32.dll we need to resolve the address of VirtualAlloc.
We can do this using GetModuleHandle and GetProcAddress
Using mona.py we have generated the necessary gadgets to call VirtualAlloc.
Unfortunately, the address to VirtualAlloc was not found in our binary’s import table.
To make the exploit more reliable across different versions of kernel32.dll we need to resolve the address of VirtualAlloc.
We can do this using GetModuleHandle and GetProcAddress
We need to add a function that will convert our shellcode to a string array of integers. It will simply loop through the byte array and convert every four bytes to its integer equivalent, convert it to a string, and add it to the comma delimited list.
From here you basically just have to grind through the list of available gadgets and piece everything together based on the exploit design.
Before you ever throw this exploit on a live penetration test make sure you test it thoroughly in your lab.
Make sure your red team lead and any white team leads give you permission before you test on live systems.
Add it to your arsenal.
Depending on your customers and the install base of the software you are looking at, the reporting will likely be different. The particular case study we gave, we felt it best to notify Cybercom since the software affected a GOTS piece of software.
From here you basically just have to grind through the list of available gadgets and piece everything together based on the exploit design.