Incident Response | ZipExec
A new foe has appeared !
Earlier this week, a super cool project was uploaded to GitHub by an Optiv researcher called ZipExec. (And of course, we need to include the awesome ASCII art!)
__________.__ ___________
\____ /|__|_____\_ _____/__ ___ ____ ____
/ / | \____ \| __)_\ \/ // __ \_/ ___\
/ /_ | | |_> > \> <\ ___/\ \___
/_______ \|__| __/_______ /__/\_ \\___ >\___ >
\/ |__| \/ \/ \/ \/
From the Repo:
“ZipExec is a Proof-of-Concept (POC) tool to wrap binary-based tools into a password-protected zip file. This zip file is then base64 encoded into a string that is rebuilt on disk. This encoded string is then loaded into a JScript file that when executed, would rebuild the password-protected zip file on disk and execute it. This is done programmatically by using COM objects to access the GUI-based functions in Windows via the generated JScript loader, executing the loader inside the password-protected zip without having to unzip it first. By password protecting the zip file, it protects the binary from EDRs and disk-based or anti-malware scanning mechanisms.”
In Simple Terms
The tool allows us to drop a binary onto a host by rebuilding it from memory, instead of relying on the file to be “physically” present. The process of building a password-protected ZIP file on the host also means that EDR solutions won’t have any visibility into the archive, and static analysis won’t return any indications of malware hiding inside. Additionally, RNG means unique hashes so hash-based blocking won’t be an effective mitigation.
Blue Team / Incident Response
As cool as Red Teaming is, we often forget that the objective is to identify gaps in visibility so we can enable security teams to build detections and mitigate emerging threats appropriately. I decided to utilize good old Windows calculator (calc.exe) to test the dropper generated by ZipExec and see what kind of logs get generated - Specifically Windows Event logs. Running ZipExec and feeding Calc.exe into it results in a loader built similar to what’s below (JavaScript that runs via Wscript):
{
mKgiiUuU(RsKSoIpknBC,PRtKDvycW+"\\calc.zip");
function YBBczP()
{
var TdNEq = new ActiveXObject("shell.application");
var kvIOjM = new ActiveXObject("WScript.Shell");
var IGSJZYR;
var XwUvS = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\HideFileExt";
var wRUopyHBRk = ""+PRtKDvycW+"\\calc.zip";
IGSJZYR = TdNEq.NameSpace(wRUopyHBRk);
var LMnF;
LMnF = IGSJZYR.Items();
WScript.Sleep(5000);
var BmIQFRRrQwS = kvIOjM.RegRead(XwUvS);
if (BmIQFRRrQwS < 1) {
BXIINCa = LMnF.Item(LMnF.Item(0).Name);
}else {
BXIINCa = LMnF.Item((LMnF.Item(0).Name)+".exe");
}
BXIINCa.Verbs().Item(0).DoIt()
}
var PASgmHmKn = new ActiveXObject("Wscri"+"pt.shell");
var ihWAhC = PASgmHmKn.ExpandEnvironmentStrings("%TEMP%");
var hMpsBiYJ = new ActiveXObject("shell.application");
hMpsBiYJ.ShellExecute('cmdkey', '/generic:Microsoft_Windows_Shell_ZipFolder:filename='+ihWAhC+'\\calc.zip /pass:mrimBxyDv /user:""','','',0);
YBBczP();
WScript.Sleep(5000);
hMpsBiYJ.ShellExecute('cmdkey', '/delete Microsoft_Windows_Shell_ZipFolder:filename='+ihWAhC+'\\calc.zip','','',0);
}
Examining the Loader
Re-Building the Payload from Memory
The very first function of note is what actually rebuilds the ZIP file containing our payload onto this host - mKgiiUuU(RsKSoIpknBC,PRtKDvycW+"\\calc.zip");
. This function takes in two arguments: the first is RsKSoIpknBC
(all var names are randomly generated at run time so no loader will be the same). This first argument is the string containing the Base64 encoded byte information for our payload. The second argument, PRtKDvycW
, refers to var PRtKDvycW = IrBtx.GetSpecialFolder(2);
and IrBtx
refers to var IrBtx = new ActiveXObject("Scripting.FileSystemObject");
. Essentially we’re rebuilding the payload based on the Base64 encoding, and storing it in the file calc.zip
.
Detection Methods
I think the most obvious way of catching this loader is going to be the JavaScript loader writing this file to the disk. Any modern EDR solution should be able to support alerting that detects a ZIP filemod event sourcing from Wscript. The loader itself will probably have some static analysis engine hits for potential Loader behavior. Remember though, this is just a POC and any malicious actor can take the concepts in this tool and potentially obfuscate further to circumvent static analysis detections for behavior and heuristic detections.
What the hell is CMDKEY.exe?
The next part of the loader actually executes our payload by using CMDKEY to pass the generated password into our COM object without any visual cues hinting to an end-user that something malicious occurred (think PowerShell hidden window). Which brings me to the question I had when I first read through the loader’s generated script… what the hell is CMDKEY.exe???
Well according to Microsoft documentation, it lets us store and manage credentials via the command line. Why is this relevant? Because the whole point of this tool is to perform activity that the end-user is unaware of. Our generated payload is a password protected ZIP, but we still want to execute whatever is inside without tipping off the user or the EDR.
var hMpsBiYJ = new ActiveXObject("shell.application");
hMpsBiYJ.ShellExecute('cmdkey', '/generic:Microsoft_Windows_Shell_ZipFolder:filename='+ihWAhC+'\\calc.zip /pass:mrimBxyDv /user:""','','',0);
In this command block, we can see the COM object being called, and we use CMDKEY’s /generic flag to add a temporary credential for the file "Microsoft_Windows_Shell_ZipFolder:filename='+ihWAhC+'\\calc.zip"
- which we know from the loader is stored in %TEMP%
.
What does this all look like in terms of Windows Logging?
First Detection Point
The good news is that we can easily build detections to catch this tool. There are three primary points where we can catch ZipExec in action. The first is the loader dropping a ZIP file onto the host - which in practice is Wscript resulting in a filemod for a ZIP file in %TEMP%
.
Second Detection Point
The second point where we can catch this activity, is the COM object having a credential passed into it via CMDKEY:
Log:
10/25/2021 11:51:27 PM
LogName=Security
EventCode=4688
EventType=0
SourceName=Microsoft Windows security auditing.
Keywords=Audit Success
TaskCategory=Process Creation
Message=A new process has been created.
Process Information:
New Process ID: 0x1868
New Process Name: C:\Windows\System32\cmdkey.exe
Token Elevation Type: %%1936
Mandatory Label: S-1-16-12288
Creator Process ID: 0x183c
Creator Process Name: C:\Windows\System32\wscript.exe
Process Command Line: "C:\Windows\System32\cmdkey.exe" /generic:Microsoft_Windows_Shell_ZipFolder:filename=C:\Users\vagrant\AppData\Local\Temp\calc.zip /pass:mrimBxyDv /user:""
Detection Methods
Here, we can just look for wscript.exe spawning cmdkey.exe, and possibly even adding RegEx that catches “Microsoft_Windows_Shell_ZipFolder” in the command line. We can get pretty granular here as the behavior is pretty simple to predict. But basically 4688 of wscript spawning cmdkey.
Third Detection Point
A third detection point is the actual payload being executed, and if we think about it, it would be super strange to see an EXE spawning from a .zip
file.
Log:
10/25/2021 11:51:33 PM
LogName=Security
EventCode=4688
EventType=0
SourceName=Microsoft Windows security auditing.
Keywords=Audit Success
TaskCategory=Process Creation
Message=A new process has been created.
Process Information:
New Process ID: 0x1894
New Process Name: C:\Users\vagrant\AppData\Local\Temp\Temp1_calc.zip\calc.exe
Token Elevation Type: %%1936
Mandatory Label: S-1-16-12288
Creator Process ID: 0x183c
Creator Process Name: C:\Windows\System32\wscript.exe
Process Command Line: "C:\Users\vagrant\AppData\Local\Temp\Temp1_calc.zip\calc.exe"
The strangest part about how this is logged is that our payload/dropped zip is not actually logged in the command line that spawns the process (calc.exe). The file “Temp1_calc.zip” gets called, but inside of %TEMP%
we wrote “calc.zip”.
Detection Methods
Again, building detection from this log is easy - 4688 where wscript spawns an exe….from inside a zip file (Temp1_calc.zip\calc.exe).
Detection TLDR
This entire tool can essentially be detected by implementing alerting around Wscript and behavior that isn’t prevalent within the environment. The three detection points presented here aren’t a catch-all, but rather three easy spots we can catch this tool in action. It’s by no means definitive or the “best” way of building detection. I am not a detection developer or SIEM architect, but from my experience in incident response - I think this approach is a relatively reasonable approach to building alerts.
I’m going to be playing with this tool some more, because there’s definitely some other stuff we can check for (Netcons sourcing from a Zip file for one), and I’m curious to know how all of it gets represented in logs. Tomorrow, I’m going to build some Splunk alerts for this and append to the post for anyone that may be interested.