{
	"id": "89ffcdb1-c05f-4665-ba0c-93d6031da28d",
	"created_at": "2026-04-06T00:06:13.018669Z",
	"updated_at": "2026-04-10T13:12:28.890063Z",
	"deleted_at": null,
	"sha1_hash": "9e1e2c3b47b47d5d7199ee3c88d5deb07dde1c7e",
	"title": "Zloader Analysis | ThreatLabz",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 272013,
	"plain_text": "Zloader Analysis | ThreatLabz\r\nBy ThreatLabz\r\nPublished: 2024-01-19 · Archived: 2026-04-05 18:20:45 UTC\r\nTechnical Analysis\r\nIn the following sections, we dive into the technical details surrounding Zloader’s new updates to their anti-analysis techniques, embedded configuration, DGA, and network encryption.\r\nAnti-analysis techniques\r\nZloader uses a combination of API import hashing, junk code, a filename check, and string obfuscation. The\r\nfollowing sections analyze each technique.\r\nImports and API resolution\r\nThe newest Zloader samples only import a few functions from the kernel32 library. The remaining imports are\r\nresolved at runtime using checksums to obfuscate the functions that are used. This technique, already present in\r\nolder versions, changes its implementation, adding an XOR constant which changes between samples. Python\r\ncode that replicates the API hashing algorithm is shown below.\r\ndef calculate_checksum(func_name, xor_constant):\r\n checksum = 0\r\n for element in func_name.upper():\r\n checksum = 16 * checksum - (0 - (ord(element)+1))\r\n if checksum \u0026 0xf0000000 != 0:\r\n checksum = ((((checksum \u0026 0xf0000000) \u003e\u003e 24) ^ checksum) \u0026 0xfffffff)\r\n return checksum ^ xor_constant\r\nCode sample available on GitHub.\r\nJunk code \r\nSimilar to previous versions, Zloader uses custom obfuscation. The new version of Zloader adds junk code that\r\nconsists of various arithmetic operations, as shown in Figure 1 below.\r\nhttps://www.zscaler.com/blogs/security-research/zloader-no-longer-silent-night\r\nPage 1 of 6\n\nFigure 1. Example Zloader 2.1 junk code\r\nIn Figure 1, the instructions inside the red box are the junk code.\r\nAnti-sandbox\r\nEach Zloader sample expects to be executed with a specific filename. If the filename does not match what the\r\nsample expects, it will not execute further. This could evade malware sandboxes that rename sample files. Figure\r\n2 shows an example of a Zloader sample that expects its filename to be CodeForge.exe.\r\nFigure 2. Example of Zloader’s anti-analysis filename check\r\nThreatLabz has observed Zloader use the following filenames:\r\nCodeForge.exe\r\nCyberMesh.exe\r\nEpsilonApp.exe\r\nFusionBeacon.exe\r\nFusionEcho.exe\r\nIonBeacon.dll\r\nhttps://www.zscaler.com/blogs/security-research/zloader-no-longer-silent-night\r\nPage 2 of 6\n\nIonPulse.exe\r\nKineticaSurge.dll\r\nQuantumDraw.exe\r\nSpectraKinetic.exe\r\nUltraApp.exe\r\nString obfuscation\r\nSimilar to prior versions, Zloader implements a string obfuscation algorithm for some of the malware’s important\r\nstrings such as registry paths, DLL names, and the DGA’s top-level domain (TLD) using XOR with a hardcoded\r\nkey. Python code that replicates the string obfuscation algorithm is shown below:\r\ndef str_deobfuscate(enc_bin, enc_key):\r\n res = ''\r\n for i, element in enumerate(enc_bin):\r\n res += chr( ((element ^ 0xff) \u0026 (enc_key[i % len(enc_key)])) | (~(enc_key[i % len(enc_key)]) \u0026 element))\r\n return res\r\nCode sample available on GitHub. \r\nThe encryption key differs between samples and is also hardcoded in the .rdata section as shown in Figure 3\r\nbelow.\r\nFigure 3. Example string obfuscation key used by Zloader\r\nA list of Zloader’s obfuscated strings is shown in the Appendix.\r\nStatic configuration encryption and structure\r\nThe Zloader static configuration is still encrypted using RC4 with a hardcoded alphanumeric key, but the structure\r\nis slightly different. The botnet ID, campaign name, and command-and-control servers (C2s) are set at fixed\r\noffsets, in addition to an RSA public key that replaces the old RC4 key that was used for network encryption.\r\nThreatLabz has observed 15 unique new Zloader samples and all of them have the same RSA public key, likely\r\nindicating there is currently only a single threat actor using the malware.\r\nhttps://www.zscaler.com/blogs/security-research/zloader-no-longer-silent-night\r\nPage 3 of 6\n\nAn example Zloader static configuration is shown below.\r\n00000000 00 00 00 00 42 69 6e 67 5f 4d 6f 64 35 00 00 00 |....Bing_Mod5...|\r\n00000010 00 00 00 00 00 00 00 00 00 4d 31 00 00 00 00 00 |.........M1.....|\r\n00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 68 74 |..............ht|\r\n00000030 74 70 73 3a 2f 2f 61 64 73 6c 73 74 69 63 6b 65 |tps://adslsticke|\r\n00000040 72 68 69 2e 77 6f 72 6c 64 00 00 00 00 00 00 00 |rhi.world.......|\r\n00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|\r\n*\r\n000002b0 00 00 00 00 00 00 00 00 02 00 00 00 01 00 00 00 |................|\r\n000002c0 2d 2d 2d 2d 2d 42 45 47 49 4e 20 50 55 42 4c 49 |-----BEGIN PUBLI|\r\n000002d0 43 20 4b 45 59 2d 2d 2d 2d 2d 0a 4d 49 47 66 4d |C KEY-----.MIGfM|\r\n000002e0 41 30 47 43 53 71 47 53 49 62 33 44 51 45 42 41 |A0GCSqGSIb3DQEBA|\r\n000002f0 51 55 41 41 34 47 4e 41 44 43 42 69 51 4b 42 67 |QUAA4GNADCBiQKBg|\r\n00000300 51 44 4b 47 41 4f 57 56 6b 69 6b 71 45 37 54 79 |QDKGAOWVkikqE7Ty|\r\n00000310 4b 49 4d 74 57 49 38 64 46 73 61 0a 6c 65 54 61 |KIMtWI8dFsa.leTa|\r\n00000320 4a 4e 58 4d 4a 4e 49 50 6e 52 45 2f 66 47 43 7a |JNXMJNIPnRE/fGCz|\r\n00000330 71 72 56 2b 72 74 59 33 2b 65 78 34 4d 43 48 45 |qrV+rtY3+ex4MCHE|\r\n00000340 74 71 32 56 77 70 70 74 68 66 30 52 67 6c 76 38 |tq2Vwppthf0Rglv8|\r\n00000350 4f 69 57 67 4b 6c 65 72 49 4e 35 50 0a 36 4e 45 |OiWgKlerIN5P.6NE|\r\n00000360 79 43 66 49 73 46 59 55 4d 44 66 6c 64 51 54 46 |yCfIsFYUMDfldQTF|\r\n00000370 30 33 56 45 53 38 47 42 49 76 48 71 35 53 6a 6c |03VES8GBIvHq5Sjl|\r\n00000380 49 7a 37 6c 61 77 75 77 66 64 6a 64 45 6b 61 48 |Iz7lawuwfdjdEkaH|\r\n00000390 66 4f 6d 6d 75 39 73 72 72 61 66 74 6b 0a 49 39 |fOmmu9srraftk.I9|\r\n000003a0 67 5a 4f 38 57 52 51 67 59 31 75 4e 64 73 58 77 |gZO8WRQgY1uNdsXw|\r\n000003b0 49 44 41 51 41 42 0a 2d 2d 2d 2d 2d 45 4e 44 20 |IDAQAB.-----END |\r\n000003c0 50 55 42 4c 49 43 20 4b 45 59 2d 2d 2d 2d 2d 0a |PUBLIC KEY-----.|\r\n000003d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|\r\n*\r\n000003fc\r\nDomain generation algorithm\r\nWhen the primary C2 server is not available, Zloader reverts to a DGA. The DGA algorithm has changed in the\r\nlatest version and no longer contains a different seed per botnet. Python code that replicates Zloader’s new DGA\r\nalgorithm is shown below.\r\nimport time\r\nfrom datetime import datetime, timedelta\r\ndef uint32(val):\r\n return val \u0026 0xffffffff\r\ndef get_dga_time():\r\n now = datetime.now()\r\n ts = time.time()\r\nhttps://www.zscaler.com/blogs/security-research/zloader-no-longer-silent-night\r\nPage 4 of 6\n\nutc_offset = (datetime.fromtimestamp(ts) - datetime.utcfromtimestamp(ts)).total_seconds() / 3600\r\n midnight = now.replace(hour=0, minute=0, second=0, microsecond=0)\r\n midnight = midnight + timedelta(hours=utc_offset)\r\n return int(midnight.timestamp())\r\ndef generate_zloader_dga_domains():\r\n domains = []\r\n t = get_dga_time()\r\n for i in range(32): # number of domains to generate\r\n domain = \"\"\r\n for j in range(20): # domain name length\r\n v = uint32(ord('a') + (t % 25 ))\r\n t = uint32(t + v)\r\n t = (t \u003e\u003e 24) \u0026 ((t \u003e\u003e 24) ^ 0xFFFFFF00) | uint32(t\r\nCode sample available on GitHub.\r\nThe code generates 32 domains per day by using the local system time at midnight (converted to UTC) as a seed.\r\nEach of the DGA domains have a length of 20 characters followed by the “.com” TLD.\r\nNetwork communications\r\nZloader continues to use HTTP POST requests to communicate with its C2 server. However, the network\r\nencryption is now using 1,024-bit RSA with RC4 and the Zeus “visual encryption” algorithms. Zloader uses the\r\ncustom Zeus BinStorage format where the first 128 bytes are the RSA encrypted RC4 key (32 random bytes) and,\r\nthe remaining bytes are encrypted with the RC4 key and visual encryption as shown in Figure 4:\r\nFigure 4. Zloader BinStorage object for a hello message (prior to encryption)\r\nhttps://www.zscaler.com/blogs/security-research/zloader-no-longer-silent-night\r\nPage 5 of 6\n\nThe Zeus BinStorage structure uses an ID integer value to represent the information stored, followed by the length\r\nand data. The BinStorage ID values in this example are shown in Table 1.\r\nValue (Decimal) Value (Hexadecimal) Description\r\n10002 0x2712 Botnet ID\r\n10025 0x2729 Campaign ID\r\n10001 0x2711 Bot ID\r\n10003 0x2713 Malware version\r\n10006 0x2716 Unknown flag (set to 0x1)\r\nTable 1. Zloader BinStorage hello message fields\r\nThreatLabz has observed samples containing the following botnet IDs:\r\nBing_Mod2\r\nBing_Mod3\r\nBing_Mod4\r\nBing_Mod5\r\nAll of the campaign IDs have been set to the value M1.\r\nExplore more Zscaler blogs\r\nSource: https://www.zscaler.com/blogs/security-research/zloader-no-longer-silent-night\r\nhttps://www.zscaler.com/blogs/security-research/zloader-no-longer-silent-night\r\nPage 6 of 6",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"ETDA",
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.zscaler.com/blogs/security-research/zloader-no-longer-silent-night"
	],
	"report_names": [
		"zloader-no-longer-silent-night"
	],
	"threat_actors": [],
	"ts_created_at": 1775433973,
	"ts_updated_at": 1775826748,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/9e1e2c3b47b47d5d7199ee3c88d5deb07dde1c7e.pdf",
		"text": "https://archive.orkl.eu/9e1e2c3b47b47d5d7199ee3c88d5deb07dde1c7e.txt",
		"img": "https://archive.orkl.eu/9e1e2c3b47b47d5d7199ee3c88d5deb07dde1c7e.jpg"
	}
}