Back to Intelligence

APT28 'Swallowtail' Espionage Campaign: Hookedge Backdoor Hits NATO Defense Firms — OTX Pulse Detection Pack

SA
Security Arsenal Team
October 20, 2026
9 min read

Threat Summary

AlienVault OTX pulse data confirms an active Russian state-sponsored espionage operation tracked as Swallowtail, attributed to APT28 (also tracked as Forest Blizzard, Fancy Bear, Sofacy, STRONTIUM). The campaign targeted organizations across two NATO member states, including:

  • A law enforcement agency
  • A naval shipbuilder
  • A military aircraft engine manufacturer

The intrusion at the naval shipbuilder persisted for approximately two months, during which operators conducted hands-on-keyboard activity and harvested credentials. The delivery mechanism was spear-phishing with malicious Microsoft Word documents, dropping the Hookedge backdoor as the primary implant.

The strategic objective is clear: long-term intelligence collection against NATO defense industrial base (DIB) entities, specifically maritime and aerospace programs. Credential theft during hands-on-keyboard operations indicates the actors sought lateral movement into high-value engineering and program-management enclaves — consistent with APT28's historical tradecraft of combining commodity initial access with surgical, operator-driven post-exploitation.

This is not opportunistic cybercrime. It is a state-level collection campaign against defense supply chains, and any organization adjacent to NATO defense contracts should treat this pulse as directly relevant.

Threat Actor / Malware Profile

APT28 / Forest Blizzard

APT28 is assessed to be operated by Russia's GRU (Unit 26165). The group has a decade-plus operational history targeting government, military, media, and defense organizations across NATO and partner nations. Known tradecraft includes:

  • Initial Access: Spear-phishing with weaponized Office documents, credential harvesting portals, and exploitation of edge devices and mail infrastructure.
  • Post-Exploitation: Hands-on-keyboard operations using legitimate administrative tooling (PsExec, WMI, net.exe) to blend with normal traffic.
  • Credential Access: Dumping LSASS memory, harvesting browser credential stores, and using keyloggers during interactive sessions.
  • Exfiltration: Staged archives pushed over HTTPS or via compromised legitimate infrastructure to evade egress filtering.

Hookedge Backdoor

Hookedge is the implant deployed in the Swallowtail campaign:

  • Distribution: Embedded in malicious Word documents — typically delivered via macro execution or template-injection payloads triggered on document open.
  • Payload Behavior: Establishes an implant beacon that grants remote operators command execution, file staging, and interactive shell access. The two-month dwell time at the shipbuilder indicates Hookedge serves as a stable access implant, not a smash-and-grab loader.
  • C2 Communication: HTTPS-based beaconing with periodic polling intervals. Expect outbound TLS connections from user workstations to low-reputation or freshly registered infrastructure, often with small, regular payload sizes consistent with tasking/check-in loops.
  • Persistence: Registry Run keys and scheduled tasks are the most common mechanisms for document-delivered implants of this class; hunt both.
  • Anti-Analysis: Maldoc-based droppers typically use sandbox evasion via sleep/delayed execution, environment checks, and encrypted payloads unpacked in memory. Hash-based detection alone is insufficient — behavioral detection is mandatory.

IOC Analysis

The pulse contains 34 indicators, dominated by file hashes:

TypeCount (sample)Operational Use
FileHash-SHA256e.g. a92413d4951a28822ec85e5c0d1948d4160b91388c5f3d86504611fc286a4d13, 1bff55104206d3f55cd72ca58ffecd2fa620a428c5a3c6987d3c4cc68285d335, 49e276498fc4e7d65ebf9fa2acf64ec2a0c25e75ac621cd6a203d64fb75aa495, e068794cf43e381b26c82d746cca107b9f84327a2a8308d5b87ea5529963c4c8Block at EDR/email gateway; retro-hunt across file systems
FileHash-SHA1e.g. 512920c5e31d08d65940877bdb29d0a17738ce37, c52f2c9d9a1aceb30fedd940e93e6f1557fdd05eSecondary validation; useful against legacy tooling output
FileHash-MD5e.g. 39cc6af95d0425f160571032a6719ad3, fdeb005810c3230ee1b1e0204a2fd05fMatch against AV/EDR telemetry and sandbox submissions

