{
	"id": "cec01318-c746-4e1b-8664-1eeccec1f11f",
	"created_at": "2026-04-06T00:14:17.762345Z",
	"updated_at": "2026-04-10T13:11:47.791506Z",
	"deleted_at": null,
	"sha1_hash": "5554564537649b1a0d445c487f02b4b4b58cb03b",
	"title": "Threat Hunting Introduction: Cobalt Strike",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 87004,
	"plain_text": "Threat Hunting Introduction: Cobalt Strike\r\nBy Artem Golubin\r\nPublished: 2025-06-23 · Archived: 2026-04-02 12:01:35 UTC\r\nCobalt Strike is a threat simulation tool that is used by red teams to perform penetration tests (simulate cyber-security attacks). However, it is also used by malicious actors to perform real-world attacks. In this article, I will\r\ndemonstrate how anyone can find Cobalt Strike servers on the internet and retrieve metadata from them.\r\nAfter reading this article, you will be able to peek inside the Cobalt Strike servers and see how big companies or\r\nmalicious actors are using it. Doing this can be pretty fun, it's like being able to hack into hackers or security\r\nexperts.\r\nI will also introduce you to my tool written in Rust, called SigStrike, which I wrote to increase crawling speed by\r\n20x.\r\nThreat Hunting\r\nThreat hunting is a proactive process of searching for threats that can potentially attack your company. The part of\r\nthe threat-hunting process consists of the collection of so-called IoCs (Indicators of Compromise). IoCs are\r\nartifacts that researchers use to identify malicious activity.\r\nThe most common IoCs are:\r\nIP addresses\r\nDomain names\r\nFile hashes\r\nNetwork traffic patterns\r\nBinary signatures (e.g., YARA rules)\r\nIn this post, I will focus on the IP addresses since they can be obtained by scanning internet. Even if you are not a\r\nsecurity researcher, this can be fun!\r\nHow do people typically handle IP IoCs in large companies? They collect them from different sources and block\r\nthem in their firewalls. They also monitor the history of connections to these IP addresses and domains within\r\ntheir networks.\r\nWhat is Cobalt Strike?\r\nCobalt Strike, a commercial tool, is used to gain remote access to a system and perform post-exploitation\r\nactivities. It's important to note that this happens after the system has already been compromised. You can think of\r\nit as a remote control tool that is relatively stealthy to deploy and use.\r\nCobalt Strike consists of two main components:\r\nhttps://rushter.com/blog/threat-hunting-cobalt-strike/\r\nPage 1 of 8\n\nServer – is used to control the compromised systems as well as serve malware from it.\r\nBeacon – is the agent that is installed on the compromised system (executable file).\r\nThe server part is usually hosted on cloud infrastructure, sometimes on a bulletproof hosting provider. It consists\r\nof a web server and a command and control (C2) server that communicates with infected machines.\r\nIf staging is enabled, the web server hosts beacons (executables) and serves them to the compromised systems.\r\nThe interesting part here is that oftentimes, the beacon (executable) can be obtained by any person.\r\nIn this post, I will demonstrate how to exploit this fact and find Cobalt Strike servers on the internet and get\r\nmetadata from them.\r\nFinding Cobalt Strike servers\r\nMost of the Cobalt Strike servers can be directly accessed via IPv4 address. There is no need to know a domain\r\nname.\r\nBut how do you find IP addresses?\r\nIf you have the capability to scan the internet, you can use tools like masscan and scan popular ports that Cobalt\r\nStrike uses. The default ports are 80 and 443 and it's a good starting point. If you don't have such capability, you\r\ncan use services like Shodan, Censys, Hunt.io, Fofa, or ZoomEye.\r\nSome of these services already tag servers as Cobalt Strike, so you can just search for them. For example, this is a\r\nquery for shodan (no registration is required):\r\nPlease note that this will only return a portion of Cobalt Strike servers that are easy to detect. Shodan\r\nautomatically parses the metadata and outputs it in a human-readable format. However, it can't parse and detect\r\nsome of them when non-default encryption keys are used, or the config is slightly modified. So you will still have\r\nto query them for potential candidates and validate them yourself.\r\nAlternatively, you can just grab some sample data from drb-ra/C2IntelFeeds repository.\r\nScanning the internet\r\nWhen using mass internet scanners, you only get information about which ports are open and which services they\r\nare running. But how do you know that the server is actually a Cobalt Strike server?\r\nAs it turns out, the default Cobalt Strike server has a very specific response to HTTP requests.\r\nWhen you hit the main page of the server, it will return a 404 Not Found response with a specific header:\r\nHTTP/1.1 404 Not Found\r\nDate: Sat, 21 Jun 2025 21:48:05 GMT\r\nContent-Type: text/plain\r\nContent-Length: 0\r\nhttps://rushter.com/blog/threat-hunting-cobalt-strike/\r\nPage 2 of 8\n\nIf you scan the whole internet for 404 Not Found responses with zero content length, you will get around 16\r\nmillion results. You can filter down it to only 30-50k records by also filtering by Content-Type: text/plain\r\nheader. The problem with such an approach is that Content-Type header can be easily changed in Cobalt Strike,\r\nunlike the HTTP 404 Not Found response with zero content length.\r\nThere are more than 500 million unique IP and Port combinations that are open on the internet. Using simple\r\nsignatures reduces the candidates to a manageable number.\r\nIf you want to find as many servers as possible, you will have to probe each response that returns HTTP 404 Not\r\nFound with zero content length. That's why I wrote a tool that can do it fast.\r\nMost of the search engines (mentioned above) allow you to query such responses as well.\r\nObviously, not all the servers that return such responses are Cobalt Strike servers.\r\nWhat if you don't have the capability to scan the whole internet but still want to perform some small scans?\r\nYou can always limit the scanning scope to specific hosting providers that are known to host a lot of Cobalt Strike\r\nservers. But keep in mind that your can be blocked by your hosting provider if you scan too aggressively.\r\nHow to actually find Cobalt Strike servers?\r\nWhen staging is enabled, Cobalt Strike servers serve small executable files (agents) that later download bigger\r\npayloads.\r\nStager executable can be downloaded directly by sending a GET request with a specific path that contains\r\nchecksum.\r\nFor checksum, Cobalt Strike uses 8-bit checksum algorithm similar to used in meterpreter.\r\nBasically, your request should send a specific 4-character string that returns one of the following checksums:\r\n92 - Checksum for x86 binary\r\n93 - Checksum for x64 binary\r\nHere are example of such URLs:\r\nhttp://\u003cip\u003e:\u003cport\u003e/tdN6 - x86 binary\r\nhttp://\u003cip\u003e:\u003cport\u003e/ZrJG - x64 binary\r\nBoth of these values can be used on any Cobalt Strike server, but you can also randomize them. There are tens of\r\nthousands of 4 character combinations that can generate the same checksum values.\r\nWhen you hit a potential server with such URLs, it should return HTTP 200 OK response with a small executable\r\nfile.\r\nExtracting metadata\r\nhttps://rushter.com/blog/threat-hunting-cobalt-strike/\r\nPage 3 of 8\n\nOnce you have the executable file, you can extract metadata from it.\r\nThe metadata itself is usually encrypted within the binary. There are several encryption layers, but they all come\r\ndown to a simple XOR algorithm with a key that can usually be brute-forced.\r\nRecent versions of Cobalt Strike can also use the Guardrails feature that encrypts config based on the following\r\nvalues:\r\nIP address\r\nUsername\r\nServer name\r\nDomain\r\nSo if a machine does not match the values, it will not be able to decrypt the configuration and execute the payload.\r\nExplaining the details of the encryption is beyond the scope of this article. Fortunately, there are tools to do so. So\r\nyou don't have to worry about it for now.\r\nMy tool can crawl and validate millions of potential servers pretty fast. You can find it here: sigstrike. There is\r\nalso alternative library called dissect.cobaltstrike. I used it to understand the whole encryption and decryption\r\nprocess.\r\nIf you want to understand how the decryption works, I would suggest reading the source code of the\r\ndissect.cobaltstrike library since Python code is easier to read.\r\nCobalt Strike configs\r\nEach executable file of Cobalt Strike contains a configuration that is used to connect to the server. Since Cobalt\r\nStrike is also used by real malicious actors, extracting configs from it makes it even more fun. Sometimes, you\r\ncan get a peek of big attacks that are happening right now.\r\nHere is what the typical Cobalt Strike config looks like (I've replaced some unique data with dots):\r\n{\r\n \"SETTING_BOF_ALLOCATOR\": \"VirtualAlloc\",\r\n \"SETTING_C2_CHUNK_POST\": 0,\r\n \"SETTING_C2_POSTREQ\": [\r\n [\"_HEADER\", \"Content-Type: application/octet-stream\"],\r\n [\"BUILD\", \"id\"],\r\n [\"PARAMETER\", \"id\"],\r\n [\"BUILD\", \"output\"],\r\n [\"PRINT\", true],\r\n ],\r\n \"SETTING_C2_RECOVER\": [[\"print\", true]],\r\n \"SETTING_C2_REQUEST\": [[\"BUILD\", \"metadata\"], [\"BASE64\", true], [\"HEADER\", \"Cookie\"]],\r\n \"SETTING_C2_VERB_GET\": \"GET\",\r\n \"SETTING_C2_VERB_POST\": \"POST\",\r\nhttps://rushter.com/blog/threat-hunting-cobalt-strike/\r\nPage 4 of 8\n\n\"SETTING_CFG_CAUTION\": 0,\r\n \"SETTING_CLEANUP\": 0,\r\n \"SETTING_CRYPTO_SCHEME\": 0,\r\n \"SETTING_DOMAINS\": \"....,/ca\",\r\n \"SETTING_DOMAIN_STRATEGY\": 0,\r\n \"SETTING_DOMAIN_STRATEGY_FAIL_SECONDS\": 4294967295,\r\n \"SETTING_DOMAIN_STRATEGY_FAIL_X\": 4294967295,\r\n \"SETTING_DOMAIN_STRATEGY_SECONDS\": 4294967295,\r\n \"SETTING_EXIT_FUNK\": 0,\r\n \"SETTING_GARGLE_NOOK\": 0,\r\n \"SETTING_HOST_HEADER\": \"\",\r\n \"SETTING_HTTP_NO_COOKIES\": 1,\r\n \"SETTING_JITTER\": 0,\r\n \"SETTING_KILLDATE\": 0,\r\n \"SETTING_MAXGET\": 1048576,\r\n \"SETTING_MAX_RETRY_STRATEGY_ATTEMPTS\": 0,\r\n \"SETTING_MAX_RETRY_STRATEGY_DURATION\": 0,\r\n \"SETTING_MAX_RETRY_STRATEGY_INCREASE\": 0,\r\n \"SETTING_PORT\": 5566,\r\n \"SETTING_PROCINJ_ALLOCATOR\": 0,\r\n \"SETTING_PROCINJ_BOF_REUSE_MEM\": 1,\r\n \"SETTING_PROCINJ_EXECUTE\": [\"CreateThread\", \"SetThreadContext\", \"CreateRemoteThread\", \"RtlCreateUserThread\"]\r\n \"SETTING_PROCINJ_MINALLOC\": 0,\r\n \"SETTING_PROCINJ_PERMS\": 64,\r\n \"SETTING_PROCINJ_PERMS_I\": 64,\r\n \"SETTING_PROCINJ_STUB\": \"b50b86d7...4ad8d01781c\",\r\n \"SETTING_PROCINJ_TRANSFORM_X64\": [[\"append\", \"\"], [\"prepend\", \"\"]],\r\n \"SETTING_PROCINJ_TRANSFORM_X86\": [[\"append\", \"\"], [\"prepend\", \"\"]],\r\n \"SETTING_PROTOCOL\": [\"HTTP\"],\r\n \"SETTING_PROXY_BEHAVIOR\": 2,\r\n \"SETTING_PUBKEY\": \"51a8d41b43f9....9f9bae3fb9b82c43e40e7289\",\r\n \"SETTING_SLEEPTIME\": 60000,\r\n \"SETTING_SMB_FRAME_HEADER\": \"\",\r\n \"SETTING_SPAWNTO\": \"d7a9ca15a07f8....b63020da38aa16\",\r\n \"SETTING_SPAWNTO_X64\": \"%windir%\\\\sysnative\\\\rundll32.exe\",\r\n \"SETTING_SPAWNTO_X86\": \"%windir%\\\\syswow64\\\\rundll32.exe\",\r\n \"SETTING_SUBMITURI\": \"/submit.php\",\r\n \"SETTING_TCP_FRAME_HEADER\": \"\",\r\n \"SETTING_USERAGENT\": \"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; BOIE9;ENIN)\",\r\n \"SETTING_WATERMARK\": \"....\",\r\n \"SETTING_WATERMARKHASH\": \"idv...PjBw==\"\r\n}\r\nHere are explanations of some settings:\r\nSETTING_DOMAINS - lists server URLs that the beacon will connect to.\r\nhttps://rushter.com/blog/threat-hunting-cobalt-strike/\r\nPage 5 of 8\n\nSETTING_PUBKEY - a public key that is used to encrypt the communication between the beacon and the\r\nserver.\r\nSETTING_SPAWNTO_... - the path to the executable that will be used to spawn the beacon.\r\nSETTING_USERAGENT - the user agent that will be used to identify the beacon.\r\nScanning your first data\r\nYou can use the following Python script to obtain a sample of IPs from the drb-ra source:\r\nimport json\r\nimport requests\r\nURL = \"https://raw.githubusercontent.com/drb-ra/C2IntelFeeds/master/C2_configs/cobaltstrike-30day.json\"\r\ndef fetch_data():\r\n r = requests.get(URL)\r\n r.raise_for_status()\r\n for line in r.text.splitlines():\r\n try:\r\n data = json.loads(line)[\"result\"]\r\n except Exception:\r\n continue\r\n if not data[\"ip\"] or not data[\"Port\"]:\r\n continue\r\n try:\r\n host_str = data[\"ip\"] + \":\" + str(int(data[\"Port\"]))\r\n except Exception:\r\n continue\r\n yield \"http://%s/\" % host_str\r\n yield \"https://%s/\" % host_str\r\ndef write_to_file(data, output_path):\r\n with open(output_path, mode=\"wt\") as fout:\r\n for item in data:\r\n fout.write(item + \"\\n\")\r\nif __name__ == \"__main__\":\r\n write_to_file(fetch_data(), \"input_30d.json\")\r\nIt will store the URLs in the input_30d.json file.\r\nhttps://rushter.com/blog/threat-hunting-cobalt-strike/\r\nPage 6 of 8\n\nYou can then rescan those URLs to find active servers.\r\nFirst, you need to install the sigstrike tool. You can install it via cargo (Rust package) or pip (Python\r\npackage):\r\ncargo install sigstrike # Rust\r\npip install sigstrike # Python 3.9+\r\nThen, you can run the following command to crawl the URLs and extract metadata:\r\nsigstrike crawl --input-path input_30d.json --output-path output.json --max-concurrent 1000\r\nCrawl Summary:\r\n Total URLs processed: 1936\r\n Found: 301\r\n Failed: 1635\r\n Non-matching content type/status: 70\r\n Unreachable: 1565\r\nThe result will be stored in the output.json file.\r\nCobalt Strike servers tend to die/go offline quickly, so it's completely normal to have a lot of unreachable servers\r\nfrom the past 30-day scans.\r\nThere are services that send abuse reports to hosting providers when they detect Cobalt Strike.\r\nWhen doing scans, it's better to perform them from an empty VPS server since you are dealing with potentially\r\nmalicious infrastructure.\r\nNext Steps\r\nIt's interesting to see how big companies or malicious actors are using Cobalt Strike. The good thing is that you\r\ndon't have to be a security expert to give it a try and play with the data.\r\nProfessional read teams or experienced threat actors use various techniques to hide their Cobalt Strike servers. It's\r\ncalled Operational Security (OpSec).\r\nIn reality, you can still find high-profile servers since people are sometimes lazy and make mistakes.\r\nThere are numerous reports on the internet where almost default Cobalt Strike configurations were used in real-world and sophisticated attacks.\r\nThreat hunting is a never-ending process, and there are always new techniques to find more servers.\r\nFor example, the scanning process can be improved by:\r\nUsing more ports, especially randomized ports.\r\nScanning domains\r\nhttps://rushter.com/blog/threat-hunting-cobalt-strike/\r\nPage 7 of 8\n\nIgnoring main page responses and hitting every possible web server with a GET request.\r\nIf you don't have the capability to scan the internet, you have to be creative and clever to find more stuff.\r\nThreat hunting is not limited to Cobalt Strike, a similar approach is used to find C2 servers of various malware\r\nfamilies.\r\nThe typical process for every malware family is the same:\r\nObtain a sample of the running malware server\r\nFind a way to detect it by writing a signature or a query. This can be:\r\nHTTP response signature (e.g., 404 Not Found with zero content length)\r\nCertificate fingerprint\r\nJARM fingerprint\r\nJA4x fingerprint.\r\nTCP response fingerprint\r\nSSH fingerprint\r\nPatterns in domain names\r\nScan the internet for it or use search engines to find it.\r\nSource: https://rushter.com/blog/threat-hunting-cobalt-strike/\r\nhttps://rushter.com/blog/threat-hunting-cobalt-strike/\r\nPage 8 of 8",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://rushter.com/blog/threat-hunting-cobalt-strike/"
	],
	"report_names": [
		"threat-hunting-cobalt-strike"
	],
	"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": 1775434457,
	"ts_updated_at": 1775826707,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/5554564537649b1a0d445c487f02b4b4b58cb03b.pdf",
		"text": "https://archive.orkl.eu/5554564537649b1a0d445c487f02b4b4b58cb03b.txt",
		"img": "https://archive.orkl.eu/5554564537649b1a0d445c487f02b4b4b58cb03b.jpg"
	}
}