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:
| Type | Count (sample) | Operational Use |
|---|---|---|
| FileHash-SHA256 | e.g. a92413d4951a28822ec85e5c0d1948d4160b91388c5f3d86504611fc286a4d13, 1bff55104206d3f55cd72ca58ffecd2fa620a428c5a3c6987d3c4cc68285d335, 49e276498fc4e7d65ebf9fa2acf64ec2a0c25e75ac621cd6a203d64fb75aa495, e068794cf43e381b26c82d746cca107b9f84327a2a8308d5b87ea5529963c4c8 | Block at EDR/email gateway; retro-hunt across file systems |
| FileHash-SHA1 | e.g. 512920c5e31d08d65940877bdb29d0a17738ce37, c52f2c9d9a1aceb30fedd940e93e6f1557fdd05e | Secondary validation; useful against legacy tooling output |
| FileHash-MD5 | e.g. 39cc6af95d0425f160571032a6719ad3, fdeb005810c3230ee1b1e0204a2fd05f | Match against AV/EDR telemetry and sandbox submissions |
How SOC teams should operationalize:
- Push all hashes into your EDR blocklist and email security gateway immediately. Hookedge samples and their maldoc droppers should be quarantined on sight.
- 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.
- Pivot on parent processes: Hash matches are the floor, not the ceiling. Hunt for
WINWORD.EXEspawningpowershell.exe,cmd.exe,rundll32.exe, orwscript.exe— the maldoc execution signature. - 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, orhashdeep) supports cross-format matching against the SHA256/SHA1/MD5 sets.
Detection Engineering
---
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
// 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
# 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.EXEspawning 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.dllMiniDump 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.