For those of you who follow me on Twitter, you may have noticed that I posted a few teasers related to replacing processes in Powershell. Without further ado, I am releasing Replace-x64-Process. This tool is intended solely as a proof-of-concept tool. I say that because I make absolutely no guarantees that it will work in all cases. In fact, it won't work in many cases.
The intent of this tool is to circumvent application whitelisting products. Assuming Powershell is whitelisted, you can use this tool to load a blacklisted executable within a whitelisted process. I have not tested this tool on any whitelisting products, however so I cannot attest to its level of effectiveness.
Replace-x64-Process makes use of some common techniques seen in malware to replace a suspended process' executable image. Fortunately, Powershell gives us access to many of the mechanisms required to achieve this goal.
Basic steps required to replace a process in memory:
1) Load the host process in a suspended state.
2) Open a handle to the main thread of the executable
3) Get the context of the suspended thread. In 64-bit the entry point to the process is located in RCX. A pointer to the PEB (Process Environment Block) is located in RDX.
4) Call ZwUnmapViewOfSection to unmap the image of the host process
5) Parse the section headers of the target process
6) Find the image base of the target process
7) Allocate space to contain the image of the target process
8) Map the PE header and each section of the executable to the newly allocated memory.
9) Update the PEB to reflect the new image base address
10) Call SetThreadContext to redirect execution to the target process
11) Resume the process
Here is an example of the script in action:
|Replacing Internet Explorer with cmd.exe|
|Replacing notepad.exe with a 64-bit bind shell|
In the last example, it is worth noting that the Microsoft code signature is not invalidated after loading the malicious process. This is due to the fact that code signatures are validated prior to the main thread loading. This is an unintended but awesome side effect of this process.
Lastly, I have a 32-bit version of this script. It is however even more flaky than the 64-bit version. I suspect it's due to the fact that I don't account for relocations. Because instructions in 64-bit are RIP-relative, relocations are no longer necessary. I may release a more polished script for both 32 and 64-bit in the future once I become more familiar with the loading process.
Replace-x64-Process Help File
Enjoy and try not to get too frustrated when the tool doesn't work for you. Also, if you use the -verbose option, you'll find that much of the code in this script demonstrates the beginnings of a full-fledged PE parser. Perhaps more on that in a future posting... If you have any suggestions on how to increase the reliability of this tool, please leave a comment.