Back to reports

Six Stages, Zero Detections, and a VPS Hostname Baked Into the LNK: Anatomy of a German-Targeted Attack Chain

A Cloudflare Quick Tunnel hosts a complete LNK-to-shellcode chain with zero prior detections

PublishedApril 3, 2026
cloudflare-tunnellnkshellcodeprocess-injectionzero-detection

Security researcher @smica83 flagged a Cloudflare Quick Tunnel URL hosting a WsgiDAV open directory. The subdomain -- requires-fortune-nutten-eligible -- was auto-generated by Cloudflare's tunnel service. Inside: a complete, previously unreported attack chain targeting German-speaking users, with zero detections across every major threat intelligence platform.

No VirusTotal hits. No MalwareBazaar entries. No ThreatFox records. No URLhaus submissions. No URLScan results. Every sample in this chain was seeing daylight for the first time when we downloaded it.

The Open Directory

The Cloudflare Quick Tunnel at requires-fortune-nutten-eligible.trycloudflare[.]com hosts a WsgiDAV WebDAV server with anonymous read-write access. Directory listing enabled. Inside, eight files forming a complete six-stage attack chain.

The entry point is DKM_00KS0095283.PDF.lnk -- a Windows shortcut file disguised as a German financial PDF. The DKM prefix and numeric format mimic German financial document conventions (Darlehenskasse Münster or similar banking identifiers). The .PDF.lnk double extension exploits Windows' default behavior of hiding known file extensions, presenting the file as a simple PDF.

The Chain

Stage 1 -- LNK (DKM_00KS0095283.PDF.lnk) The shortcut uses a Microsoft Edge icon for visual credibility and calls wscript.exe to execute the next stage. LNK metadata reveals the operator's machine: hostname vps-756346, built under the Administrator account. This is a cloud VPS hostname -- the operator built the payload on their staging server and forgot to sanitize the metadata.

Stage 2 -- WSH (oa.wsh) A Windows Script Host configuration file that loads JScript from the WebDAV server. This is an unusual choice -- .wsh files are rarely seen in malware chains because most developers use .js or .vbs directly. The indirection adds a layer that bypasses some email and web gateway filters that block script extensions.

Stage 3 -- JScript (ccv.js) Uses ActiveXObject to create a Scripting.FileSystemObject, copies final.bat from the WebDAV share to %TEMP%\r.bat, and executes it hidden. The JScript stage serves as a bridge between the WebDAV delivery and the batch installer.

Stage 4 -- Batch Installer (final.bat) This is where the chain gets interesting. The batch file:

  • Downloads Python 3.11.8 embedded (the minimal, no-installer Python distribution)
  • Extracts it to a local directory
  • Installs pyaes and requests packages via pip
  • Downloads an encrypted payload file
  • Launches the Python loader

The operator chose Python 3.11.8 embedded specifically because it doesn't require installation, doesn't touch the registry, and leaves minimal forensic artifacts. The embedded distribution is a single directory of .pyd files and a python.exe -- drop it anywhere and it runs.

Stage 5 -- Python Loader (encrypted_loader.py) A Python script that:

  • Reads an encrypted binary blob
  • Decrypts it using AES-256-CBC with a hardcoded key
  • Calls VirtualAllocEx to allocate memory in explorer.exe
  • Writes the decrypted shellcode via WriteProcessMemory
  • Creates a remote thread with CreateRemoteThread

This is textbook process injection -- allocate, write, execute in a remote process. Using Python for the injection stage is uncommon and effective. Python's ctypes library provides direct access to Windows API functions, and Python processes are rarely flagged by EDR as suspicious.

Stage 6 -- Shellcode (101,634 bytes) The decrypted payload is position-independent x86_64 shellcode that walks the Process Environment Block (PEB) to resolve API addresses at runtime -- a standard technique for shellcode that needs to operate without import tables. The outer shellcode contains approximately 77 KB of additional encrypted data, suggesting a second decryption layer protecting the final implant (likely a RAT or C2 beacon).

Without dynamic execution or identification of the second-layer cipher, the final payload remains encrypted. The double-encryption architecture provides defense-in-depth for the operator -- even if the first AES layer is broken (as we did), the inner payload remains protected.

OPSEC Failures

Three mistakes that gave this operation away:

  1. VPS hostname in LNK metadata: vps-756346 is baked into the shortcut file's machine identifier. This reveals the operator uses a numbered cloud VPS (likely from a European hosting provider that uses this naming convention) and built the payload there rather than on a sanitized build machine.

  2. Administrator account: The LNK was created by the Administrator user -- the operator didn't create a low-privilege build account or sanitize the file metadata before deployment.

  3. Anonymous read-write WebDAV: The WsgiDAV server allows anonymous writes. Anyone who discovers the URL can modify the payload chain -- replacing the shellcode, altering the batch installer, or injecting their own stages. The operator's victims could be hijacked by a third party.

Detection

Seven YARA rules covering each stage of the chain -- LNK with VPS metadata, WSH loader, JScript ActiveXObject dropper, batch Python installer, encrypted loader, AES-256 shellcode decryptor, and PEB-walking shellcode -- are available on our GitHub:

Indicators of Compromise

Network Indicators

  • requires-fortune-nutten-eligible[.]trycloudflare[.]com

File Indicators

All 8 samples with SHA256 hashes are listed in the full report and published to our GitHub repository.

Behavioral Indicators

  • Python 3.11.8 embedded extraction to user-writable directory
  • pyaes package installation via pip
  • Python process calling VirtualAllocEx/WriteProcessMemory/CreateRemoteThread targeting explorer.exe
  • WsgiDAV WebDAV traffic over Cloudflare tunnel
  • LNK file with vps-756346 machine identifier

h/t @smica83 for the initial URL.

Share