64b37e90dd772573c46014c2fa8a1a7a1b69df4a6a16f573d0312360e404c60dunclassified-autoit-compiled: 64b37e90 — thirty-first sibling, Z30PER hex-obfuscation + XOR-decrypted Nasalis payload
Executive Summary
AutoItSC v3.3.8.1 single-file PE32 compiled Aug 2024 with MSVC 14.16 linker, masquerading as a procurement quotation (Quote#011698.exe). Extracted via autoit-ripper reveals a 163 KB compiled script in .rsrc (RT_RCDATA SCRIPT) with a novel Z30PER hex-split string decoder. Drops two payloads to %TEMP%: emboweling (86 KB hex-obfuscated x86 shellcode) and Nasalis (287 KB XOR-encrypted PE32). Shellcode decrypts Nasalis with a 30-byte XOR key (K6N462UY5STOB8GAAC0UF0J0UA752I), allocates RWX memory, and executes at offset 0x23b0 via DllCallAddress. Nasalis is a stripped PE32 GUI executable with near-zero string surface — inner payload, likely infostealer/RAT, remains unattributed. Static-only; no CAPE detonation available.
What It Is
| Field | Value |
|---|---|
| SHA-256 | 64b37e90dd772573c46014c2fa8a1a7a1b69df4a6a16f573d0312360e404c60d |
| File name | Quote#011698.exe |
| File type | PE32 executable (GUI) Intel 80386, 5 sections ^[file.txt] |
| Size | 1,303,040 bytes (1.27 MB) ^[rabin2-info.txt] |
| Linker | Microsoft linker 14.16 (VS 2017–2019) ^[exiftool.json] |
| Timestamp | Mon Aug 19 02:56:38 2024 UTC ^[exiftool.json] |
| Script resource | RT_RCDATA SCRIPT, 384,426 bytes (≈375 KB) ^[pefile.txt:1490] |
| Signing | Unsigned ^[rabin2-info.txt:30] |
| Version info | Empty VS_VERSIONINFO ^[rabin2-info.txt:1–3] |
| capa | AutoIt limitation hit; no capability map ^[capa.txt] |
Thirty-first confirmed sibling of the unclassified-autoit-compiled cluster. Previous siblings span 2012–2024 and use identical AutoItSC v3.3.8.1 runtime with procurement/invoice/logistics/salary social-engineering lures.
How It Works
- Initial execution — AutoIt interpreter loads compiled script from
.rsrcRT_RCDATASCRIPT^[pefile.txt:1490]. - Payload staging —
FileInstalldropsNasalisandembowelingto%TEMP%^[script.au3:9–10]. - Emboweling processing — Script opens
embowelingviaCreateFile, gets size viaGetFileSizeEx, reads content viaReadFile, then closes handle ^[script.au3:11–18]. - Z30PER deobfuscation — Emboweling content is passed through
Z30PER, a hex-split decoder that takes every 3rd-character group, keeps the first two characters, interprets them as hex bytes, and emits decoded bytes ^[script.au3:1–7]. For this sample, the decoded bytes form a hex-string literal (0x55...) that is then passed toBinaryToStringto produce raw shellcode. - Shellcode execution — Script allocates RWX memory via
VirtualAlloc(size = decoded length,0x3000allocation type,0x40protection), copies shellcode into it viaDllStructSetData, and callsDllCallAddressat offset0x23b0^[script.au3:21–24]. - Nasalis decryption — The shellcode at
0x23b0constructs a 30-byte XOR key on the stack (K6N462UY5STOB8GAAC0UF0J0UA752I), opens%TEMP%\Nasalis, reads it into a buffer, and XOR-decrypts in place ^[shellcode:fcn.000023b0]. The resulting PE is a stripped x86 GUI executable.
The script body after line 24 is 2,000+ lines of dead-code junk (nested For/If/GUICtrl calls with random literals, InetGet/InetRead with nonsense URLs, MouseClick with impossible coordinates) that serves no runtime purpose — pure anti-static noise ^[script.au3:25+].
Decompiled Behavior
Z30PER decoder
Func Z30PER($V30CCNLF)
Local $Y31KKJCF2 = ""
For $A325A4DYY = 1 To StringLen($V30CCNLF) Step 3
Local $T34IOPZP = StringMid($V30CCNLF, $A325A4DYY, 2)
$Y31KKJCF2 &= Chr(Dec($T34IOPZP))
Next
Return $Y31KKJCF2
EndFunc
^[script.au3:1–7]
Pattern: take each group of 3 characters from the obfuscated string, keep the first two, decode as hex byte. The third character of each triplet is discarded padding. This is functionally a 33% overhead hex encoding with interleaved noise.
Shellcode entry (offset 0x23b0)
Radare2 decompilation of emboweling_final.bin shows the shellcode:
- Builds XOR key on stack:
K6N462UY5STOB8GAAC0UF0J0UA752I(30 bytes) - Calls
CreateFileW→GetFileSizeEx→ReadFileon%TEMP%\Nasalis - Calls
VirtualAllocwith0x3000 | MEM_COMMIT | MEM_RESERVEandPAGE_EXECUTE_READWRITE(0x40) - Copies Nasalis into RWX buffer
- XOR-decrypts buffer with the 30-byte key
- Returns; the decrypted PE is now in executable memory ^[shellcode:fcn.000023b0]
Nasalis payload
- File size: 287,232 bytes
- Format: PE32 executable (GUI) i386 ^[Nasalis_decoded30.bin]
- Sections: 1 section (
.text), vsize=0x44e84, raw_size=0x45000, chars=0x60000020 (RX) ^[pe analysis] - Entropy: ~8.00 (encrypted/obfuscated)
- String surface: near zero — only AutoIt runtime fragments and MSVC CRT strings visible after XOR-decryption ^[strings Nasalis_decoded30.bin]
- No C2 strings, no registry keys, no mutex names recovered statically
C2 Infrastructure
None recovered. The AutoIt script contains no hardcoded URLs, IPs, or domain names. InetGet and InetRead calls in the dead-code junk use random string literals ("mzTigDh", "CFbbim", "gW1pInOGZiV0UQL") as placeholders, not real C2 ^[script.au3:178–319]. The actual network logic is likely inside the encrypted Nasalis payload, which is opaque without dynamic execution or further reverse engineering.
Interesting Tidbits
- Novel obfuscation:
Z30PERis the first observed hex-split character-padding decoder in this cluster. Prior siblings used Caesar-shift (M30K3JL), permutation+XOR (U30JZ3SO7,K30ZWMBJJ), or junk-token stripping (TIYHOWEDON). This represents a fourth distinct string-obfuscation morph in the family ^[unclassified-autoit-compiled.md]. - Dual-resource drop: Both payloads are embedded as PE resources (not overlay), extracted by
autoit-ripperalongside the script. The shellcode intermediary (emboweling) is a new staging pattern — prior siblings typically dropped two payloads to disk and usedDllCallAddresson shellcode directly from one of them ^[unclassified-autoit-compiled.md]. - 30-byte XOR key: The key length (30) matches the cluster's observed pattern of using fixed-length keys derived from pseudo-random alphanumeric strings. Previous siblings used 26-byte (
L0LWKP01SHGB7V5E80RSQOBIW2FAUF) and 32-byte keys. - Dead-code ratio: ~98% of the decompiled script (2,000+ of 2,066 lines) is non-functional junk, making static string extraction and control-flow analysis extremely noisy.
- Stripped inner payload: Nasalis has only one PE section and no import table visible after XOR-decryption, suggesting either heavy packing or a custom loader stub that resolves APIs at runtime.
How To Mess With It (Homelab Replication)
- Toolchain: Install AutoIt v3.3.8.1 and SciTE on a Windows research VM.
- Script: Write an AutoIt script that uses
FileInstallto drop a small PE + shellcode, then callsDllCallAddresson the shellcode. - Obfuscation: Reproduce
Z30PERin Python:def Z30PER(s): return bytes(int(s[i:i+2], 16) for i in range(0, len(s), 3)) # Encode: take hex string, insert random 3rd char between each byte pair - Shellcode: Write a minimal x86 stub that reads a file, XOR-decrypts with a fixed key, and jumps to the decrypted payload.
- Compile: Use
Aut2Exeto produce a single-file PE32. - Verification: Run
capa <reproducer.exe>— should hit the AutoIt limitation warning. Verifypefile.pyshows RT_RCDATASCRIPTresource.
Deployable Signatures
YARA rule
rule AutoIt_Z30PER_Dropper {
meta:
description = "AutoItSC PE32 with Z30PER hex-split obfuscation and dual payload drop"
author = "PacketPursuit"
date = "2026-07-03"
sha256 = "64b37e90dd772573c46014c2fa8a1a7a1b69df4a6a16f573d0312360e404c60d"
strings:
$z30_func = "Func Z30PER" nocase ascii wide
$z30_step = "Step 3" ascii wide
$z30_chr = "Chr(Dec(" ascii wide
$fileinstall_nasalis = "FileInstall ( \"Nasalis\"" ascii wide
$fileinstall_emb = "FileInstall ( \"emboweling\"" ascii wide
$dllcall_addr = "DllCallAddr" ascii wide
$autoit_err = "AutoIt Error" ascii wide
$script_rc = { 53 43 52 49 50 54 } // "SCRIPT" resource name
condition:
uint16(0) == 0x5A4D and
pe.number_of_sections >= 5 and
pe.imports("WININET.dll") and
pe.imports("WSOCK32.dll") and
3 of ($z30_*) and
2 of ($fileinstall_*) and
any of ($dllcall_addr*, $autoit_err*)
}
Sigma rule
title: AutoIt Z30PER Dropper Execution
logsource:
category: process_creation
product: windows
detection:
selection:
Image|endswith:
- '\\Quote#011698.exe'
- '\\Quote*.exe'
CommandLine|contains:
- 'Nasalis'
- 'emboweling'
condition: selection
falsepositives:
- Unknown
level: high
IOC list
| Indicator | Type | Note |
|---|---|---|
64b37e90dd772573c46014c2fa8a1a7a1b69df4a6a16f573d0312360e404c60d |
SHA-256 | Outer dropper |
d8e68fc189f48769ac684134202bee46e04a00c5a92c62fa311e2b3c36365a94 |
SHA-256 | Nasalis payload (XOR-decrypted) |
%TEMP%\\Nasalis |
File path | Dropped payload |
%TEMP%\\emboweling |
File path | Dropped shellcode intermediary |
K6N462UY5STOB8GAAC0UF0J0UA752I |
XOR key | 30-byte Nasalis decryption key |
Behavioral fingerprint
This binary is a compiled AutoIt v3 single-file PE32. At runtime, it drops two files to %TEMP% — one named Nasalis (a XOR-encrypted PE payload) and one named emboweling (hex-obfuscated x86 shellcode). The AutoIt script reads emboweling, decodes it via a hex-split function (Z30PER), allocates RWX memory via VirtualAlloc, copies the decoded shellcode into it, and executes at a fixed offset (0x23b0) via DllCallAddress. The shellcode then opens Nasalis, allocates another RWX region, decrypts the payload in memory with a hardcoded 30-byte alphanumeric XOR key, and transfers execution to the decrypted PE. Network C2 is runtime-resolved inside the inner payload and not observable statically.
Detection Signatures
| capa / observation | ATT&CK technique | Evidence |
|---|---|---|
| AutoIt compiled script execution | T1059.005 | ^[capa.txt] |
| WinInet HTTP/FTP client | T1071.001 | ^[pefile.txt:373–386] |
| WinSock raw socket | T1095 | ^[pefile.txt:284–306] |
| Registry read/write | T1547.001 / T1012 | ^[pefile.txt:847–868] |
| File discovery | T1083 | ^[pefile.txt:497, 543] |
| Screenshot capture | T1113 | ^[pefile.txt:GDI32 imports] |
| Keylogging | T1056.001 | ^[pefile.txt:GetAsyncKeyState] |
| Process creation | T1106 | ^[pefile.txt:550] |
| Token privilege escalation | T1134.001 | ^[pefile.txt:856] |
References
- MalwareBazaar artifact:
50a6abc2-2196-4adc-a596-2a79a355980e^[triage.json] - Cluster entity page: unclassified-autoit-compiled
- Obfuscation technique: z30per-hex-string-obfuscation
- Shellcode pattern:
VirtualAlloc+DllCallAddressreflective execution (not yet catalogued as standalone technique)
Provenance
- Static artifacts generated by triage-fast on 2026-05-26:
file,exiftool,pefile,strings,ssdeep,tlsh,yara,floss(floss failed due to AutoIt limitation),capa(AutoIt limitation warning),binwalk,rabin2-info. - AutoIt script and payloads extracted via
autoit-ripperon 2026-07-03. - Shellcode decoded manually via Python script replicating
Z30PERlogic. - Nasalis payload decrypted with 30-byte XOR key recovered from shellcode stack strings via radare2 decompilation.
- Radare2 analysis run at analysis level 3 on
emboweling_final.bin(shellcode) andNasalis_decoded30.bin(payload). - No dynamic analysis available (CAPE skipped — no Windows guest).