typeanalysisfamilyunclassified-autoit-compiledconfidencehighcreated2026-07-03updated2026-07-03malware-familyloaderautoitpeevasionc2discoverypersistence
SHA-256: 64b37e90dd772573c46014c2fa8a1a7a1b69df4a6a16f573d0312360e404c60d

unclassified-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

  1. Initial execution — AutoIt interpreter loads compiled script from .rsrc RT_RCDATA SCRIPT ^[pefile.txt:1490].
  2. Payload stagingFileInstall drops Nasalis and emboweling to %TEMP% ^[script.au3:9–10].
  3. Emboweling processing — Script opens emboweling via CreateFile, gets size via GetFileSizeEx, reads content via ReadFile, then closes handle ^[script.au3:11–18].
  4. 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 to BinaryToString to produce raw shellcode.
  5. Shellcode execution — Script allocates RWX memory via VirtualAlloc (size = decoded length, 0x3000 allocation type, 0x40 protection), copies shellcode into it via DllStructSetData, and calls DllCallAddress at offset 0x23b0 ^[script.au3:21–24].
  6. Nasalis decryption — The shellcode at 0x23b0 constructs 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 CreateFileWGetFileSizeExReadFile on %TEMP%\Nasalis
  • Calls VirtualAlloc with 0x3000 | MEM_COMMIT | MEM_RESERVE and PAGE_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: Z30PER is 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-ripper alongside the script. The shellcode intermediary (emboweling) is a new staging pattern — prior siblings typically dropped two payloads to disk and used DllCallAddress on 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)

  1. Toolchain: Install AutoIt v3.3.8.1 and SciTE on a Windows research VM.
  2. Script: Write an AutoIt script that uses FileInstall to drop a small PE + shellcode, then calls DllCallAddress on the shellcode.
  3. Obfuscation: Reproduce Z30PER in 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
    
  4. Shellcode: Write a minimal x86 stub that reads a file, XOR-decrypts with a fixed key, and jumps to the decrypted payload.
  5. Compile: Use Aut2Exe to produce a single-file PE32.
  6. Verification: Run capa <reproducer.exe> — should hit the AutoIt limitation warning. Verify pefile.py shows RT_RCDATA SCRIPT resource.

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 + DllCallAddress reflective 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-ripper on 2026-07-03.
  • Shellcode decoded manually via Python script replicating Z30PER logic.
  • 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) and Nasalis_decoded30.bin (payload).
  • No dynamic analysis available (CAPE skipped — no Windows guest).