I’m very interested in supporting alternative remote administration tools in Cobalt Strike. Meterpreter is awesome as an active RAT, but I need something less chatty to hold my accesses when I’m not using them. I plan to talk about about this in my upcoming Dirty Red Team Tricks II talk. In this post, I’d like to talk about how to deliver a custom payload with one of the Metasploit Framework’s existing stagers.
Problem Statement
Part of the value I offer with Cobalt Strike and Armitage is a workflow around the Metasploit Framework. As such, any third-party stuff I create has to integrate well into the framework and feel like a first-class part of the tool’s workflow.
When I sat down to look at this problem, I had the following requirements in mind:
- I want to use my third-party payload with remote and client-side exploits
- I’d like to use my third-party payload with generate executables (e.g., I want them to work with psexec, I want to be able to embed it in an existing executable, etc.)
My ideal integration point is Cobalt Strike’s listener management feature. Through this dialog, users may start multi/handlers for different payloads, configure them, and name them. Later, users may pick from these listeners when setting up a client-side attack or generating a social engineering package.
Solution
Matt Weeks covered a few options for using custom playloads in Metasploit 4. He talked about how to use the generic/custom option to embed your own shellcode. He also covered the EXE::Custom option.
The best solution to my problem is the dllinject payload shipped with the Metasploit Framework. dllinject allows me to specify a reflective DLL and load it using the http, https, or tcp stagers.
To use dllinject, I need to:
- create a reflective DLL
- patch the reflective DLL to make it compatible with the dllinject stager
- deliver the patched reflective DLL to the dllinject stager
How to create a reflective DLL
A reflective DLL is one built with Stephen Fewer’s Reflective DLL Loader code. To build a reflective DLL, you will need Visual Studio 2008. The dllinject stager will not load an arbitrary DLL for you.
I tried Visual Studio 2010 initially, but the DLL would crash the process I injected it into when using it on versions of Windows before XP SP3. I spent some time tweaking the different compiler and linker options to mitigate this with no dice. Visual Studio 2008 Express is still available for free and it works, I recommend that you use it.
Next, create a project and import the Reflective DLL files into it.
You will also want to right-click the project, navigate to Properties -> C/C++ -> PreProcessor and define the REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR and REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN constants. You’re just defining these as true essentially.
This will allow you to use DllMain as the entry point once the DLL is reflectively loaded. See ReflectiveDLL.c.
Now you should be able to compile the project without any issues.
To test your reflective DLL, use the inject program included in the package.
Now you’re all set.
I want to deliver the DLL to the stager, myself…
To take advantage of dllinject, I have an additional problem. I plan to have my custom payload communicate to my web server running on port 80. I can stage dllinject from a different port, but this isn’t as clean. I’d like to deliver my custom payload to the stager from my web server. This introduces a few additional steps which are worth documenting if you need to do something similar.
Patch the Reflective DLL
The DLL inject stager will not accept the reflective DLL as-is. It must be patched. The payload handler for dllinject handles this step for us automatically. Since I want to host the DLL myself, I must patch it myself.
The code for this patching is in reflectivedllinject.rb. I’m opting to cheat and force the Metasploit Framework to patch my DLL for me. To do this, I will automatically launch a reverse tcp handler for the dllinject payload. Connect to it, download the patched DLL, and save it to a file I can host.
Here’s the Cortana/Sleep code that does this:
# connect to the reverse tcp dllinject handler $handle = connect("127.0.0.1", 65002); # read a 4-byte integer stating the size of our data. I use I- to account for the byte order $bytes = bread($handle, "I-")[0]; $data = readb($handle, $bytes); closef($handle); # save to r2.dll $h = openf(">r2.dll"); writeb($h, $data); closef($h);
Deliver the patched Reflective DLL
Now that I have a patched reflective DLL I can host it on my web server and deliver it when the stager requests it. The stager communicates to a 4-character random URL. This random URL is hard coded in the stager when it’s generated. I wrote a regex in my web server and instructed it to deliver my hosted DLL for any requests that match /[A-Za-z0-9]{4}. One other note, the Content-Type of the delivered DLL should be application/octet-stream.
Conclusion
With that, you now know enough to deliver your own RAT or agent using the Metasploit Framework’s DLL inject payload. An eventual Cortana goal will be to create an API that allows Armitage and Cobalt Strike to act as a way to control administration tools beyond Meterpreter. I’m still deciding what that will look like, but… having an integration point to deliver a custom payload is a good start.