Back to Intelligence

Dark Caracal's GoCaracal Espionage Framework: Detection, Hunting, and Defense Guide for SOC Teams

SA
Security Arsenal Team
August 26, 2026
11 min read

Dark Caracal — the long-running cyber espionage group previously tied to the Crosswalk and Operation Manul campaigns and widely assessed to operate in support of nation-state interests in the Middle East — has added a new weapon to its arsenal. Researchers have identified GoCaracal, a modular malware framework written in Go that expands the group's ability to steal data from compromised hosts and maintain long-term access to victim environments.

This matters to defenders for three reasons. First, Dark Caracal has a documented history of targeting governments, military organizations, financial institutions, journalists, and activists — and its operations tend to run quietly for months or years before discovery. Second, Go-compiled malware is inherently cross-platform, meaning GoCaracal modules can plausibly be retargeted across Windows, Linux, and macOS with minimal reengineering. Third, a modular architecture means the operator decides post-compromise which capabilities to deploy — credential theft, file collection, screen capture, keylogging, secondary payloads — making static indicator-based defense insufficient on its own.

If your organization operates in government, defense, energy, telecom, financial services, media, or NGO sectors, you should treat this as an active threat requiring immediate hunting, not an informational bulletin.

Technical Analysis

Who Is Dark Caracal?

Dark Caracal is an espionage actor first publicly documented in 2018 by Lookout and the Electronic Frontier Foundation. The group has historically relied on:

  • Phishing and watering-hole delivery via trojanized applications and fake secure-messaging lures
  • Pallas, its Windows surveillance malware
  • Mobile implants targeting Android devices
  • Compromised infrastructure including fake login portals harvesting credentials at scale

The addition of GoCaracal signals an ongoing investment in tooling modernization — consistent with what we see across espionage actors migrating from C/C++ and .NET implants to Go for portability, AV evasion benefits, and rapid module development.

