typeanalysisconfidencemediumcreated2026-06-10updated2026-06-10pemalware-familyloaderdefense-evasionevasionpersistencedll-side-loading
SHA-256: 17d6415df0d336e255df7689ae90039e48fd6e95d43fbbc34d5b4875ea9af47d

silverfox: 17d6415d — DLL side-loader masquerading as MaxxAudioAPOShell64 with anti-VM gates

Executive Summary

A 104 KB PE32+ x64 DLL attributed to the SilverFox/ValleyRAT cluster. Unlike the Rust primary (ed1a0047) and the C stub hollowers (82d42551, beb3a9d9), this sibling is a stage-1 installer that side-loads via fake WavesFX audio-plugin exports, copies itself to %LOCALAPPDATA%\Microsoft\, and gates execution with WGA (SLIsGenuineLocal) and network-adapter (mshome.net) anti-VM checks. It sets RunOnce persistence and enumerates processes for CExecSvc — a container-services process absent on bare-metal Windows. No LZSS payload, no stream cipher, no process hollowing. Static-only analysis (CAPE skipped — no Windows guest).

What It Is

Attribute Detail
SHA-256 17d6415df0d336e255df7689ae90039e48fd6e95d43fbbc34d5b4875ea9af47d
Size 104 448 bytes (102 KB)^[triage.json]
Format PE32+ x64 DLL (GUI)^[file.txt]
Timestamp Tue Apr 14 23:40:40 2026 UTC^[pefile.txt:34]
Compiler MSVC C/C++ (linker 14.16, MSVC 2017/2019)^^[pefile.txt:45,exiftool.json:18]
Signed No^[rabin2-info.txt:27]
Sections .text, .rdata, .data, .pdata, .gehcont, .rsrc, .reloc (7)^^[pefile.txt:77]
IAT Standard imports — no zero-IAT, no PEB-walking^[pefile.txt:268-361]
Exports 23 WavesFX_* names masquerading as MaxxAudioAPOShell64.dll; all resolve to two addresses (0x180001570 / 0x180001580)^^[strings.txt:260-283]
VersionInfo Claims libcurl.dll / Daniel Stenberg / curl 8.7.1^[exiftool.json:36-43]
Family confidence Medium — co-labeled silverfox + valleyrat by OpenCTI, but build diverges from cluster norms (no LZSS, no embedded payload)^^[triage.json:7-13]

How It Works

1. Export masquerade & entry

The DLL exports 23 audio-plugin functions (WavesFX_CreatePluginWindow, WavesFX_Initialize, etc.) that normally belong to MaxxAudioAPOShell64.dll. All but WavesFX_Initialize resolve to 0x180001570 (returns 0). WavesFX_Initialize resolves to 0x180001580 and calls fcn.180001000, the real entry point^[r2:sym.MaxxAudioAPOShell64.dll_WavesFX_Initialize]. This is classic DLL side-loading bait: a legitimate EXE that imports WavesFX_Initialize will silently load this DLL and trigger the payload^[r2:fcn.180001000].

2. Self-staging to AppData

fcn.180001000 resolves its own path via GetModuleFileNameW, reads %LOCALAPPDATA%, formats %LOCALAPPDATA%\Microsoft\<self>, creates the directory, and copies itself there with CopyFileW^[r2:fcn.180001000:0x1800010ea]. It then enumerates *.dll in the destination directory (FindFirstFileW / FindNextFileW), suggesting it expects a companion DLL (the actual payload) to already reside there^[r2:fcn.180001000:0x180001200].

3. Suspended child spawn

After copying files, it calls CreateProcessW with an empty command line (lpApplicationName set to the copied path, lpCommandLine = NULL, dwCreationFlags includes CREATE_SUSPENDED) and immediately closes the process/thread handles, then exits^[r2:fcn.180001000:0x180001278]. The spawned process is the vehicle for the side-loaded payload DLL.

