{
	"id": "22cac737-ba00-4f73-b65a-373bf5c864bc",
	"created_at": "2026-04-06T00:07:49.777431Z",
	"updated_at": "2026-04-10T03:24:24.651327Z",
	"deleted_at": null,
	"sha1_hash": "a1a79148770bb7ef74fa2080c714ad7784fcaa7a",
	"title": "Cobalt Strike .VBS Loader - Decoding with Advanced CyberChef and Emulation",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 5068503,
	"plain_text": "Cobalt Strike .VBS Loader - Decoding with Advanced CyberChef\r\nand Emulation\r\nBy Matthew\r\nPublished: 2023-10-23 · Archived: 2026-04-05 19:07:17 UTC\r\nDemonstrating how to manually decode a complex .vbs script used to load Cobalt Strike shellcode into memory.\r\nThe referenced script implements heavy text-based obfuscation. We can defeat this obfuscation by utilising\r\nCyberChef and Regex.\r\nPost obfuscation, we will identify some \"malformed\" shellcode which we will manually fix, before emulating with\r\nthe SpeakEasy emulator.\r\nHash: e8710133491bdf0b0d1a2e3d9a2dbbf0d58e0dbb0e0f7c65acef4f788128e1e4\r\nSample Link on Malware Bazaar\r\nTLDR:\r\nIdentifying functionality and obfuscation types\r\nRemoving basic obfuscation with Regex and Text Editor\r\nRemoving advanced obfuscation using Regex, CyberChef and Subsections\r\nIdentifying shellcode and fixing negative byte values (Python or CyberChef)\r\nValidation and Emulation using Speakeasy.\r\nInitial Analysis\r\nThe script can be saved and unzipped using the password infected . From here we can open the file directly\r\nusing a text editor like notepad++.\r\nUpon opening, we can see that the script references some Excel objects, as well as Wscript.Shell , which is\r\ncommonly used to execute .vbs scripts.\r\nAt this stage I will jump to the assumption that Excel is being leveraged to execute code using Wscript.\r\nI will avoid analysing the Excel/Wscript component and jump straight to decoding the obfuscated\r\ncommand/code.\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 1 of 12\n\nWe can assume that the initial piece of the code is leveraging Excel and Wscript to run a vbs script that has been\r\nobfuscated.\r\nOverview of Obfuscation Techniques\r\nSo let's move on to the obfuscated part starting on line 30.\r\nHere we can see two main forms of obfuscation. This obfuscation is similar to one that i've spoken about for\r\nDcrat.\r\n1. The script is broken up into lots of small strings, eg \"hello world\" would be \"hello\"\u0026\"world\"\r\n2. The script utilises decimal encoded values that are decoded using Chr . For example, \"Hello World\" could\r\nbe \"Hell\"\u0026Chr(111)\u0026\"World\" . Where the \"o\" has been converted to it's decimal value of 111 (You can\r\nlook at an ascii table to see where these values come from)\r\n3. Each line ends with an underscore _ . This isn't obfuscation but will still need to be removed to clean up\r\nthe script.\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 2 of 12\n\nNow that we've identified 3 initial forms of \"obfuscation\", we can go ahead and remove them by utilising regex.\r\nYou could always remove and replace each value manually without regex, but that is a very tedious\r\nprocess and ideally something to be avoided. This script is a case where regex is the best way forward.\r\nMoving on, let's go ahead and remove the first form of obfuscation. We can do this using a search/replace. Using\r\nthe \"\u0026\" and an empty replace value.\r\n(Note that i've moved the encoded portion of the script to a new file so that the screenshots will be\r\neasier to read)\r\nAfter hitting enter, 290 occurrences of the string split obfuscation have been removed.\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 3 of 12\n\nNow, I will go ahead and use CyberChef to identify and remove the Chr(10) style obfuscation.\r\nThis process will involve using a regex to identify the Chr(10) , and then using a subsection hone in on the\r\nvalues and decode them, leaving the remaining script intact.\r\nTo do this, I will move the current encoded content into CyberChef.\r\nInitial Analysis With Cyberchef\r\nWith the script now moved into CyberChef, we can jump straight to prototyping a regular expression (regex) to\r\nhone in on the decimal encoded values.\r\nFor prototyping, I will use \"Regular Expression\" and \"Highlight Matches\", this is to confirm that the script\r\nmatches on the intended obfuscated content.\r\nThe regex used here is Chr\\(\\d+\\) . Let's break that down...\r\nChr - We only want decimal values that begin with Chr\r\n\\( and \\) - We only want decimal values contained in brackets, we need \\ to escape the brackets as\r\nthey have special meaning inside a regex.\r\n\\d+ - This specifies one or more numerical values.\r\nTLDR: we want \"numerical values\" + \"contained in brackets\" + \"preceded by Chr\".\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 4 of 12\n\nSince the regex looks like it's working and correctly identifying values, we can go ahead and change it to a\r\nsubsection.\r\nA subsection allows us to perform all future operations only on data that matches our regex. This allows\r\nus to keep the majority of the script intact, while decoding only values that are obfuscated and matching\r\nour regex.\r\nWe can go ahead and copy the regex into a subsection, making sure to disable the original regular expression.\r\nWith the subsection applied, we can now apply an additional regex to extract decimal values (but only those\r\ncontained with Chr ).\r\nFrom here, we can now apply a \"From decimal\" to decode the content.\r\nAt this point, we now have a signficantly better looking script than before. (albeit we still have the \u0026\r\neverywhere)\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 5 of 12\n\nMoving back to a text editor\r\nWith the primary obfuscation now defeated, we can copy the CyberChef output back into a text editor.\r\nThe ampersands that surrounded our \u0026Chr(110)\u0026 values still remain, so let's go ahead and remove those.\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 6 of 12\n\nWe also have those pesky underscores (visual basic newlines) remaining, so let's go ahead and remove those using\r\n\\s+_\\s+ , this will remove any newlines and surrounding whitespace.\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 7 of 12\n\nThe Script now looks much cleaner, albeit there are a lot of \"\" quotes around that don't seem to contribute\r\nanything useful.\r\nWe can go ahead and remove these using a regex of \"+ , this will remove all quotes from the script.\r\nAnalysing the Cleaned up Script\r\nWith the majority of junk now removed, we can go ahead and view the now decoded script.\r\nOne of the first things we can notice is that there are lots of references to api's commonly used in process injection\r\n(VirtualAllocEx, WriteProcessMemory, CreateProcessA etc).\r\nScrolling down slightly, we can also see a blob of hex bytes and a process name, likely used as the target for\r\nprocess injection.\r\n(eg, this blob of bytes is going to be injected into rundll32.exe)\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 8 of 12\n\nAt this point, we can probably assume that the bytes are shellcode. This is primarily due to the short length. Which\r\nis too short to be a standard pe/exe/dll file.\r\nBefore going forward, we can first remove the final remaining underscores.\r\nOnce removed, the blob of hex bytes should look something like this. The blob is far too short to be a full pe file,\r\nbut plenty of space to include shellcode.\r\nNow there is one trick here that slightly complicates things.\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 9 of 12\n\nFixing Negative Decimal Values Used to Represent Shellcode\r\nThat is, there are negative values present in the shellcode that will need to be fixed.\r\nI am not 100% sure how negative values work in visual basic/.vbs. But in this case, it seems that the value of -4\r\ncorresponds to 256 - 4 , which is 252 , which is 0xfc , which is a common byte (cld flag) seen at the\r\nbeginning of Shellcode.\r\nBefore analysing the possible shellcode, we will need to take all negative values and subtract them from 256 .\r\nThis can be done in CyberChef or Python, using either of the following examples.\r\nCyberChef - This can be done by using a SubSection to extract negative values, subtracting them from the value\r\n256. From here, all values can be decimal decoded.\r\nPython - Similar to cyberchef, the array of decimal values can be iterated through, subtracting negative values\r\nfrom the number 256.\r\nIn the output, we can see cleartext strings as well as the initial Shellcode byte of 0xfc .\r\nBoth outputs also reference a possible C2 address of 47.98.51[.]47 .\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 10 of 12\n\nIn addition, both outputs reference an EICAR string. (This is a string that will automatically trigger all antiviruses)\r\nAccording to Mandiant and Fortra (authors of Cobalt Strike), this is an intentional string designed to prevent\r\nabuse of the Trial Edition of Cobalt Strike.\r\nShellcode Emulation With SpeakEasy.\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 11 of 12\n\nThe short length and presence of the 0xfc byte can give us strong confidence that the result is shellcode.\r\nFor extra confirmation, we can go ahead and emulate the output inside of the SpeakEasy emulator.\r\nThis confirms that the bytes are shellcode, which act as a http-based downloader from the ip of 47.98.41[.]47\r\nConclusion\r\nIn this blog, we have analysed a visual basic script containing a shellcode loader for cobalt strike. We have gone\r\nover some basic tips for analysing scripts, as well as some advanced functionality for decoding using CyberChef.\r\nIn the end, we have successfully identified a C2 Address and confirmed the shellcode functionality using the\r\nSpeakEasy emulator.\r\nSign up for Embee Research\r\nMalware Analysis Insights\r\nNo spam. Unsubscribe anytime.\r\nSource: https://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nhttps://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/\r\nPage 12 of 12",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://embee-research.ghost.io/decoding-a-cobalt-strike-vba-loader-with-cyberchef/"
	],
	"report_names": [
		"decoding-a-cobalt-strike-vba-loader-with-cyberchef"
	],
	"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": 1775434069,
	"ts_updated_at": 1775791464,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/a1a79148770bb7ef74fa2080c714ad7784fcaa7a.pdf",
		"text": "https://archive.orkl.eu/a1a79148770bb7ef74fa2080c714ad7784fcaa7a.txt",
		"img": "https://archive.orkl.eu/a1a79148770bb7ef74fa2080c714ad7784fcaa7a.jpg"
	}
}