{
	"id": "4a84f18a-90c9-43e6-b05c-fa8f1584c1ef",
	"created_at": "2026-04-06T01:31:15.910042Z",
	"updated_at": "2026-04-10T03:24:23.82991Z",
	"deleted_at": null,
	"sha1_hash": "6236586c685e9891b660c5705e571e88ac63b1a3",
	"title": "Detecting Cobalt Strike with memory signatures",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 183785,
	"plain_text": "Detecting Cobalt Strike with memory signatures\r\nBy ByJoe Desimone\r\nPublished: 2021-03-16 · Archived: 2026-04-06 01:23:10 UTC\r\nThis blog discusses, mentions, or contains links to an Elastic training program that is now retired. For more Elastic\r\nresources, please visit the Getting Started page.\r\nAt Elastic Security, we approach the challenge of threat detection with various methods. Traditionally, we have\r\nfocused on machine learning models and behaviors. These two methods are powerful because they can detect\r\nnever-before-seen malware. Historically, we’ve felt that signatures are too easily evaded, but we also recognize\r\nthat ease of evasion is only one of many factors to consider. Performance and false positive rates are also critical\r\nin measuring a detection technique's effectiveness.\r\nSignatures, while unable to detect unknown malware, have false positive rates that approach zero and have\r\nassociated labels that help prioritize alerts. For example, an alert for TrickBot or REvil Ransomware requires more\r\nimmediate action than a potentially unwanted adware variant. Even if we could hypothetically catch only half of\r\nknown malware with signatures, that is still a huge win when layered with other protections, considering the other\r\nbenefits. Realistically we can do even better.\r\nOne roadblock to creating signatures that provide long-term value is the widespread use of packers and throw-away malware loaders. These components rapidly evolve to evade signature detection; however, the final malware\r\npayload is eventually decrypted and executed in memory.\r\nTo step around the issue of packers and loaders, we can focus signature detection strategies on in-memory content.\r\nThis effectively extends the shelf life of the signature from days to months. In this post, we will use Cobalt Strike\r\nas an example for leveraging in-memory signatures. \r\nSignaturing Cobalt Strike\r\nCobalt Strike is a popular framework for conducting red team operations and adversary simulation. Presumably\r\ndue to its ease of use, stability, and stealth features, it is also a favorite tool for bad actors with even more\r\nnefarious intentions. There have been various techniques for detecting Beacon, Cobalt Strike’s endpoint payload.\r\nThis includes looking for unbacked threads, and, more recently, built-in named pipes. However, due to the level of\r\nconfigurability in Beacon, there are usually ways to evade public detection strategies. Here we will attempt to use\r\nmemory signatures as an alternative detection strategy.\r\nBeacon is typically reflectively loaded into memory and never touches disk in a directly signaturable form.\r\nFurther, Beacon can be configured with a variety of in-memory obfuscation options to hide its payload. For\r\nexample, the obfuscate-and-sleep option attempts to mask portions of the Beacon payload between callbacks to\r\nspecifically evade signature-based memory scans. We will need to consider this option when developing\r\nsignatures, but it is still easy to signature Beacon even with these advanced stealth features.\r\nhttps://www.elastic.co/blog/detecting-cobalt-strike-with-memory-signatures\r\nPage 1 of 6\n\nDiving in\r\nWe will start by obtaining a handful of Beacon payloads with the sleep_mask option enabled and disabled with\r\nthe most recent releases (hashes in reference section). Starting with a sample with sleep_mask disabled, after\r\ndetonation we can locate Beacon in memory with Process Hacker by looking for a thread which calls SleepEx\r\nfrom an unbacked region:\r\nFrom there, we can save the associated memory region to disk for analysis:\r\nThe easiest win would be to pick a few unique strings from this region and use those as our signature. To\r\ndemonstrate, will will be writing signatures with yara, an industry standard tool for this purpose:\r\nhttps://www.elastic.co/blog/detecting-cobalt-strike-with-memory-signatures\r\nPage 2 of 6\n\nrule cobaltstrike_beacon_strings\r\n{\r\nmeta:\r\n author = \"Elastic\"\r\n description = \"Identifies strings used in Cobalt Strike Beacon DLL.\"\r\nstrings:\r\n $a = \"%02d/%02d/%02d %02d:%02d:%02d\"\r\n $b = \"Started service %s on %s\"\r\n $c = \"%s as %s\\\\%s: %d\"\r\ncondition:\r\n 2 of them\r\n}\r\nThis would give us a good base of coverage, but we can do better by looking at the samples with\r\nsleep_maskenabled. If we look in memory where the MZ/PE header would normally be found, we now see it is\r\nobfuscated:\r\nQuickly looking at this, we can see a lot of repeated bytes (0x80 in this case) where we would actually expect null\r\nbytes. This can be an indication that Beacon is using a simple one-byte XOR obfuscation. To confirm, we can use\r\nCyberChef:\r\nhttps://www.elastic.co/blog/detecting-cobalt-strike-with-memory-signatures\r\nPage 3 of 6\n\nAs you can see, the “This program cannot be run in DOS mode” string appears after decoding, confirming our\r\ntheory. Because a single byte XOR is one of the oldest tricks in the book, yara actually supports native detection\r\nwith the xor modifier:\r\nrule cobaltstrike_beacon_xor_strings\r\n{\r\nmeta:\r\n author = \"Elastic\"\r\n description = \"Identifies XOR'd strings used in Cobalt Strike Beacon DLL.\"\r\nstrings:\r\n $a = \"%02d/%02d/%02d %02d:%02d:%02d\" xor(0x01-0xff)\r\n $b = \"Started service %s on %s\" xor(0x01-0xff)\r\n $c = \"%s as %s\\\\%s: %d\" xor(0x01-0xff)\r\ncondition:\r\n 2 of them\r\n}\r\nWe can confirm detection for our yara rules thus far by providing a PID while scanning:\r\nhttps://www.elastic.co/blog/detecting-cobalt-strike-with-memory-signatures\r\nPage 4 of 6\n\nHowever, we are not quite done. After testing this signature on a sample with the latest version of Beacon (4.2 as\r\nof this writing), the obfuscation routine has been improved. The routine can be located by following the call stack\r\nas shown earlier. It now uses a 13-byte XOR key as shown in the following IDA Pro snippet:\r\nFortunately, Beacon’s obfuscate-and-sleep option only obfuscates strings and data, leaving the entire code section\r\nripe for signaturing. There is the question of which function in the code section we should develop a signature for,\r\nbut that is worth its own blog post. For now, we can just create a signature on the deobfuscation routine, which\r\nshould work well:\r\nrule cobaltstrike_beacon_4_2_decrypt\r\n{\r\nmeta:\r\n author = \"Elastic\"\r\n description = \"Identifies deobfuscation routine used in Cobalt Strike Beacon DLL version 4.2.\"\r\nstrings:\r\n $a_x64 = {4C 8B 53 08 45 8B 0A 45 8B 5A 04 4D 8D 52 08 45 85 C9 75 05 45 85 DB 74 33 45 3B CB 73\r\n $a_x86 = {8B 46 04 8B 08 8B 50 04 83 C0 08 89 55 08 89 45 0C 85 C9 75 04 85 D2 74 23 3B CA 73 E6\r\ncondition:\r\n any of them\r\n}\r\nWe can validate that we can detect Beacon even while it is in its stealthy sleep state (both 32- and 64-bit variants):\r\nhttps://www.elastic.co/blog/detecting-cobalt-strike-with-memory-signatures\r\nPage 5 of 6\n\nTo build this into a more robust detection, we could regularly scan all processes on the system (or entire\r\nenterprise). This could be done with the following powershell one-liner:\r\npowershell -command \"Get-Process | ForEach-Object {c:\\yara64.exe my_rules.yar $_.ID}\"\r\nWrapping up\r\nSignature-based detection, while often looked down upon, is a valuable detection strategy — especially when we\r\nconsider in-memory scanning. With only a handful of signatures, we can detect Cobalt Strike regardless of\r\nconfiguration or stealth features enabled with an effective false positive rate of zero.\r\nReference hashes\r\n7d2c09a06d731a56bca7af2f5d3badef53624f025d77ababe6a14be28540a17a\r\n277c2a0a18d7dc04993b6dc7ce873a086ab267391a9acbbc4a140e9c4658372a\r\nA0788b85266fedd64dab834cb605a31b81fd11a3439dc3a6370bb34e512220e2\r\n2db56e74f43b1a826beff9b577933135791ee44d8e66fa111b9b2af32948235c\r\n3d65d80b1eb8626cf327c046db0c20ba4ed1b588b8c2f1286bc09b8f4da204f2\r\nLearn more about Elastic Security\r\nFamiliarize yourself (if you haven't already) with the powerful protection, detection, and response capabilities of\r\nElastic Agent. Start your free 14-day trial (no credit card required) or download our products, free, for your on-prem deployment. And take advantage of our Quick Start training to set you up for success.\r\nSource: https://www.elastic.co/blog/detecting-cobalt-strike-with-memory-signatures\r\nhttps://www.elastic.co/blog/detecting-cobalt-strike-with-memory-signatures\r\nPage 6 of 6",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://www.elastic.co/blog/detecting-cobalt-strike-with-memory-signatures"
	],
	"report_names": [
		"detecting-cobalt-strike-with-memory-signatures"
	],
	"threat_actors": [
		{
			"id": "610a7295-3139-4f34-8cec-b3da40add480",
			"created_at": "2023-01-06T13:46:38.608142Z",
			"updated_at": "2026-04-10T02:00:03.03764Z",
			"deleted_at": null,
			"main_name": "Cobalt",
			"aliases": [
				"Cobalt Group",
				"Cobalt Gang",
				"GOLD KINGSWOOD",
				"COBALT SPIDER",
				"G0080",
				"Mule Libra"
			],
			"source_name": "MISPGALAXY:Cobalt",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		}
	],
	"ts_created_at": 1775439075,
	"ts_updated_at": 1775791463,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/6236586c685e9891b660c5705e571e88ac63b1a3.pdf",
		"text": "https://archive.orkl.eu/6236586c685e9891b660c5705e571e88ac63b1a3.txt",
		"img": "https://archive.orkl.eu/6236586c685e9891b660c5705e571e88ac63b1a3.jpg"
	}
}