typeanalysisfamilysilverfoxconfidencehighcreated2026-06-04updated2026-06-04malware-familyloaderdefense-evasionpersistencec2evasionobfuscationpecode-injection
SHA-256: 452e085f42d6054435f95d363588f3d516f1a52d28b033f33a91e843ac4d720e

silverfox: 452e085f — MSVC C++ x64 process hollowing injector with LZSS decompressor and privilege escalation

Executive Summary

A stripped MSVC C++ x64 PE (228 KB) that decompresses an LZSS-compressed payload, escalates privileges to SeDebugPrivilege, enumerates running processes, and injects the decompressed second stage into a suspended child via VirtualAllocEx/NtWriteVirtualMemory/CreateProcessW. Also embeds an alternate ShellExecuteExW execution path and imports MoveFileExW for delayed self-erasure. No hardcoded C2 found statically; payload delivery and C2 are assumed to live inside the decompressed stage. This is the sixth confirmed SilverFox sibling, linking the 50K C stub (82d4255) and the RC4 loader (139329dc9) into a single toolchain evolution.

What It Is

Attribute Detail
SHA-256 452e085f42d6054435f95d363588f3d516f1a52d28b033f33a91e843ac4d720e^[triage.json]
File type PE32+ executable (GUI) x86-64, stripped, for MS Windows^[file.txt]
Size 233 880 bytes (228.4 KB)^[triage.json]
Compiler MSVC 14.0 (C/C++)^[pefile.txt:45]^,^[exiftool.json:18]
Linker MSVC 2015/2017 (14.0)^[pefile.txt:45]
Sections .text, .rdata, .data, .pdata, .rsrc, .reloc (6 sections, standard names)^[pefile.txt:75]
Stripped Yes (external PDB only)^[pefile.txt:39]
Exports 0^[pefile.txt:268]
Signature Unsigned (no Authenticode)^[rabin2-info.txt:27]
Imports KERNEL32.dll, ntdll.dll, ADVAPI32.dll, SHELL32.dll, PSAPI.DLL (5 DLLs, 46 total imports)^[pefile.txt:268]
Labels silverfox, trojan/silverfox.bg[qtsc]^[triage.json]

How It Works

Entry chain is a simple two-call thunk: entry @ 140001000FUN_140001020FUN_140001030.^[ghidra:entry:140001000] The main payload routine (FUN_140001030) orchestrates the full infection lifecycle.

Decompression. FUN_140001030 calls FUN_140004000 twice (at 140001723 and 140001c5b) to perform in-memory LZSS sliding-window decompression.^[ghidra:FUN_140001030] The decompressor recovers a 12-bit length/offset encoding with SSE-accelerated back-reference copies via FUN_1400065c0.^[ghidra:FUN_140004000] This is the same algorithm used by siblings ed1a0047 and beb3a9d9.^lzss-payload-decompression

Privilege escalation. Two internal helpers (FUN_1400038c0 and FUN_140003f80) both execute the same token-manipulation sequence: OpenProcessTokenLookupPrivilegeValueWAdjustTokenPrivileges to enable SeDebugPrivilege.^[ghidra:FUN_1400038c0, ghidra:FUN_140003f80] This prepares the injector for cross-session process access.

Process enumeration. CreateToolhelp32Snapshot / Process32FirstW / Process32NextW walk the process list; lstrcmpiW matches a target name decrypted at runtime.^[ghidra:FUN_140001030:process-enumeration] The target name is not recoverable statically.

Injection. VirtualAllocEx + NtWriteVirtualMemory (or WriteProcessMemory) write the decompressed payload into the remote process, followed by CreateProcessW with a custom STARTUPINFO built by FUN_140005190.^[ghidra:FUN_140001030:injection-chain] This is classic process-hollowing without CreateRemoteThread — the child is created suspended and its memory is overwritten before resumption.

Alternate execution path. If injection fails or the target process is unavailable, FUN_1400044b0 launches a new process via ShellExecuteExW.^[ghidra:FUN_1400044b0] This provides a reliability fallback.

Self-erasure. The binary imports MoveFileExW (no MOVEFILE_DELAY_UNTIL_REBOOT constant is visible statically, but the import profile and sibling behavior make the intent clear).^[pefile.txt:302]

Anti-analysis / sandbox evasion. No debugger checks or VM artifacts were found in the decompiled stub. The binary does enumerate loaded modules via NtQuerySystemInformation (SystemModuleInformation) in FUN_140005c00, looking for a specific decrypted module name; if absent, the execution path may diverge.^[ghidra:FUN_140005c00]

Decompiled Behavior

Entry point (entry @ 140001000)

// entry
  FUN_140001020();
  RtlExitUserProcess(0);

FUN_140001020 is a trivial wrapper that calls FUN_140001030 and returns.^[ghidra:FUN_140001020] All behavior lives in the single large routine at 140001030.

Main orchestrator (FUN_140001030)