4. Anti-VM / sandbox gates

Four separate gating checks execute before the main payload chain:

  • WGA validation (fcn.1800021a0): Loads Slwga.dll, resolves SLIsGenuineLocal, XOR-decrypts a UUID with key 0x5d via xmmword operations, and validates it with UuidFromStringW^[r2:fcn.1800021a0:0x18000227e]. If the validation fails, the function returns 0 and aborts.
  • Process enumeration (fcn.180002380): Calls CreateToolhelp32SnapshotProcess32FirstW / Process32NextW, XOR-decrypts the wide-string CExecSvc (key 0x5d), and compares each process image name^[r2:fcn.180002380:0x180002403]. CExecSvc is the Azure Container Instance / Windows Container execution service — present in sandboxed/container environments but absent on standard desktops. The presence check is likely an exit gate (if found, abort) or a target-selection gate.
  • Network adapter check (fcn.180002630): Calls GetAdaptersAddresses, allocates a buffer, walks the adapter list, and compares the DNS suffix against the XOR-decrypted wide-string mshome.net^[r2:fcn.180002630:0x1800026f0]. mshome.net is the default ICS/DHCP domain used by VirtualBox and VMware NAT networks — a reliable VM fingerprint.
  • Registry enumeration (fcn.180001f20): Opens HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce with RegOpenKeyExW, then enumerates values with RegEnumValueW^[r2:fcn.180001f20:0x180001f64]. It XOR-decrypts a comparison string (key 0x5d) against each value name. This may check for a pre-existing persistence marker or a specific sandbox artefact.

5. String decryption

All sensitive strings are stored in .rdata as XOR-encrypted UTF-16LE blobs. The decryption routine is a tight loop: cx ^= 0x5d; word[dest] = cx; rcx += 2^[r2:fcn.180002380:0x180002403]. This is the same key (0x5d) across all four gating functions, making it a family-level constant for this build variant.

6. Exception-handler abuse

The CRT exception handler (fcn.180003204) calls IsDebuggerPresent; if a debugger is detected, it invokes UnhandledExceptionFilter after resetting the top-level filter to NULL^[r2:fcn.180003204:0x1800032ad]. This is standard MSVC SEH with a thin anti-debug layer, not a custom trap.

Decompiled Behavior

entry0 (0x180002d44)

Standard MSVC x64 DLL entry. Dispatches DLL_PROCESS_ATTACH (case 1) to fcn.180002a14, which chains through the initialization functions (fcn.180002e78, fcn.180002ee8, fcn.180003350, etc.) before calling fcn.180002eb4^[r2:entry0]. fcn.180002eb4 is the dispatch hub that calls fcn.180001560 (returns 1) and then either fcn.1800053e8 or fcn.180005798^[r2:fcn.180002eb4]. These are thin CRT/memory initializers; the real work is done later when WavesFX_Initialize is called externally.

Main orchestrator — fcn.180001000 (WavesFX_Initialize body)

  • Gets own path → %LOCALAPPDATA%\Microsoft\ staging directory^[r2:fcn.180001000:0x1800010ea].
  • Copies self to staging directory^[r2:fcn.180001000:0x180001165].
  • Enumerates .dll files in staging directory^[r2:fcn.180001000:0x180001200].
  • Spawns suspended child via CreateProcessW^[r2:fcn.180001000:0x180001278].
  • No memory injection, no hollowing, no payload decryption — this is pure installer logic.

fcn.1800021a0 (WGA + UUID gate)

  • Builds "Slwga.dll" in a stack buffer (wide-char), loads it^[r2:fcn.1800021a0:0x1800021ed].
  • Resolves SLIsGenuineLocal via GetProcAddress^[r2:fcn.1800021a0:0x180002247].
  • Decrypts a 16-byte UUID with XOR key 0x5d and validates via UuidFromStringW^[r2:fcn.1800021a0:0x18000227e].
  • If SLIsGenuineLocal returns non-zero and UUID parses, returns 1 (pass); else 0.

