New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add synchronization to the DLL payload template #14410
Conversation
Looks like this works in my tests however the behavior of
|
That does look odd. Have you tried to reproduce it without these changes to see if it's related? If it's unrelated could you open an issue for it? |
Huh so interestingly I got the same result on
I will test this again with the reverse shell payload though as I realized with a bind shell one may be stopped as the target may only be able to listen on that port once so its not a good test of the new features vs a reverse shell where the target could connect back to our listener multiple times. My fault for not realizing this 😓 |
Okay looks like old version of the code allows multiple connections back, does not have the same issue with
With the changes the reverse shells work as expected and one has to close down the current reverse shell and then open a new one for things to work. Note that any existing shells on the system will not connect back, so you have to spawn a new shell after closing the existing one for things to work. @zeroSteiner can you confirm if this is expected behavior or not? Also note that the two connections you see at the beginning are from previous attempts so sessions 1 and 2 are not part of the second round of testing but are remaints from testing on
|
Yeah that's right. There's no timeout so you can't spawn a new rundll32 process to host the payload until the previous one (if it exists) has exited. You can't spawn multiple sessions concurrently from the same generated DLL by design. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good but did find one case where the code might accidentally allow a process to be spawned even though it shouldn't be. Rest of the code looks good.
Release NotesAdded synchronization to the DLL payload template for ensuring that even if a target machine loads a DLL multiple times, users will only get one session on the host, preventing cases where a user may get multiple shells from a single exploit, which can result in excessive activity that could easily reduce the stealthiness of a user's attack. |
@@ -0,0 +1,14 @@ | |||
@echo off | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This adds synchornization logic to the DLL payload template with the intention of preventing a payload generated by Metasploit to be run multiple times in parallel. The goal behind this is to execute and deliver exactly one session even in cases where the host process may load the DLL multiple times. This was the case when working on #14409. Sessions are great and all, but I don't think getting 6 or more at a time is super great for stealth.
The sync technique I'm proposing leverages handle inheritance, specifically to a named event. This named event will be randomized by Metasploit each time the payload DLL is generated, so even with the same datastore options and repeated exploit attempts, the user should get one session each time. I tried to document the technique through step by step comments in the code, so hopefully that explains how it works sufficiently. The technique does permit the payload DLL to deliver a session again once the original host process has exited and thus close the event handle.
One notable concern I have with this is that users that are generating their payload DLLs will no longer be able to execute them multiple times to yield a session each time. I don't think this is terribly common since folks looking to do this are probably using EXEs instead. In this case the first execution would yield a session, but subsequent executions would not while that original session is still running. I don't think there's a way around this since it's effectively the user creating the scenario that we're trying to avoid.
Less Important Changes
I also removed the old bash build script that would only compile the 32-bit version and replaced it with a batch script that will compile both the 32-bit and 64-bit versions. I also took this opportunity to increase the payload space from 2048 to 4096 and normalized whitespace within the template.
Verification
If you test this from a combined branch with #14409, those steps as written will work with the only change that you should get exactly 1 session and not multiple sessions. Additionally, each time the module is executed, a single new session should be opened.
msfconsole
use payload/windows/meterpreter/reverse_tcp
to_handler
to start the handlergenerate -f dll -o /path/to/payload.x86.dll
to generate the payloadrundll32 C:\Path\To\payload.x86.dll,Whatever
to run the payloadrundll32
multiple times and see that no new sessions are created