How SOC teams should operationalize:

  1. Push all hashes into your EDR blocklist and email security gateway immediately. Hookedge samples and their maldoc droppers should be quarantined on sight.
  2. Retro-hunt: Hashes are point-in-time — APT28 recompiles. Search endpoint telemetry for any historical execution of these hashes over the last 90 days, matching the two-month dwell window.
  3. Pivot on parent processes: Hash matches are the floor, not the ceiling. Hunt for WINWORD.EXE spawning powershell.exe, cmd.exe, rundll32.exe, or wscript.exe — the maldoc execution signature.
  4. Tooling: Ingest the pulse via the OTX API into your TIP (OpenCTI, MISP, ThreatConnect). Auto-sync indicators to Sentinel/Defender via the OTX DirectConnect integration or STIX/TAXII feeds. Hash validation tooling (e.g., Get-FileHash, sigcheck, or hashdeep) supports cross-format matching against the SHA256/SHA1/MD5 sets.

Detection Engineering

YAML
---
title: Suspicious Office Application Spawning Scripting or Command Shell
description: Detects Microsoft Word spawning command interpreters or script hosts, consistent with Hookedge maldoc delivery in APT28 Swallowtail campaign
status: experimental
author: Security Arsenal Threat Intelligence
logsource:
    category: process_creation
    product: windows
    service: sysmon
detection:
    selection_parent:
        ParentImage|endswith:
            - '\WINWORD.EXE'
            - '\EXCEL.EXE'
            - '\POWERPNT.EXE'
    selection_child:
        Image|endswith:
            - '\powershell.exe'
            - '\pwsh.exe'
            - '\cmd.exe'
            - '\wscript.exe'
            - '\cscript.exe'
            - '\rundll32.exe'
            - '\mshta.exe'
    condition: selection_parent and selection_child
fields:
    - CommandLine
    - ParentCommandLine
    - User
falsepositives:
    - Legitimate Office add-ins (rare)
level: high
tags:
    - attack.initial_access
    - attack.t1566.001
    - attack.t1204.002
---
title: Hookedge Backdoor Known File Hash Execution
description: Detects execution of files matching Hookedge backdoor and maldoc dropper hashes published in the Swallowtail OTX pulse
status: experimental
author: Security Arsenal Threat Intelligence
logsource:
    category: process_creation
    product: windows
    service: sysmon
detection:
    selection_sha256:
        Hashes|contains:
            - 'a92413d4951a28822ec85e5c0d1948d4160b91388c5f3d86504611fc286a4d13'
            - '1bff55104206d3f55cd72ca58ffecd2fa620a428c5a3c6987d3c4cc68285d335'
            - '49e276498fc4e7d65ebf9fa2acf64ec2a0c25e75ac621cd6a203d64fb75aa495'
            - 'e068794cf43e381b26c82d746cca107b9f84327a2a8308d5b87ea5529963c4c8'
    selection_md5:
        Hashes|contains:
            - '39cc6af95d0425f160571032a6719ad3'
            - 'fdeb005810c3230ee1b1e0204a2fd05f'
    selection_sha1:
        Hashes|contains:
            - '512920c5e31d08d65940877bdb29d0a17738ce37'
            - 'c52f2c9d9a1aceb30fedd940e93e6f1557fdd05e'
    condition: 1 of selection_*
fields:
    - Image
    - Hashes
    - CommandLine
falsepositives:
    - None expected for exact hash matches
level: critical
tags:
    - attack.execution
    - attack.t1059
---
title: Credential Dumping via LSASS Memory Access
description: Detects suspicious access to LSASS process memory consistent with APT28 hands-on-keyboard credential theft observed in Swallowtail intrusions
status: experimental
author: Security Arsenal Threat Intelligence
logsource:
    category: process_access
    product: windows
    service: sysmon
detection:
    selection_target:
        TargetImage|endswith: '\lsass.exe'
    selection_access:
        GrantedAccess|contains:
            - '0x1010'
            - '0x1410'
            - '0x1438'
            - '0x143a'
            - '0x1fffff'
    filter_legitimate:
        SourceImage|endswith:
            - '\MsMpEng.exe'
            - '\svchost.exe'
            - '\wininit.exe'
    condition: selection_target and selection_access and not filter_legitimate
fields:
    - SourceImage
    - GrantedAccess
    - SourceUser
falsepositives:
    - Backup agents, legitimate credential vaulting tools, some EDR components
level: high
tags:
    - attack.credential_access
    - attack.t1003.001
