XOR string decryption loop
A static string obfuscation technique observed in Zig-compiled malware where encrypted blobs and their XOR keys are stored in .rdata, then decrypted at runtime into stack-allocated buffers before use.
Detection / Fingerprint
In disassembly, the pattern is a tight loop:
; rcx = encrypted data (rip-relative)
; rdx = key (rip-relative)
loop:
r8b = byte [rdx + (rax & 0xf)]
r8b ^= byte [rcx + rax]
byte [rsp + rax + offset] = r8b
rax++
cmp rax, length
jne loop
Key lengths are short (0x0A–0x36 bytes). The and r8d, 0xf suggests a repeating 16-byte key or offset masking. Multiple consecutive loops decrypt different strings, separated by API calls that consume the decrypted buffers.
Implementation Patterns Observed
In silentnet sample dbe586b5, the entry function contains at least six such loops, decrypting registry key paths, value names, C2 hostnames, and process command lines. Decrypted strings are consumed immediately by RegOpenKeyExA, RegQueryValueExA, getaddrinfo, and CreateProcessW.
Defensive Countermeasures
- Dynamic analysis (CAPE, sandbox) captures plaintext strings post-decryption.
- Memory forensics: scan stack buffers near entry for ASCII/UTF-16 shortly after
VirtualAllocor stack allocation. - Emulation: single-step through entry point to extract decrypted strings without full execution.