This ~2700-byte function (Ghidra) contains 30+ API calls and 15 internal helper calls. Key order of operations inferred from callee list:

  1. GetModuleFileNameW — retrieves own path (self-reference check)
  2. CreateToolhelp32Snapshot + Process32FirstW / Process32NextW — enumerate processes
  3. lstrcmpiW — compare process names against a runtime-decoded target
  4. DuplicateHandle + GetProcessId — obtain a usable handle to the target
  5. OpenProcessTokenLookupPrivilegeValueWAdjustTokenPrivileges — escalate to SeDebugPrivilege
  6. GetSystemDirectoryW / GetTempPathW / GetTempFileNameW — prepare staging paths
  7. CreateFileW / CreateFileMappingW / MapViewOfFile — map payload buffer
  8. FUN_140004000 — LZSS decompress embedded payload into mapped view
  9. VirtualProtect — adjust page permissions on decompressed buffer
  10. VirtualAllocEx + NtWriteVirtualMemory — write payload into remote process
  11. CreateProcessW (via FUN_140005190) — create suspended child or reinject
  12. ShellExecuteExW (via FUN_1400044b0) — fallback launch
  13. MoveFileExW / DeleteFileW — cleanup / self-delete
  14. Sleep — pacing / sandbox evasion

LZSS decompressor (FUN_140004000)

Called from two call sites inside FUN_140001030. Signature: void FUN_140004000(longlong out_buf, ulonglong out_len, longlong in_buf, uint in_len, undefined4 *bytes_written). Uses 12-bit length/offset tokens, 4-byte SSE copy loops (FUN_1400065c0), and back-reference sliding-window reconstruction. Identical structural fingerprint to sibling beb3a9d9.^[ghidra:FUN_140004000]

Token escalators (FUN_1400038c0 and FUN_140003f80)

Both functions implement the same OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ...)LookupPrivilegeValueW(NULL, L"SeDebugPrivilege", ...)AdjustTokenPrivileges(..., SE_PRIVILEGE_ENABLED, ...) sequence.^[ghidra:FUN_1400038c0, ghidra:FUN_140003f80] Two copies suggest either linker artifact or deliberate redundancy.

Module enumerator (FUN_140005c00)

Resolves NtQuerySystemInformation dynamically (string-decoded), queries SystemModuleInformation (class 5), walks the module list looking for a decrypted target name, and extracts a DWORD from offset 0x2c of the matching entry.^[ghidra:FUN_140005c00] Used for environment gating or EDR targeting.

C2 Infrastructure

No hardcoded C2 strings recovered statically. All network-relevant indicators (domains, IPs, URLs, mutexes, named pipes) are absent from the string table. The binary is a pure loader/stager; C2 logic is expected to reside in the LZSS-decompressed second stage.

Interesting Tidbits

  • Embedded filename: UaaxkcZq.exe appears twice at 14001d914 and 14001d98c, likely a randomized per-build dropper name.^[strings.txt]
  • Version string: 9.8.4400.291 at 14001d8d8 and 14001da00 — probably a masquerade version or internal build tag.^[strings.txt]
  • No anti-debug: Unlike the RC4 loader sibling (139329dc9), this sample has no IsDebuggerPresent, no CheckRemoteDebuggerPresent, and no TLS callback anti-analysis.^[capa.txt]
  • Standard IAT: Unlike the PEB-walking variants (139329dc9, 82d4255), this binary uses a normal import table (46 imports across 5 DLLs), making static analysis straightforward once symbols are resolved.^[pefile.txt:268]
  • Size class: 228 KB sits neatly between the 50K C stub (82d4255) and the 173K RC4 loader (139329dc9), suggesting a progression: lean stub → medium IAT injector → heavy RC4 loader.

How To Mess With It (Homelab Replication)

Toolchain: MSVC 2017/2019 (v14.x), x64 Release.

Key ingredients:

  1. LZSS compressor (12-bit window) — any standard implementation works; pack a second-stage DLL/EXE into .rdata
  2. VirtualAllocEx + NtWriteVirtualMemory + CreateProcessW(CREATE_SUSPENDED) for hollowing
  3. OpenProcessTokenLookupPrivilegeValueW(L"SeDebugPrivilege")AdjustTokenPrivileges
  4. MoveFileExW(MOVEFILE_DELAY_UNTIL_REBOOT) for self-cleanup
  5. ShellExecuteExW fallback launcher

Verification step: Build a test injector that writes "HELLO" into a suspended notepad.exe. Run capa on the resulting binary — it should hit inject code into process, allocate or change RWX memory, and manipulate process privileges.

Deployable Signatures

YARA

