9e95f20b6a922c573706918d93a3d99cdc726d374ff12654c708fcbb6f3cd9b7unclassified-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:
.rsrcsection, resource type10(RT_RCDATA), encrypted bytecode withAU3!EA06header ^[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:
- Stage payloads to disk:
FileInstall("turbinate", @TempDir & "\turbinate", 1)andFileInstall("selectee", @TempDir & "\selectee", 1)^[script.au3:1-2] - Read and strip marker: Reads
selectee, strips a 64-byte hex marker (1A6E71D...) from the file content ^[script.au3:3-4] - Allocate RWX memory:
VirtualAllocviaDllCallagainstkernel32, size =BinaryLen($U30erNlqASK), allocation type0x3000(MEM_COMMIT|MEM_RESERVE), protection0x40(PAGE_EXECUTE_READWRITE) ^[script.au3:5] - Copy shellcode:
DllStructCreate("byte [" & BinaryLen(...) & "]", $V33W0T9F4)thenDllStructSetDatato copy the decoded payload into the allocated buffer ^[script.au3:7-8] - 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:
- Key-scheduled permutation: For each character position
i, computeX = (ord(key[i % len(key)]) * i) % len(s) + 1, then fill a permutation tableZvia linear probing on collision. - Rearrangement: Apply the inverse permutation to the ciphertext.
- 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
U30JZ3SO7permutation-XOR cipher. Previous siblings usedK30ZWMBJJ(XOR key"AA", permutation table) ^[/intel/analyses/b017d1897d3c5b5c51f02fafcbe48700943ebe0921c1c881d4f7ea37fe1eefdc.html] andO30MJJHT(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) whereselecteeacts as a bootstrap loader andturbinateis the heavy payload. This mirrors thecontrapose/endochylousshellcode-intermediary pattern seen inaa4d237cbut with different file names. - No UPX packing: Plain PE32 (non-UPX), 5 standard sections. The
.rsrcentropy 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
- Artifact ID:
88ed83dc-1cea-4f8d-9581-0275abc1d3b9^[metadata.json] - MalwareBazaar source via OpenCTI connector
- Related: unclassified-autoit-compiled cluster page
- Related technique: k30zwmbjj-string-obfuscation (prior sibling variant)
Provenance
file.txt—filecommand outputpefile.txt— pefile.py parsed PE headersstrings.txt— raw strings extraction (2436 lines)capa.txt— Mandiant capa v8.x output (AutoIt limitation warning)binwalk.txt— binwalk embedded artefact scanrabin2-info.txt— radare2rabin2 -Iheader summaryscript.au3— decompiled AutoIt script viaautoit-ripperturbinate/selectee— extracted payload files fromautoit-ripperdynamic-analysis.md— CAPE skipped (no Windows guest available)