{
	"id": "8828e360-86c0-46bd-99b2-b25d3e9edd3c",
	"created_at": "2026-04-06T00:18:40.087937Z",
	"updated_at": "2026-04-10T03:37:00.028986Z",
	"deleted_at": null,
	"sha1_hash": "9262dc167da7e8a3b1a77428a09cc1f93ac36d28",
	"title": "Embracing offensive tooling: Building detections against Koadic using EQL",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 2750561,
	"plain_text": "Embracing offensive tooling: Building detections against Koadic\r\nusing EQL\r\nBy Daniel Stepanic\r\nPublished: 2022-06-01 · Archived: 2026-04-05 16:13:54 UTC\r\nThis year at BSidesDFW, my local security conference, I highlighted a continuing trend of adversaries using open\r\nsource offensive tools. The talk reviewed one of these post-exploitation frameworks named Koadic and walked\r\nthrough different ways defenders can build behavioral detections through the use of Event Query Language\r\n(EQL). In this post, I wanted to review this research by providing background into Koadic and its features, why\r\nit’s relevant, and then dive into some EQL examples where I will share different detection strategies against the\r\nKoadic framework.\r\nAdversaries continue to adopt open source attack frameworks as part of their toolset. By using these off-the-shelf\r\ntools, attackers are able to complete their objectives while reducing their development costs and present attribution\r\nproblems for incident responders. These tools challenge traditional investigative techniques by creating the idea of\r\nplausible deniability and leave fewer toolmarks that can be traced back to an adversary. Even with strong threat\r\nintelligence capabilities and proper defensive visibility, it’s not always an easy task to differentiate red team\r\noperations from real adversary behavior — especially in the early phases of an attack.\r\nAs defenders, we are required to actively monitor offensive open source projects. These projects serve as canaries\r\nin a coal mine, giving us an opportunity to gain insights into new attacker tradecraft. Not only does this get us into\r\nan attacker mindset, but all the code is freely available for emulation and review. Some different ways to get value\r\nfrom dissecting these tools can be through validating your detection capabilities, generating new analytics,\r\ndeveloping threat hunting hypotheses, or by simply transferring knowledge around an underlying behavior.\r\nWhy Koadic?\r\nKoadic is a great candidate to demonstrate behavior-based detections due its interesting way of leveraging\r\ntechnologies built into the Windows OS — such as Windows Script Host (WSH) and the Component Object\r\nModel (COM). COM and WSH fall into the general category of “living off the land” tools, which allow\r\nadversaries to proxy the execution of their toolset through built-in Windows programs.\r\nThis can be very desirable from an attacker’s standpoint, as it allows them to blend in better within the network\r\nwhile producing less of a forensic footprint — rather than dropping and executing a file on disk. COM and WSH\r\nare particularly attractive to attackers because of a lack of robust, built-in logging capabilities in contrast to tools\r\nlike PowerShell (for which Windows has added extensive logging capabilities in newer versions). Koadic is good\r\nenough for mature threat groups such as APT28 and has received frequent updates over the last couple years.\r\nhttps://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nPage 1 of 11\n\nKoadic overview\r\nKoadic overview \u0026 features\r\nEQL\r\nSome of the more exciting parts of my job as a practitioner come when writing behavioral detections using EQL.\r\nThis process brings out my inner detective skills that I find to be fulfilling and challenging at the same time. The\r\nlanguage enables practitioners to go beyond matching static values such as Indicators of Compromise (IoCs) to a\r\nmuch more comprehensive and flexible way to detect adversary behaviors. With the ability to leverage features\r\nlike time-bound sequencing or track process lineage, more options are opened up to us as defenders to build\r\nreliable and lasting detections.\r\nI find this to be rewarding, as I can directly apply my previous SOC work experience around host-based forensics\r\ninto a much more dynamic detection that holds up against the latest attacker tradecraft. The best part is that EQL\r\nhas a very simple syntax with a short learning curve, so if you aren’t able to adopt EQL today, hopefully the logic\r\nwithin these queries can be applied to your current solution.\r\nFor a quick recap into the language itself and its core capabilities, I recommend reviewing our previous blog post:\r\nIntroducing Event Query Language. In summary, EQL is a schema-independent and OS-agnostic language built\r\nfor real-time detection with stream processing. It supports multiple-event behaviors and also offers post-processing commands used to analyze large amounts of data. With that background, let’s start diving into some of\r\nthe different ways to detect Koadic using EQL.\r\nInitial access\r\nSpearphishing Attachment (T1193)\r\nValidating parent-child process relationships continues to be a fruitful technique for hunting and building\r\ndetections. As attacker activity becomes more evasive, however, we also have a need for flexibility as defenders.\r\nThis first example shows off the value of tracking process ancestry using EQL’s descendant function, which lets\r\nus maintain state and track full process genealogy. This is an important concept because it goes beyond the typical\r\nparent-child process paradigm that many languages are limited to.\r\nhttps://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nPage 2 of 11\n\nBy tracking further descendant processes, defenders have the ability to follow process chains infinitely down the\r\nprocess tree. This provides more freedom in how we can express suspicious behavior together while also allowing\r\ntighter controls around process ancestry.\r\nDescendant process tree\r\nDescendant process tree visualization (APT28)\r\nThis process chain comes from a sample reported by Palo Alto Networks in June 2018 associated with APT28\r\nactivity. In this EQL expression, we are monitoring all descendant processes of our email client (Outlook.exe) and\r\nonly looking for new process creation events tied to Mshta. This allows us to focus on the initial attack vector\r\n(Spearphishing email) and then filter on Windows programs being used to execute attacker code. This is a great\r\nfoundation for strong analytics — if we wanted to create something more robust, we could build out a longer array\r\nof cohorts associated with initial compromise stages, as well as add the entire Microsoft Office suite as\r\ndescendants.\r\nInitial access and execution - spearfishing\r\nInitial access \u0026 execution - Spearphishing example\r\nEQL query:\r\nhttps://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nPage 3 of 11\n\nprocess where process_name == \"mshta.exe\" and descendant of\r\n[process where process_name == \"outlook.exe\"]\r\nDefense evasion/execution\r\nMshta (T1170), Rundll32 (T1085)\r\nTools like Koadic often include some usability features that help facilitate payload building, also known as\r\nstagers. These small pieces of code get executed on the victim machine and are used to establish a network\r\nconnection back to the attacker in order to bring in a staged payload for execution. Stagers represent a significant\r\nportion of the early phases of the intrusion process. The following example continues exploring the detection\r\nstrategy for a variety of Windows utilities used to proxy execution with Koadic stagers.\r\nThe EQL query below uses the sequence operator, a function of EQL that matches based on the order of events in\r\na sequence. In this case, we are matching when one of these standard Windows administration utilities initiates a\r\nnetwork connection. Where another language might require an analyst to write several rules — one for each of\r\nthese utilities — EQL enables us to build an array capable of matching many permutations.\r\nUsing the filter operator joins these events in sequence by their process identifier (PID). I like this example\r\nbecause it’s capable of detecting malware and other offensive tools that aren’t specific to Koadic. With that said, it\r\nmight take a little filtering to remove potentially benign events such as network administrative activity, but this\r\nkind of behavior is something every organization should be tracking and reviewing on a certain cadence.\r\nDefense evasion and execution - Mshta\r\nDefense evasion \u0026 execution - stagers\r\nEQL query:\r\nhttps://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nPage 4 of 11\n\nsequence by unique_pid\r\n[process where subtype.create and process_name in\r\n(\"mshta.exe\", \"regsvr32.exe\", \"rundll32.exe\", \"wmic.exe\")]\r\n[network where process_name in\r\n(\"mshta.exe\", \"regsvr32.exe\", \"rundll32.exe\", \"wmic.exe\")]\r\nOne of the more interesting takeaways when reviewing offensive tooling is finding the different artifacts that get\r\nleft behind unintentionally. All it takes is one “loud” artifact, such as a file or registry modification that sticks out,\r\nto quickly find suspicious activity.\r\nIn Koadic’s case, HTTP stagers use Internet Explorer’s core architecture to make a web request by default, which\r\ncauses the stager to be created within the Temporary Internet Files directory. This behavior occurs due to the way\r\nInternet Explorer caches browser content to quickly load web pages. Monitoring this kind of behavior with certain\r\nexecutables can lead to reliable detections outside Koadic, such as generic cradles used to download and execute\r\nmalicious code.\r\nDefense evasion \u0026 execution - cached stager\r\nDefense evasion \u0026 execution - cached stager\r\nEQL query:\r\nfile where process_name in\r\n(\"mshta.exe\",\"regsvr32.exe\", \"rundll32.exe\", \"wmic.exe\")\r\nand subtype.create and file_path == \"*Content.IE5*\"\r\nDiscovery\r\nAccount Discovery (T1087), Remote System Discovery (T1096)\r\nhttps://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nPage 5 of 11\n\nDiscovery - macro\r\nDiscovery - macro\r\nA feature of EQL is the ability to share or reuse similar logic between queries. By using macro declaration, we can\r\nbundle a collection of items together and call the array like a variable. A good example would be grouping\r\nMicrosoft Office applications into a macro, or, in this case, several different Windows programs that can be used\r\nfor discovery and enumeration.\r\nEQL query (macro):\r\nmacro KOADIC_DISCOVERY(name)\r\nname in (\r\n\"arp.exe\", \"findstr.exe\", \"hostname.exe\", \"ipconfig.exe\",\r\n\"nbtstat.exe\", \"net.exe\", \"net1.exe\", \"netsh.exe\",\r\n\"nltest.exe\", \"ping.exe\", \"systeminfo.exe\", \"tasklist.exe\",\r\n\"tracert.exe\", \"whoami.exe\"\r\n)\r\nThe Elastic Endpoint Resolver view below helps provide some context about how Koadic spawns child processes.\r\nBy using the Koadic module (exec_cmd), and running a natively supported command such as “whoami /groups”,\r\nwe can see the Rundll32.exe application was invoked by WmiPrvse.exe and passes instructions down to the\r\ncommand prompt before launching the Whoami.exe application.\r\nhttps://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nPage 6 of 11\n\nElastic Endpoint Resolver\r\nElastic Endpoint Resolver visualization\r\nNow that we have a better understanding of the attack chain, let’s tie our previous macro\r\n(KOADIC_DISCOVERY) into a sequence-based detection looking for three process creation events from any one\r\nof those enumeration programs within a period of 10 minutes, executed by the same user. This same feature would\r\nlet you monitor for processes that were previously observed. For example, maybe 15 days later the process makes\r\na network connection to pull down an additional payload. What other language lets you find long-term payloads\r\nthat sit dormant for weeks or months?\r\nEQL query:\r\nsequence by user_name with maxspan=10m\r\n[process where subtype.create and KOADIC_DISCOVERY(process_name)]\r\n[process where subtype.create and KOADIC_DISCOVERY(process_name)]\r\n[process where subtype.create and KOADIC_DISCOVERY(process_name)]\r\n| unique user_name\r\nThe query above is fully-functional and can be used as a generic detection for initial discovery and enumeration.\r\nBut what if we had some reason to tighten the logic around Koadic specifically? Understanding the process\r\ngenealogy of Koadic at the endpoint level, we can leverage different process relationship tracking functions in\r\nEQL such as child of and descendant of.\r\nhttps://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nPage 7 of 11\n\nBy using the child of function and setting the parent process to Rundll32.exe, we are essentially getting the\r\ngrandchildren of Rundll32.exe. Then if we wanted to take it even further, we can add the descendant of parent\r\nprocess WmiPrvse.exe. This example demonstrates the flexibility of EQL to provide powerful detection\r\ncapabilities for real adversary behavior.\r\nProcess tree visualization - child of and descendant of\r\nProcess tree visualization - child of and descendant of\r\nEQL query:\r\nsequence by user_name with maxspan=10m\r\n[process where child of [process where parent_process_name == \"rundll32.exe\"]\r\nand KOADIC_DISCOVERY(process_name) and\r\ndescendant of [process where parent_process_name == \"wmiprvse.exe\"]]\r\n[process where child of [process where parent_process_name == \"rundll32.exe\"]\r\nand KOADIC_DISCOVERY(process_name) and\r\ndescendant of [process where parent_process_name == \"wmiprvse.exe\"]]\r\n| unique user_name\r\nPrivilege escalation\r\nBypass User Account Account (T1088)\r\nWhile attackers control targeting of victims in many cases, they don’t always wind up with an elevated user during\r\ninitial compromise. Even when a spearphishing victim is a local administrator, the attacker will oftentimes need to\r\nescalate from a Medium to High integrity process before continuing. Off-the-shelf offensive tools like Koadic can\r\nenable that transition with relative ease, including several different UAC Bypass modules out of the box.\r\nFor this example, we’ll examine a well-known UAC Bypass technique published by Matt Nelson (@enigma0x3)\r\nwhile leveraging the Computer Management launcher — CompMgmtLauncher.exe — which is interoperable with\r\nthe Microsoft Management Console (MMC). Details about this technique, which still works on Windows 7\r\nendpoints, can be found here.\r\nhttps://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nPage 8 of 11\n\nThis technique involves modifying the Windows Registry to change the default association of files the MMC\r\ninteracts with (HKCU\\Software\\Classes\\mscfile\\shell\\open\\command) to an application of the attacker’s choice.\r\nBy deploying a malicious script object with a compatible extension and altering this registry key value to launch a\r\nbuilt-in script interpreter, an adversary is able to circumvent controls.\r\nRight after this registry modification, look for the new process creation event tied to the auto-elevated Microsoft\r\nprogram (CompMgmtLauncher.exe), followed by common Koadic stager descendant processes such as Mshta.exe\r\nor Rundll32.exe — processes that should be running in a high integrity context. We can combine those events into\r\nan ordered sequence and constrain the total run-time for all the steps to complete within 10 seconds.\r\nPrivilege escalation - UAC bypass\r\nPrivilege escalation - UAC bypass\r\nEQL query:\r\nsequence with maxspan=10s\r\n[registry where length(bytes_written_string) \\\u003e 0 and key_type in\r\n(\"sz\", \"expandSz\") and key_path == \"*\\\\mscfile\\\\shell\\\\open\\\\command\\\\\"\r\nand user_name != \"SYSTEM\"]\r\n[process where process_path == \"C:\\\\Windows\\\\System32\\\\CompMgmtLauncher.exe\"]\r\n[process where process_name in (\"mshta.exe\",\"rundll32.exe\") and\r\nintegrity_level == \"high\"]\r\nCollection/exfiltration\r\nData from Local System (T1005)\r\nKoadic’s method of C2 may be interesting to analysts of several kinds due to the transactional way it exchanges\r\ndata between implants and server. This behavior is highlighted through some direct examples of specific\r\nhttps://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nPage 9 of 11\n\ncommands executed below:\r\nSpecific commands\r\nCommand shell redirection into text files\r\nKoadic redirects STDOUT/STDERR to a temporary text file that stores the output of the operator’s commands as\r\nthey were presented to the server. These commands are then read back into the Koadic C2 terminal. One second\r\nafter this file is initially created, it is automatically deleted.\r\nWith the right endpoint visibility, malicious behaviors you might be incapable of otherwise detecting stand out. To\r\ndemonstrate a detection around this, we will use the event of function to filter only for processes that come from\r\ncmd.exe that contain a redirector (\\\u003e), then tie the PID of that process to same PID that performed file activity\r\nrelated to the text (.txt) file activity.\r\nEQL query:\r\nfile where file_name == \"*.txt\" and\r\nevent of [process where process_name == \"cmd.exe\" and command_line == \"*\\\u003e*\"]\r\nExample results\r\nExample results showing file modification\r\nIf you wanted to get more context, such as what command was passed from Koadic, we can turn the detection into\r\na sequence and add the process event.\r\nEQL query:\r\nsequence with maxspan=5s by unique_pid\r\n[process where subtype.create and process_name == \"cmd.exe\" and command_line == \"*\\\u003e*\" and\r\ndescendant of [process where process_name == \"wmiprvse.exe\"]]\r\n[file where subtype.create and wildcard(file_name, \"*.txt\", \"*.log\")]\r\nExample results\r\nExample results combining process and file modification\r\nConclusion\r\nhttps://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nPage 10 of 11\n\nTo summarize, we analyzed one offensive framework (Koadic) and several of its prominent features, reviewed a\r\nflexible query language (EQL) to express detection logic, and stepped through several ways to identify behavior\r\ntied to Koadic with example analytics.\r\nI see the availability of offensive frameworks like Koadic as an opportunity for defenders, and a motivation to stay\r\nvigilant. Thinking creatively about how to detect these post-exploitation behaviors and assessing how these tools\r\nperform against their own detection capabilities will put an organization on a path to greater success in stopping\r\nsimilar threats.\r\nTo help enable organizations, we’ve added all the queries in this post into the EQLLib repository. For readers\r\ninterested in the original presentation from BSidesDFW this year, here is a link to the slides.\r\nEQL support is being added to Elasticsearch.\r\nSource: https://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nhttps://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql\r\nPage 11 of 11",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://www.elastic.co/security-labs/embracing-offensive-tooling-building-detections-against-koadic-using-eql"
	],
	"report_names": [
		"embracing-offensive-tooling-building-detections-against-koadic-using-eql"
	],
	"threat_actors": [
		{
			"id": "2864e40a-f233-4618-ac61-b03760a41cbb",
			"created_at": "2023-12-01T02:02:34.272108Z",
			"updated_at": "2026-04-10T02:00:04.97558Z",
			"deleted_at": null,
			"main_name": "WildCard",
			"aliases": [],
			"source_name": "ETDA:WildCard",
			"tools": [
				"RustDown",
				"SysJoker"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "730dfa6e-572d-473c-9267-ea1597d1a42b",
			"created_at": "2023-01-06T13:46:38.389985Z",
			"updated_at": "2026-04-10T02:00:02.954105Z",
			"deleted_at": null,
			"main_name": "APT28",
			"aliases": [
				"Pawn Storm",
				"ATK5",
				"Fighting Ursa",
				"Blue Athena",
				"TA422",
				"T-APT-12",
				"APT-C-20",
				"UAC-0001",
				"IRON TWILIGHT",
				"SIG40",
				"UAC-0028",
				"Sofacy",
				"BlueDelta",
				"Fancy Bear",
				"GruesomeLarch",
				"Group 74",
				"ITG05",
				"FROZENLAKE",
				"Forest Blizzard",
				"FANCY BEAR",
				"Sednit",
				"SNAKEMACKEREL",
				"Tsar Team",
				"TG-4127",
				"STRONTIUM",
				"Grizzly Steppe",
				"G0007"
			],
			"source_name": "MISPGALAXY:APT28",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "256a6a2d-e8a2-4497-b399-628a7fad4b3e",
			"created_at": "2023-11-30T02:00:07.299845Z",
			"updated_at": "2026-04-10T02:00:03.484788Z",
			"deleted_at": null,
			"main_name": "WildCard",
			"aliases": [],
			"source_name": "MISPGALAXY:WildCard",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "e3767160-695d-4360-8b2e-d5274db3f7cd",
			"created_at": "2022-10-25T16:47:55.914348Z",
			"updated_at": "2026-04-10T02:00:03.610018Z",
			"deleted_at": null,
			"main_name": "IRON TWILIGHT",
			"aliases": [
				"APT28 ",
				"ATK5 ",
				"Blue Athena ",
				"BlueDelta ",
				"FROZENLAKE ",
				"Fancy Bear ",
				"Fighting Ursa ",
				"Forest Blizzard ",
				"GRAPHITE ",
				"Group 74 ",
				"PawnStorm ",
				"STRONTIUM ",
				"Sednit ",
				"Snakemackerel ",
				"Sofacy ",
				"TA422 ",
				"TG-4127 ",
				"Tsar Team ",
				"UAC-0001 "
			],
			"source_name": "Secureworks:IRON TWILIGHT",
			"tools": [
				"Downdelph",
				"EVILTOSS",
				"SEDUPLOADER",
				"SHARPFRONT"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "ae320ed7-9a63-42ed-944b-44ada7313495",
			"created_at": "2022-10-25T15:50:23.671663Z",
			"updated_at": "2026-04-10T02:00:05.283292Z",
			"deleted_at": null,
			"main_name": "APT28",
			"aliases": [
				"APT28",
				"IRON TWILIGHT",
				"SNAKEMACKEREL",
				"Group 74",
				"Sednit",
				"Sofacy",
				"Pawn Storm",
				"Fancy Bear",
				"STRONTIUM",
				"Tsar Team",
				"Threat Group-4127",
				"TG-4127",
				"Forest Blizzard",
				"FROZENLAKE",
				"GruesomeLarch"
			],
			"source_name": "MITRE:APT28",
			"tools": [
				"Wevtutil",
				"certutil",
				"Forfiles",
				"DealersChoice",
				"Mimikatz",
				"ADVSTORESHELL",
				"Komplex",
				"HIDEDRV",
				"JHUHUGIT",
				"Koadic",
				"Winexe",
				"cipher.exe",
				"XTunnel",
				"Drovorub",
				"CORESHELL",
				"OLDBAIT",
				"Downdelph",
				"XAgentOSX",
				"USBStealer",
				"Zebrocy",
				"reGeorg",
				"Fysbis",
				"LoJax"
			],
			"source_id": "MITRE",
			"reports": null
		}
	],
	"ts_created_at": 1775434720,
	"ts_updated_at": 1775792220,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/9262dc167da7e8a3b1a77428a09cc1f93ac36d28.pdf",
		"text": "https://archive.orkl.eu/9262dc167da7e8a3b1a77428a09cc1f93ac36d28.txt",
		"img": "https://archive.orkl.eu/9262dc167da7e8a3b1a77428a09cc1f93ac36d28.jpg"
	}
}