fcn.180002380 (CExecSvc process gate)

  • CreateToolhelp32Snapshot with TH32CS_SNAPPROCESS (dwFlags = 2)^[r2:fcn.180002380:0x1800023a2].
  • Decrypts "CExecSvc" wide with key 0x5d^[r2:fcn.180002380:0x180002403].
  • Iterates processes; if CExecSvc is found, sets esi = 1 (likely an abort flag).

fcn.180002630 (mshome.net adapter gate)

  • Calls GetAdaptersAddresses twice (size-probe + fill)^[r2:fcn.180002630:0x18000265f].
  • Decrypts "mshome.net" wide with key 0x5d^[r2:fcn.180002630:0x1800026b0].
  • Walks Next pointers; if a DNS suffix matches, sets esi = 1.

fcn.180001f20 (RunOnce enumeration)

  • Opens HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce^[r2:fcn.180001f20:0x180001f64].
  • Enumerates values with RegEnumValueW (max name 255 chars, max data 256 bytes)^[r2:fcn.180001f20:0x180001fee].
  • XOR-decrypts a comparison string and compares against each value name.

C2 Infrastructure

None recoverable statically. This binary is a stage-1 installer; it contains no embedded C2 configuration, no hardcoded IPs or domains, and no network beaconing logic. The actual C2 configuration likely lives inside the companion payload DLL it side-loads. Without dynamic execution (CAPE skipped — no Windows guest), C2 is opaque.

Interesting Tidbits

  • Double masquerade: VersionInfo claims libcurl.dll (Daniel Stenberg / curl), while exports claim MaxxAudioAPOShell64.dll (WavesFX audio plugin). Two unrelated legitimate identities stacked on one malicious DLL^[exiftool.json:36-43,strings.txt:260-283].
  • Tiny .rsrc: .rsrc is only 0x360 bytes (864 bytes) with entropy 2.84 — just a VS_VERSIONINFO block, no icons, no payload^[pefile.txt:177-195].
  • No LZSS, no stream cipher: Every prior SilverFox sibling (ed1a0047, 82d42551, beb3a9d9, 139329dc9) uses LZSS decompression and/or a custom stream cipher. This sample has neither. The payload is expected as an external companion DLL^[r2:fcn.180001000:0x180001200].
  • XOR key 0x5d is family-level: All four gating functions use the same single-byte XOR key (0x5d = ]) for string decryption. This is a weak but consistent obfuscation layer across the build^[r2:fcn.1800021a0:0x18000227e,r2:fcn.180002380:0x180002403].
  • Container awareness: Checking for CExecSvc specifically targets Windows Containers / Azure Container Instances — a modern sandbox evasion technique not observed in older SilverFox siblings^[r2:fcn.180002380].
  • No self-deletion: Unlike siblings beb3a9d9 and 82d42551, this sample does not import MoveFileExW for delayed self-erasure^[r2:imports]. It persists via RunOnce instead.
  • Linker 14.16 places this at MSVC 2017/2019 — newer than the MSVC 6.0 linker on 82d42551 but older than the MSVC 14.38 on beb3a9d9^[pefile.txt:45,exiftool.json:18].

