{
	"id": "bb95c115-b565-440e-bb00-844a18be71ed",
	"created_at": "2026-04-06T00:13:44.368745Z",
	"updated_at": "2026-04-10T03:20:43.30692Z",
	"deleted_at": null,
	"sha1_hash": "d4aeea27e2e308d3f31cb57c4725a8288206955c",
	"title": "Three Variants of Murofet's DGA",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 67372,
	"plain_text": "Three Variants of Murofet's DGA\r\nArchived: 2026-04-05 16:33:30 UTC\r\nMurofet, also called LICAT, is a member of the ZeuS family [1], [2], [3]. It uses a Domain Generation Algorithm\r\n(DGA) to determine the current C2 domain names. There exist at least three different versions of Murofet’s DGA,\r\nsome of which I couldn’t find reimplementations online. In this short blog post I list the three variants that I\r\nlooked at and discuss the properties of each. Although all versions share a similar algorithm, the resulting domains\r\nare very different.\r\nThe DGAs\r\nAll DGAs share the following procedure:\r\n1. Pick a start index based by multiplying the current minute by 17\r\n2. Concatenate the following values:\r\n1. year + 0x30 (one byte)\r\n2. month (one byte)\r\n3. day rounded to the frequency freq (one byte)\r\n4. (variant 2 only) value 0 (zero or one byte)\r\n5. the index (four bytes); variant 2 rounds the index to multiples of 2.\r\n3. XOR the resulting 7 to 8 bytes with an optional four byte key. Only variant 2 uses a key.\r\n4. MD5 hash the 7 to 8 bytes.\r\n5. Iterate over the 16 bytes of the md5 hash and determine characters of the second level domain based on the\r\nbytes.\r\n6. Append a top level domain based on the current index.\r\n7. Increment the index, taking the result modulo 60*17 = 1020. Repeat from step 2 up to 800 times.\r\nThe following pseudo-code summarizes the DGA:\r\nSET startindex = minute*17\r\nSET tlds to array of top level domains\r\nFOR i in 0 TO 799\r\n index = (startindex + i) % (60*17)\r\n hash = md5( XOR_key(\r\n (year \u0026 0xFF) + 0x30 .\r\n month .\r\nhttps://bin.re/blog/three-variants-of-murofets-dga/\r\nPage 1 of 5\n\nfloor(date.day/freq)*freq .\r\n optionally_round(index)\r\n )\r\n )\r\n domain = \"\"\r\n FOREACH byte in hash DO\r\n append zero or more characters to *domain* based on *byte*\r\n ENDFOR\r\n FOR index = 0 TO LEN(tlds) - 1\r\n tld = tlds[j]\r\n m = len(tlds) - index\r\n IF i % m = 0 THEN\r\n append *tld* to *domain*\r\n break\r\n ENDFOR\r\n PRINT domain\r\nENDFOR\r\nThe main difference between the DGA variants is how they generate second level characters based on the md5\r\nbytes.\r\nVariant 1\r\nVariant 1 doesn’t use a key. Domains change every week (freq = 7). It generates the second level characters with\r\nthe following loop:\r\nFOREACH byte in hash DO\r\n d = (byte \u0026 0x1F) + 'a'\r\n c = (byte \u003e\u003e 3) + 'a'\r\n IF d != c THEN\r\n IF d \u003c= 'z' THEN\r\n domain += d\r\n IF c \u003c= 'z' THEN\r\n domain += c\r\nENDFOR\r\nThe top level domains are .ru, .biz, .info, .org, .net, and .com. A complete implementation in Python can be found\r\nhere.\r\nVariant 2\r\nVariant 2 uses a key. Keys observed in the wild are for example 0xD6d7A4BE and 0xDEADC2DE. Variant 2 has\r\na granularity of 1 day and generates the second level characters with the following loop:\r\nhttps://bin.re/blog/three-variants-of-murofets-dga/\r\nPage 2 of 5\n\nFOREACH byte in hash DO\r\n tmp = (byte \u0026 0xF) + (byte \u003e\u003e 4) + 'a'\r\n IF tmp \u003c= 'z' THEN\r\n domain += tmp\r\nENDFOR\r\nThe top level domains are .biz, .info, .org, .net, and .com. A complete implementation in Python can be found here.\r\nVariant 3\r\nVariant 3 does not use a key. Domains change every 7 days. Second level characters are generated as follows:\r\nFOREACH byte in hash DO\r\n a = (byte \u0026 0xF) + 'a'\r\n b = (byte \u003e\u003e 4) + 'q'\r\n IF b \u003e 'z' THEN\r\n b = b - 'J'\r\n c = (a % 10) + '0'\r\n ELSE\r\n c = None\r\n domain += a\r\n domain += b\r\n IF c THEN\r\n domain += c\r\nENDFOR\r\nThe top level domains are .ru, .biz, .info, .org, .net, and .com. A complete implementation in Python can be found\r\nhere.\r\nProperties\r\nThe properties of the domains of the three variants are as follows:\r\nProperty Variant 1 Variant 2 Variant 3\r\nGranularity 1 week 1 day 1 week\r\nKeyed no yes no\r\nTLDs\r\n.ru, .biz, .info,\r\n.org, .net, .com\r\n.biz, .info, .org, .net, .com\r\n.ru, .biz, .info, .org,\r\n.net, .com\r\nSLD\r\ncharacters\r\na-z a-z a-z, 0-9\r\nhttps://bin.re/blog/three-variants-of-murofets-dga/\r\nPage 3 of 5\n\nProperty Variant 1 Variant 2 Variant 3\r\nSLD length\r\nrange\r\n0 - 32 0 - 16 32 - 48\r\nSLD expected\r\nlength\r\n25.2 15.1 38\r\nSLD\r\nproperties\r\nuniformly\r\ndistributed\r\np the most frequent, dropping of on both\r\nsides (a being very uncommon). Domains\r\nappear in pairs.\r\ndigits appear in pairs\r\nonly, and only from 10\r\nto 69\r\nExamples\r\nVariant 1\r\nThe second level characters are more or less equally distributed. The domains can’t be easily attributed to Murofet\r\nsimply looking at them:\r\ngiywswshrgxcvoqgvrkthmfa.ru\r\nxaiqpbprgymbvrwmzgiyprgdsk.com\r\namgqgularpzxeapztxenbx.net\r\npfscijbmthyfiyjgergugtkbqyh.org\r\nxglfcmsgorvwfilhmzlcxxvkfege.info\r\nrcteqwkequojntibvfyfaluwh.biz\r\nmjfqylbiaunffuaeunzdqdwscu.ru\r\nqobeylpxgpfknlptukyddqvklztg.com\r\nrgwgizukficdgetwsxovtcknwkfm.info\r\nbetgyaeswxorwcvsdezdupbmb.org\r\nVariant 2\r\nThe second level characters are noticeably more frequent around p. The lengths are 14 - 16, seldom much shorter.\r\nAlso domains come in pairs:\r\nvxzyptrgrsndon.biz\r\nvxzyptrgrsndon.com\r\ngpkfnvjuvvoyqpv.net\r\ngpkfnvjuvvoyqpv.org\r\nimjfpqgmjtdlojn.info\r\nimjfpqgmjtdlojn.biz\r\nrepkmqpzfilmwzf.org\r\nrepkmqpzfilmwzf.com\r\nxugoslqquofodj.info\r\nxugoslqquofodj.org\r\nhttps://bin.re/blog/three-variants-of-murofets-dga/\r\nPage 4 of 5\n\nThe DGA not only changes domain sets every day (compared to weekly for variant 1 and 3), but also supports\r\nvirtually unlimited distinct sets of domain because of the key.\r\nVariant 3\r\nIn contrast to the first two variants, the second level characters also contain digits. Digits always appear as tuples,\r\nand are always between 10 and 69 in value. The length of the sld is at least 32, and can go up to 48:\r\ngui45gzgzmtbtp22c59fxatf62k47bvmzhwfq.ru\r\no21aua67pqpym49g33mqf62b28m39guixbtd50cv.com\r\nawgyg13nva57b48p52g23j26eqkxjzl28e51nqn20.net\r\npscriubwkzh34fui45j56gsb48g13g53dvbyit.org\r\nhtlscwctoyf22fupvhwjvc59h64l28fvfsgs.info\r\nbrpzeym69gveyexjwoziqf42f32fqove21lt.biz\r\nesmum69fyivbua17nsf12ase61n30dynrgzc19.ru\r\naxbsivpxhtpskwmvnxpzevirdyfvl38dt.com\r\nbtgti35evfuc59mrgsd20c69h44o11drkwgvfw.info\r\nbsd40g33asc29o21oyczgrfzdsjre41pqmqcz.org\r\nSource: https://bin.re/blog/three-variants-of-murofets-dga/\r\nhttps://bin.re/blog/three-variants-of-murofets-dga/\r\nPage 5 of 5",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://bin.re/blog/three-variants-of-murofets-dga/"
	],
	"report_names": [
		"three-variants-of-murofets-dga"
	],
	"threat_actors": [],
	"ts_created_at": 1775434424,
	"ts_updated_at": 1775791243,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/d4aeea27e2e308d3f31cb57c4725a8288206955c.pdf",
		"text": "https://archive.orkl.eu/d4aeea27e2e308d3f31cb57c4725a8288206955c.txt",
		"img": "https://archive.orkl.eu/d4aeea27e2e308d3f31cb57c4725a8288206955c.jpg"
	}
}