17d6415df0d336e255df7689ae90039e48fd6e95d43fbbc34d5b4875ea9af47dsilverfox: 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): LoadsSlwga.dll, resolvesSLIsGenuineLocal, XOR-decrypts a UUID with key0x5dviaxmmwordoperations, and validates it withUuidFromStringW^[r2:fcn.1800021a0:0x18000227e]. If the validation fails, the function returns 0 and aborts. - Process enumeration (
fcn.180002380): CallsCreateToolhelp32Snapshot→Process32FirstW/Process32NextW, XOR-decrypts the wide-stringCExecSvc(key0x5d), and compares each process image name^[r2:fcn.180002380:0x180002403].CExecSvcis 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): CallsGetAdaptersAddresses, allocates a buffer, walks the adapter list, and compares the DNS suffix against the XOR-decrypted wide-stringmshome.net^[r2:fcn.180002630:0x1800026f0].mshome.netis the default ICS/DHCP domain used by VirtualBox and VMware NAT networks — a reliable VM fingerprint. - Registry enumeration (
fcn.180001f20): OpensHKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOncewithRegOpenKeyExW, then enumerates values withRegEnumValueW^[r2:fcn.180001f20:0x180001f64]. It XOR-decrypts a comparison string (key0x5d) 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
.dllfiles 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
SLIsGenuineLocalviaGetProcAddress^[r2:fcn.1800021a0:0x180002247]. - Decrypts a 16-byte UUID with XOR key
0x5dand validates viaUuidFromStringW^[r2:fcn.1800021a0:0x18000227e]. - If
SLIsGenuineLocalreturns non-zero and UUID parses, returns 1 (pass); else 0.
fcn.180002380 (CExecSvc process gate)
CreateToolhelp32SnapshotwithTH32CS_SNAPPROCESS(dwFlags = 2)^[r2:fcn.180002380:0x1800023a2].- Decrypts
"CExecSvc"wide with key0x5d^[r2:fcn.180002380:0x180002403]. - Iterates processes; if
CExecSvcis found, setsesi = 1(likely an abort flag).
fcn.180002630 (mshome.net adapter gate)
- Calls
GetAdaptersAddressestwice (size-probe + fill)^[r2:fcn.180002630:0x18000265f]. - Decrypts
"mshome.net"wide with key0x5d^[r2:fcn.180002630:0x1800026b0]. - Walks
Nextpointers; if a DNS suffix matches, setsesi = 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 claimMaxxAudioAPOShell64.dll(WavesFX audio plugin). Two unrelated legitimate identities stacked on one malicious DLL^[exiftool.json:36-43,strings.txt:260-283]. - Tiny .rsrc:
.rsrcis 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
0x5dis 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
CExecSvcspecifically 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
beb3a9d9and82d42551, this sample does not importMoveFileExWfor delayed self-erasure^[r2:imports]. It persists viaRunOnceinstead. - Linker 14.16 places this at MSVC 2017/2019 — newer than the MSVC 6.0 linker on
82d42551but older than the MSVC 14.38 onbeb3a9d9^[pefile.txt:45,exiftool.json:18].
How To Mess With It (Homelab Replication)
- Toolchain: MSVC 2017/2019 (
cl.exe19.16 /link.exe14.16) targetingx64. - Build flags:
/O2 /GS- /LD(optimized, no canary, DLL output). Use/EXPORT:WavesFX_Initializeto force the export. - Masquerade: Embed a
VS_VERSIONINFOresource claiminglibcurl.dllor any legitimate DLL identity. Add decoy exports that return 0. - String obfuscation: Store wide-char strings XORed with
0x5din.rdata. Decrypt at runtime with a tightxor cx, 0x5dloop. - Anti-VM gates:
- Load
Slwga.dll→GetProcAddress("SLIsGenuineLocal")→ call it. CreateToolhelp32Snapshot→ walk forCExecSvc.exe.GetAdaptersAddresses→ walk for DNS suffixmshome.net.
- Load
- Installer logic:
GetModuleFileNameW→GetEnvironmentVariableW("LOCALAPPDATA")→CreateDirectoryW("%LOCALAPPDATA%\Microsoft\<name>")→CopyFileW→FindFirstFileW("*.dll")→CreateProcessW(..., CREATE_SUSPENDED). - Verification: Build a dummy EXE that imports
WavesFX_Initializefrom 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 | CreateToolhelp32Snapshot → Process32FirstW / 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.rdatapayload 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
aaaanalysis +pdcdecompilation - 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.