typeanalysisfamilyunclassified-autoit-compiledconfidencehighcreated2026-07-02updated2026-07-02malware-familyloaderautoitevasionpescriptc2discovery
SHA-256: 9e95f20b6a922c573706918d93a3d99cdc726d374ff12654c708fcbb6f3cd9b7

unclassified-autoit-compiled: 9e95f20b — procurement-BOQ lure with U30JZ3SO7 permutation-XOR obfuscation

Executive Summary

AutoItSC single-file PE32 (~1.1 MB) masquerading as a procurement document (SPECIFICATIONS,_BOQ_DOC_pdf.exe). Decompiled script reveals a two-stage payload delivery chain: a 270 KB compressed binary (turbinate) and a 14 KB hex-encoded shellcode stub (selectee) that allocates RWX memory and jumps to offset 9136. String obfuscation uses a custom keyed-permutation + XOR cipher (U30JZ3SO7) with hardcoded key "06". No plaintext C2 recovered statically. Twenty-ninth confirmed sibling in the unclassified-autoit-compiled cluster.

What It Is

  • Filename: SPECIFICATIONS,_BOQ_DOC_pdf.exe — Bill-of-Quantities / specifications procurement lure ^[metadata.json]
  • File type: PE32 executable (GUI) Intel 80386, 5 sections ^[file.txt]
  • Size: 1,139,200 bytes (1.09 MB) ^[triage.json]
  • Timestamp: Sun Jul 7 22:53:19 2024 UTC ^[pefile.txt:34]
  • Linker: MSVC 12.0 (VS 2013), MajorLinkerVersion=0xC ^[pefile.txt:45]
  • Compiler language: AutoIt v3 single-file compiled (AutoItSC) ^[capa.txt]
  • Script placement: .rsrc section, resource type 10 (RT_RCDATA), encrypted bytecode with AU3!EA06 header ^[strings.txt:782] ^[binwalk.txt]
  • Signing: Unsigned ^[rabin2-info.txt:30]
  • VS_VERSIONINFO: Empty (LangID 0809 0x04b0, no strings) ^[pefile.txt:260-272]

How It Works

The outer PE is the AutoIt3 interpreter runtime. On execution it decrypts and runs the compiled script stored in .rsrc. The script (decompiled via autoit-ripper) performs the following:

  1. Stage payloads to disk: FileInstall("turbinate", @TempDir & "\turbinate", 1) and FileInstall("selectee", @TempDir & "\selectee", 1) ^[script.au3:1-2]
  2. Read and strip marker: Reads selectee, strips a 64-byte hex marker (1A6E71D...) from the file content ^[script.au3:3-4]
  3. Allocate RWX memory: VirtualAlloc via DllCall against kernel32, size = BinaryLen($U30erNlqASK), allocation type 0x3000 (MEM_COMMIT|MEM_RESERVE), protection 0x40 (PAGE_EXECUTE_READWRITE) ^[script.au3:5]
  4. Copy shellcode: DllStructCreate("byte [" & BinaryLen(...) & "]", $V33W0T9F4) then DllStructSetData to copy the decoded payload into the allocated buffer ^[script.au3:7-8]
  5. Transfer execution: DllCallAddress("int", $V33W0T9F4 + 9136) — jumps to offset 9136 within the allocated RWX region ^[script.au3:9]

The turbinate file (270,848 bytes) is a compressed/encrypted binary payload extracted as a resource. Static analysis shows it contains no valid PE header at natural alignment; it may be a custom-packed second stage or additional shellcode/data consumed by the selectee stub at runtime. ^[turbinate:hexdump]

The selectee file, after stripping the marker and hex-decoding, yields 14,336 bytes of x86 shellcode. ^[selectee:dehex]

Decompiled Behavior

The decompiled AutoIt script is heavily padded with ~980 lines of dead code (junk For loops, If branches on impossible conditions, GUI API calls with random constants) following the real logic in lines 1–9. ^[script.au3:10-1008]

The string obfuscation function U30JZ3SO7($S373337Z7D, $J373338QRO) implements a three-phase cipher:

  1. Key-scheduled permutation: For each character position i, compute X = (ord(key[i % len(key)]) * i) % len(s) + 1, then fill a permutation table Z via linear probing on collision.
  2. Rearrangement: Apply the inverse permutation to the ciphertext.
  3. XOR decrypt: For each character, plaintext[i] = chr((rearranged[i] - 5) ^ ord(key[i % len(key)])).

