{
	"id": "b72f7ffd-3a8a-4f6b-bcee-c7989f7e1c19",
	"created_at": "2026-04-06T00:11:02.143922Z",
	"updated_at": "2026-04-10T13:12:56.394343Z",
	"deleted_at": null,
	"sha1_hash": "685e2b7ffa3c2450821745ea0d5f2323aa581275",
	"title": "Cobalt Strikes Again: An Analysis of Obfuscated Malware | Huntress",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 10860714,
	"plain_text": "Cobalt Strikes Again: An Analysis of Obfuscated Malware | Huntress\r\nArchived: 2026-04-05 14:42:16 UTC\r\nHow deep can a rabbit hole go? Recently, we discovered a suspicious-looking run key on a victim system. It was clear that\r\nthe key was likely malicious, but it didn’t seem like anything out of the ordinary.\r\nLittle did we know, we were about to encounter Cobalt Strike malware hidden across almost 700 registry values and encased\r\nwithin multiple layers of fileless executables.\r\nThis particular malware sample went to great lengths to hide itself, deploying numerous evasion tactics and obfuscation\r\ntechniques in order to evade detection and analysis. And as you'll see, it goes to show the great lengths hackers will go to\r\nevade detection and compromise their targets. \r\nLet's dive in.\r\nWhat is Cobalt Strike?\r\nCobalt Strike is a commercial threat-emulation and post-exploitation tool commonly used by malicious attackers and\r\npenetration testers to compromise and maintain access to networks. The tool uses a modular framework comprising\r\nnumerous specialized modules, each responsible for a particular function within the attack chain. Some are focused on\r\nstealth and evasion, while others are focused on the silent exfiltration of corporate data.\r\nWhile the intent of Cobalt Strike is to better equip legitimate red teams and pen testers with the capabilities of sophisticated\r\nthreat actors, it is often misused when in the wrong hands. You know what they say... with great power comes great\r\nresponsibility. Cobalt Strike is an undeniably powerful framework, but it's easily weaponized by malicious actors as a go-to\r\ntool for undercover attacks.\r\nFinding Cobalt Strike Malware\r\nIt all started with a RunOnce key, which is typically found here:\r\nHKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\r\nThis key is used to automatically execute a program when a user logs into their machine. Since this is a “RunOnce” key, it\r\nwill automatically be deleted once it has executed. Typically, this is used by legitimate installation and update tools to\r\nresume an update after reboot—but not to resume after every reboot.\r\nThere are also “Run” keys, which don’t get removed each time and are used both legitimately and maliciously to create\r\npersistent footholds between reboots.\r\nIn this particular case, we found multiple commands for legitimate applications contained in the RunOnce key, but there\r\nwas one that looked awfully suspicious. 👀\r\nWe inspected the command in the suspicious key and found this, which seemed to be executing a PowerShell command\r\nstored in one user’s environment variables.\r\nLooking at the command in further detail, we can note that it does the following:\r\nloads PowerShell in a hidden window\r\nloads the environment variables of the current user\r\nloads a value from the environment with the same name as the current user\r\nretrieves the data from this value and uses them as arguments for the PowerShell command\r\nThis was starting to look extremely suspicious, and we knew we had to find out what was lurking in that environment\r\nvariable.\r\nAfter extracting that environment variable from the machine, we found a PowerShell command, this time executing a\r\nBase64 encoded string. After decoding and cleaning up the Base64 string, it ended up looking like this:\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 1 of 12\n\nWhat Does This Script Do?\r\nIf you’re unfamiliar with PowerShell, that script may look a bit intimidating. Ultimately, the PowerShell script achieves four\r\nmain things:\r\nLoads an obfuscated string that has been stored in the registry.\r\nDe-obfuscates the string and converts the result into a byte array.\r\nLoads the byte array into memory as a DLL using PowerShell reflection (this is a common evasion technique that\r\navoids writing a decoded payload to disk).\r\nExecutes the “test” method of that DLL, located in the “Open” object class.\r\nFrom a more technical lens, here’s a line-by-line breakdown of the PowerShell script in action:\r\nLines 1-9: This section is used to pull data from some more registry keys (up to 700 of them) and stores this data in a\r\nstring.\r\nLines 10-17: This defines a function that takes that string and converts it into a byte array. This usually indicates that\r\nthe string will be used to create an executable file.\r\nLines 19-25: This section is a bit strange. It essentially generates the number 1000 and stores it into the $ko variable.\r\nIt does this in a way that takes a million loop iterations to generate—which might be an anti-analysis technique.\r\nLine 27: Loads the StringToBytes function, but first replaces any instance of the # character with the number in $ko.\r\nLine 28: Utilizes reflection to load the byte array into memory as a DLL. This avoids writing the payload to disk and\r\nis a common antivirus evasion technique.\r\nLine 29: Executes the “test” function of the loaded DLL.\r\nThe Huntress Security team was able to retrieve the relevant registry values from the victim system and modify the script to\r\ndump out the payload as a file instead of loading it into memory. This resulted in our first executable payload.\r\nThe First Binary File\r\nAfter successfully reversing that first PowerShell script, we were able to recreate the binary file that it was loading into\r\nmemory. This file was a 6KB 32-bit .NET binary file. \r\nGiven the rather small size (only 6KB) of this file, we were suspicious that we might have missed something. The file\r\nseemed too small to contain a proper payload. We suspected that this was not the final payload and was likely a stager used\r\nto retrieve another payload.\r\nSince the file was written in .NET, we were able to load it into dnSpy to analyze the source code. This is possible because\r\n.NET does not fully compile in the same way that C/C++ code does and instead “compiles” to an intermediary bytecode\r\nformat that can be converted back into source code by tools like dnSpy.\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 2 of 12\n\nSo, we loaded the file into the dnSpy tool and were quickly able to find the “Open” class referenced by the PowerShell\r\nscript—which is where we found the following code.\r\nWhat's interesting is that this code seemed to be loading even more registry values from a suspicious registry key and\r\nresetting the RunOnce registry values that initially triggered the investigation. This allows the malware to persist across\r\nreboots as if it were a regular Run key.\r\nOur team was then able to retrieve the suspicious registry key that was being loaded from the user’s machine, where we\r\nfound encoded data that was spread across 662 Registry values. Since the data was pre-formatted in JSON, it was simple to\r\nwrite a regex to dump only the relevant data to a text file. Once this was done, we were able to decode it using a simple\r\nPython script—which was essentially just a wrapper around the original code used by the malware.\r\nThe Second Binary File\r\nUsing the output of the Python script, we were able to produce another 32-bit .NET binary file. This one was significantly\r\nlarger than the first file, so we knew we were getting somewhere!\r\nSince this was another .NET file, we loaded it up into dnSpy for another round of analysis. This is where we noticed some\r\ninteresting evasion and anti-analysis techniques.\r\nEvasion Techniques: Part One\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 3 of 12\n\nThe first thing we noticed was numerous sleep functions scattered across the code, which would cause the program to sleep\r\nfor 60 seconds between the components of its initial setup.\r\nThis technique is often used to bypass automated scanning tools that don’t have the time to wait for the sleep functions to\r\ncomplete. It can also be used to evade manual dynamic analysis, since an analyst may falsely believe that the malware is not\r\ndoing anything when it’s actually just taking a quick nap.\r\nLearn More: To dive into more defense evasion techniques, check out our Intro to Antivirus Evasion session from this\r\nyear's hack_it event!\r\nObfuscation\r\nDeeper down in the code, we observed numerous references to functions used to perform process injection. The names of\r\nthese functions were lightly obfuscated using exclamation marks, which can be seen on the right side of the below\r\nscreenshot.\r\nBrowsing further, we find the victim process that the malware is targeting for the injection. In this case, it was the genuine\r\n(and signed) Windows “Werfault.exe” process.\r\nThis is a legitimate process used by the Windows OS for error reporting—and it was likely targeted for two reasons:\r\nIt's a genuine and signed Windows process. These are sometimes ignored or whitelisted by detection systems. (Look\r\nup LOLBAS as to why it’s a terrible idea to whitelist Microsoft binaries.)\r\nSince the Werfault.exe process performs error reporting, it may have legitimate reasons for making external network\r\nconnections, meaning any malicious traffic created by the malware will have something to blend in with.\r\nThis is consistent with SpecterOps’ usage recommendations for Cobalt Strike.\r\n\"Consider choosing a binary that would not look strange making network connections.\"\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 4 of 12\n\nAs we continued browsing, we found that a large string contained the payload to be injected into Werfault.exe. If you look\r\nclosely, you can see that it is lightly obfuscated with # values, which are later replaced with the number 1000.\r\nThe Third Binary File\r\nGetting closer! But this time, the data we saved as our third binary file was not a .NET, so we can’t peek at the source code\r\nusing dnSpy.\r\nWe are dealing with a 32-bit Delphi compiled binary, with a fake compiler timestamp dated in 1992. In case you’re not\r\nfamiliar with Delphi, it’s a programming language that allows you to write, package and deploy cross-platform native\r\napplications across a number of operating systems.\r\nEvasion Techniques: Part Two\r\nWe initially performed some basic static analysis and found that the strings within the code contained references to\r\nVirtualProtect (commonly used in process injection), but this function was not listed in the import table. This indicated that\r\nthe code was likely resolving some functions at runtime, which is suspicious behavior—and yet another tactic used to evade\r\npreventive security tools and thwart analysis.\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 5 of 12\n\nWe also noted the presence of GetProcAddress and LoadLibrary, which further confirmed our suspicions that the file may be\r\nloading functions at runtime.\r\nIf you’re not familiar, GetProcAddress is a Win32 API call often used in reflection techniques that can be used to find the\r\nmemory address of a given symbol (essentially a function) at runtime. LoadLibrary is another Win32 API that loads a DLL\r\ninto the context of the currently running process. These two functions combined allow a piece of malware to hide\r\nfunctionality from static analysis and potentially evade some basic forms of detection.\r\nLoading up the file within the x32dbg debugger, we observed a large number of calls to the sleep function, which would\r\ncause the program to sleep 10 seconds between performing suspicious actions. This is yet another anti-analysis tactic.\r\nAfter getting through the sleep calls, we finally made it to some suspicious functions—namely some calls to VirtualAlloc\r\nand VirtualProtect.\r\nVirtualAlloc is a Win32 API call that will allocate a section of memory that can be used later in the program’s runtime.\r\nTypically, malware might allocate memory and then move malicious code (such as shellcode) into that section before\r\nexecuting it with another API call like CreateThread.\r\nVirtualProtect is an API call that will change the memory protections on a given memory section, this is used to mark a\r\nsection of memory as readable, writable and/or executable.\r\nPaying close attention to suspicious functions and newly allocated sections of memory, we eventually hit a breakpoint on\r\nCreateThread, which was targeting one of the newly allocated sections of memory created by the VirtualAlloc calls. We\r\ninspected that section further and found an MZ header, indicating that we had found our fourth binary file.\r\nThe Fourth Binary File\r\nAfter dumping the newly discovered section from the debugger, and re-aligning the sections using PE-bear, we were able to\r\nretrieve a fourth binary file: a 32-bit DLL, 315KB in size.\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 6 of 12\n\nInspecting the imports of the function, we observed even more references to VirtualAlloc and VirtualProtect, indicating that\r\nmore process injection was about to take place.\r\nHowever, this time we noticed references to MemCpy, indicating that the process may be injecting or overwriting code into\r\nitself rather than into a separate process. Note that if this code was executing as intended, then “itself” would refer to the\r\nalready injected Werfault.exe process.\r\nA few lines below the memory imports, we see references to named pipe functions being imported by the malware. In most\r\ncases, named pipes are legitimately used for inter-process communication. But they are also a key component of Cobalt\r\nStrike beacons and a common tactic used to evade automated analysis as they tend to cause issues for emulation tools and\r\nautomated sandboxes.\r\nBelow, we can see something else interesting: a reference to a named pipe that is highly consistent with the Default Naming\r\nScheme of named pipes used by Cobalt Strike.\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 7 of 12\n\nWe won’t dive too much into this, but there are a few great write-ups on this topic on the Cobalt Strike blog and by F-Secure\r\nLabs.\r\nIn order to confirm that this was really Cobalt Strike malware, and to try and pull more information, we parsed the file using\r\nthis Cobalt Strike Parser.\r\nThis worked great and confirmed our suspicions that this was Cobalt Strike.\r\nIt also allowed us to view the Cobalt Strike configuration file, which included the communication method (HTTPS POST\r\nrequests) and the IP of the C2 Server.\r\nSubmitting that IP address to VirusTotal, we observed only 1/82 detections. This indicated that the server may not have been\r\nwidely used, or that it was potentially still active.\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 8 of 12\n\nThe Fifth Binary File\r\nWe are well beyond the point of necessary analysis, but we decided to continue down this rabbit hole.\r\nUsing a debugger, we tried to monitor the buffers used by the named pipes, as they are often used to move payloads and\r\nmalicious data used by Cobalt Strike.\r\nShortly after monitoring these buffers, we found a new file appearing in memory. Note the MZRE Header, which is part of\r\nthe default configuration of Cobalt Strike.\r\nDumping out that segment, we were able to pull a fifth binary file. This time, it appeared to be the Reflective Loader used by\r\nthe Cobalt Strike Beacon. And as we loaded up the new binary, we can see that it is another 32-bit DLL, about 211KB in\r\nsize.\r\nDoing some basic static analysis, we saw that the file is potentially downloading a PowerShell script from localhost,\r\nindicating that there may be a tiny web server storing PowerShell commands somewhere else in the code.\r\nManually Finding Indicators of Compromise (IOCs)\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 9 of 12\n\nEventually, we hit LoadLibrary again and observed the WinInet.DLL and WS2_32.DLL module being loaded. Since these\r\nare Windows libraries used for network and web communication, we knew that the code might be about to reach out to its\r\nC2 Server.\r\nWe were able to set breakpoints on web-related functions, which confirmed some of the malicious indicators extracted from\r\nthe Cobalt Strike parsing tool. And one thing that we noticed was that the beacon references the Avant Browser in the user-agent of its C2 requests. This likely means that the C2 server won’t respond (or will return something benign) unless it sees\r\nthat header.\r\nDigging deeper, we also find pieces of the Malleable C2 commands used by the beacon, which in this case are embedded\r\ninto HTTP cookie headers.\r\n\u0026”Cookie:\r\nJn9f/eO8Xfay/dYKGpmuBIXL6ZpnGtPuLtugLgeU5vsP4K/bMWYy21s2ulMVQjYmUq9ClOYS8XWbLNMwPV3y10tGAbupka2lk+gbRlJ\r\nAlthough it looked like the data was Base64 encoded, we were unable to extract anything meaningful from using variations\r\nof Base64 decoders.\r\nBut wait – are these actually addresses?\r\nLooking at the cookie data within the dump view, we noticed that there were three valid memory addresses contained within\r\nthe encoded version of the cookie data.\r\nOne of these referenced the ws2_32.DLL, and the other two referenced a suspicious section of memory.\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 10 of 12\n\nRunning strings on the memory sections referenced in the red underlines provided some interesting results – namely lots of\r\ninformation about my virtual machine that the malware was likely trying to send to the C2 server.\r\nContinuing on, we noticed some more references to the C2 server and the communication methods used, as well as a\r\nreference to a full URL used by the payload.\r\nUnfortunately, we didn’t have networking enabled on our test machine; so these requests all failed, causing an infinite loop\r\nwhere the beacon would sleep for a while and try again. If we were to enable networking, the beacon would likely download\r\nsome additional payload modules and begin to truly compromise our machine. Maybe in a later article we can retrieve one\r\nof these payloads and do a deeper technical analysis of what this Cobalt Strike malware is capable of. \r\n• • •\r\nThat wraps up our analysis of this persistence mechanism and the binary files involved. It was a wild ride, and hopefully you\r\nenjoyed reading as much as we enjoyed researching.\r\nIf there's one lesson this should leave you with, it's that we simply can't rely on automated tools alone to protect our systems.\r\nThrough all these layers of obfuscation and evasion tactics, it's clear just how many hoops hackers will jump through to\r\nexecute their malware – and that's why you need some type of human element to catch these sneaky threat actors in their\r\ntracks.\r\nWe’ll come back to this another day, but for now, this is the end of this rabbit hole.\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 11 of 12\n\nSource: https://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nhttps://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware\r\nPage 12 of 12",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.huntress.com/blog/cobalt-strike-analysis-of-obfuscated-malware"
	],
	"report_names": [
		"cobalt-strike-analysis-of-obfuscated-malware"
	],
	"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": 1775434262,
	"ts_updated_at": 1775826776,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/685e2b7ffa3c2450821745ea0d5f2323aa581275.pdf",
		"text": "https://archive.orkl.eu/685e2b7ffa3c2450821745ea0d5f2323aa581275.txt",
		"img": "https://archive.orkl.eu/685e2b7ffa3c2450821745ea0d5f2323aa581275.jpg"
	}
}