{
	"id": "4116963d-815f-47c9-957a-f1849e6f444a",
	"created_at": "2026-04-06T01:30:01.316675Z",
	"updated_at": "2026-04-10T13:12:22.682271Z",
	"deleted_at": null,
	"sha1_hash": "147667a4c2352c6976b126c8526e3de8c1711045",
	"title": "Aura Stealer #1 36bytesmademelosemymind",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1735303,
	"plain_text": "Aura Stealer #1 36bytesmademelosemymind\r\nPublished: 2025-10-22 · Archived: 2026-04-06 01:06:56 UTC\r\nHello it’s me again\r\ntoday i gonna share my thought process and experience with aura stealer\r\ni was looking for some new malware with either a virtual machine or some neat obfuscation. lookin through some\r\nforums and news i saw a stealer named Aura Stealer mentioned couple of times. it does not seem to be a big\r\nstealer yet but lets see how lumma doing in the next couple of months with all the law enforcement on their asses.\r\nsooo i decided to focus on that one i got the hash from this blog https://foresiet.com/blog/aura-stealer-malware-analysis/\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 1 of 15\n\nthe random generated icon looks kinda cool tho :3\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 2 of 15\n\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 3 of 15\n\nafter seeing this i was a bit overwhelmed. to make sure this was the real aurastealer and not some packer/crypter i\r\nran it and dumped it with pd32 https://github.com/glmcdona/Process-Dump\r\nafter dumping we can see that the file went from 2.40MB to 408B which gave me hope\r\nthe binary is still obfuscated but much less. so after traveling some functions and examining the startin route i\r\nfound this.\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 4 of 15\n\nhere we can see the return a1 this means that a1 is most likely important ;3 so lets look into that.\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 5 of 15\n\nRunImage sounds good lets dig deeper.\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 6 of 15\n\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 7 of 15\n\nhere we can see some xoring from some byte array going on nice. That is a good indicator ^-^\r\ni assume this is decompression because of the size calculation and would fit into typical malware thingis.\r\nsize_compressed = 285851 - dword_1349000\r\nfirst i tried decrypt_xor -\u003e decompress but that did not work o_O sooo lets find out why:\r\nif we look into our first file (right picture) we can find the same unpacking mechanism like in our dumped file\r\n(left picture) just with another key and another byte array.\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 8 of 15\n\nlets write some python script to extract that.\r\n^ for the pattern\r\nimport sys\r\nimport pefile\r\nimport struct\r\nimport os\r\nPATTERNS = [\r\n {\r\n 'name': 'xor_decrypt_loop',\r\n 'asm': [\r\n 'movzx eax, byte ptr [eax + KEY_ADDR]',\r\n 'xor al, byte ptr [edx + BLOB_ADDR]'\r\n ],\r\n 'sig': '0F B6 80 ?? ?? ?? ?? 32 82 ?? ?? ?? ??',\r\n 'key_offset': 3,\r\n 'blob_offset': 9,\r\n 'size_check': {\r\n 'asm': 'cmp edx, SIZE',\r\n 'sig': '81 FA ?? ?? ?? ??',\r\n 'value_offset': 2,\r\n 'search_range': 0x100\r\n }\r\n }\r\n]\r\ndef parse_sig(sig):\r\n parts = sig.split()\r\n pat = []\r\n for p in parts:\r\n if p == '??':\r\n pat.append(None)\r\n else:\r\n pat.append(int(p, 16))\r\n return pat\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 9 of 15\n\ndef find_pat(data, sig):\r\n pat = parse_sig(sig)\r\n for i in range(len(data) - len(pat)):\r\n match = True\r\n for j, b in enumerate(pat):\r\n if b is not None and data[i + j] != b:\r\n match = False\r\n break\r\n if match:\r\n return i\r\n return -1\r\ndef find_addrs(exe_path):\r\n pe = pefile.PE(exe_path)\r\n \r\n for sec in pe.sections:\r\n if b'.text' not in sec.Name:\r\n continue\r\n \r\n data = sec.get_data()\r\n \r\n for pat in PATTERNS:\r\n off = find_pat(data, pat['sig'])\r\n if off == -1:\r\n continue\r\n \r\n key_start = off + pat['key_offset']\r\n key_va = struct.unpack('\u003cI', data[key_start:key_start + 4])[0]\r\n \r\n blob_start = off + pat['blob_offset']\r\n blob_va = struct.unpack('\u003cI', data[blob_start:blob_start + 4])[0]\r\n \r\n sz_check = pat['size_check']\r\n search_end = off + sz_check['search_range']\r\n sz_off = find_pat(data[off:search_end], sz_check['sig'])\r\n if sz_off == -1:\r\n continue\r\n \r\n sz_start = off + sz_off + sz_check['value_offset']\r\n sz = struct.unpack('\u003cI', data[sz_start:sz_start + 4])[0]\r\n \r\n return key_va, blob_va, sz\r\n \r\n return None, None, None\r\ndef decrypt_exe(exe_path):\r\n pe = pefile.PE(exe_path)\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 10 of 15\n\nkey_va, blob_va, sz = find_addrs(exe_path)\r\n \r\n if not all([key_va, blob_va, sz]):\r\n print(\"Pattern not found\")\r\n return False\r\n \r\n print(f\"Key address: 0x{key_va:08X}\")\r\n print(f\"Blob address: 0x{blob_va:08X}\")\r\n print(f\"Size: 0x{sz:X} ({sz} bytes)\")\r\n \r\n key_rva = key_va - pe.OPTIONAL_HEADER.ImageBase\r\n blob_rva = blob_va - pe.OPTIONAL_HEADER.ImageBase\r\n \r\n key = pe.get_data(key_rva, 32)\r\n enc = pe.get_data(blob_rva, sz)\r\n \r\n if not key or not enc:\r\n print(\"Failed to extract data\")\r\n return False\r\n \r\n print(f\"Key: {' '.join(f'{b:02X}' for b in key[:32])}\")\r\n print(f\"First 32 bytes of encrypted data: {' '.join(f'{b:02X}' for b in enc[:32])}\")\r\n \r\n dec = bytearray(sz)\r\n for i in range(sz):\r\n dec[i] = enc[i] ^ key[i \u0026 0x1F]\r\n \r\n off = 0x4F4\r\n if off \u003c len(dec) and dec[off:off + 2] == b'MZ':\r\n dec = dec[off:]\r\n \r\n out = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"decrypted.bin\")\r\n with open(out, \"wb\") as f:\r\n f.write(dec)\r\n \r\n print(f\"Wrote {len(dec)} bytes to {out}\")\r\n return True\r\ndef main():\r\n if len(sys.argv) != 2:\r\n sys.exit(1)\r\n \r\n decrypt_exe(sys.argv[1])\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 11 of 15\n\nif __name__ == \"__main__\":\r\n main()\r\nnow we can compare the clean decrypted.bin with our initial dumped file\r\nyeah this confirms the problem we had before. the dumped file already is decrypted so we just need to use lzma on\r\nthat. the problem we had before was that we basically encrypted it again kek.\r\n*i wanted to write a full unpacker but for some reason the lzma was corrupted and 36 bytes were different - after\r\n12h i could not figure out why. if you do pls tell me, this shit keeps me up at night ty ;3 that means we can just\r\ndump the left buffer and extract at the starting lzma header offset and then decompress it.\r\nimport ida_bytes\r\nimport os\r\naddr = 0x1349078\r\nsize = 0x45C9B - 0x48\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 12 of 15\n\ndata = ida_bytes.get_bytes(addr, size)\r\nif data:\r\n output_path = os.path.join(os.path.expanduser(\"~\"), \"Desktop\", \"dump.bin\")\r\n with open(output_path, \"wb\") as f:\r\n f.write(data)\r\n print(\"Wrote %d bytes to %s\" % (len(data), output_path))\r\nelse:\r\n print(\"Failed to read data at 0x%X\" % addr)\r\nsoooOoo lets open dump in ida and look at our new stage. first i wanted to make sure that this is the real stealer\r\nand looked for some indicators.\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 13 of 15\n\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 14 of 15\n\nlooking at the strings we can see some chromium browser paths which should be enough. I wonder if APPBYKEY\r\nhas anything to do with Chrome’s Appbound encryption \u0026 decryption O_o\r\nthe next blogs about aura will cover the obfuscation and config decrypter.\r\nSHA-256: bac52ffc8072893ff26cdbf1df1ecbcbb1762ded80249d3c9d420f62ed0dc202\r\nthanks for reading!\r\ngreetz to ma homies\r\neversince\r\ndeluks\r\nand c0ner0ne\r\nyou are cool and badass \u003e:3\r\nSource: https://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nhttps://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/\r\nPage 15 of 15",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://blog.xyris.mov/posts/aura-stealer-%231-36bytesmademelosemymind/"
	],
	"report_names": [
		"aura-stealer-%231-36bytesmademelosemymind"
	],
	"threat_actors": [
		{
			"id": "9f101d9c-05ea-48b9-b6f1-168cd6d06d12",
			"created_at": "2023-01-06T13:46:39.396409Z",
			"updated_at": "2026-04-10T02:00:03.312816Z",
			"deleted_at": null,
			"main_name": "Earth Lusca",
			"aliases": [
				"CHROMIUM",
				"ControlX",
				"TAG-22",
				"BRONZE UNIVERSITY",
				"AQUATIC PANDA",
				"RedHotel",
				"Charcoal Typhoon",
				"Red Scylla",
				"Red Dev 10",
				"BountyGlad"
			],
			"source_name": "MISPGALAXY:Earth Lusca",
			"tools": [
				"RouterGod",
				"SprySOCKS",
				"ShadowPad",
				"POISONPLUG",
				"Barlaiy",
				"Spyder",
				"FunnySwitch"
			],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "18a7b52d-a1cd-43a3-8982-7324e3e676b7",
			"created_at": "2025-08-07T02:03:24.688416Z",
			"updated_at": "2026-04-10T02:00:03.734754Z",
			"deleted_at": null,
			"main_name": "BRONZE UNIVERSITY",
			"aliases": [
				"Aquatic Panda",
				"Aquatic Panda ",
				"CHROMIUM",
				"CHROMIUM ",
				"Charcoal Typhoon",
				"Charcoal Typhoon ",
				"Earth Lusca",
				"Earth Lusca ",
				"FISHMONGER ",
				"Red Dev 10",
				"Red Dev 10 ",
				"Red Scylla",
				"Red Scylla ",
				"RedHotel",
				"RedHotel ",
				"Tag-22",
				"Tag-22 "
			],
			"source_name": "Secureworks:BRONZE UNIVERSITY",
			"tools": [
				"Cobalt Strike",
				"Fishmaster",
				"FunnySwitch",
				"Spyder",
				"njRAT"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "6abcc917-035c-4e9b-a53f-eaee636749c3",
			"created_at": "2022-10-25T16:07:23.565337Z",
			"updated_at": "2026-04-10T02:00:04.668393Z",
			"deleted_at": null,
			"main_name": "Earth Lusca",
			"aliases": [
				"Bronze University",
				"Charcoal Typhoon",
				"Chromium",
				"G1006",
				"Red Dev 10",
				"Red Scylla"
			],
			"source_name": "ETDA:Earth Lusca",
			"tools": [
				"Agentemis",
				"AntSword",
				"BIOPASS",
				"BIOPASS RAT",
				"BadPotato",
				"Behinder",
				"BleDoor",
				"Cobalt Strike",
				"CobaltStrike",
				"Doraemon",
				"FRP",
				"Fast Reverse Proxy",
				"FunnySwitch",
				"HUC Port Banner Scanner",
				"KTLVdoor",
				"Mimikatz",
				"NBTscan",
				"POISONPLUG.SHADOW",
				"PipeMon",
				"RbDoor",
				"RibDoor",
				"RouterGod",
				"SAMRID",
				"ShadowPad Winnti",
				"SprySOCKS",
				"WinRAR",
				"Winnti",
				"XShellGhost",
				"cobeacon",
				"fscan",
				"lcx",
				"nbtscan"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "d53593c3-2819-4af3-bf16-0c39edc64920",
			"created_at": "2022-10-27T08:27:13.212301Z",
			"updated_at": "2026-04-10T02:00:05.272802Z",
			"deleted_at": null,
			"main_name": "Earth Lusca",
			"aliases": [
				"Earth Lusca",
				"TAG-22",
				"Charcoal Typhoon",
				"CHROMIUM",
				"ControlX"
			],
			"source_name": "MITRE:Earth Lusca",
			"tools": [
				"Mimikatz",
				"PowerSploit",
				"Tasklist",
				"certutil",
				"Cobalt Strike",
				"Winnti for Linux",
				"Nltest",
				"NBTscan",
				"ShadowPad"
			],
			"source_id": "MITRE",
			"reports": null
		}
	],
	"ts_created_at": 1775439001,
	"ts_updated_at": 1775826742,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/147667a4c2352c6976b126c8526e3de8c1711045.pdf",
		"text": "https://archive.orkl.eu/147667a4c2352c6976b126c8526e3de8c1711045.txt",
		"img": "https://archive.orkl.eu/147667a4c2352c6976b126c8526e3de8c1711045.jpg"
	}
}