KQL — Microsoft Sentinel / Defender
// Swallowtail / Hookedge hunt: maldoc child processes, known hashes, LSASS access
let HookedgeHashes = dynamic([
    "a92413d4951a28822ec85e5c0d1948d4160b91388c5f3d86504611fc286a4d13",
    "1bff55104206d3f55cd72ca58ffecd2fa620a428c5a3c6987d3c4cc68285d335",
    "49e276498fc4e7d65ebf9fa2acf64ec2a0c25e75ac621cd6a203d64fb75aa495",
    "e068794cf43e381b26c82d746cca107b9f84327a2a8308d5b87ea5529963c4c8",
    "39cc6af95d0425f160571032a6719ad3",
    "fdeb005810c3230ee1b1e0204a2fd05f",
    "512920c5e31d08d65940877bdb29d0a17738ce37",
    "c52f2c9d9a1aceb30fedd940e93e6f1557fdd05e"
]);
let OfficeChildren = dynamic(["powershell.exe","pwsh.exe","cmd.exe","wscript.exe","cscript.exe","rundll32.exe","mshta.exe","regsvr32.exe","schtasks.exe"]);
union isfuzzy=true
(
    DeviceProcessEvents
    | where TimeGenerated > ago(90d)
    | where InitiatingProcessFileName in~ ("WINWORD.EXE","EXCEL.EXE","POWERPNT.EXE")
    | where FileName in~ (OfficeChildren)
    | project TimeGenerated, DeviceName, AccountName, InitiatingProcessFileName, FileName, ProcessCommandLine, SHA256, HuntType="MaldocChildProcess"
),
(
    DeviceProcessEvents
    | where TimeGenerated > ago(90d)
    | where SHA256 in~ (HookedgeHashes) or MD5 in~ (HookedgeHashes) or SHA1 in~ (HookedgeHashes)
    | project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, SHA256, MD5, HuntType="KnownHookedgeHash"
),
(
    DeviceEvents
    | where TimeGenerated > ago(30d)
    | where ActionType == "LdapSearch" or (FileName =~ "rundll32.exe" and AdditionalFields has "comsvcs")
    | project TimeGenerated, DeviceName, FileName, ProcessCommandLine, HuntType="CredentialAccessSuspect"
),
(
    DeviceNetworkEvents
    | where TimeGenerated > ago(90d)
    | where InitiatingProcessFileName in~ ("WINWORD.EXE","powershell.exe","rundll32.exe")
    | where RemotePort in (443, 8443, 8080)
    | where RemoteUrl !endswith ".microsoft.com" and RemoteUrl !endswith ".office.com"
    | summarize ConnectionCount=count(), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated) by DeviceName, InitiatingProcessFileName, RemoteIP, RemoteUrl
    | where ConnectionCount > 20
    | project FirstSeen, LastSeen, DeviceName, InitiatingProcessFileName, RemoteIP, RemoteUrl, ConnectionCount, HuntType="BeaconPattern"
)
| sort by TimeGenerated desc
PowerShell
# Swallowtail / Hookedge IOC & artifact hunt script
# Run elevated on suspect endpoints. Checks hashes, persistence, and beacon connections.

$HookedgeHashes = @(
    "a92413d4951a28822ec85e5c0d1948d4160b91388c5f3d86504611fc286a4d13",
    "1bff55104206d3f55cd72ca58ffecd2fa620a428c5a3c6987d3c4cc68285d335",
    "49e276498fc4e7d65ebf9fa2acf64ec2a0c25e75ac621cd6a203d64fb75aa495",
    "e068794cf43e381b26c82d746cca107b9f84327a2a8308d5b87ea5529963c4c8",
    "39cc6af95d0425f160571032a6719ad3",
    "fdeb005810c3230ee1b1e0204a2fd05f",
    "512920c5e31d08d65940877bdb29d0a17738ce37",
    "c52f2c9d9a1aceb30fedd940e93e6f1557fdd05e"
)

$findings = @()

# 1. Hash sweep in common drop locations
$searchPaths = @("$env:TEMP", "$env:APPDATA", "$env:LOCALAPPDATA", "$env:USERPROFILE\Downloads", "C:\ProgramData")
foreach ($path in $searchPaths) {
    if (Test-Path $path) {
        Get-ChildItem -Path $path -Recurse -File -ErrorAction SilentlyContinue |
            Where-Object { $_.Length -lt 50MB } | ForEach-Object {
            $h = Get-FileHash -Path $_.FullName -Algorithm SHA256 -ErrorAction SilentlyContinue
            if ($h -and ($HookedgeHashes -contains $h.Hash.ToLower())) {
                $findings += [PSCustomObject]@{Type="HashMatch"; Path=$_.FullName; Hash=$h.Hash}
            }
        }
    }
}

