{
	"id": "143d9887-e893-45ce-a94f-14bc5c1a20f6",
	"created_at": "2026-04-10T03:22:00.799771Z",
	"updated_at": "2026-04-10T13:12:13.567827Z",
	"deleted_at": null,
	"sha1_hash": "1e7326381361c891ec32f73fca829cf9e3c5fc8f",
	"title": "MetaStealer: String Decryption and DGA overview",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1447910,
	"plain_text": "MetaStealer: String Decryption and DGA overview\r\nBy Jason Reaves\r\nPublished: 2023-05-09 · Archived: 2026-04-10 02:35:35 UTC\r\n5 min read\r\nMay 9, 2023\r\nBy: Jonathan McCay, Joshua Platt and Jason Reaves\r\nUnit42[1] recently tweeted about a campaign starting with a malicious email link that downloads a OneNote file\r\nused to drop and execute MetaStealer. While investigating the MetaStealer sample[2], we noticed it attempts to\r\nconnect to multiple domains that seemed to be randomly named. After landing on the C2 routine, instead of\r\ndecrypting a static list of servers, the sample used a domain generation algorithm[3], (DGA) to derive the list.\r\nPredominantly used as a fall back mechanism, a domain from the DGA can be registered to communicate when\r\nthe primary C2s are not available. The use of a DGA as a primary method of contacting the threat actor’s\r\ninfrastructure is interesting.\r\nSample:\r\nPress enter or click to view image in full size\r\nString Decryption:\r\nOn top of the MetaStealer binary being highly obfuscated, the author inserted garbage code while also encoding\r\nthe important onboard strings. The encoding used has been previously mentioned by NCC[4], but a lack of listing\r\nof the decoded strings in existing research was noticed. The strings are organized as DWORD values and pushed\r\nonto the stack along with the XOR key:\r\nPress enter or click to view image in full size\r\nhttps://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nPage 1 of 11\n\nThe PXOR instruction allows for using 64 bit(MMX) or 128 bit(XMM) length operands. In this case, you can see\r\nthat most of the DWORD values are the same. This is because the encoded strings are NULL padded to make the\r\nlength fit. Ultimately, in the screen above, the data is just XOR encoded:\r\n\u003e\u003e\u003e a = struct.pack('\u003cIIII', 0x7D414F85, 0x677C8C64, 0x0AB4023C0, 0x0FF480D71)\r\n\u003e\u003e\u003e b = struct.pack('\u003cIIII', 0x73837AB, 0x677C8C64, 0x0AB4023C0, 0x0FF480D71)\r\n\u003e\u003e\u003e a = bytearray(a)\r\n\u003e\u003e\u003e b = bytearray(b)\r\n\u003e\u003e\u003e for i in range(len(a)):\r\n... a[i] ^= b[i]\r\n...\r\n\u003e\u003e\u003e a\r\nbytearray(b'.xyz\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\r\nAttempting to decode all or the majority of the strings in an automatic manner would require finding the relevant\r\nblocks of code. After some investigation, it seems longer strings use the VPXOR instruction, which can leverage\r\n128 bit(XMM) or 256 bit(YMM) length operands.\r\nPress enter or click to view image in full size\r\nhttps://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nPage 2 of 11\n\nA quick and dirty way to decode strings is to find all the PXOR and VPXOR instructions and then walk\r\nbackwards to find all the DWORD stack loads to get most of the strings decoded.\r\nrule_source = '''\r\nrule meta_s\r\n{\r\n meta:\r\n author = \"sysopfb\"\r\n strings:\r\n $snippet1 = {66 0? ef}\r\n $snippet2 = {c5 ?? ef}\r\nhttps://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nPage 3 of 11\n\ncondition:\r\n ($snippet1 or $snippet2)\r\n}\r\n'''\r\ndef yara_scan(raw_data, rule_name):\r\n addresses = {}\r\n yara_rules = yara.compile(source=rule_source)\r\n matches = yara_rules.match(data=raw_data)\r\n for match in matches:\r\n if match.rule == 'meta_s':\r\n for item in match.strings:\r\n if item.identifier == rule_name:\r\n addresses[item.identifier] = item.instances\r\n return addresses\r\ndata = open(sys.argv[1], 'rb').read()\r\nret = []\r\nout = None\r\nlength_off = False\r\nsnippet = yara_scan(data, '$snippet1')\r\nprev_offset = 0\r\nfor val in snippet['$snippet1']:\r\n offset = val.offset\r\n test = data[prev_offset:offset]\r\n vals = re.findall(b'''\\xc7\\x85..\\xff\\xff....''',test)\r\n if vals != []:\r\n if len(vals) \u003e 8:\r\n temp = vals[-8:]\r\n else:\r\n temp = vals\r\n try:\r\n xdata = temp[0][-4:]\r\n xdata += temp[1][-4:]\r\n xdata += temp[2][-4:]\r\n xdata += temp[3][-4:]\r\n xkey = temp[4][-4:]\r\n xkey += temp[5][-4:]\r\n xkey += temp[6][-4:]\r\n xkey += temp[7][-4:]\r\n xdata = bytearray(xdata)\r\n xkey = bytearray(xkey)\r\n for i in range(len(xdata)):\r\n xdata[i] ^= xkey[i]\r\n print(b''.join(xdata.split(b'\\x00')))\r\n except:\r\n pass\r\n prev_offset = offset\r\nhttps://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nPage 4 of 11\n\nThen repeating a similar approach for PVXOR but accounting for larger assortment of strings, as previously\r\nmentioned this will only get a majority of the strings decoded but it is enough to determine that this stealer has\r\nmuch functionality including references to starting socks, backconnect, punching holes in the firewall and\r\ndetonating shellcode:\r\nDecrypted Strings:\r\nsys\r\nchrome\r\nfirefox\r\nedge\r\nnotepad\r\nip\r\npassword\r\ncmd\r\ninput\r\nFG Started\r\nshellcode\r\nmode\r\nResult:\r\nbc_addr\r\nport\r\nsocks started\r\n:1775\r\nuuid\r\n/api/client/new\r\nffox\r\ndir=in\r\nversion\r\n.xyz\r\nok\r\nos_crypt\r\nencrypted_key\r\nRtlGetVersion\r\nWindows 10\r\nWindows Vista\r\nWindows 7\r\nWindows 8\r\nWindows 8.1\r\nPro\r\naction\r\nstatus\r\npasswd\r\nloader_id\r\nfiles\r\ndur\r\nhttps://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nPage 5 of 11\n\nscript\r\nFALSE\r\ntype\r\ntask_result\r\n/tasks/collect\r\nROOT\r\nname\r\nvalue\r\nhost_key\r\nis_httponly\r\nhttponly\r\npath\r\nis_secure\r\nsecure\r\nexpires_utc\r\nencrypted_value\r\ndomain\r\nexpirationDate\r\nhost\r\nisHttpOnly\r\nisSecure\r\nexpiry\r\norigin_url\r\npassword_value\r\nurl\r\nntdll\r\nFile-Type\r\ncmd.exe\r\nmicrosoft\\\\windows\r\n/c \"echo start \"\" \"\r\nFailed to create task definition\r\naction=allow program=\"\r\n(\\\\d{1,3})\\\\.(\\\\d{1,3})\r\n\\\\Default\\\\Login Data\r\n\\\\Default\\\\Web Data\r\nA more exhaustive method for harvesting stack loaded and then decoded strings would be using a CPU emulator\r\nsimilar to how we showed against BazaLoader[5] previously.\r\nDomain Generation Algorithm:\r\nGet Jason Reaves’s stories in your inbox\r\nJoin Medium for free to get updates from this writer.\r\nRemember me for faster sign in\r\nhttps://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nPage 6 of 11\n\nAdditional domains the sample attempts to communicate with that appeared to be DGA.\r\nIDA: Pushing seed, (0x1234) before calling DGA\r\nIDA: DGA Routine\r\nhttps://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nPage 7 of 11\n\nConverted to Python:\r\nPress enter or click to view image in full size\r\nhttps://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nPage 8 of 11\n\nNow that the host names have been generated, the url can be built using the tld and uri from the decrypted strings.\r\nAn attempt to connect to each host will be made until a response is received. At the time of writing this, only one\r\nof the derived hostnames, (wgcuwcgociewewoo.xyz) would resolve. The ip it resolves to, (pictured below) also\r\ncontains another hostname that used to be active, (mmswgeewswyyywqk.xyz). Both of these domains are in the\r\nlist derived by the DGA when using the seed value 0x1234. Going back further we can find additional seed values\r\nbeing used at different time periods; 0xabc8, 0x9b2f, 0x7b2f, 0xc17a, 0x2f73 and 0x4b9a.\r\nWhen KELA[6] first observed the threat actor “_META_” offering a new stealer, it was marketed as having the\r\nsame functionality and panel as RedLine[7] Stealer. After seeing references to backconnect, socks, and loader id’s\r\nhttps://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nPage 9 of 11\n\nin the decrypted strings, we can see that the improvements made to this tool now offer more than just credential\r\ntheft.\r\nIOCs\r\nEndpoint:\r\npowershell -inputformat none -outputformat none –NonInteractive -Command Add-MpPreference -ExclusionE\r\nAppData\\Local\\Microsoft\\Windows\\hyper-v.exe\r\nhyper-v.ver\r\nNetwork:\r\nmmswgeewswyyywqk.xyz\r\nwgcuwcgociewewoo.xyz\r\nyiogqkksoyysqiky.xyz\r\nikuasuggwiewymsi.xyz\r\nuosqysascuwmqgyk.xyz\r\nuiouaqcqqcgueweg.xyz\r\nuawqgawkguwiqeyk.xyz\r\nkaewquswkswcmsim.xyz\r\naaycciywcgaqwkky.xyz\r\nmkgcsmogqewauaiw.xyz\r\n185.172.129.192\r\n185.203.116.71\r\n167.88.12.112\r\n[a-z]{16}.xyz:1775/api/client/new\r\n[a-z]{16}.xyz:1775/api/client/verify\r\n[a-z]{16}.xyz:1775/api/client_hello\r\n[a-z]{16}.xyz:1775/tasks/get_worker\r\n[a-z]{16}.xyz:1775/tasks/collect\r\n[a-z]{16}.xyz:1775/avast_update\r\nFull DGA dump for every currently known seed can be found at:\r\nhttps://github.com/sysopfb/open_mal_analysis_notes/tree/master/metastealer_dga\r\nReferences\r\n1: https://twitter.com/Unit42_Intel/status/1646940355936256000\r\n2: https://www.virustotal.com/gui/file/6cf8bfba1b221effcb1eccec0c91fb0906d0b8996932167f654680cb3ac53aac\r\n3: https://en.wikipedia.org/wiki/Domain_generation_algorithm\r\n4: https://research.nccgroup.com/2022/05/20/metastealer-filling-the-racoon-void/\r\nhttps://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nPage 10 of 11\n\n5: https://medium.com/walmartglobaltech/decrypting-bazarloader-strings-with-a-unicorn-15d2585272a9\r\n6: https://www.bleepingcomputer.com/news/security/new-blackguard-password-stealing-malware-sold-on-hacker-forums/\r\n7: https://www.proofpoint.com/us/blog/threat-insight/new-redline-stealer-distributed-using-coronavirus-themed-email-campaign\r\nSource: https://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nhttps://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd\r\nPage 11 of 11\n\nauthor strings: = \"sysopfb\"  \n$snippet1 = {66 0? ef} \n$snippet2 = {c5 ?? ef} \n   Page 3 of 11",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://medium.com/walmartglobaltech/metastealer-string-decryption-and-dga-overview-5f38f76830cd"
	],
	"report_names": [
		"metastealer-string-decryption-and-dga-overview-5f38f76830cd"
	],
	"threat_actors": [],
	"ts_created_at": 1775791320,
	"ts_updated_at": 1775826733,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/1e7326381361c891ec32f73fca829cf9e3c5fc8f.pdf",
		"text": "https://archive.orkl.eu/1e7326381361c891ec32f73fca829cf9e3c5fc8f.txt",
		"img": "https://archive.orkl.eu/1e7326381361c891ec32f73fca829cf9e3c5fc8f.jpg"
	}
}