Triage Insights

Triage Insights: WinLol, a Rust Dropper Chain Delivering a WebRTC Remote Desktop RAT

Blog.

WinLol: A Multi-Stage Rust Dropper Delivering a WebRTC Remote Desktop RAT

We discovered a new, publicly unreported malware toolkit that we call WinLol, after the Go module path its author compiled into the final payload: win-lol/cmd/agent. It is a four-stage chain. A Rust dropper fetches in-memory shellcode, the shellcode downloads a Go remote desktop agent, and the agent is launched through a DLL sideload of a legitimate, signed OneDrive executable. The agent then streams the victim’s screen to the operator over WebRTC.

It started in July 2026, when a researcher shared a sample on X (source) that had no family attribution at the time.

That sample (260721-xzvc3sgr6s) turned out to be the Rust dropper at the start of the chain.

Key Takeaways

Technical Analysis

Targeted Sample Information

In the first sample, every stage that uses the network talks to workinghardo[.]link (103.193.173[.]199) over plain HTTP on port 80.

Stage 1: Rust Dropper

The first stage is a 5.9 MB 64-bit Rust executable. Before downloading anything, it checks that it is not in a sandbox and that the operator still wants new infections:

Kill switch. For each configured server, the dropper requests /payload.txt and only continues if the response starts with ok (the C2 answered ok\r\n). By changing one file, the operator can stop every dropper before it reaches stage 2. The path itself is stored encrypted and decrypted with two XOR keys embedded in the code:

cipher @0x14047F5FC : F7 A9 82 EA 58 74 AC 97 | 6F AB A5 31
key                 : D8 D9 E3 93 34 1B CD F3 | 41 DF DD 45
                      └─ 0xF3CD1B3493E3D9D8 ─┘  └ 0x45DDDF41 ┘
plain               : /  p  a  y  l  o  a  d  | .  t  x  t

Configuration. The C2 list is stored in resource 101 as JSON, XOR-encrypted with a 2-byte key (AB CD in every build we found):

24 00 00 00 | d0 ef d8 a8 d9 bb ce bf ...   ->   {"servers":["workinghardo[.]link:80"]}

Decoy. Resource 100 holds a decoy document, opened only in builds with the decoy option enabled. The July builds carry a three-page PDF that uses Chinese fonts.

Preparing the sideload. The dropper does not ship OneDrive. It looks for the OneDrive.exe already installed on the victim’s machine and copies it to %TEMP%, where it will act as a trusted host for the malicious DLL.

Next to it, the dropper writes the malicious version.dll. The DLL is stored inside the dropper in a small embedded SQLite database that keeps files by name, each one XOR-encrypted with its own 32-byte key. The dropper looks up the row named version.dll, decrypts it and writes it to %TEMP%\version.dll. In every build we found, this is the only file in the database. When OneDrive.exe is later started from %TEMP%, Windows loads this version.dll instead of the real one.

Stage 2: [payload-c] Downloader

The dropper downloads /payload.bin and runs it inside its own process, so this stage never touches disk. It is a small C downloader that logs with a [payload-c] prefix. The downloader:

The downloader also tries to start the agent as administrator without a UAC prompt. Instead of asking the user, it asks Windows for an elevated copy of a built-in component (CMSTPLUA) and lets that component launch the agent, so the agent runs with full admin rights. If this fails, the agent is started as a normal user. Just before launching, the downloader also tries to remove the “downloaded from the internet” mark (Mark-of-the-Web) from the agent, so Windows is less likely to warn about it.

Stage 3: version.dll Sideload Proxy

This small DLL (19 KB) is the bridge between the legitimate OneDrive.exe and the RAT. It is not a program of its own: when OneDrive.exe starts from %TEMP%, Windows looks for version.dll in OneDrive’s own folder first, finds this one, and loads it into OneDrive’s memory. From then on, the DLL’s code runs as part of a signed Microsoft process.