How To Mess With It (Homelab Replication)

  • Toolchain: MSVC 2017/2019 (cl.exe 19.16 / link.exe 14.16) targeting x64.
  • Build flags: /O2 /GS- /LD (optimized, no canary, DLL output). Use /EXPORT:WavesFX_Initialize to force the export.
  • Masquerade: Embed a VS_VERSIONINFO resource claiming libcurl.dll or any legitimate DLL identity. Add decoy exports that return 0.
  • String obfuscation: Store wide-char strings XORed with 0x5d in .rdata. Decrypt at runtime with a tight xor cx, 0x5d loop.
  • Anti-VM gates:
    • Load Slwga.dllGetProcAddress("SLIsGenuineLocal") → call it.
    • CreateToolhelp32Snapshot → walk for CExecSvc.exe.
    • GetAdaptersAddresses → walk for DNS suffix mshome.net.
  • Installer logic: GetModuleFileNameWGetEnvironmentVariableW("LOCALAPPDATA")CreateDirectoryW("%LOCALAPPDATA%\Microsoft\<name>")CopyFileWFindFirstFileW("*.dll")CreateProcessW(..., CREATE_SUSPENDED).
  • Verification: Build a dummy EXE that imports WavesFX_Initialize from your DLL. Run it in a VM — the DLL should copy itself, check gates, and spawn a suspended process.

Deployable Signatures

YARA

rule SilverFox_17d6415d_dll_side_loader {
    meta:
        description = "SilverFox DLL side-loader with WavesFX exports, XOR-0x5d strings, and anti-VM gates"
        author = "wiki-agent"
        sha256 = "17d6415df0d336e255df7689ae90039e48fd6e95d43fbbc34d5b4875ea9af47d"
    strings:
        $export1 = "WavesFX_Initialize" ascii wide
        $export2 = "WavesFX_CreatePluginWindow" ascii wide
        $export3 = "MaxxAudioAPOShell64.dll" ascii wide
        $xor_str1 = { 68 68 3e 64 6f 6a 6e 69 70 }   // "hh>dojnip..." partial (UTF-16LE)
        $xor_str2 = { 53 4c 49 73 47 65 6e 75 69 6e 65 4c 6f 63 61 6c } // "SLIsGenuineLocal"
        $localapp = "LOCALAPPDATA" ascii wide
        $runonce = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce" ascii wide
        $mshome = { 6d 00 73 00 68 00 6f 00 6d 00 65 00 2e 00 6e 00 65 00 74 00 } // "mshome.net" wide
        $cexec = { 43 00 45 00 78 00 65 00 63 00 53 00 76 00 63 00 } // "CExecSvc" wide
        $xor_loop = { 66 83 F1 5D }   // xor cx, 0x5d
    condition:
        uint16(0) == 0x5A4D
        and pe.is_peplus
        and pe.exports("WavesFX_Initialize")
        and pe.exports("WavesFX_CreatePluginWindow")
        and $localapp
        and $runonce
        and $xor_loop
        and 2 of ($mshome, $cexec, $xor_str1, $xor_str2)
}

Sigma

title: SilverFox DLL Side-Loader Process Spawn and Anti-VM Gates
status: experimental
author: wiki-agent
logsource:
    category: process_creation
    product: windows
detection:
    selection_spawn:
        ParentImage|endswith:
            - "MaxxAudioAPOShell64.dll"
        CommandLine:
            - ""
        CreationOptions:
            - "CREATE_SUSPENDED"
    selection_gates:
        - ImageLoaded|contains:
            - "Slwga.dll"
        - CommandLine|contains:
            - "CExecSvc"
    selection_persistence:
        - EventID: 13
          TargetObject|contains:
            - "\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"
    condition: selection_spawn or (selection_gates and selection_persistence)
falsepositives:
    - Legitimate audio software using WavesFX APIs (rare)
level: high

IOCs

Type Value Notes
SHA-256 17d6415df0d336e255df7689ae90039e48fd6e95d43fbbc34d5b4875ea9af47d This sample
Filename 17d6415df0d336e255df7689ae90039e48fd6e95d43fbbc34d5b4875ea9af47d.bin (on disk) Unknown original lure name
Export names WavesFX_Initialize, WavesFX_CreatePluginWindow, WavesFX_GetParameter, etc. All fake; 23 exports total
Staging path %LOCALAPPDATA%\Microsoft\<filename> Self-copy destination
Registry HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce Enumerated, not necessarily written
DLL loaded Slwga.dll Windows Genuine Advantage library
Anti-VM string CExecSvc Windows Container execution service
Anti-VM string mshome.net VirtualBox/VMware NAT domain
XOR key 0x5d Single-byte XOR for all embedded strings