How GoCaracal Works (Defender's View of the Attack Chain)

Based on the reported capabilities, the attack chain defenders should model looks like this:

  1. Initial access — consistent with Dark Caracal tradecraft, expect spear-phishing with malicious attachments/links, trojanized applications, or compromised websites. The implant typically lands in a user-writable directory (%APPDATA%, %LOCALAPPDATA%\Temp, ~/Library, /tmp, or a user's home directory on Linux).
  2. Execution — Go binaries are characteristically large (often 5–15 MB+ due to static runtime linking) and frequently unsigned or signed with invalid/self-signed certificates. GoCaracal's core implant acts as a loader and tasking agent.
  3. Persistence — modular espionage frameworks of this class typically establish persistence via registry Run keys, scheduled tasks, or service installation on Windows, and via cron, systemd units, or shell profile modification on Linux/macOS.
  4. Module staging — the core implant downloads or receives additional modules from C2 (data collection, credential theft, screenshot, keylogging). Modules may execute in memory, leaving minimal disk artifacts.
  5. Collection and staging — stolen data is aggregated in a staging directory (commonly under a temp or user profile path, sometimes disguised with innocuous folder names) before exfiltration.
  6. Exfiltration / C2 — encrypted communications over HTTP/HTTPS to attacker-controlled infrastructure, often domains registered to mimic legitimate services. Dark Caracal has historically reused hosting providers and registrars, which supports infrastructure clustering.

Exploitation Status

GoCaracal is a confirmed active malware framework observed in the wild as part of Dark Caracal operations. No CVE is associated with this news item — this is not a vulnerability story; it is a tooling story. The defensive priority is behavioral detection of the implant lifecycle and hunting for existing compromise, not patching. Because Dark Caracal campaigns historically persist undetected for extended periods, organizations in targeted sectors should assume the possibility of pre-existing intrusion and hunt retroactively, not just monitor going forward.

Affected Platforms

Because GoCaracal is Go-based, defenders should assume cross-platform capability: Windows workstations and servers, Linux servers, and macOS endpoints are all within scope. Historical Dark Caracal activity also included Android; mobile device management telemetry should not be ignored.

Detection & Response

The detections below target the behaviors most reliably observable across a modular Go-based espionage implant: unsigned Go binaries executing from user-writable paths, persistence via Run keys and scheduled tasks pointing at unusual locations, and staging/collection activity. Every rule is designed to be high-signal in a well-managed environment — tune the allowlists to your environment before production deployment.

Sigma Rules

The first rule catches a strong generic signal: unsigned executables with Go runtime characteristics running from user-writable directories — the classic landing pattern for Go-based implants. The second targets persistence creation pointing at those same paths. The third targets mass collection staging via archive utilities spawned by unexpected parent processes.

YAML
---
title: Unsigned Go Binary Executing from User-Writable Directory
id: 3f8c2a71-9b4d-4e6a-b1c7-2d5e8f0a1b3c
status: experimental
description: Detects execution of unsigned binaries exhibiting Go runtime characteristics from user-writable paths, consistent with Go-based implant landing behavior observed in espionage frameworks such as GoCaracal.
references:
  - https://www.darkreading.com/cyberattacks-data-breaches/dark-caracal-adds-new-malware-cyber-espionage-arsenal
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.execution
  - attack.defense_evasion
  - attack.t1059
  - attack.t1027
logsource:
  category: process_creation
  product: windows
detection:
  selection_path:
    Image|contains:
      - '\AppData\Roaming\'
      - '\AppData\Local\Temp\'
      - '\AppData\Local\Microsoft\Windows\'
      - '\Users\Public\'
      - '\ProgramData\'
  selection_unsigned:
    Signed: 'false'
  filter_known_good:
    Image|contains:
      - '\AppData\Local\Microsoft\Teams\'
      - '\AppData\Local\slack\'
      - '\AppData\Local\Discord\'
      - '\AppData\Roaming\Zoom\'
      - '\AppData\Local\Programs\'
  condition: selection_path and selection_unsigned and not filter_known_good
falsepositives:
  - Legitimate user-installed applications (Slack, Teams, Zoom, Discord updaters) — allowlist per environment
  - Developer tooling compiled locally
level: high
---
title: Persistence via Run Key or Scheduled Task Pointing to User-Writable Path
id: 6a1d4e92-7c3b-4f58-a2d9-1e8c5b0f3a7d
status: experimental
description: Detects registry Run key modification or scheduled task registration whose target executable resides in a user-writable or temp directory, a persistence pattern consistent with modular espionage implants such as GoCaracal.
references:
  - https://www.darkreading.com/cyberattacks-data-breaches/dark-caracal-adds-new-malware-cyber-espionage-arsenal
  - https://attack.mitre.org/techniques/T1060/
  - https://attack.mitre.org/techniques/T1053/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.persistence
  - attack.t1547.001
  - attack.t1053.005
logsource:
  category: registry_set
  product: windows
detection:
  selection_key:
    TargetObject|contains:
      - '\CurrentVersion\Run\'
      - '\CurrentVersion\RunOnce\'
  selection_value:
    Details|contains:
      - '\AppData\Local\Temp\'
      - '\Users\Public\'
      - '%temp%'
      - '$Recycle.Bin'
  condition: selection_key and selection_value
falsepositives:
  - Rare; legitimate software does not normally persist from temp paths. Investigate all hits.
level: critical
---
title: Archive Utility Spawned by Unsigned Process for Data Staging
id: 9c2e7b45-3d1a-4f86-b5c2-8a0d6e4f1b9c
status: experimental
description: Detects compression/archiving utilities (rar, 7z, tar) spawned by unsigned or non-standard parent processes, indicating potential data staging prior to exfiltration by espionage malware.
references:
  - https://www.darkreading.com/cyberattacks-data-breaches/dark-caracal-adds-new-malware-cyber-espionage-arsenal
  - https://attack.mitre.org/techniques/T1560/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.collection
  - attack.t1560.001
logsource:
  category: process_creation
  product: windows
detection:
  selection_tool:
    Image|endswith:
      - '\rar.exe'
      - '\7z.exe'
      - '\7za.exe'
      - '\winzip.exe'
      - '\tar.exe'
  selection_parent:
    ParentImage|contains:
      - '\AppData\'
      - '\Users\Public\'
      - '\ProgramData\'
      - '\Temp\'
  condition: selection_tool and selection_parent
falsepositives:
  - Backup agents and software installers extracting archives — verify parent process reputation and signer
level: high

KQL — Microsoft Sentinel / Defender Hunt

This hunt joins process execution with network activity to surface unsigned Go-style binaries in user paths that also beacon outbound — the strongest composite signal for a staged implant. Run it over at least 30 days given Dark Caracal's historically low-and-slow operational tempo.

KQL — Microsoft Sentinel / Defender
// Hunt: unsigned binaries in user-writable paths with outbound network connections
// Consistent with Go-based espionage implant behavior (GoCaracal / Dark Caracal)
let Lookback = 30d;
let SuspiciousPaths = dynamic([@"\AppData\Local\Temp", @"\AppData\Roaming", @"\Users\Public", @"\ProgramData", @"$Recycle.Bin"]);
let ProcHits =
    DeviceProcessEvents
    | where TimeGenerated > ago(Lookback)
    | where FolderPath has_any (SuspiciousPaths)
    | where not(FolderPath has_any (@"\Microsoft\Teams", @"\slack\", @"\Discord", @"\Zoom", @"\AppData\Local\Programs"))
    | summarize ProcessCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
      by DeviceName, FileName, FolderPath, SHA256, InitiatingProcessFileName;
let NetHits =
    DeviceNetworkEvents
    | where TimeGenerated > ago(Lookback)
    | where RemoteIPType == "Public"
    | summarize Connections = count(), RemoteIPs = make_set(RemoteIP, 10), RemoteUrls = make_set(RemoteUrl, 10)
      by DeviceName, InitiatingProcessFileName, InitiatingProcessFolderPath, InitiatingProcessSHA256;
ProcHits
| join kind=inner (NetHits)
  on $left.SHA256 == $right.InitiatingProcessSHA256
| project DeviceName, FileName, FolderPath, SHA256, ProcessCount, FirstSeen, LastSeen, Connections, RemoteIPs, RemoteUrls
| order by FirstSeen asc;

A complementary hunt for the persistence behavior, using endpoint registry telemetry:

KQL — Microsoft Sentinel / Defender
// Hunt: Run key / RunOnce persistence pointing at temp or public user paths
let Lookback = 30d;
DeviceRegistryEvents
| where TimeGenerated > ago(Lookback)
| where RegistryKey has_any (@"\CurrentVersion\Run", @"\CurrentVersion\RunOnce")
| where RegistryValueData has_any (@"\Temp\", @"\Users\Public\", @"%temp%", @"$Recycle.Bin")
| project TimeGenerated, DeviceName, RegistryKey, RegistryValueName, RegistryValueData, InitiatingProcessFileName, InitiatingProcessFolderPath
| order by TimeGenerated desc;

Velociraptor VQL

This artifact triages a suspected host for unsigned executables in user-writable paths that also hold established outbound connections — the fastest way to validate a GoCaracal lead during IR:

VQL — Velociraptor
-- Hunt: unsigned processes in user-writable paths with established outbound connections
-- Deploy as a Velociraptor hunt across targeted sectors/endpoints
SELECT Pid, Name, Exe, CommandLine, Username,
       netstat().RemoteIP AS RemoteIP,
       netstat().RemotePort AS RemotePort,
       netstat().Status AS ConnStatus,
       authenticode(filename=Exe).Trusted AS SignatureTrust
FROM pslist()
WHERE Exe =~ '(AppData|Users.Public|ProgramData|Temp)'
  AND netstat().Status =~ 'ESTAB'
  AND NOT authenticode(filename=Exe).Trusted =~ 'trusted'

A second artifact to sweep for persistence artifacts and recently written executables in staging locations:

VQL — Velociraptor
-- Sweep persistence keys and recently created executables in user-writable dirs
SELECT "RunKey" AS ArtifactType,
       FullPath AS Location,
       Data.value AS ValueData
FROM glob(globs='HKEY_USERS\*\Software\Microsoft\Windows\CurrentVersion\Run*\**', accessor='registry')
WHERE Data.value =~ '(Temp|Public|ProgramData)'
UNION ALL
SELECT "RecentExe" AS ArtifactType,
       FullPath AS Location,
       '' AS ValueData
FROM glob(globs='C:\Users\*\AppData\**\*.exe')
WHERE timestamp(epoch=Ctime) > now() - 2592000

Verification and Hardening Script

Use this PowerShell triage script during IR scoping or as a scheduled audit on high-value assets. It enumerates suspicious persistence entries, unsigned executables in user-writable paths, and recent large outbound-transfer candidates.

PowerShell
# GoCaracal / Go-implant triage — run elevated on suspected hosts
# 1) Audit Run/RunOnce keys for suspicious target paths
Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run*',
                     'HKLM:\Software\Microsoft\Windows\CurrentVersion\Run*' -ErrorAction SilentlyContinue |
  ForEach-Object {
    $_.PSObject.Properties | Where-Object {
      $_.Value -is [string] -and $_.Value -match 'Temp|Public|ProgramData|\$Recycle'
    } | Select-Object @{n='Key';e={$_.Name}}, @{n='Value';e={$_.Value}}
  }

# 2) Inventory scheduled tasks pointing at user-writable paths
Get-ScheduledTask | ForEach-Object {
  $actions = $_.Actions | Where-Object { $_.Execute -match 'AppData|Public|Temp' }
  if ($actions) { [pscustomobject]@{ Task=$_.TaskName; Path=$_.TaskPath; Exe=($actions.Execute -join ';') } }
}

# 3) Find unsigned executables in user-writable directories (last 30 days)
$cutoff = (Get-Date).AddDays(-30)
Get-ChildItem -Path "$env:APPDATA","$env:LOCALAPPDATA\Temp","C:\Users\Public","C:\ProgramData" `
  -Recurse -Filter *.exe -ErrorAction SilentlyContinue |
  Where-Object { $_.CreationTime -gt $cutoff } |
  ForEach-Object {
    $sig = Get-AuthenticodeSignature $_.FullName
    if ($sig.Status -ne 'Valid') {
      [pscustomobject]@{ File=$_.FullName; Created=$_.CreationTime; SizeMB=[math]::Round($_.Length/1MB,1); SigStatus=$sig.Status }
    }
  }

# 4) Enable/verify key audit telemetry for forward detection
AuditPol /set /subcategory:"Process Creation" /success:enable /failure:enable
AuditPol /set /subcategory:"Security System Extension" /success:enable
wevtutil set-log Microsoft-Windows-Sysmon/Operational /enabled:true 2>$null
Write-Output "Triage complete. Review unsigned EXEs and persistence entries above; isolate host if confirmed."

Remediation and Defensive Recommendations

Because this is a tooling/capability disclosure rather than a patchable vulnerability, remediation is about detection posture, attack surface reduction, and retroactive hunting:

  1. Hunt retroactively now. Run the KQL queries above across a minimum 30–90 day window. Dark Caracal operations historically persist undetected for long periods; a clean 7-day window means nothing.
  2. Enforce application control. Deploy WDAC or AppLocker policies blocking unsigned executables from running out of user-writable directories. This single control breaks the default landing pattern of most Go-based implants.
  3. Harden persistence surfaces. Alert on any Run key, RunOnce key, or scheduled task creation referencing %TEMP%, %APPDATA%, C:\Users\Public, or C:\ProgramData. Legitimate software almost never persists from these locations.
  4. Constrain egress. Deny direct outbound internet access from servers; force workstation traffic through authenticated proxies with TLS inspection where policy permits. Alert on endpoints with sustained low-volume periodic connections to uncommon external IPs — classic low-and-slow beaconing.
  5. Monitor for staging behavior. Alert on archive utilities (rar, 7z, tar) executed by non-standard parent processes, and on creation of large compressed archives in user directories.
  6. Address the phishing vector. Dark Caracal's historical access vector is credential phishing and trojanized applications. Enforce phishing-resistant MFA (FIDO2/passkeys) for all remote access, deploy DMARC enforcement, and restrict macro execution and unsigned application installation.
  7. Include Linux and macOS in scope. Go's cross-compilation means the same framework can target your server fleet and executive MacBooks. Ensure Sysmon-for-Linux, osquery, or equivalent EDR coverage exists beyond Windows endpoints.
  8. Cluster infrastructure. Feed any confirmed GoCaracal C2 domains/IPs into passive DNS and netflow retro-searches. Dark Caracal has historically reused hosting providers and registrars — one confirmed indicator often uncovers adjacent campaign infrastructure.
  9. If compromise is confirmed: isolate the host, capture memory before remediation (modular implants frequently execute capabilities in memory only), preserve the implant binary for reverse engineering, reset credentials used on or reachable from the host, and conduct a full enterprise hunt for lateral movement and secondary staging before declaring containment.

Related Resources

Security Arsenal Incident Response Services AlertMonitor Platform Book a SOC Assessment incident-response Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.