The DLL does two things:

  1. Keeps OneDrive working. It exports the same 17 functions as the real version.dll and copies Microsoft’s version resource. When OneDrive.exe calls one of them, the DLL loads the real C:\Windows\System32\version.dll and passes the call through, so OneDrive behaves normally and nothing looks broken.
  1. Starts the RAT. As soon as it is loaded, a constructor starts a thread that waits two seconds, builds the path RiotClientServices.exe in its own folder (the name is assembled from pieces at runtime), and launches it hidden with ShellExecuteA. The DLL contains no RAT functionality itself; it is only the launcher.

The result looks like this:

OneDrive.exe  (legitimate, Microsoft-signed, copied to %TEMP% by stage 1)
 │
 ├─ version.dll  (stage 3, loaded inside OneDrive.exe)
 │    ├─ forwards OneDrive's calls to the real System32\version.dll
 │    └─ ShellExecuteA("RiotClientServices.exe")
 │
 └─ RiotClientServices.exe  (stage 4, the RAT, a separate child process of OneDrive.exe)

This is what makes the stage important: the RAT is started by a signed Microsoft process. In a process tree it would appear as a child of OneDrive.exe instead of the dropper, which makes the chain much harder to spot.

Stage 4: Go WebRTC Remote Desktop Agent

The final payload is a 12.4 MB Go executable. Its build information names the project and shows it was built from uncommitted code:

path    win-lol/cmd/agent
mod     win-lol v0.0.0-20260721235613-6c4109e75a17+dirty

Key dependencies are pion/webrtc v3.3.6 (with pion ICE, DTLS, SCTP and SRTP), gorilla/websocket, kbinani/screenshot, and lxn/win. Function names in the main package show what this Remote Access Trojan can do.

It captures the screen with DXGI, encodes it as H.264 (x264 or NVIDIA NVENC) and streams it over WebRTC. It can also launch itself into the user’s session from session 0, hide its process and inject a DLL.

The process hiding is aimed at Task Manager. main.startProcessHider drops an embedded DLL to the temp folder and shares the agent’s PID with it through a named file mapping. A background loop then looks for taskmgr.exe every 150 ms and injects the DLL into each new instance. Each Task Manager process is injected only once, and the agent logs every attempt ([hider] found taskmgr.exe pid=%d, injecting...).

Its C2 and an agent key are compiled in. The key 55yf5Lit5ZCI5qyi5aSp5LiL56ys5LiA is base64 for the Chinese phrase 真中合欢天下第一 (“True Chinese Acacia is the best in the world”). An agent_config.json next to the executable can override the servers, but not the key.

The key is a shared secret for each build, not a per-victim ID. On first start, the agent enrolls with POST /api/auto-register, sending the key in an X-Agent-Key header and a label in the JSON body. The server replies with a code that identifies this victim from then on. The agent then opens a websocket to /ws/agent and announces itself with that code. The operator sends commands over this websocket, such as redirecting the agent to another server or starting a stream.

When the operator starts a stream, the agent fetches STUN/TURN servers and credentials from /api/rtc/ice-config, again with the X-Agent-Key header. It then exchanges the WebRTC offer, answer and ICE candidates over the websocket, and sends the screen as a video track. The stream is view-only: there is no data channel and no keyboard or mouse input.

The video itself is encrypted with DTLS-SRTP and often relayed through TURN on port 3478, so it reveals little. The control traffic is plain HTTP and websocket, without TLS. The /api/auto-register and /api/rtc/ice-config requests, the X-Agent-Key header and the /ws/agent upgrade are all visible on the wire, which makes them the best network indicators.

Campaign Evolution

Using the Recorded Future Malware Analysis and Threat Intelligence platform to hunt for related samples, we found ten dropper builds, three standalone downloader builds and three agent builds submitted between 2 July and 26 August 2026. Across these builds, the toolkit changed as follows:

Attribution

We have not linked WinLol to any known actor. Two details point weakly to a Chinese-speaking developer or audience: the decoy document uses Chinese fonts, and the agent key decodes to a Chinese phrase. Neither is strong evidence on its own. The Riot Games branding of the lures suggests the campaign is aimed at gamers.

Detection

Triage detects the dropper, the downloader (on disk and in memory) and the agent as family winlol, and extracts their C2 servers.

