Custom payloads in Metasploit 4

One of the key features of Metasploit is the customization of the framework; for example, different payloads can be generated with many different options and placed in any of a large number of exploits. Custom scripts can be written with many commands for automated post-exploit actions. Nevertheless, there have still been a number of customizations that have been awkward to implement. Many of those deal with adding a payload that isn't in the framework, or modifying it in a way that the framework does not directly support. So for Metasploit 4, I made a few tweaks to increase payload flexibility.

Generic/custom

The first change was an addition of a single custom payload. Prior to this, a custom payload existed for command execution exploits for UNIX (payload/cmd/unix/generic) but there was no analogous payload for command execution exploits for Windows, or for that matter any other architecture or platform. If you are developing a payload that could benefit from Metasploit integration, writing a payload module is preferable. But in some cases, such as generating multiple payloads, Metasploit might not currently support the UI or backend to generate the payload in a conventional way, and you may want to import the payload from a file or option. Or while writing a payload, it can be easier to import a payload into the framework than change a module.

Multipayloads

The second change made it easier to combine multiple payloads into one exploit, since you may not get a second chance to exploit your target service, get them to open an exploit document, etc.

The first shot at allowing the framework to creating a single payload that is a combination of a number of payloads was the "none" exitfunc. Most payloads allow you to set the "EXITFUNC" option. This option effectively sets a function hash in the payload that specifies a DLL and function to call when the payload is complete. Usually it is set to thread or process, which corresponds to the ExitThread or ExitProcess calls. I added a 'none' that calls GetLastError, effectively a no-op. The thread will then continue executing, allowing you to simply cat multiple payloads together to be run in serial.

For some reason that didn't function in my XP vm, but it worked fine in my win7 VM. When the first reverse shell either failed or ran and the shell exited, the second reverse shell was started. Unfortunately this doesn't help you if the first freezes, but it's a start.

Unfortunately the biggest problem is that many payloads don't have a clean execution path after the exitfunc. For example, the windows/exec payload places the exitfunc block before the command to be executed, so instead of running to the next payload, it tries to execute the ascii command as x86 instructions. This fails badly.

Parallel multipayloads

The solution is to enable running payloads in parallel, using roughly the same technique as in the exe payload injection code. That code injects a payload into an existing exe to run in a new thread while the old exe code continues to run normally. (-f option in msfvenom and msfencode) So now with the -c option, you can generate shellcode to be run in a new thread while the shellcode in the file specified by the -c option will be run in the main thread. And of course you can continue to add payloads to be run in parallel in subsequent commands.

This code generates an executable that runs a messagebox payload in one thread while a reverse-connect meterpreter is spawned in another thread.

Custom executables

The last change came in response to a number of requests to use a custom executable in the psexec exploit that generates and drops an executable onto the target system to execute. Since some antivirus products will block metasploit generated exe's, yet it is not difficult to manually generate an undetected executable, it makes sense to allow exploits like psexec to use an external exe as the payload. This change was implemented in the exe mixin used by executable-dropping exploits, and so is available in all similar exploits as well. The option is the advanced option EXE::Custom.