{
	"id": "b3f955a2-47b5-4bf9-8613-0af0f6a12d29",
	"created_at": "2026-04-06T00:10:00.698105Z",
	"updated_at": "2026-04-10T03:36:13.585968Z",
	"deleted_at": null,
	"sha1_hash": "7cb6b9603141f0aa416c5944f2882ad88d1800fb",
	"title": "The Domain Generation Algorithm of BazarLoader - A DGA based on the Emercoin TLD .bazar",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 107197,
	"plain_text": "The Domain Generation Algorithm of BazarLoader - A DGA based\r\non the Emercoin TLD .bazar\r\nArchived: 2026-04-05 21:26:44 UTC\r\nEdit 2020-07-19: Cybereason published an excellent article A Bazar of Tricks: Following Team9’s Development\r\nCycles. They only show the seeding part of the domain generation algorithm, however, the listing of generated\r\nbazar domains matches the algorithm in this blog post (apart from the first two domains alztwfdicu.bazar and\r\nocgjqlaspr.bazar which are hardcoded). The article shows that the DGA is part of Bazar Loader, which will try\r\nto download Bazar Backdoor. I therefore renamed most instances of BazarBackdoor to BazarLoader.\r\nEdit 2020-07-14: I have documented some additions to the DGA of BazarLoader:\r\nThere exists a version of BazarLoader with a faulty DGA. I documented it in a separate blog post.\r\nThe attackers registered four of the DGA domains, which @Securityinbits long before I published this\r\npost. I listed them here.\r\nThe malware transforms the A RR of registered DGA domains, see the paragraph on sinkholing\r\nBazarLoader (also known as Bazar Loader, Bazar Backdoor or Team9 Backdoor) is a module of the dreaded\r\nTrickBot Trojan. It is mostly used to gain a foothold in compromised enterprise networks 1 \r\n2\r\n \r\n3\r\n \r\n4\r\n. The malware is\r\nnamed after the C\u0026C domains with top level domain .bazar. This TLD is provided by EmerDNS, a peer-to-peer\r\ndecentralized domain name system in OpenNIC. This makes it very difficult, if not impossible, for law\r\nenforcement to take over these domains.\r\nBazarLoader has been using a handful of hard-coded domains such as bestgame.bazar , forgame.bazar or\r\nnewgame.bazar in the past, but today a sample was uploaded to Virustotal that tries a plethora of domains such\r\nas:\r\necfgjkehhgjm.bazar\r\nafhhjkakjhjm.bazar\r\nbeggklbjigkn.bazar\r\ncfhhjkckjhjm.bazar\r\nbdehklbighkn.bazar\r\ndcegjldhggjn.bazar\r\nadggjkaiigjm.bazar\r\ndcghkldhihkn.bazar\r\ndehhikdjjhim.bazar\r\nceegkkcjggkm.bazar\r\neeegjkejggjm.bazar\r\ncfehjkckghjm.bazar\r\ncehhimcjjhio.bazar\r\nddfgjldihgjn.bazar\r\nafhijlakjijn.bazar\r\nhttps://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nPage 1 of 11\n\nccfgimchhgio.bazar\r\neefhklejhhkn.bazar\r\nacgiimahiiio.bazar\r\necghjkehihjm.bazar\r\ncehiklcjjikn.bazar\r\nThese look like algorithmically generated — and it turns out they are. This blog post shows how the underlying\r\ndomain generation algorithm works.\r\nSample\r\nI analysed the aforementioned sample from Virustotal:\r\nMD5\r\nfdffbfa1380ab1a0ee2e26ff1be432b1\r\nSHA1\r\n5a004286c5b97afd97beec4b1332777c494d6ff1\r\nSHA256\r\ne77e27630277a31276539c379671f54095d6b735f0568a3c457ac6a189c4c5b4\r\nSize\r\n288 KB (295424 Bytes)\r\nCompile Timestamp\r\n2020-06-12 09:35:14 UTC\r\nLinks\r\nMalwareBazaar, Cape, VirusTotal\r\nFilenames\r\nBthCxn.exe, v86.exe_ (VirusTotal)\r\nDetections\r\nMalwareBazaar: BazaLoader, Virustotal: 23/76 as of 2020-07-10 04:00:39 - Trojan:Win32/Trickbot.KB\r\n(Microsoft), Trojan.Trickbot!8.E313 (CLOUD) (Rising)\r\nMany AV classify the sample as malicious, but only Microsoft and Rising also name the sample, both as Trickbot\r\n— which is at correct in the broader sense. The binary unpacks to this:\r\nMD5\r\n599b72d329b4b876390ae0567991da01\r\nSHA1\r\na8128b487bf6efd80b78c453e24a3447208008dd\r\nSHA256\r\n6b24ebfb84665cb844410ec9f948cfcf7f6d08f4ede16d52930c53236390848f\r\nSize\r\n141 KB (144896 Bytes)\r\nCompile Timestamp\r\n2020-06-12 09:34:11 UTC\r\nhttps://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nPage 2 of 11\n\nLinks\r\nMalwareBazaar, VirusTotal\r\nFilenames\r\nnone\r\nDetections\r\nVirustotal: 10/75 as of 2020-07-10 13:52:07\r\nThe detection for this sample is worse and none of the AV products assigns a non-generic name. The sample will\r\nfinally inject the following executable, which only 3 out of 76 products even classify as malicious.\r\nMD5\r\nd1c4d25673be94db051dcd5271c64ae1\r\nSHA1\r\ncc4d30072bbd16fbdc387eb546aeb4dc38a5ea4a\r\nSHA256\r\nb4b7f0fd63cda1269ee937fa398fb80b6655d205066e6593fefceda7e3b09f6b\r\nSize\r\n132 KB (135168 Bytes)\r\nCompile Timestamp\r\n2020-06-11 11:16:31 UTC\r\nLinks\r\nMalwareBazaar,VirusTotal\r\nFilenames\r\nnone\r\nDetections\r\nVirustotal: 3/76 as of 2020-07-10 13:52:05\r\nDGA Disassembly\r\nThe domain generation algorithm of BazarLoader is in a single function, including seeding (click to enlarge):\r\nhttps://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nPage 3 of 11\n\nhttps://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nPage 4 of 11\n\nThe algorithm roughly consists of these three steps:\r\n1. Determine the first six letters of the second level domain at random.\r\n2. Generate a seed based on the current date\r\n3. Calculate the last six letters of the second level domain based on the first six and the seed.\r\nStep 1: First Six Letters\r\nThe (simplified) decompilation of the first step is as follows:\r\ni = 0;\r\ndo\r\n{\r\n r = (GetTickCount() % 25) / (i + 6);\r\n i_1 = i++;\r\n *domain++ = 2 * i_1 + r + 'a';\r\n}\r\nwhile ( i \u003c 6 );\r\nThe function GetTickCount usually doesn’t bode well for DGAs: since this functions is largely unpredictable, it\r\nalmost always means that the generated domains will be unpredictable as well. However, this algorithm is\r\ndifferent. The tick count is mapped to a value between 0 and 24, which is then divided by 6+i. The division\r\nshrinks down the range of numbers, and ultimately the range of potential letters. The character set is also offset by\r\ndouble the loop index, leading to these choices of letters:\r\nindex random number range potential letters\r\n0 0–4 abcde\r\n1 0–3 cdef\r\n2 0–3 efgh\r\nhttps://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nPage 5 of 11\n\nindex random number range potential letters\r\n3 0–2 ghi\r\n4 0–2 ijk\r\n5 0–2 klm\r\nSo even though the exact letters can’t be predicted, there are only 2160 combinations. Since the malware\r\ncontinuously tries to contact newly generated domains, registering a few of the 2160 domains is probably enough\r\nto get lucky with GetTickCount within a couple of minutes of malware runtime.\r\nStep 2: Seeding\r\nSeeding is based on on the current date, which is determined by GetDateFormatA .\r\nif ( !seeding_done )\r\n{\r\n GetDateFormatA(LOCALE_INVARIANT, 0, 0i64, 0i64, lpCurrentDate, 24);\r\n szMonth = lpCurrentDate[0];\r\n szYear = *\u0026lpCurrentDate[3];\r\n v15 = 0;\r\n v17 = 0;\r\n str_to_int = resolve_api(0i64, 19i64, 2865918183i64, 534i64);\r\n if ( str_to_int )\r\n nYear = str_to_int(\u0026szYear);\r\n else\r\n nYear = 0;\r\n str_to_int_0 = resolve_api(0i64, 19i64, 2865918183i64, 534i64);\r\n if ( str_to_int_0 )\r\n nMonth = str_to_int_0(\u0026szMonth);\r\n else\r\n nMonth = 0;\r\n LODWORD(nYearMinus18) = nYear - 18;\r\n wnsprintfA(szSeedStr, 7, \"%.2d%d\", (12 - nMonth), nYearMinus18);\r\n seeding_done = 1;\r\n}\r\nThe function GetDateFormatA with LOCALE_INVARIANT locale returns the current date formatted as\r\n\u003cmonth\u003e/\u003cday\u003e/\u003cyear\u003e , so for example 07/10/2020 for July 10, 2020. The month and year are taken from this\r\nstring and converted into integers. The month is then turned into a two-digit number by calculating a = 12 -\r\nmonth and padding it with zero if necessary. The year is transformed into a four-digit number according to b =\r\nyear - 18 . The two values are then concatenated into a string. For example, July 2020 turns into 052002 .\r\nStep 3: Last Six Letters\r\nhttps://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nPage 6 of 11\n\nThe last six characters of the second level domain are based on the seed and the first six letters:\r\nj = 6;\r\n[...]\r\nszDomainPlusSix = szDomain + 6;\r\ndo\r\n{\r\n ascii_code = *(szDomainPlusSix - 6) + szDomainPlusSix[szSeedStr - szDomain - 6] - '0';\r\n if ( ascii_code \u003c 'a' )\r\n ascii_code = 'z';\r\n *szDomainPlusSix++ = ascii_code;\r\n --j;\r\n}\r\nwhile ( j );\r\nszDomain[12] = 0;\r\nThis simply treats each character of the seed string as an integer, and uses that to offset the characters of the first\r\nsix letters to form the last six letters. For instance, let’s look at the seed string 052002 applied to the randomly\r\npicked first six letters cfhiilc :\r\n1. Add 0 to c to get c .\r\n2. Add 5 to f to get k .\r\n3. Add 2 to h to get j .\r\n4. Add 0 to i to get i .\r\n5. Add 0 to i to get i .\r\n6. Add 2 to l to get n .\r\nThe malware’s check if the letter falls before a is actualy not necessary, as the offset is always positive between\r\n0 and 9. A check to see if the letter falls beyond z would be more reasonable, but is also unnecessary: the\r\n“largest” letter in the first half is “m”, which offset by 9 leads to “v”. The following image illustrates the\r\nprocedure:\r\nPython Reimplementation\r\nhttps://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nPage 7 of 11\n\nWhen implemented in Python, the DGA looks something like this:\r\nimport argparse\r\nfrom datetime import datetime\r\nfrom itertools import product\r\ndef dga(date):\r\n month = date.month\r\n year = date.year\r\n date_str = \"{0:02d}{1:04d}\".format(12-month, year-18)\r\n valid_chars = [\r\n \"abcde\",\r\n \"cdef\",\r\n \"efgh\",\r\n \"ghi\",\r\n \"ijk\",\r\n \"klm\"\r\n ]\r\n valid_chars = [list(_) for _ in valid_chars]\r\n for part1 in product(*valid_chars):\r\n domain = \"\".join(part1)\r\n for i, c in enumerate(part1):\r\n domain += chr(ord(c) + int(date_str[i]) )\r\n domain += \".bazar\"\r\n yield domain\r\nif __name__==\"__main__\":\r\n parser = argparse.ArgumentParser()\r\n parser.add_argument(\"-d\", \"--date\", help=\"date when domains are generated\")\r\n args = parser.parse_args()\r\n if args.date:\r\n d = datetime.strptime(args.date, \"%Y-%m-%d\")\r\n else:\r\n d = datetime.now()\r\n for domain in dga(d):\r\n print(domain)\r\nRegex\r\nThe possible letters per position is very limited. Assuming that the year is between 2020 and 2029, the domains\r\nmatch the following regular expression (Edit 2020-11-10: Fixed the regular expression, thanks to Luca Corbatto\r\nfor providing the correct regex):\r\nhttps://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nPage 8 of 11\n\n[a-e][c-f][e-h][g-i][i-k][k-m][a-f][c-o][g-j][g-i][i-l][k-v]\\.bazar\r\nCharacteristics\r\nThe following table summarizes the properties of BazarLoader’s DGA.\r\nproperty value\r\ntype\r\nTDD (time-dependent-deterministic), to some extend TDN (time-dependent non-deterministic)\r\ngeneration scheme arithmetic\r\nseed current date\r\ndomain change\r\nfrequency\r\nevery month\r\ndomains per day 2160\r\nsequence random selection, might pick domains multiple times\r\nwait time between\r\ndomains\r\nNone\r\ntop level domain .bazar\r\nsecond level characters a-v\r\nregex [a-e][c-f][e-h][g-i][i-k][k-m][a-f][c-o][g-j][i-k][k-m][k-v]\\.bazar\r\nsecond level domain\r\nlength\r\n12\r\nDomain to Seed\r\nSince the function to determine the second half of the domain is reversible, the month and year can be calculated\r\nfrom the domains. I wrote a small Javascript form that does just that. For those of you who block Javascript, here’s\r\na screenshot. The same code in Python can also be found on my GitHub page\r\nhttps://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nPage 9 of 11\n\nRegistered Domains\r\nAs far as I can tell, the attackers registered five domains using the Emercoin address\r\nETQERUknhW2A5cBmfHN4VBqL7VGiFnKQRh. Also see tweets by Brad @malware_traffic and Security-in-bits @Securityinbits:\r\ndate domain valid for\r\n2020-05-18 10:24:32 UTC cdghilckihin.bazar May 2020\r\n2020-05-18 10:24:32 UTC cefgilclhgin.bazar May 2020\r\n2020-07-03 11:08:26 UTC defikldjhikn.bazar July 2020\r\n2020-07-03 11:14:24 UTC aeehjkajghjm.bazar July 2020\r\n2020-07-14 14:13:16 UTC cdfhimcihhio.bazar July 2020\r\nSinkholing\r\nThe IP resource record of the DGA domains are XOR decrypted with key 0xFE to get the real IP of the C2\r\nservers. You can use this Javascript form to calculate the transformation.\r\n1. In-depth analysis of the new Team9 malware family ↩︎\r\n2. BazarBackdoor: TrickBot gang’s new stealthy network-hacking malware ↩︎\r\n3. TrickBot BazarLoader In-Depth ↩︎\r\n4. Group Behind TrickBot Spreads Fileless BazarBackdoor ↩︎\r\nhttps://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nPage 10 of 11\n\nSource: https://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nhttps://johannesbader.ch/blog/the-dga-of-bazarbackdoor/\r\nPage 11 of 11",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://johannesbader.ch/blog/the-dga-of-bazarbackdoor/"
	],
	"report_names": [
		"the-dga-of-bazarbackdoor"
	],
	"threat_actors": [
		{
			"id": "f8dddd06-da24-4184-9e24-4c22bdd1cbbf",
			"created_at": "2023-01-06T13:46:38.626906Z",
			"updated_at": "2026-04-10T02:00:03.043681Z",
			"deleted_at": null,
			"main_name": "Tick",
			"aliases": [
				"G0060",
				"Stalker Taurus",
				"PLA Unit 61419",
				"Swirl Typhoon",
				"Nian",
				"BRONZE BUTLER",
				"REDBALDKNIGHT",
				"STALKER PANDA"
			],
			"source_name": "MISPGALAXY:Tick",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "54e55585-1025-49d2-9de8-90fc7a631f45",
			"created_at": "2025-08-07T02:03:24.563488Z",
			"updated_at": "2026-04-10T02:00:03.715427Z",
			"deleted_at": null,
			"main_name": "BRONZE BUTLER",
			"aliases": [
				"CTG-2006 ",
				"Daserf",
				"Stalker Panda ",
				"Swirl Typhoon ",
				"Tick "
			],
			"source_name": "Secureworks:BRONZE BUTLER",
			"tools": [
				"ABK",
				"BBK",
				"Casper",
				"DGet",
				"Daserf",
				"Datper",
				"Ghostdown",
				"Gofarer",
				"MSGet",
				"Mimikatz",
				"Netboy",
				"RarStar",
				"Screen Capture Tool",
				"ShadowPad",
				"ShadowPy",
				"T-SMB",
				"down_new",
				"gsecdump"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "d4e7cd9a-2290-4f89-a645-85b9a46d004b",
			"created_at": "2022-10-25T16:07:23.419513Z",
			"updated_at": "2026-04-10T02:00:04.591062Z",
			"deleted_at": null,
			"main_name": "Bronze Butler",
			"aliases": [
				"Bronze Butler",
				"CTG-2006",
				"G0060",
				"Operation ENDTRADE",
				"RedBaldNight",
				"Stalker Panda",
				"Stalker Taurus",
				"Swirl Typhoon",
				"TEMP.Tick",
				"Tick"
			],
			"source_name": "ETDA:Bronze Butler",
			"tools": [
				"8.t Dropper",
				"8.t RTF exploit builder",
				"8t_dropper",
				"9002 RAT",
				"AngryRebel",
				"Blogspot",
				"Daserf",
				"Datper",
				"Elirks",
				"Farfli",
				"Gh0st RAT",
				"Ghost RAT",
				"HOMEUNIX",
				"HidraQ",
				"HomamDownloader",
				"Homux",
				"Hydraq",
				"Lilith",
				"Lilith RAT",
				"McRAT",
				"MdmBot",
				"Mimikatz",
				"Minzen",
				"Moudour",
				"Muirim",
				"Mydoor",
				"Nioupale",
				"PCRat",
				"POISONPLUG.SHADOW",
				"Roarur",
				"RoyalRoad",
				"ShadowPad Winnti",
				"ShadowWali",
				"ShadowWalker",
				"SymonLoader",
				"WCE",
				"Wali",
				"Windows Credential Editor",
				"Windows Credentials Editor",
				"XShellGhost",
				"XXMM",
				"gsecdump",
				"rarstar"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434200,
	"ts_updated_at": 1775792173,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/7cb6b9603141f0aa416c5944f2882ad88d1800fb.pdf",
		"text": "https://archive.orkl.eu/7cb6b9603141f0aa416c5944f2882ad88d1800fb.txt",
		"img": "https://archive.orkl.eu/7cb6b9603141f0aa416c5944f2882ad88d1800fb.jpg"
	}
}