MITRE ATT&CK Techniques

ID Technique
T1497.001 / T1497.003 Virtualization/Sandbox Evasion: System Checks, Time Based Evasion
T1105 Ingress Tool Transfer
T1620 Reflective Code Loading
T1574.002 DLL Side-Loading
T1548.002 Bypass User Account Control
T1553.005 Mark-of-the-Web Bypass
T1547.001 Registry Run Keys
T1562.004 Disable or Modify System Firewall
T1113 Screen Capture

Conclusion

WinLol pairs a carefully built delivery chain with a modern remote desktop implant: a Rust dropper with a server-side kill switch, an in-memory downloader, DLL sideloading through a signed Microsoft binary, and a Go agent that streams the desktop over encrypted WebRTC. Almost every configuration value can be recovered statically, which makes new builds straightforward to track.

We will continue to monitor potential threats, including recent trends and emerging families. Stay tuned and follow our blog posts to get the most out of our sandbox. If you haven’t signed up yet, visit tria.ge to register for a free account!

Indicators of Compromise (IOCs)

Stage 1: Rust Dropper

SHA256 Triage submit
1e82f3fa779038d208279eca1a420f168bb4b9be95ba521362e5658cd33840e7 261008-r5gfhs1t2n
5fff61dff1fe18f59ebabe729c5ff9c42de64911248fb424815755fc7e76d5a1 261002-q19e3a1tev
18868595393c5345e99ebe6dbfe60780aef388836b125696a3201f1a88e67c47 261008-r5f5raywhy
7de267b3b415386424cefb3cb935436462ec0490a624e886615513e80606b9b2 261008-r7thvshz4n
b967ebdcb56423fd2021ce01248769ebc073f7fd00eb14870e0f45cb345f9aee 261008-r5hzcaywh1
d3740b8d4744dea17e58e918485273980380c3595c31cb4b938c06bd4d1222a3 261008-r5jwmshz2r
f2e81dff1c3bb139f8865327180c4d45fce68cf44e4ec445c4df8b49158bed9d 261008-r5kg6shz3w
a1a91d9cd396186c4fde28e050f88aa68062b05195aaea091e7b3a1ca7539893 261008-r5hnksywhz
82400db6e1195da7dd6db5526f795362ca9f13ef7ed5d2dba8b730fba7663f78 261008-r5hctahz2l
e7ccdf128df08e131c910e904a0be711273a2f33a531e208ec531ca19b0d091e 261008-r83g6ahz7x

Stage 2: [payload-c] Downloader

SHA256 Triage submit
e7e640540ef158cf77b8d84e1b153cf0133d07cb70133f501ba306ae1e00586d 261002-q192lawdrf
3690c237facca095803acfd0b5e702643fcf7a22f3b16a7ac00d1bc2337d370b 261008-r5graa1t2p
713ec0de0e018e22642e280d02ca1516e05235fb99d72355abb1d7bca5737dd2 261008-r5graahz3v

Stage 3: version.dll Sideload Proxy

SHA256 Triage submit
593d05c817b5f41bd0cbdcfbd9729c6a875173303f700c4dd953046f9b2f6de7 260722-3ldq3asxbw (dropped file)
668c0851af5a3a1f685f3e632e4cce3f71aed73808deefe4c5b59bf40088d4fa 260728-y4zzssgq8s

Stage 4: Go Agent

SHA256 Triage submit
4eae9858ccc07ad60b3e5deb45d30e0439d0f30309ddc75097d1878e784b3aaf 260721-xzvc3sgr6s (dropped file)
c1dfd3712d6f927acf98a78f1b77367d0b57aefbcd6ea8a7120d61a2b8a76525 261005-n1awds1hqd
baa36514329766db2993e8435d92209f167b27725e54ca166239158bd100794f 261008-r5jkwahz2p

Network

Indicator Type
workinghardo[.]link Domain
havefunnn[.]win Domain
103.193.173[.]199 IP
103.193.173[.]83 IP
47.108.192[.]193 IP

You may also like: