Z30PER Hex-Split String Obfuscation
What It Does
A string-obfuscation technique used in compiled AutoIt v3 scripts where plaintext strings are encoded as a sequence of 3-character groups. Each group consists of two hex digits representing one byte, followed by a single noise/padding character that is discarded during decoding. This creates a ~33% overhead but defeats naive string extraction because the raw bytes are split across triplets and interleaved with noise.
Detection / Fingerprint
Look for AutoIt decompiled scripts containing:
- A function named
Z30PER(case-insensitive variants possible) - A loop with
Step 3iterating over the obfuscated string StringMid(..., ..., 2)followed byChr(Dec(...))or equivalent- The function is called with long alphanumeric strings inside
Execute()wrappers
Implementation Pattern Observed
Func Z30PER($input)
Local $result = ""
For $i = 1 To StringLen($input) Step 3
Local $pair = StringMid($input, $i, 2)
$result &= Chr(Dec($pair))
Next
Return $result
EndFunc
^[/intel/analyses/64b37e90dd772573c46014c2fa8a1a7a1b69df4a6a16f573d0312360e404c60d.html]
The decoded output is typically used inside Execute() wrappers to reconstruct API names, DLL names, file paths, or shellcode bytes at runtime.
Reproduce on Your Own VMs
import random
def Z30PER(s):
"""Decode: take first 2 chars of each 3-char group, hex decode."""
return bytes(int(s[i:i+2], 16) for i in range(0, len(s), 3))
def Z30PER_encode(data: bytes) -> str:
"""Encode: hex each byte, append random padding char."""
out = []
for b in data:
noise = random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
out.append(f'{b:02x}{noise}')
return ''.join(out)
# Example: encode "kernel32.dll"
encoded = Z30PER_encode(b"kernel32.dll")
print(f"Encoded: {encoded}")
print(f"Decoded: {Z30PER(encoded)}")
Verification: search decompiled AutoIt scripts for Func Z30PER or Step 3 + Chr(Dec.
Defensive Countermeasures
- AutoIt decompilers (
autoit-ripper,MyAut2Exe) can extract the compiled script, revealing the obfuscation function. - Once the function is identified, automated decoders can be applied to all strings in the script.
- The technique is brittle — changing the step size or padding strategy breaks the decoder, but the function name and loop structure are highly distinctive.
Cross-References
- Observed in unclassified-autoit-compiled family, sample
64b37e90. - Similar in concept to u30jz3so7-permutation-xor-obfuscation and k30zwmbjj-string-obfuscation, but uses hex-split rather than permutation or Caesar shift.