Tropic Trooper Turns VS Code Tunnels and GitHub Issues into a Stealth C2, Plants Trojanized SumatraPDF on Devs

Introduction

Zscaler ThreatLabz has unwound a Tropic Trooper campaign — the same crew tracked elsewhere as Earth Centaur and Pirate Panda — that swaps out the group's old Cobalt Strike and Merlin tooling for an open-source AdaptixC2 beacon, a custom listener that runs on top of GitHub Issues, and Visual Studio Code tunnels for hands-on remote access. The initial dropper masquerades as a SumatraPDF binary inside a ZIP whose lure is a "comparative analysis" of US-UK and US-Australia nuclear-submarine cooperation, aimed at Chinese-speaking targets in Taiwan, South Korea, and Japan.

What Happened

Victims open a ZIP archive containing a renamed PE that looks like a SumatraPDF reader. The binary is real Sumatra plus a shellcode loader Zscaler identifies as TOSHIS, the same family used in earlier Tropic Trooper and TAOTH activity. TOSHIS pulls a decoy PDF from 58.247.193[.]100, opens it via ShellExecuteW so the user sees a believable document, then fetches an AES-128-CBC-encrypted second stage from the same host and runs it in memory.

That second stage is an AdaptixC2 Beacon. AdaptixC2 is open-source post-exploitation tooling, which on its own is unusual for a state-aligned crew that usually pays for or builds its own. The interesting modification is the listener: instead of beaconing to an attacker-controlled HTTP server, the agent writes to GitHub Issues on a repository the operators control. The beacon issues a POST to "Issue #1" with an RC4-encrypted session key and a randomly generated agent ID, then polls open issues for new tasks whose titles match patterns like upload or fileupload. Replies are uploaded back to the same repo as Base64-encoded files. To frustrate post-incident analysis, posted beacons are deleted within ten seconds, taking the per-session RC4 keys with them.

When ThreatLabz observed an operator decide a host was "interesting," the next step was to install Visual Studio Code and bring up a VS Code tunnel — Microsoft's authenticated remote-development feature — so the attacker had an interactive shell that traverses corporate egress over *.tunnels.api.visualstudio.com. On some hosts the operators dropped trojanized everyday applications next to legitimate ones to camouflage further activity. The C2 infrastructure also hosted Cobalt Strike Beacon and an EntryShell backdoor previously associated with the same crew.

Why It Matters

This is a near-perfect "live off trusted services" blueprint. Every leg of the kill chain rides on infrastructure that most enterprises explicitly cannot block: GitHub for source, vscode.dev and *.visualstudio.com for development, ipinfo.io for IP lookup. Network detections that lean on bad-domain reputation will see nothing actionable. Endpoint detections that focus on known C2 frameworks will miss it because AdaptixC2 plus a custom listener is not Cobalt Strike.

For DevOps and platform teams, the headline risk is the VS Code tunnel feature itself. By default it lets any user authenticated with a GitHub or Microsoft account expose their workstation as a remote-development target reachable from the open internet. That is fine for a developer working from a coffee shop; it is a backdoor when the workstation is sitting on your corporate VLAN with privileged credentials cached in memory. Tropic Trooper has now demonstrated that abuse path operationally, which means commodity actors will follow within months.

Who Is Affected

  • Organisations in Taiwan, South Korea and Japan with Chinese-speaking employees, especially those in defence, foreign affairs, and adjacent research domains.
  • Any environment that allows VS Code tunnels and GitHub API access from corporate workstations without per-user controls — Tropic Trooper has now field-tested using this combination as a live RAT.
  • Software users who download "PDF reader" or other utility binaries from email attachments or web downloads rather than vendor sites.
  • Indirectly, every defender who has been treating GitHub repositories as inherently trusted egress, since the listener depends on exactly that assumption.

How to Protect Yourself

Block or scope VS Code tunnels at the network and identity layer, not just on the endpoint. Microsoft documents the relevant hostnames; treat them as production-only egress for known users:

# example egress allowlist policy (conceptual; translate to your firewall syntax)
# only authorized dev workstations may reach VS Code tunnel infra
deny tcp any any host *.tunnels.api.visualstudio.com
allow tcp dev-workstations.corp any host *.tunnels.api.visualstudio.com

# audit who has used vscode tunnels on a fleet
# (run on workstations via your endpoint management)
code --list-extensions | findstr -i tunnel
code tunnel status

Microsoft also exposes a tenant-level policy. If you run Microsoft Entra ID, restrict tunnel creation to a named group rather than the default of "any signed-in user," and log every Tunnel.Create event into your SIEM.

Hunt for the GitHub-as-C2 pattern. The agent posts to a small set of issues per repository and deletes its own posts inside ten seconds; sustained, rapid issue traffic from a workstation IP to a repository nobody on that team owns is the canonical signal:

# enterprise audit log query (replace ORG)
gh api -H "Accept: application/vnd.github+json" \
  "/orgs/ORG/audit-log?phrase=action:issues.opened+OR+action:issues.deleted&per_page=100" \
  | jq '.[] | {actor, action, repo, created_at}'

# per-host hunt: short-lived outbound to api.github.com from non-developer machines
ss -tnp | grep api.github.com
journalctl --since '24 hours ago' | grep -E 'api\.github\.com.*POST|DELETE'

Lock down trojanized-binary delivery. Application allowlisting in WDAC or AppLocker that pins SumatraPDF to its known publisher signature is enough to stop the loader cold:

# example AppLocker publisher rule for a single trusted SumatraPDF version
New-AppLockerPolicy -RuleType Publisher -User Everyone -RuleNamePrefix "SumatraPDF" `
  -FileInformation (Get-AppLockerFileInformation -Path "C:\Program Files\SumatraPDF\SumatraPDF.exe") `
  -Optimize | Set-AppLockerPolicy -LDAP "LDAP://..."

On Linux developer workstations, the same principle applies via bwrap or firejail profiles for any reader-style binary launched from email or downloads.

Finally, the infection chain creates persistence via scheduled tasks with names like MSDNSvc or MicrosoftUDN — straight Living-off-the-Land impersonation. Treat those names as IoCs:

Get-ScheduledTask | Where-Object {
  $_.TaskName -match 'MSDNSvc|MicrosoftUDN' -or
  $_.Actions.Execute -match 'sumatra|temp\\.*\.exe'
} | Format-List TaskName, TaskPath, Actions, Triggers

If anything matches, image the host before remediation: the same workstation likely has a VS Code tunnel beacon and a GitHub repo waiting for the operator's next call-in.

Source