Milkman: Creating processes as any currently logged in user
One of the problems with using PSEXEC from Metasploit (any of the psexec modules) is that it runs as SYSTEM. What’s the problem with that? Isn’t SYSTEM god mode? Ya, and normally I’d agree that it’s the best level to have, but the defenses these days have gotten better, and getting direct connections out is pretty rare. That leaves proxies, and as you know SYSTEM doesn’t get any proxy settings.
Here is a blog post that I made about setting the proxies for SYSTEM but leaving settings like this set is not only sloppy but hard to clean up.
Along comes RunAsCurrentUser-2.0.3.1.exe
I found this gem by messing up a search on google for RunAsUser. Found it on this IBM support post.
Link to direct download: http://software.bigfix.com/download/bes/util/RunAsCurrentUser-2.0.3.1.exe
Here is a mirror uploaded to my Post Exploitation repo: https://github.com/mubix/post-exploitation/blob/master/win32bins/RunAsCurrentUser-2.0.3.1.exe
This binary takes a path to another executable as an argument. It then finds the currently logged in user and starts the provided executable as that user. AWESOME! This basically solves the whole PSEXEC->SYSTEM no-proxy settings issue. And it’s created by a legitimate company for legitimate reasons? w00tw00t. Game on!
Only two problems:
-
It is 335K, which doesn’t seem like much but over high latency lines that can take an eternity to transfer, especially over doubly encrypted channels like with a reverse_https meterpreter session.
-
It takes an argument which normally isn’t a huge challenge, but in our specific use case, psexec modules in Metasploit, it isn’t something we can do easily. You would have to upload your C2 binary, as well as the 335K RunAsCurrentUser over to the target host, then run the psexec_command module to execute them both, one as the argument of the other. Kinda sloppy.
So I set to try and figure out how this binary did it’s magic. As I’m not much of a reverse engineer I uploaded it to VirusTotal so I could take a look at it’s insides (plus, double check to see if it was being detected as malicious at all).
As far as I can tell the important pieces are the Windows API calls ImpersonateLoggedOnUser, and CreateProcessAsUserA. I set to trying to reproduce what it did in AutoIT (awesome stuff if you have never checked it out). I couldn’t quite get the API calls right, so I decided to give C++ a shot. Turned out to be pretty simple. I present to you “Milkman”:
https://gist.github.com/mubix/5d0cacdabfe092922fa3 (full source included below)
This program (once compiled) takes one argument (or none at all) and runs calc.exe for every instance of the process you tell it to. If you run it without arguments it auto selects explorer.exe. So if you create a service:
|
|
It will start up every time the computer starts, which is completely useless, since there won’t be any users logged in at that point, but you get where this can go. Features to add to this at point are:
- Create a service binary that responds to START/STOP/PAUSE commands and such so that running this as a persistence method would actually be useful.
- Add a loop so that it continues to run checking for explorer.exe every so often so it can catch when someone is logged in.
- Finally the obvious one is to change it from being calc.exe that it runs by accepting another argument or some other kind of config option.
Thoughts? What would you like Milkman to do, or what use case do you think a tweak would make it work better for? Leave a comment below.