# 2. Registry Run key persistence check
$runKeys = @(
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
    "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
    "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"
)
foreach ($key in $runKeys) {
    if (Test-Path $key) {
        Get-ItemProperty -Path $key | ForEach-Object {
            $_.PSObject.Properties | Where-Object { $_.Value -match "temp|appdata|rundll32|powershell" } | ForEach-Object {
                $findings += [PSCustomObject]@{Type="RunKeyPersistence"; Path="$key\$($_.Name)"; Hash=$_.Value}
            }
        }
    }
}

# 3. Scheduled task persistence check
Get-ScheduledTask | Where-Object {
    $_.Actions.Execute -match "powershell|rundll32|wscript|cmd" -and
    $_.TaskPath -notmatch "Microsoft"
} | ForEach-Object {
    $findings += [PSCustomObject]@{Type="SuspiciousScheduledTask"; Path=$_.TaskName; Hash=$_.Actions.Execute}
}

# 4. Active outbound connections from scripting/Office-adjacent processes
Get-NetTCPConnection -State Established -ErrorAction SilentlyContinue |
    Where-Object { $_.RemotePort -in @(443,8443,8080) } | ForEach-Object {
    $proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
    if ($proc.ProcessName -match "powershell|rundll32|wscript|winword|regsvr32") {
        $findings += [PSCustomObject]@{Type="SuspectBeacon"; Path="$($proc.ProcessName) -> $($_.RemoteAddress):$($_.RemotePort)"; Hash=$proc.Path}
    }
}

# 5. Recent Word docs in temp/internet caches (maldoc staging)
Get-ChildItem "$env:LOCALAPPDATA\Microsoft\Windows\INetCache","$env:TEMP" -Recurse -Include *.doc,*.docm,*.dotm -ErrorAction SilentlyContinue |
    Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-90) } | ForEach-Object {
    $findings += [PSCustomObject]@{Type="RecentMaldocCandidate"; Path=$_.FullName; Hash=$_.LastWriteTime}
}

$findings | Format-Table -AutoSize
$findings | Export-Csv -Path ".\swallowtail_hunt_$(Get-Date -Format 'yyyyMMdd_HHmm').csv" -NoTypeInformation
Write-Host "[+] Hunt complete. $($findings.Count) findings exported." -ForegroundColor Cyan

Response Priorities

Immediate (0–4 hours)

  • Block all 34 IOC hashes at EDR, email gateway, and web proxy layers.
  • Retro-hunt 90 days of process telemetry for WINWORD.EXE spawning script interpreters and for any hash matches — the confirmed dwell time is two months.
  • Isolate any host with a hash match or beacon-pattern network hit pending forensic acquisition.
  • Review outbound TLS from workstations to low-reputation destinations over the past 60 days.

24 Hours

  • Credential theft is confirmed in this campaign — treat all credentials on any touched host as compromised. Force resets for all accounts that authenticated to suspect systems, prioritizing privileged and service accounts.
  • Invalidate sessions/tokens (Azure AD/Entra ID, VPN, SSO) for affected users; do not rely on password resets alone.
  • Audit LSASS access telemetry and hunt for comsvcs.dll MiniDump abuse and procdump-style dumping.
  • Check lateral movement artifacts: PsExec service creation (Event 7045), WMI process creation, and abnormal SMB admin-share writes.

1 Week

  • Disable Office macros by default via GPO and enable Attack Surface Reduction rules blocking Office child processes.
  • Deploy the Sigma and KQL detections above into production with tuned thresholds.
  • Harden email ingress: strip or sandbox detonate all Word attachments; enforce attachment content disarm and reconstruction (CDR) for defense-adjacent business units.
  • Segment engineering and program-management enclaves from general user VLANs; APT28's objective is IP theft from these zones.
  • Brief executive leadership: defense-sector targeting by a GRU unit warrants board-level awareness and potential government/CERT notification per your sector's reporting obligations.

Related Resources

Security Arsenal Incident Response Managed SOC & MDR Services AlertMonitor Threat Detection From The Dark Side Intel Hub

Is your security operations ready?

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