rule silverfox_x64_injector_452e085f {
    meta:
        description = "SilverFox x64 process hollowing injector with LZSS decompressor"
        author = "PacketPursuit SOC"
        date = "2026-06-04"
        sha256 = "452e085f42d6054435f95d363588f3d516f1a52d28b033f33a91e843ac4d720e"
        family = "silverfox"
    strings:
        $uaax = "UaaxkcZq.exe" wide ascii
        $ver  = "9.8.4400.291" wide ascii
        $lzss_loop = { 48 8B 44 24 ?? 48 8B 4C 24 ?? E8 ?? ?? ?? ?? }  // FUN_1400065c0 copy helper
        $ntq = "NtQuerySystemInformation" wide ascii
        $se_debug = "SeDebugPrivilege" wide ascii
        $movf = "MoveFileExW" wide ascii
    condition:
        uint16(0) == 0x5a4d
        and pe.is_64()
        and ($uaax or $ver)
        and (pe.imports("KERNEL32.dll", "CreateProcessW")
             and pe.imports("KERNEL32.dll", "VirtualAllocEx")
             and pe.imports("ntdll.dll", "NtWriteVirtualMemory")
             and pe.imports("ADVAPI32.dll", "AdjustTokenPrivileges")
             and pe.imports("SHELL32.dll", "ShellExecuteExW"))
        and filesize < 300KB
}

Sigma

title: SilverFox Process Hollowing Injector
description: Detects SilverFox-like process injection chain with privilege escalation and LZSS decompressor
logsource:
    product: windows
    category: process_creation
detection:
    selection:
        CommandLine|contains:
            - "UaaxkcZq.exe"
            - "9.8.4400.291"
    selection_parent:
        ParentImage|endswith:
            - "UaaxkcZq.exe"
    selection_api:
        - ImageLoaded|endswith:
            - "\\psapi.dll"
        - CommandLine|contains:
            - "CreateProcessW"
            - "VirtualAllocEx"
            - "NtWriteVirtualMemory"
            - "AdjustTokenPrivileges"
    condition: selection or selection_parent or selection_api
falsepositives:
    - Unknown
level: high

IOCs

IOC Value Type
SHA-256 452e085f42d6054435f95d363588f3d516f1a52d28b033f33a91e843ac4d720e Hash
Embedded filename UaaxkcZq.exe String
Version string 9.8.4400.291 String
LZSS decompressor FUN_140004000 @ 0x140004000 Function
Token escalator 1 FUN_1400038c0 @ 0x1400038c0 Function
Token escalator 2 FUN_140003f80 @ 0x140003f80 Function
Main orchestrator FUN_140001030 @ 0x140001030 Function
Entry point 0x140001000 Address

Behavioral Fingerprint

This binary decompresses an LZSS payload at runtime, escalates privileges to SeDebugPrivilege, enumerates running processes via CreateToolhelp32Snapshot, and writes the decompressed payload into a suspended child process using VirtualAllocEx and NtWriteVirtualMemory. It also contains a fallback ShellExecuteExW execution path and imports MoveFileExW for delayed self-deletion. No hardcoded C2 is present; all network logic is assumed to live in the decompressed stage.

Detection Signatures

capa rule ATT&CK ID Evidence
inject code into process T1055 VirtualAllocEx, NtWriteVirtualMemory, CreateProcessW^[ghidra:FUN_140001030]
allocate or change RWX memory T1055 VirtualAllocEx / VirtualProtect^[ghidra:FUN_140001030]
manipulate process privileges T1055.012 OpenProcessToken, AdjustTokenPrivileges^[ghidra:FUN_1400038c0]
load library T1070.004 LoadLibraryW, GetProcAddress^[ghidra:FUN_140001030]
reference anti-VM strings T1497.001 None found static
encrypt data using RC4 T1027 None found (LZSS, not RC4)

Note: capa reports reference anti-VM strings but no specific strings were recovered in static analysis; this may be a false positive or the strings are runtime-decoded inside the LZSS payload.^[capa.txt]

References

  • silverfox — family entity page
  • lzss-payload-decompression — LZSS decompression technique
  • process-hollowing — process hollowing technique
  • SeDebugPrivilege-escalation — privilege escalation technique
  • NtQuerySystemInformation-module-enumeration — module enumeration technique
  • MoveFileExW-delayed-self-deletion — self-deletion procedure
  • ed1a00479fe2ea2555882c67719abc86e98b512f122aea79adacf37355cab996 — Rust sibling
  • 82d425516199d497c3a25edc4c3ad05c14469f697230f3ad17fe03ce73cd0216 — C stub sibling
  • 139329dc9992e132f9c8d887ad685660161cefcfb0a18867d616a7d217a0605e — RC4 loader sibling
  • beb3a9d9fa738ac7ebac7dc8f5357c9a6673cfae1bc50fd73497d350afd5ed1c — Authenticode sibling
  • e772de930167a24868814510021d73d8c061b4d7af0946ac302e53bb1c9cba56 — Sangfor masquerade sibling

Provenance

  • Static analysis performed with Ghidra (MCP) and radare2 (MCP) on pp-hermes LXC.
  • Imported binary: <sample 452e085f42d6.bin>
  • Ghidra project name: 452e085f42d6054435f95d363588f3d516f1a52d28b033f33a91e843ac4d720e.bin-1cdd44
  • radare2 analysis level: 2 (271 functions)
  • CAPE detonation: skipped — no Windows guest available. Dynamic behavior inferred from static decompilation.