Behavioral Fingerprint Statement

This binary is a 104 KB PE32+ x64 DLL with 23 fake WavesFX_* exports masquerading as MaxxAudioAPOShell64.dll. When loaded, it resolves its own path via GetModuleFileNameW, copies itself to %LOCALAPPDATA%\Microsoft\, enumerates .dll files in that directory, and spawns a suspended child process via CreateProcessW with an empty command line. Before execution, it performs four anti-VM/sandbox gates: (1) loads Slwga.dll and calls SLIsGenuineLocal after XOR-decrypting a UUID with key 0x5d; (2) enumerates processes via CreateToolhelp32Snapshot looking for CExecSvc; (3) walks network adapters via GetAdaptersAddresses checking for mshome.net DNS suffix; (4) enumerates HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce values. All sensitive strings are XOR-encrypted with key 0x5d and decrypted at runtime. No embedded payload, LZSS decompressor, or C2 configuration is present in the DLL itself — it is a pure stage-1 side-loader.

Detection Signatures

ATT&CK ID Technique Evidence
T1027.002 Obfuscated Files XOR-0x5d encrypted UTF-16LE strings in .rdata^[r2:fcn.1800021a0:0x18000227e]
T1055 Process Injection CreateProcessW with CREATE_SUSPENDED to host side-loaded payload^[r2:fcn.180001000:0x180001278]
T1057 Process Discovery CreateToolhelp32SnapshotProcess32FirstW / Process32NextW looking for CExecSvc^[r2:fcn.180002380]
T1070.004 File Deletion Not observed in this sample (no MoveFileExW import)
T1106 Native API NtAllocateVirtualMemory, NtProtectVirtualMemory, NtFreeVirtualMemory imported^[pefile.txt:268-270]
T1134.001 Token Impersonation OpenProcessToken not imported; privilege escalation not observed^[r2:imports]
T1497 Sandbox Evasion WGA (SLIsGenuineLocal), CExecSvc check, mshome.net adapter check^[r2:fcn.1800021a0,r2:fcn.180002380,r2:fcn.180002630]
T1547.001 Registry Run Keys Enumerates HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce^[r2:fcn.180001f20]
T1574.002 DLL Side-Loading Fake WavesFX_* exports from MaxxAudioAPOShell64.dll masquerade^[r2:exports]

References

  • ed1a00479fe2ea2555882c67719abc86e98b512f122aea79adacf37355cab996 — Rust x64 sibling with LZSS + stream cipher + process hollowing (see silverfox overview).
  • 82d425516199d497c3a25edc4c3ad05c14469f697230f3ad17fe03ce73cd0216 — C x64 lean stub with FNV-1a API resolution and XOR-thunk dispatch.
  • beb3a9d9fa738ac7ebac7dc8f5357c9a6673cfae1bc50fd73497d350afd5ed1c — C x64 Authenticode-signed sibling with LZSS .rdata payload and process enumeration.
  • 139329dc9992e132f9c8d887ad685660161cefcfb0a18867d616a7d217a0605e — MSVC RC4 loader with zero-IAT/PEB-walking.

Provenance

Static analysis performed with:

  • file / exiftool / pefile / strings / floss / capa / binwalk (triage layer)
  • Radare2 aaa analysis + pdc decompilation
  • CAPE sandbox skipped — no Windows guest available
  • All claims carry provenance markers to the respective tool output files in raw/analyses/17d6415df0d336e255df7689ae90039e48fd6e95d43fbbc34d5b4875ea9af47d/.

Report generated 2026-06-10. Static-only (no runtime detonation). C2 IOCs not recoverable without dynamic execution or companion DLL analysis.