Key used: "06" (two bytes). Decoded strings include API names (kernel32, VirtualAlloc, dword) and struct type descriptors (byte [, int). ^[script.au3:980-1007]

The shellcode at offset 9136 within the selectee payload was not fully disassembled due to the static-only analysis constraint, but the allocation pattern (RWX, copy, jump) is consistent with reflective loading or process injection.

C2 Infrastructure

No plaintext C2 strings recovered. The decompiled script contains no hardcoded URLs, IPs, domains, SMTP credentials, or Telegram bot tokens. Network capability is inferred from the AutoIt runtime import table:

  • InternetOpenW, InternetConnectW, HttpOpenRequestW, HttpSendRequestW, InternetReadFile ^[strings.txt:830-841]
  • WSAStartup, socket, connect, send, recv ^[strings.txt:803]
  • FtpOpenFileW, FtpGetFileSize ^[strings.txt:838-839]

C2 is likely resolved or downloaded at runtime by the shellcode in selectee or the secondary payload in turbinate.

Interesting Tidbits

  • New obfuscation variant: This is the first sibling in the cluster to use the U30JZ3SO7 permutation-XOR cipher. Previous siblings used K30ZWMBJJ (XOR key "AA", permutation table) ^[/intel/analyses/b017d1897d3c5b5c51f02fafcbe48700943ebe0921c1c881d4f7ea37fe1eefdc.html] and O30MJJHT (Caesar-5 shift, XOR key "WH") ^[/intel/analyses/aa4d237c7a9b4ec7915c582ad703c886422d59ceb40ded57307d7da15ec9bfc8.html]. The "06" key here is only two bytes, making brute-force trivial if the function is recognized.
  • Procurement lure specificity: "BOQ" (Bill of Quantities) is a construction/engineering procurement term, narrower than generic "invoice" or "PO" lures seen in siblings. Suggests targeting of construction, engineering, or government-procurement verticals.
  • Two-file staging: Most cluster siblings drop a single payload file (e.g., misrun, endochylous). This sample uses a dual-file model (turbinate + selectee) where selectee acts as a bootstrap loader and turbinate is the heavy payload. This mirrors the contrapose/endochylous shellcode-intermediary pattern seen in aa4d237c but with different file names.
  • No UPX packing: Plain PE32 (non-UPX), 5 standard sections. The .rsrc entropy is 7.96, near-maximum, from the encrypted script. ^[pefile.txt:152]
  • Full PCRE regex runtime present: The AutoIt interpreter bundles a complete PCRE 8.x library with Unicode script-name tables (line 680–781 of strings.txt), enabling script-side pattern matching for data harvesting. ^[strings.txt:587-782]

How To Mess With It (Homelab Replication)

Toolchain: AutoIt v3.3.8.1 or later + SciTE editor on Windows. The single-file compiler (Aut2Exe) produces the PE.

Reproduce the obfuscation:

Func U30JZ3SO7($S373337Z7D, $J373338QRO)
    Local $D373339LGH = StringLen($J373338QRO)
    Local $M373431BTD = StringLen($S373337Z7D)
    Local $Z3734355OKKZG[$M373431BTD]
    Local $D373437SNRQ[$M373431BTD]
    Local $K373439AQ = ""
    For $X31330CINR1U = 1 To $M373431BTD
        Local $X373532OE = Mod((Asc(StringMid($J373338QRO, Mod(($X31330CINR1U - 1), $D373339LGH) + 1, 1)) * $X31330CINR1U), $M373431BTD) + 1
        While $Z3734355OKKZG[$X373532OE - 1] <> ""
            $X373532OE = Mod($X373532OE, $M373431BTD) + 1
        WEnd
        $Z3734355OKKZG[$X373532OE - 1] = $X31330CINR1U
    Next
    For $X31330CINR1U = 1 To $M373431BTD
        $D373437SNRQ[$Z3734355OKKZG[$X31330CINR1U - 1] - 1] = StringMid($S373337Z7D, $X31330CINR1U, 1)
    Next
    For $X31330CINR1U = 0 To UBound($D373437SNRQ) - 1
        $K373439AQ &= $D373437SNRQ[$X31330CINR1U]
    Next
    Local $L373738BZ4OK = ""
    For $X31330CINR1U = 1 To StringLen($K373439AQ)
        Local $P3738316D = Asc(StringMid($K373439AQ, $X31330CINR1U, 1))
        Local $N373834EVC = Asc(StringMid($J373338QRO, Mod(($X31330CINR1U - 1), $D373339LGH) + 1, 1))
        $L373738BZ4OK &= Chr(BitXOR($P3738316D - 5, $N373834EVC))
    Next
    Return $L373738BZ4OK
EndFunc

Verification: Compile a test script with FileInstall of a dummy payload and DllCall("kernel32.dll", "ptr", "VirtualAlloc", ...) using obfuscated strings via U30JZ3SO7. Run capa on the output — should hit autoit file limitation and allocate RWX memory.

What you'll learn: How AutoIt malware authors abuse the interpreter's DllCall/DllCallAddress primitives to inject shellcode without ever touching a native compiler. The obfuscation is weak (2-byte key, trivial permutation) but effective against string-only tools.

Deployable Signatures

YARA Rule

rule AutoItSC_U30JZ3SO7_Obfuscation
{
    meta:
        description = "AutoItSC single-file PE with U30JZ3SO7 permutation-XOR string obfuscation"
        author = "PacketPursuit"
        date = "2026-07-02"
        sha256 = "9e95f20b6a922c573706918d93a3d99cdc726d374ff12654c708fcbb6f3cd9b7"
        family = "unclassified-autoit-compiled"
    strings:
        $au3_header = "AU3!EA06"
        $func_name = "U30JZ3SO7"
        $func_name2 = "U30jz3so7"
        $key_06 = "\"06\""
        $virtualalloc_obf = { 60 47 5D 5A 58 5F 08 09 }  // "`G]ZX_\b\t" obfuscated "kernel32"
        $turbinate = "turbinate" ascii wide
        $selectee = "selectee" ascii wide
        $marker = "1A6E71D4810309FDFC6D43D3E9A6A999A1918E3376ACA2EEC40F44C89B681ADD6AA0260BDF66FE84DA"
    condition:
        uint16(0) == 0x5A4D and
        ($au3_header or $func_name or $func_name2) and
        ($turbinate or $selectee or $marker)
}

Sigma Rule

title: AutoIt RWX Memory Allocation and Shellcode Execution
status: experimental
description: Detects AutoIt interpreter allocating RWX memory and calling an address within it, indicative of shellcode injection.
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    - Image|endswith: 'AutoIt3.exe'
    - CommandLine|contains:
      - 'turbinate'
      - 'selectee'
  condition: selection
falsepositives:
  - Rare legitimate AutoIt automation scripts using similar filenames
level: high

IOC List

Indicator Type Value Notes
SHA-256 Hash 9e95f20b6a922c573706918d93a3d99cdc726d374ff12654c708fcbb6f3cd9b7 Outer PE
Filename String SPECIFICATIONS,_BOQ_DOC_pdf.exe Procurement lure
Marker String 1A6E71D4810309FDFC6D43D3E9A6A999A1918E3376ACA2EEC40F44C89B681ADD6AA0260BDF66FE84DA Strip marker in selectee
Obfuscation key String 06 U30JZ3SO7 cipher key
Temp path Path %TEMP%\turbinate Staged payload
Temp path Path %TEMP%\selectee Staged shellcode
RWX alloc offset Behaviour VirtualAlloc offset 9136, then DllCallAddress Shellcode entry

Behavioral Fingerprint Statement

This binary is an AutoItSC single-file PE32 that drops two files to %TEMP% — a large compressed payload (turbinate) and a hex-encoded shellcode stub (selectee). It strips a 64-byte marker from selectee, hex-decodes the remainder, allocates RWX memory via VirtualAlloc, copies the shellcode into it, and transfers execution via DllCallAddress at offset 9136. No hardcoded C2 is visible in the script; network capability is provided by the AutoIt runtime's WinInet and WinSock imports. The sample uses a custom U30JZ3SO7 string-obfuscation function with a 2-byte key ("06") to hide API names at rest.

Detection Signatures

  • capa: autoit file limitation (cannot analyze AutoIt scripts statically) ^[capa.txt]
  • YARA: PE_File_Generic, Suspicious_Wininet_Imports ^[yara.txt]
  • MITRE ATT&CK (inferred from imports + script logic):
    • T1059.005 — Command and Scripting Interpreter: Visual Basic / AutoIt
    • T1055 — Process Injection (RWX allocation + DllCallAddress shellcode execution)
    • T1071.001 — Application Layer Protocol: Web Protocols (WinInet)
    • T1095 — Non-Application Layer Protocol (WinSock)
    • T1083 — File and Directory Discovery
    • T1012 — Query Registry
    • T1113 — Screen Capture (GDI32 present)
    • T1056.001 — Input Capture: Keylogging (GetAsyncKeyState present)

References

Provenance

  • file.txtfile command output
  • pefile.txt — pefile.py parsed PE headers
  • strings.txt — raw strings extraction (2436 lines)
  • capa.txt — Mandiant capa v8.x output (AutoIt limitation warning)
  • binwalk.txt — binwalk embedded artefact scan
  • rabin2-info.txt — radare2 rabin2 -I header summary
  • script.au3 — decompiled AutoIt script via autoit-ripper
  • turbinate / selectee — extracted payload files from autoit-ripper
  • dynamic-analysis.md — CAPE skipped (no Windows guest available)