{
	"id": "4327e1f0-5747-46b4-849e-fdba800e7622",
	"created_at": "2026-04-06T00:22:19.016744Z",
	"updated_at": "2026-04-10T03:23:52.259641Z",
	"deleted_at": null,
	"sha1_hash": "cdfd4171171e03b62b1318ce898b0d9c41c470e6",
	"title": "Analyzing Emotet with Ghidra — Part 1",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1503377,
	"plain_text": "Analyzing Emotet with Ghidra — Part 1\r\nBy Cafe Babe\r\nPublished: 2019-04-22 · Archived: 2026-04-05 14:51:17 UTC\r\nThis post I’ll show how I used Ghidra in analyzing a recent sample of Emotet.\r\nIf you have read this, here is Part 2.\r\nSHA256: ee0a206415cce60f8b3afb29d8c17f86fe1923cbdf69812be139a3012b2fa24b\r\nThe analysis is done on the unpacked binary file. In this post I’m skipping how I unpacked the file, since what I\r\nprimarily want to show is how I used Ghidra’s python scripting manager to decrypt strings and API calls.\r\nSome short descriptions:\r\nWhat is Ghidra?\r\nIt is an open source reverse engineering tool suite. You can find out more here — https://ghidra-sre.org/\r\nWhy Emotet?\r\nEmotet is a prevalent malware. Started out as a banking trojan. It is persistent and keeps evolving its\r\ninfection mechanisms. There are other existing analyses done. A search can lead you there —\r\nhttps://www.google.com/search?q=emotet\r\nWhy Ghidra and Emotet?\r\nFor starters, I am looking for a new gig (a.k.a unemployed) and hence cannot afford an IDA Pro license.\r\nPlus I want to continue being a Malware Analyst.\r\nUsing the free version IDA v7.0 is still amazing, but I miss not being able to use IDA Python. I did use\r\nIDA’s own scripting language IDC but…I like python. Implemented just one of the functions of Emotet\r\nhere.\r\nOpening up Emotet with Ghidra\r\nGhidra is about creating projects. Following the on-screen instructions, I created a project named “Emotet”. To\r\nadd files to analyze into the project, simple type I or go to File -\u003e Import File.\r\nPress enter or click to view image in full size\r\nhttps://medium.com/@0xd0cf11e/analyzing-emotet-with-ghidra-part-1-4da71a5c8d69\r\nPage 1 of 7\n\n1. Imported Emotet binary\r\nGhidra displays properties regarding the file that gets imported. Double click on the file name and it opens it up in\r\nCodeBrowser which is a tool that disassembles the file.\r\nPress enter or click to view image in full size\r\n2. Emotet view in CodeBrowser\r\nUnder the Symbol Tree (usually on the left or you can go to Window -\u003e Symbol Tree), I filtered for “entry” to get\r\nto the binary’s entry point.\r\nhttps://medium.com/@0xd0cf11e/analyzing-emotet-with-ghidra-part-1-4da71a5c8d69\r\nPage 2 of 7\n\nPress enter or click to view image in full size\r\n3. Entry Point of Emotet\r\nUnder Listing we see the compiled code and on the right is its decompiled code. Since I’ve already analyzed these\r\nbinaries, some of the sub routine calls and offsets in these images will have been renamed by me. To rename an\r\noffset, right-click an offset value and select Edit Label (or type L).\r\nEmotet’s Function Calls\r\nEmotet encrypts its strings and stores its API call names as hashes. So statically viewing this file, is a pain to read.\r\nWithout going into much detail about Emotet’s payload (that would require another blog entry), I will show how\r\nto make this binary a bit more easy to follow. It does require to initially go through each function and figure out\r\nthe math (possibly using Olldbg, Wingdb or whichever debugger so to make it a little less painful).\r\nIn this case I wanted to figure 2 methods used by Emotet. The first function is a simple xor routine that it uses to\r\ndecrypt strings. It looked deceiving complex (because of the use of shift operators in the function), only till after\r\nrunning one iteration in Ollydbg that I realized what was happening… . The second function finds which API\r\nname matches which hash (I will cover this in Part 2). This I felt was a bit more clever, but still easy to understand\r\nafter running in Ollydbg.\r\nGet Cafe Babe’s stories in your inbox\r\nJoin Medium for free to get updates from this writer.\r\nRemember me for faster sign in\r\nThen using Ghidra’s Script Manager, I’ll show how I implemented the python scripts to decrypt the strings and\r\nresolve the API calls used in the binary.\r\nHow are the Strings encrypted?\r\nhttps://medium.com/@0xd0cf11e/analyzing-emotet-with-ghidra-part-1-4da71a5c8d69\r\nPage 3 of 7\n\nIn the binary, I’ve noticed a lot of references to the function call at 0x00401b70. This call decrypts for the strings.\r\nI renamed it to decode_strings. To find references made to the function, right click the function and select\r\nReferences -\u003e Show References to.\r\n4. References to decode_strings\r\nPress enter or click to view image in full size\r\n5. Call being made to decode_strings\r\nThe function decode_strings takes in 2 arguments that are stored in ECX and EDX (Image 5). ECX is the offset of\r\nthe encrypted string. EDX is the xor key. The decrypted string gets stored in memory allocated in the heap and the\r\naddress gets passed to EAX.\r\n(Side Track: I have added the string “ecx = offset \\n edx = key” as a repeatable comment to the function. Right\r\nclick the address and select Comments -\u003e Set Repeatable Comment or type ;)\r\nhttps://medium.com/@0xd0cf11e/analyzing-emotet-with-ghidra-part-1-4da71a5c8d69\r\nPage 4 of 7\n\nThe first dword at the offset xor’ed with the key returned the length of the string. The next subsequent set of\r\ndwords were xor’ed up until the string’s length.\r\nNow for the more exiting part, automating this with a python script in Ghidra.\r\nUsing Python to Automate Decryption\r\n6. Script Manager Icon\r\nIn the top toolbar section of Ghidra, we see this icon in image 6. It takes us to the Script Manager. Else you can\r\nselect Window -\u003e Script Manager.\r\nPress enter or click to view image in full size\r\n7. Script manager\r\nThe Script Manager displays a list of scripts written in either Java or Python. They come with the installation. The\r\nscript manager also has some python script examples. So, I filtered for .py scripts to help me understand how to\r\nproceed in writing a python script. The Python Interpreter interacts with Ghidra’s Java API through Jython. The\r\ndocumentation on the Java APIs provided can be found in a zipped file in the docs directory of your Ghidra\r\ninstallation.\r\nPress enter or click to view image in full size\r\n8. Create new script icon\r\nhttps://medium.com/@0xd0cf11e/analyzing-emotet-with-ghidra-part-1-4da71a5c8d69\r\nPage 5 of 7\n\nTo create a new python script, select this icon — image 8. Select Python and enter a name you’d like to give to\r\nyour script.\r\nPress enter or click to view image in full size\r\n8. A sample test.py script created\r\nAdditionally, going through the help docs (under Help -\u003e Contents) and reading under Script Development, there\r\nis a description of the metadata tags that gets generated when creating a new script.\r\nI’ve uploaded the script into my github repo and you can follow it here —\r\nhttps://github.com/0xd0cf11e/ghidra/blob/master/ghidra_emotet_decode_strings.py\r\n9. Decrypted string displayed as comment\r\nThe idea behind the script is to display the strings that get decrypted as comments next to the instruction where its\r\noffset is moved to ECX (Image 9).\r\n10. Bytes patched in the binary.\r\nhttps://medium.com/@0xd0cf11e/analyzing-emotet-with-ghidra-part-1-4da71a5c8d69\r\nPage 6 of 7\n\nAnd as well to patch the bytes in the binary (Image 10).\r\nFirst step, I wanted to find all the code references made to the decode_strings function.\r\nIterating through each reference, the next step was locating for the opcode instructions MOV ECX and MOV\r\nEDX. The instructions weren’t always immediately before the call to the function. So I iterated through a max of\r\n100 instructions to search for the opcodes.\r\nAfter that I was all set to carry out the xor routine and patch the bytes and comment at the instruction offset where\r\nMOV ECX was carried out.\r\nSource: https://medium.com/@0xd0cf11e/analyzing-emotet-with-ghidra-part-1-4da71a5c8d69\r\nhttps://medium.com/@0xd0cf11e/analyzing-emotet-with-ghidra-part-1-4da71a5c8d69\r\nPage 7 of 7",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"ETDA",
		"Malpedia"
	],
	"references": [
		"https://medium.com/@0xd0cf11e/analyzing-emotet-with-ghidra-part-1-4da71a5c8d69"
	],
	"report_names": [
		"analyzing-emotet-with-ghidra-part-1-4da71a5c8d69"
	],
	"threat_actors": [
		{
			"id": "d90307b6-14a9-4d0b-9156-89e453d6eb13",
			"created_at": "2022-10-25T16:07:23.773944Z",
			"updated_at": "2026-04-10T02:00:04.746188Z",
			"deleted_at": null,
			"main_name": "Lead",
			"aliases": [
				"Casper",
				"TG-3279"
			],
			"source_name": "ETDA:Lead",
			"tools": [
				"Agentemis",
				"BleDoor",
				"Cobalt Strike",
				"CobaltStrike",
				"RbDoor",
				"RibDoor",
				"Winnti",
				"cobeacon"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434939,
	"ts_updated_at": 1775791432,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/cdfd4171171e03b62b1318ce898b0d9c41c470e6.pdf",
		"text": "https://archive.orkl.eu/cdfd4171171e03b62b1318ce898b0d9c41c470e6.txt",
		"img": "https://archive.orkl.eu/cdfd4171171e03b62b1318ce898b0d9c41c470e6.jpg"
	}
}