{
	"id": "7d98d416-928a-4cf6-bd2b-80cfc0a6b139",
	"created_at": "2026-04-06T02:12:07.364839Z",
	"updated_at": "2026-04-10T03:21:09.721201Z",
	"deleted_at": null,
	"sha1_hash": "c32b37795debaf236d4b4bfa56616cf5a5ed630b",
	"title": "Emotet: Dangerous Malware Keeps on Evolving",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 3811307,
	"plain_text": "Emotet: Dangerous Malware Keeps on Evolving\r\nBy Threat Intel\r\nPublished: 2020-03-30 · Archived: 2026-04-06 01:29:21 UTC\r\nResearch into the latest Emotet variant by Symantec’s Threat Engineering Team\r\nhas revealed details about which compression algorithm the gang behind Emotet\r\nhas customized and is using in its code.\r\n12 min read\r\nMar 30, 2020\r\nAuthors: Nguyen Hoang Giang, Mingwei Zhang\r\nPress enter or click to view image in full size\r\nEmotet is one of the most dangerous malware threats active today. Emotet (Trojan.Emotet) began life as a banking\r\nTrojan but evolved several years ago to act as a malware loader for other threats — Emotet infects a machine and\r\nthen downloads another threat e.g. the TrickBot information stealer, onto the infected system. Emotet is now one\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 1 of 18\n\nof the biggest threat distributors out there, renting its infrastructure out to all sorts of other threats, including\r\nransomware, information stealers, and cryptocurrency miners.\r\nWe wrote a detailed blog about Emotet’s evolution in 2018, which gives you more background on the threat and\r\nits development.\r\nRecently our threat engineering team noticed some updates to Emotet (Version 5, 20200201), and performed some\r\nanalysis on the malware sample to see exactly what was going on.\r\nWhat’s New?\r\nThe first thing we noticed is that Emotet has updated its techniques for obfuscating its flow of code. This anti-analysis technique makes it more difficult to analyze and track modifications between variant binaries. The second\r\nthing is a change in the communication protocol between the botnet and its command and control (C\u0026C) servers.\r\nA detailed technical analysis of these changes follows.\r\nAnti-Analysis\r\nControl Flow Flattening\r\nThis Emotet binary (unpacked) is using an obfuscation technique called Control Flow Flattening, which works as\r\nfollows:\r\nEach basic block is assigned a number.\r\nThe obfuscator introduces a block number variable, indicating which block should execute.\r\nEach block, instead of transferring control to a successor with a branch instruction, as usual, updates the\r\nblock number variable to its chosen successor.\r\nThe ordinary control flow is replaced with a switch statement over the block number variable, wrapped\r\ninside of a loop.\r\nPress enter or click to view image in full size\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 2 of 18\n\nFigure 1. Control flow graph of one of the functions is obfuscated by Control Flow Flattening\r\ntechnique\r\nEncrypted Strings and Resources\r\nAll strings and other resources (such as RSA public key) are encrypted and only decrypt at runtime. The\r\ndecryption algorithm is described in Figure 2.\r\nPress enter or click to view image in full size\r\nFigure 2. How Emotet decrypts strings and resources\r\nWe can use IDAPython to create a script to decrypt the data:\r\ndef decrypt_data(ea):\r\n key1 = idc.get_wide_dword(ea)\r\n key2 = idc.get_wide_dword(ea + 4)\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 3 of 18\n\nsize = key1 ^ key2\r\n data_size = (size + 3) \u0026 0xFFFFFFFC\r\n ea += 8\r\n s = ''\r\n for i in range(data_size/4):\r\n dec_dword = idc.get_wide_dword(ea + i * 4) ^ key1\r\n s += struct.pack('\u003cI', dec_dword)\r\n return s[:size]\r\nPython\u003eprint(decrypt_data(0x40a810))\r\nwininet.dll\r\nDynamic API Resolve\r\nIn this version, Emotet resolves API(s) by looking up the hashes of the API name and DLL name once it needs-to-use instead of loading them all at one time as previous versions. We observed that this behavior is similar to the\r\ncode of Dridex or the Bitpaymer/ DopplePaymer ransomware:\r\nFigure 3. How Emotet loads and calls API ExitProcess by looking up hash values of kernel32 and\r\nExitProcess\r\nThe customized hash function is calculated as follows:\r\ndef emotet_hash(api_name):\r\n i = 0\r\n for c in api_name:\r\n i = (i \u003c\u003c 16) + (i \u003c\u003c 6) + ord(c) – i\r\n # xor dword (0x165308FE) varies between binaries and different\r\n # between functions resolving api name hash and module name hash\r\n return (i \u0026 0xFFFFFFFF) ^ 0x165308FE\r\nMain Work\r\nUpon first infection, the Emotet sample runs through two stages. During the first stage, the sample runs as a first\r\ninstance, does some setup and checks the victim system, it then executes the second instance. The second instance\r\nwill run in the second stage, where it communicates with embedded C\u0026C server addresses in its binary.\r\nFirst Stage — Dropper Instance\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 4 of 18\n\nWhen it first runs, Emotet tries to decrypt information from additional DLLs that it requires to load. Among the\r\nDLLs it uses are:\r\nurlmon.dll\r\nuserenv.dll\r\nwininet.dll\r\nshell32.dll\r\ncrypt32.dll\r\nadvapi32.dll\r\nwtsapi32.dll\r\nThen, Emotet gets the volume serial number of the Windows partition. This volume serial number is used to create\r\na series of mutex and event handles, with object names as follows (%X is the format of the volume serial number):\r\nGlobal\\\\I%X — MutexI\r\nGlobal\\\\M%X — MutexM\r\nGlobal\\\\E%X — EventE\r\nA pair, EventE and MutexM, is created for synchronization between the first instance and second instance (by\r\nusing API SignalObjectAndWait), to ensure that the second instance is only able to connect to the C\u0026C servers\r\nonce the first instance is exited.\r\nCheck Privilege and Delete Old Variant\r\nEmotet checks its running privilege by calling API OpenSCManagerW with parameter\r\nSC_MANAGER_ALL_ACCESS, if this API call is successful, then the sample is considered to be running with\r\nhigh privilege.\r\nThen the sample decrypts a list of words as below and uses the volume serial number to calculate and select two\r\nwords from that list. It then combines them to get the filenames of old Emotet binaries that were dropped by\r\nEmotet’s previous version. Depending on whether it is running with high privilege or not, the old binary with that\r\nfilename will be deleted from CISIDL_SYSTEMX86 or CSIDL_LOCAL_APPDATA.\r\nduck,mfidl,targets,ptr,khmer,purge,metrics,acc,inet,msra,symbol,driver,sidebar,restore,msg,volume,ca\r\nIf the sample is running with high privilege, it checks if its running filename contains a number, if so, it will try to\r\ndelete any other files with the same filename. It looks like this latest sample of Emotet is trying to remove old\r\ntraits of the previous version(s).\r\nCheck Setting From Registry\r\nFor its next step, Emotet checks the registry value name (is volume serial number) in:\r\nHKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer — If Emotet is\r\nrunning with high privilege\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 5 of 18\n\nHKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer — If Emotet is running\r\nwith low privilege\r\nThe data of this registry value name is the encrypted filename of the Emotet binary that will be dropped by the\r\ncurrent version. It is XOR-encrypted and the key is the volume serial number. If this registry value is not\r\navailable, it means that the Emotet sample is running in its first stage and it will set this value for use in the second\r\ninstance.\r\nPress enter or click to view image in full size\r\nFigure 4. Data is saved in the registry as the encrypted filename of dropped file\r\nFilename of New Dropped File\r\nTo drop the Emotet binary for the second stage, Emotet needs to get a filename. This sample will scan in\r\nCSIDL_SYSTEM, only filenames with the extensions .dll and .exe are selected. This is similar to the Bitpaymer\r\nransomware, which also clones an executable file in the system directory to hide its binary in the ADS stream of\r\nthe cloned file. This new filename is saved to the registry as previously described.\r\nPress enter or click to view image in full size\r\nFigure 5. Emotet scans for filenames of .exe and .dll files in %SYSTEM% to generate filename of\r\ndropped file\r\nEmotet then makes a path to drop itself to. If it is running with high privilege, it drops the binary to\r\nCSIDL_SYSTEMX86, otherwise, it drops it to CSIDL_LOCAL_APPDATA (using API SHFileOperation with the\r\nparameter FO_MOVE).\r\nPress enter or click to view image in full size\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 6 of 18\n\nFigure 6. Emotet calls API SHFileOperation to clone itself to destination path\r\nThe path of the dropped file is:\r\n“(CSIDL_SYSTEMX86|CSIDL_LOCAL_APPDATA)\\\\%s\\\\%s.exe” % (new_filename, new_filename)\r\nWhen it is running with high privilege, Emotet gains persistence by creating a service for the dropped file:\r\n“CSIDL_SYSTEMX86\\\\%s\\\\%s.exe” % (new_filename, new_filename)\r\nService name: new_filename\r\nService display name: new_filename\r\nOtherwise, Emotet gains persistence in the registry by setting a registry value (only after it has its first connected\r\nto its C\u0026C servers):\r\nHKEY_CURRENT_USER\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\r\nValue name: new_filename\r\nValue data: CSIDL_LOCAL_APPDATA\\\\%s\\\\%s.exe % (new_filename, new_filename)\r\nFinally, Emotet launches the second instance by calling API CreateProcessW to the dropped file.\r\nSecond Stage — Bot Instance\r\nThe second instance goes through the same steps as the first instance until it is able to get the saved data of the\r\nfilename from the registry. Then it performs some checks before communicating with the C\u0026C servers:\r\nChecks current filename is the same as the filename saved in the registry. If not, it runs similar to the first\r\nstage to launch another instance.\r\nCheck if its parent process is services.exe, meaning it is running as a service. If it is, it runs similar to the\r\nfirst stage to launch another instance.\r\nThe communication protocol is changed in this version. We will describe this in detail below.\r\nGet List C\u0026C IP Port / RSA Public Key and Generate AES Key\r\nIn this version, the IP addresses and ports of the C\u0026C servers continue storing in binary as 8-byte blocks.\r\nPress enter or click to view image in full size\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 7 of 18\n\nFigure 7. IP(s) and port(s) of C\u0026C servers are embedded in binary\r\nEmotet retrieves the RSA public key from encrypted data. RSA public key is in PEM format:\r\n-----BEGIN PUBLIC KEY-----\r\nMHwwDQYJKoZIhvcNAQEBBQADawAwaAJhANQOcBKvh5xEW7VcJ9totsjdBwuAclxS\r\nQ0e09fk8V053lktpW3TRrzAW63yt6j1KWnyxMrU3igFXypBoI4lVNmkje4UPtIIS\r\nfkzjEIvG1v/ZNn1k0J0PfFTxbFFeUEs3AwIDAQAB\r\n-----END PUBLIC KEY-----\r\nThen the sample will generate an AES-128-CBC session key handle and an SHA-1 hash key handle. The RSA\r\npublic key, AES-128-CBC Key, and SHA-1 hash are combined to secure the connection between Emotet samples\r\nand the C\u0026C servers.\r\nPress enter or click to view image in full size\r\nFigure 8. Emotet is retrieving IP/Port list and generating crypto key handles to secure\r\ncommunication\r\nSetup Post Request\r\nPlaintext Packet\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 8 of 18\n\nGet Threat Intel’s stories in your inbox\r\nJoin Medium for free to get updates from this writer.\r\nRemember me for faster sign in\r\nNext, the Emotet sample starts building a plaintext packet for the request. This is basic information to generate\r\npackets after that. The plaintext packet has the following format:\r\nstruct plain_packet\r\n{\r\n uint32_t victim_id_size;\r\n uint8_t victim_id[victim_id_size]; // hostname + hex volume serial number\r\n uint32_t system_info;\r\n uint32_t session_id;\r\n uint32_t bot_id; // 0x1343B09 or 20200201 in decimal – it looks like the date\r\n uint32_t unknown_id; // 0x7D0 or 2000 in decimal\r\n uint32_t procname_buffer_size;\r\n uint8_t procname_buffer[procname_buffer_size];\r\n uint32_t module_id_array_size;\r\n uint8_t module_id_array[module_id_array_size];\r\n}\r\nPress enter or click to view image in full size\r\nFigure 9. Emotet is generating VICTIM_ID based on computer name and volume serial number\r\nPress enter or click to view image in full size\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 9 of 18\n\nFigure 10. Emotet is calculating system info value based on OS version, product type, and\r\nprocessor architecture\r\nPress enter or click to view image in full size\r\nFigure 11. Emotet gets session ID from its process ID\r\nFigure 12. Emotet enumerates running process names (no duplicated process names, no process\r\nnames where parent process ID is 0, and not including Emotet’s process name) puts them in buffer,\r\nseparated by comma, and in ASCII\r\nFigure 13. Emotet enumerates ID of plugins, which it downloads from C\u0026C and executes. Plugin\r\nID(s) are saved to buffer as DWORD(s).\r\nPress enter or click to view image in full size\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 10 of 18\n\nFigure 14. Full buffer of plaintext packet, which Emotet created\r\nEmotet then compresses this plaintext packet by using an unknown compression algorithm. After digging deeply\r\ninto this compression algorithm, we can point out which compression library the actors behind Emotet are using\r\nand what they customized in that library. Let’s keep going and look at how the compressed data is repacked to a\r\ncommand packet.\r\nClient Command Packet\r\nThe command package is composed of the compressed data of the plaintext packet:\r\nstruct client_cmd_packet\r\n{\r\n uint32_t cmd_id; // 0x01 for register command\r\n uint32_t comp_data_size;\r\n uint8_t comp_data[comp_data_size];\r\n}\r\nFinally, Emotet performs encryption on the command packet (by AES-128-CBC) to generate a final packet, which\r\nis posted to the C\u0026C servers through HTTP POST. The format of the final packet is as follows:\r\nstruct final_packet\r\n{\r\n uint8_t enc_session_key[0x60]; // reversed order of encrypted session key (AES-128-CBC key is en\r\n uint8_t comp_data_hash[0x14]; // SHA-1 hash of Command Packet (before encryption)\r\n uint8_t encrypted_data[]; // AES-128-CBC encrypted data of Command Packet\r\n}\r\nPress enter or click to view image in full size\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 11 of 18\n\nFigure 15. Emotet repackages the final packet before embedding it to a POST header request\r\nAt this point, Emotet has gotten the data to post it to the C\u0026C server. Next, it sets up fields in the POST header.\r\nGenerate URI Path\r\nThis URI path is composed of 1–6 substrings. Each substring is 4–19 bytes and is randomly generated by selecting\r\nfrom [A-Za-z1–9]. The referrer path is the same as the URI path.\r\nFigure 16. Emotet generates subpaths for the POST request\r\nReferrer Path\r\nThe referrer path is set by the IP address of the C\u0026C server and generated URI path above.\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 12 of 18\n\nReferrer: http://%s/%s\\r\\n\r\nMultipart/Form-Data\r\nCurrently, instead of sending the final packet as a simple POST body, Emotet submits that data by encoding it in\r\nmultipart/form-data. The multipart/form-data has the following format:\r\nContent-Type: multipart/form-data; boundary=%s\\r\\n\\r\\n--%S\\r\\nContent-Disposition: form-data; name=\"%\r\nBoundary\r\nGenerated by random numbers and written in the following format:\r\n---------------------------%04u%04u%04u%03u\r\nPress enter or click to view image in full size\r\nFigure 17. Emotet generates boundary string\r\nForm Name and Attachment Filename\r\nThis form name is generated randomly. It is composed of 4–19 bytes and is randomly generated by selecting from\r\n[A-Za-z]. Similarly, the attachment filename is generated with the same algorithm.\r\nFigure 18. Emotet generates form name and filename of multipart/form-data\r\nNow, Emotet is ready to POST data to a C\u0026C server. If the C\u0026C server address is live and replies to the message,\r\nEmotet will parse and decrypt the message by AES-128-CBC then verify the SHA-1 hash of the decrypted data\r\nusing the RSA public key.\r\nResponded Packet\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 13 of 18\n\nThe respond packet is formatted as follows:\r\nstruct c2_resp_packet\r\n{\r\n uint8_t signature[0x60]; // signature data to be verified\r\n uint8_t decrypted_data_hash[0x14]; // SHA-1 hash of encrypted data after decryption\r\n uint8_t encrypted_data[]; // AES-128-CBC encrypted data of the C\u0026C’s responded message\r\n}\r\nPress enter or click to view image in full size\r\nFigure 19. Emotet receives a packet from the C\u0026C, decrypts and verifies it\r\nAfter receiving valid decrypted data, Emotet decompresses it and then parses commands and data from the\r\ndecompressed packet. Data from the decompressed packet is a chain of blocks of the C\u0026C server’s command\r\npackets:\r\nstruct decomp_data\r\n{\r\n uint32_t cmd_packet1_size; // size of cmd_packet1 data\r\n uint8_t cmd_packet1[cmd_packet1_size];\r\n uint32_t cmd_packet2_size;\r\n uint8_t cmd_packet2[cmd_packet2_size];\r\n .....\r\n uint32_t cmd_packetN_size;\r\n uint8_t cmd_packetN[cmd_packetN_size];\r\n}\r\nEach block of the C\u0026C server’s command packets is formatted as follows:\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 14 of 18\n\nstruct c2_cmd_packet\r\n{\r\n uint32_t id; // plugin id\r\n uint32_t command; // command id\r\n uint32_t payload_size; // payload size\r\n uint8_t payload[payload_size]; // payload data\r\n}\r\nCurrently, this Emotet sample receives three commands from the C\u0026C server:\r\nCommand ID 01: Downloads an executable file and executes it\r\nCommand ID 02: Downloads an executable file, checks if there is another active Terminal Service session\r\nother than the current session identifier of the running Emotet sample, then launches downloaded\r\nexecutable in that active Terminal Service session:\r\n- Calls API WTSQueryUserToken to obtain the Primary User token of the requested Terminal Service sess\r\n- Calls API CreateProcessAsUser to launch process\r\nCommand ID 03: Downloads a module/plugin, loads it and calls to its main function\r\nCompression/Decompression Library\r\nAs we already mentioned, this Emotet sample is using an unknown compression library to compress packets to\r\nsend to the C\u0026C server and to decompress packets received from the C\u0026C server. This is one of the recent\r\nchanges seen in the current Emotet sample as, in previous versions, Emotet was using the zlib library. Although\r\nwe can easily reverse engineer and re-implement the compression and decompression routines from the current\r\nEmotet binary, uncovering exactly which compression library it is using helps us understand more about the\r\nsample and implement compression and decompression exactly as the sample does.\r\nThe compression library is actually a well-known library named LibLZF. But the people behind Emotet made\r\nsome modifications to that library when they integrated it into the current code base of this bot. We will highlight\r\nthe modifications implemented below.\r\nBrowsing to the source code of LibLZF, we noticed this comment in file lzf_c.c:\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 15 of 18\n\nFigure 20. LibLZF defines how to calculate values\r\nInterestingly, this library’s decompression routine does not depend on the hash function used in the compression\r\nroutine. The hash function is calculated in lzf_c.c (source code of compression routine):\r\nFigure 21. How the hash table is calculated in the compression routine of LibLZF\r\nAnd in the current Emotet binary, LibLZF is compiled with these modifications:\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 16 of 18\n\nIn file lzfP.h:\r\nSet ULTRA_FAST is 0\r\nSet VERY_FAST is 0\r\nIn file lzf_c.c:\r\nComment out to block code as in Figure 21\r\nFrom this finding, we grabbed a project that is binding LibLZF to Python, changed the code as described above,\r\nand compiled it. Figure 22 shows the result of our testing with that Python compiled module on data we dumped\r\nfrom the Emotet sample’s memory:\r\nFigure 22. Verify compressed/decompressed data with Python compiled module\r\nConclusion\r\nOver time, the Emotet botnet has evolved and will no doubt continue to evolve in the future. It has proven itself to\r\nbe an extremely effective weapon for cyber criminals, and is one of the most dangerous botnets active today.\r\nIOC\r\nAnalyzed Sample:\r\naa0cbe599839db940f6cc2f4ca1383dbb9937b8c7dd6460847c983523cd63c39\r\nReferences/Further Reading\r\nControl flow flattening: https://github.com/obfuscator-llvm/obfuscator/wiki\r\nControl flow flattening write-up by Rolf Rolles: http://www.hexblog.com/?p=1248\r\nLibLZF library (by Marc Lehmann): http://oldhome.schmorp.de/marc/liblzf.html\r\nhttps://research.checkpoint.com/2018/emotet-tricky-trojan-git-clones/\r\nhttps://www.cert.pl/en/news/single/whats-up-emotet/\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 17 of 18\n\nCheck out the Security Response blog and follow Threat Intel on Twitter to keep up-to-date with the latest\r\nhappenings in the world of threat intelligence and cyber security.\r\nLike this story? Recommend it by hitting the heart button so others on Medium see it and follow Threat Intel on\r\nMedium for more great content.\r\nSource: https://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nhttps://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de\r\nPage 18 of 18",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://medium.com/threat-intel/emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de"
	],
	"report_names": [
		"emotet-dangerous-malware-keeps-on-evolving-ac84aadbb8de"
	],
	"threat_actors": [],
	"ts_created_at": 1775441527,
	"ts_updated_at": 1775791269,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/c32b37795debaf236d4b4bfa56616cf5a5ed630b.pdf",
		"text": "https://archive.orkl.eu/c32b37795debaf236d4b4bfa56616cf5a5ed630b.txt",
		"img": "https://archive.orkl.eu/c32b37795debaf236d4b4bfa56616cf5a5ed630b.jpg"
	}
}