macOS.Gaslight — North Korea-Aligned Rust Backdoor & Infostealer
Executive Summary
macOS.Gaslight is a Rust-based macOS backdoor and infostealer attributed with high confidence to North Korea-aligned actors and first reported around 2026-06-25 by SentinelOne Labs. The implant ships as an ad-hoc-signed aarch64 Mach-O, persists as a LaunchAgent whose label com.apple.system.services.activity deliberately impersonates Apple's own namespace, and uses the Telegram Bot API (getUpdates polling) wrapped in AES-GCM over certificate-pinned TLS as its command-and-control channel. Operators drive it with a small verb set — help, id, shell, kill, upload, stop (and an apparent 7th, focus).
The codename "Gaslight" comes from its analyst-deception payload: a 3.5 KB blob of 38 fabricated "system" messages delimited by {{DATA}} tokens, designed to mislead an LLM that ingests the sample during triage. This is a defense-evasion technique aimed at the analyst's tooling, not the sandbox — treat any AI-assisted verdict on this family as untrusted and corroborate with raw telemetry.
The infostealer stage base64-decodes a Python script that downloads a standalone CPython 3.10.18 runtime (from astral-sh/python-build-standalone) into user space and runs it to harvest browser data (Chrome, Brave, Firefox, Safari), terminal histories, the installed-apps list, running processes (ps aux), the system profile (system_profiler), and login.keychain-db, archiving everything to temp/collected_data.zip for exfil.
Defender priority: CrowdStrike Falcon covers macOS. The two highest-fidelity, lowest-FP catches are (1) a LaunchAgent plist written with the com.apple.system.services.activity label outside an Apple-signed installer, and (2) a non-Apple process reading login.keychain-db together with ps aux / system_profiler in a tight window. Hunt those first; the listed SHA256 hashes are exact-match backstops.
Source Review & Web Hunter Notes
| Tier | Source | Key Finding | Carry Fwd |
|---|---|---|---|
| 1 · Primary | SentinelOne Labs — "macOS Gaslight Rust backdoor turns prompt injection on the analyst" | Full technical teardown: Rust aarch64 implant, ad-hoc signing identifier, LaunchAgent label, Telegram C2, AES-GCM/cert-pinning, runtime config params, Python infostealer + CPython 3.10.18 staging, keychain harvest, 38-message prompt-injection blob, operator verbs, hashes. | Yes |
| 2 · Corrob. | The Hacker News — "New Gaslight macOS Malware Uses Prompt Injection" | Confirms DPRK attribution, prompt-injection-on-analyst angle, Telegram C2, infostealer scope. | Partial |
| 2 · Corrob. | Infosecurity Magazine — "macOS Gaslight Rust Backdoor" | Corroborates Rust backdoor + infostealer split, sibling "BONZAI" sample, collection targets. | Partial |
| 2 · Corrob. | CyberPress — "Gaslight Backdoor Misleads Analysts" | Reinforces deception payload, operator command set, persistence label. | Partial |
Web-hunter note: Four sources, one primary vendor teardown plus three corroborating outlets — high confidence. Per the cited intel, the runtime config params (tg_room_id, aes_key, main_base_url, main_upload_url) and bot tokens are NOT embedded in the sample (supplied at runtime; tokens self-redacted as file/token:redacted), so there is no static C2 string or bot token to IOC. Network detection anchors on the Telegram API host. No victim/sector names are reproduced here.
Hunt Brief & Attack Chain
Hunt hypotheses (fidelity-ordered)
- H1 (high): A LaunchAgent plist carrying the label
com.apple.system.services.activityis created by a non-Apple process — Gaslight persistence masquerading in Apple's namespace. - H2 (high): A non-Apple process reads
login.keychain-dband, in a tight window, also runsps auxandsystem_profiler— the infostealer collection burst. - H3 (high): A standalone
python3/cpython-3.10.18binary executes from a user-writable path (not/usr/bin) — the downloaded CPython runtime that runs the stealer. - H4 (medium): A shell pipeline
base64 -d/base64 --decodefeeds decoded content intopython3— staged deobfuscation of the infostealer (T1140). - H5 (medium): A macOS host makes outbound connections to
api.telegram.orgfrom a non-browser, non-messaging process — Telegram Bot API C2 polling. - H6 (high): Any process whose image SHA256 matches one of the four listed Gaslight/BONZAI/script hashes — exact-match backstop.
Attack chain
| Step | Behavior | Telemetry | Hunt Angle |
|---|---|---|---|
| 1 · Delivery | Bash installer script drops ad-hoc-signed aarch64 Rust Mach-O | ProcessRollup2, file write | Installer script hash; ad-hoc signing identifier |
| 2 · Persistence | LaunchAgent plist label com.apple.system.services.activity | File write to ~/Library/LaunchAgents | H1 — Apple-namespace label from non-Apple writer |
| 3 · Anti-analysis | 3.5 KB / 38-message prompt-injection blob; dlsym API resolution; IOPMAssertionCreateWithName (no-sleep) | Limited EDR signal (in-binary) | Distrust LLM verdicts; hash/string hunt |
| 4 · Collection | base64-decoded Python pulls CPython 3.10.18; harvests browsers, histories, apps, ps aux, system_profiler, keychain | ProcessRollup2, file read | H2/H3/H4 — keychain read + recon burst + standalone python |
| 5 · C2 / Exfil | Telegram Bot API getUpdates loop; AES-GCM over pinned TLS; upload collected_data.zip | NetworkConnectIP4, DnsRequest | H5 — api.telegram.org from non-browser process |
Consolidated IOC Table
| Type | Value | Conf | Action | Context |
|---|---|---|---|---|
| SHA256 | 6328567511d88fdc2ae0939c5ef17b7a63d2a833881900de018a4f12f4982525 | high | detect | Primary Gaslight Rust implant sample |
| SHA256 | 77b4fd46994992f0e57302cfe76ed23c0d90101381d2b89fc2ddf5c4536e77ca | high | detect | Sibling "BONZAI" sample |
| SHA256 | baabf249c77bc54c54ab0e66e15af798bd28aa5b4683554456a8b73ab8741239 | high | detect | Python infostealer payload script |
| SHA256 | b3c56d689414343589f38394d19ba2fe9a518133281200faa0556ba4e4136394 | high | detect | Bash installer script |
| Signing ID | endpoint-macos-aarch64-5555494492fc075f441637fb9d894913dde3a2ea | high | hunt | Ad-hoc signing identifier of the implant |
| Persistence label | com.apple.system.services.activity | high | hunt | LaunchAgent label masquerading in Apple namespace |
| Domain | api.telegram.org | medium | hunt | Telegram Bot API C2 (legitimate host — context-dependent) |
| Artifact path | temp/collected_data.zip | medium | hunt | Staged collection archive |
| Runtime string | cpython-3.10.18 (PY_VERSION=3.10.18, BUILD_DATE=20250708) | medium | hunt | Downloaded standalone CPython used to run the stealer |
| Config params | tg_room_id, aes_key, main_base_url, main_upload_url | medium | pivot | Runtime-supplied config keys (NOT embedded in sample) |
Note: No bot token or C2 URL is published — they are self-redacted (file/token:redacted) and supplied at runtime. api.telegram.org is a legitimate host; alert only on the behavioral combination (non-browser/non-messaging process), never on the domain alone.
Affected Surface & Telemetry Matrix
| Surface | Required Telemetry | Priority | Gap Risk |
|---|---|---|---|
| macOS endpoint — persistence | Falcon macOS file-write events to ~/Library/LaunchAgents (FileCreate/Rename on macOS sensor) | P1 | ⚠ macOS plist write fields vary by sensor version — validate in tenant |
| macOS endpoint — process exec | ProcessRollup2 / SyntheticProcessRollup2 with CommandLine, ImageFileName, SHA256HashData | P1 | Low |
| macOS endpoint — keychain read | File-open telemetry on login.keychain-db (macOS sensor) | P1 | ⚠ keychain file-read events may not be emitted by default — validate |
| Network — C2 | NetworkConnectIP4 + DnsRequest for api.telegram.org | P2 | TLS-pinned; DNS/host visibility only, no payload |
| Collection runtime | ProcessRollup2 for standalone python3 / cpython-3.10.18 from user-space paths | P2 | Low |
ATT&CK Mapping
| Tactic | Technique | Observed Behavior | Detection / Control |
|---|---|---|---|
| Persistence | T1547.015 — Login Items / LaunchAgent | LaunchAgent plist label com.apple.system.services.activity | Q1 · H1 |
| Credential Access | T1555 / T1056.004 — keychain harvest | Reads login.keychain-db | Q2 · H2 |
| Collection | T1005 — Data from Local System | Browsers, histories, apps list, ps aux, system_profiler → collected_data.zip | Q2 · Q3 |
| Defense Evasion | T1140 — Deobfuscate/Decode | base64-decoded Python staging; dlsym runtime API resolution | Q4 |
| Execution | T1059.006 — Python | Downloaded standalone CPython 3.10.18 runs the stealer | Q3 |
| Exfiltration | T1041 — Exfil over C2 Channel | Telegram Bot API getUpdates loop, AES-GCM over pinned TLS | Q5 |
| Defense Evasion | T1622 / anti-analysis | 3.5 KB / 38-message prompt-injection blob targeting LLM triage | Q6 · hash/string hunt |
Native Audit-Log Hunts (non-CQL)
Direct host checks that complement the Falcon CQL queries — run on suspect macOS endpoints or fold into an MDM/osquery sweep.
1 · Hunt the masquerading LaunchAgent (read-only)
grep -lR "com.apple.system.services.activity" \ ~/Library/LaunchAgents /Library/LaunchAgents 2>/dev/null # Legitimate Apple LaunchAgents live under /System/Library/LaunchAgents and are SIP-protected; # a plist with this label under a user/Library path is suspicious.
2 · osquery — non-Apple LaunchAgents referencing the label
SELECT name, path, program, program_arguments FROM launchd WHERE name LIKE '%com.apple.system.services.activity%' AND path NOT LIKE '/System/Library/%';
3 · Find a downloaded standalone CPython runtime in user space
find ~ /Users/Shared /tmp /var/folders -type d -name "cpython-3.10.18*" 2>/dev/null # astral-sh/python-build-standalone runtime staged outside a developer toolchain is anomalous.
4 · Spot the staged collection archive
find ~ /tmp /var/folders -type f -name "collected_data.zip" 2>/dev/null
Reminder: Do not paste the live sample into an LLM triage tool — the 38-message prompt-injection blob is designed to corrupt AI-assisted verdicts. Corroborate against raw telemetry.
CrowdStrike LogScale CQL Hunt Queries
All queries target macOS telemetry. Falcon's macOS plist-write and keychain-read field names vary by sensor build — fields flagged ⚠ below should be validated in your tenant before promotion.
Looks for: a file written to a LaunchAgents directory whose path/name carries the masquerading label com.apple.system.services.activity. Legitimate Apple agents with that string live under SIP-protected /System/Library and are not written by user processes. FP: low — the exact label outside /System/Library is anomalous; exclude approved MDM agents if any reuse the string.
// HUNT: macOS LaunchAgent masquerading as com.apple.system.services.activity // MITRE: T1547.015 // CONF: high FP: low COST: low | REQUIRES: macOS file-write telemetry (LaunchAgents) // FALSE POSITIVES: approved MDM/EDR agents that reuse the label (rare) // TUNING: exclude known-good ImageFileName installers if any legitimately write this label // NOTE: macOS plist-write field set varies by sensor build - validate TargetFileName emission in tenant #event_simpleName=/NewExecutableWritten|FileRename/ | TargetFileName=/LaunchAgents\/.*com\.apple\.system\.services\.activity.*\.plist$/i | TargetFileName!=/^\/System\/Library\// | table([ComputerName, UserName, ImageFileName, TargetFileName, SHA256HashData], limit=200)
Looks for: process execution on macOS that references login.keychain-db, system_profiler, or ps aux in the command line — the infostealer collection burst. Group by host so a single host hitting multiple of these stands out. FP: medium — admins and security tooling run system_profiler/ps aux legitimately; the keychain-db reference is the high-signal discriminator. TUNING: exclude approved asset-inventory and backup agents by ImageFileName.
// HUNT: macOS infostealer collection - keychain + recon command burst // MITRE: T1555 / T1056.004 / T1005 // CONF: high FP: medium COST: medium | REQUIRES: ProcessRollup2 (macOS) CommandLine // FALSE POSITIVES: admin/IT scripts running system_profiler or ps aux; backup tools touching keychain // TUNING: exclude approved inventory/backup agents by ImageFileName #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | CommandLine=/login\.keychain-db|system_profiler|ps\s+aux/i | table([ComputerName, UserName, ImageFileName, ParentBaseFileName, CommandLine], limit=200)
Looks for: a Python interpreter image path containing cpython-3.10.18 (the astral-sh python-build-standalone runtime the stealer downloads), executing from a user-writable location rather than a system path. FP: medium — developers legitimately use python-build-standalone; the discriminator is execution context (paired with Q2/Q5 on the same host) and the exact pinned version. TUNING: exclude developer build roots (e.g. /Users/<user>/.pyenv, project venvs) per environment.
// HUNT: macOS downloaded standalone CPython 3.10.18 running the stealer // MITRE: T1059.006 // CONF: high FP: medium COST: low | REQUIRES: ProcessRollup2 (macOS) ImageFileName // FALSE POSITIVES: developers using python-build-standalone / pyenv // TUNING: exclude known dev build roots (.pyenv, project venvs) by path #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | ImageFileName=/cpython-3\.10\.18.*\/(bin\/)?python3?$/i | ImageFileName!=/\/\.pyenv\// | table([ComputerName, UserName, ImageFileName, ParentBaseFileName, CommandLine, SHA256HashData], limit=200)
Looks for: a command line that both decodes base64 (base64 -d / --decode) and invokes python3 — the staged deobfuscation the installer uses to launch the infostealer. FP: medium — some legitimate installers and CI scripts decode-and-run; pair with Q3/Q5 and review the parent process. TUNING: exclude approved CI/build agents by ParentBaseFileName.
// HUNT: macOS base64-decode piped into python (staged deobfuscation) // MITRE: T1140 / T1059.006 // CONF: medium FP: medium COST: low | REQUIRES: ProcessRollup2 (macOS) CommandLine // FALSE POSITIVES: legitimate installers/CI that decode-and-run // TUNING: exclude approved CI/build agents by ParentBaseFileName #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | CommandLine=/base64\s+(-d|--decode)/i | CommandLine=/python3?/i | table([ComputerName, UserName, ParentBaseFileName, ImageFileName, CommandLine], limit=200)
Looks for: DNS resolution of api.telegram.org on macOS where the requesting process is not a browser or known messaging client — Gaslight's getUpdates polling loop. FP: medium — Telegram desktop and some dev tools legitimately resolve this host; the discriminator is the process context. TUNING: exclude browsers and approved messaging clients by ContextBaseFileName.
// HUNT: macOS Telegram Bot API C2 from non-browser process // MITRE: T1041 / T1102 // CONF: medium FP: medium COST: medium | REQUIRES: DnsRequest (macOS) // FALSE POSITIVES: Telegram desktop client; dev tooling using the Bot API // TUNING: exclude browsers + approved messaging clients by ContextBaseFileName #event_simpleName=DnsRequest | DomainName=/^api\.telegram\.org$/i | ContextBaseFileName!=/^(Telegram|Safari|Google Chrome|firefox|com\.apple\.WebKit|Brave Browser)/i | table([ComputerName, DomainName, ContextBaseFileName, ContextProcessId], limit=200)
Looks for: any process whose image SHA256 matches one of the four published Gaslight/BONZAI/payload-script hashes. Zero-FP exact-match backstop — promote straight to a block IOC. FP: low.
// HUNT: macOS Gaslight known-bad SHA256 (exact match) // MITRE: T1204 / multiple // CONF: high FP: low COST: low | REQUIRES: ProcessRollup2 (macOS) SHA256HashData // FALSE POSITIVES: none (exact hash match) #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | SHA256HashData=/^(6328567511d88fdc2ae0939c5ef17b7a63d2a833881900de018a4f12f4982525|77b4fd46994992f0e57302cfe76ed23c0d90101381d2b89fc2ddf5c4536e77ca|baabf249c77bc54c54ab0e66e15af798bd28aa5b4683554456a8b73ab8741239|b3c56d689414343589f38394d19ba2fe9a518133281200faa0556ba4e4136394)$/i | table([ComputerName, UserName, ImageFileName, CommandLine, SHA256HashData], limit=200)
CrowdStrike Custom IOA Recommendations
| IOA Name | Platform / Type | Pattern | Action | Exclusions |
|---|---|---|---|---|
| Gaslight — Apple-namespace LaunchAgent masquerade | macOS · File Write | plist written to LaunchAgents path with label com.apple.system.services.activity | Detect → Block (high conf) | Approved MDM agents reusing the label |
| Gaslight — keychain + recon burst | macOS · Process | CommandLine references login.keychain-db AND system_profiler/ps aux on same host in short window | Detect | Approved inventory/backup agents |
| Gaslight — standalone CPython 3.10.18 from user space | macOS · Process | ImageFileName matches cpython-3.10.18 outside dev roots | Detect | pyenv / project venvs |
| Gaslight — base64-decode → python | macOS · Process | CommandLine has base64 -d/--decode AND python3 | Detect | Approved CI/build agents |
Promotion path: Q1 and Q6 are clean enough for Detect-and-Block IOAs / IOC import today. Q2–Q5 should run as scheduled-search hunts first, baseline benign triggers for 7–14 days, then promote with the noted exclusions.
Machine-Readable IOC Appendix
One-click blocks for SOC ingestion. All atomic indicators below trace to the cited SentinelOne Labs teardown (and corroborating outlets) — no values were invented.
type,value,action,severity,expiration,description,tags sha256,6328567511d88fdc2ae0939c5ef17b7a63d2a833881900de018a4f12f4982525,prevent,critical,2026-12-27,Gaslight Rust implant,campaign:Gaslight sha256,77b4fd46994992f0e57302cfe76ed23c0d90101381d2b89fc2ddf5c4536e77ca,prevent,critical,2026-12-27,Gaslight BONZAI sample,campaign:Gaslight sha256,baabf249c77bc54c54ab0e66e15af798bd28aa5b4683554456a8b73ab8741239,prevent,high,2026-12-27,Gaslight Python infostealer,campaign:Gaslight sha256,b3c56d689414343589f38394d19ba2fe9a518133281200faa0556ba4e4136394,prevent,high,2026-12-27,Gaslight bash installer,campaign:Gaslight domain,api.telegram.org,detect,medium,2026-09-27,Telegram Bot API C2 (context-only),campaign:Gaslight
LaunchAgent label : com.apple.system.services.activity (non-/System/Library writer)
Ad-hoc signing ID : endpoint-macos-aarch64-5555494492fc075f441637fb9d894913dde3a2ea
Collection archive : temp/collected_data.zip
Runtime CPython : cpython-3.10.18 (PY_VERSION=3.10.18, BUILD_DATE=20250708)
Recon burst : login.keychain-db + system_profiler + ps aux
C2 pattern : api.telegram.org getUpdates polling, AES-GCM over pinned TLS
Runtime config keys : tg_room_id, aes_key, main_base_url, main_upload_url (not embedded)
Anti-analysis : 3.5KB / 38-message {{DATA}}-delimited prompt-injection blob; dlsym; IOPMAssertionCreateWithName
Family : macOS.Gaslight (Rust backdoor + infostealer) Sibling : BONZAI Platform : macOS aarch64 (ARM64) + x86_64, ad-hoc signed Attribution : North Korea-aligned (high confidence) C2 transport : Telegram Bot API Operator cmds: help, id, shell, kill, upload, stop, focus(7th) Reported : ~2026-06-25 (SentinelOne Labs)
[ ] Block the 4 SHA256 via Falcon IOC Management (prevent) [ ] Alert on non-Apple writers of com.apple.system.services.activity LaunchAgent [ ] Restrict keychain access; enforce Gatekeeper + require notarization (block ad-hoc signed) [ ] MDM allowlist LaunchAgents; flag user-Library plists with com.apple.* labels [ ] Egress policy / DNS logging for api.telegram.org from managed macOS fleet [ ] Analyst policy: never feed live samples to LLM triage tools (prompt-injection blob)
Detection Validation Gates
| Gate | Check | Pass Criteria |
|---|---|---|
| 1 · Telemetry ready | macOS sensors emit ProcessRollup2 + DnsRequest; confirm plist-write & keychain-read field availability | Q1/Q2 fields populate on a test macOS host |
| 2 · Benign baseline | Run Q2–Q5 over 7–14 days; catalog admin/dev triggers | FP sources enumerated and excluded |
| 3 · Positive test | In a lab: write a benign plist with the target label; run system_profiler+ps aux; resolve api.telegram.org from a script | Q1/Q2/Q5 fire as expected |
| 4 · Promotion | Promote Q1/Q6 to Detect+Block; Q2–Q5 to scheduled-search alerts with exclusions | No FP in baseline window post-tuning |
⚠ Tenant-validation: Falcon macOS field emission for LaunchAgent plist writes and login.keychain-db reads varies by sensor build. Validate that TargetFileName populates for Q1 and that keychain file access is captured before relying on Q2's keychain leg.
Hardening — Tiered & Deployable
- Block the 4 SHA256 via Falcon IOC Management (prevent). MITRE M1040
- Enforce Gatekeeper + notarization via MDM so ad-hoc-signed binaries (like the Gaslight implant) are blocked from execution. MITRE M1038 · Apple Platform Security
- Alert on non-Apple writers of LaunchAgents carrying
com.apple.*labels (Q1 / IOA). MITRE M1047
- MDM-manage LaunchAgents: inventory
~/Library/LaunchAgentsacross the fleet and flag any plist with an Apple-namespace label outside/System/Library. CIS Apple macOS Benchmark §2 (LaunchAgents) - Egress / DNS control for the managed macOS fleet: log and review
api.telegram.orgresolutions; block from servers/non-user endpoints where Telegram has no business case. MITRE M1037 - Keychain access policy: monitor and restrict programmatic reads of
login.keychain-db; require user presence for keychain unlock. MITRE M1041 · ⚠ best-practice, validate keychain telemetry
- Application allowlisting on managed macOS (MDM-deployed, signed-binary allowlist) to stop unsigned/ad-hoc Rust implants and user-space CPython runtimes. MITRE M1038 · CIS macOS
- Analyst tooling policy: codify that live malware samples are never submitted to LLM-assisted triage; route through isolated, non-AI static analysis to neutralize the prompt-injection payload. ⚠ best-practice, no formal benchmark
- Browser data protection: enforce encrypted profiles / disable plaintext credential storage where supported to blunt the infostealer's browser-harvest stage. MITRE M1027
Deployable Playbooks
1 · Fleet sweep — masquerading LaunchAgent (MDM / SSH read-only check)
#!/bin/bash # Detect Gaslight LaunchAgent persistence across user + /Library scopes (read-only). LABEL="com.apple.system.services.activity" for d in /Library/LaunchAgents /Users/*/Library/LaunchAgents; do [ -d "$d" ] || continue grep -lR "$LABEL" "$d" 2>/dev/null done # Any hit OUTSIDE /System/Library is suspicious - legitimate Apple agents are SIP-protected.
2 · Falcon IOC Management — block the published hashes
# Import the CSV from Section 10 (type,value,action,severity,expiration,description,tags) # via Falcon console: Endpoint security > IOC Management > Add indicators > Upload CSV. # All four sha256 set to action=prevent. Re-confirm expiration on review (+6mo from 2026-06-27).
3 · MDM configuration profile — require notarization (block ad-hoc signed)
# Gatekeeper assessment must be enabled; deploy via your MDM as a custom profile or # enforce with the com.apple.systempolicy.control payload. Verify on an endpoint: spctl --status # expect: assessments enabled spctl -a -vv /path/to/suspect # ad-hoc signed binaries report "rejected" / no notarization
4 · osquery scheduled pack — staged stealer artifacts
{
"schedule": {
"gaslight_cpython": {
"query": "SELECT path FROM file WHERE path LIKE '/Users/%/cpython-3.10.18%';",
"interval": 3600
},
"gaslight_archive": {
"query": "SELECT path, size FROM file WHERE filename = 'collected_data.zip';",
"interval": 3600
}
}
}
Containment Runbook
| Phase | Actions | Owner | Evidence to capture |
|---|---|---|---|
| Isolate | Network-contain the host in Falcon. Do not submit the live sample to any LLM triage tool. Preserve the LaunchAgent plist and collected_data.zip. | SOC L2 | plist path+contents, implant hash, archive, RTR process list |
| Eradicate | Remove the masquerading LaunchAgent and implant binary; delete the user-space cpython-3.10.18 runtime and staged archive; kill running implant/python processes. | SOC L2 / Endpoint | Removed file paths, killed PIDs |
| Credential reset | Assume login.keychain-db + browser credentials are stolen: rotate the user's keychain-stored secrets, browser-saved passwords, SSH keys, and any tokens; force re-auth. | IAM / IT | Reset ticket IDs, rotated secret inventory |
| Recover | Re-image if implant integrity uncertain. Re-enroll in MDM with notarization enforcement. Sweep fleet with Q1/Q6 + Section 13 scripts. | Endpoint / SOC | Sweep results, clean-state confirmation |
| Hunt-back | Pivot on the ad-hoc signing identifier and api.telegram.org context across the fleet; check for lateral movement and additional DPRK tooling. | Threat Hunt | Pivot query results, scope determination |
Detection Coverage Map
| Technique | Behavior | CQL | IOA | Coverage |
|---|---|---|---|---|
| T1547.015 | LaunchAgent masquerade label | Q1 | Yes | Good |
| T1555 / T1056.004 | login.keychain-db harvest | Q2 | Yes | Partial — keychain read telemetry tenant-dependent |
| T1005 | Recon burst (ps aux / system_profiler) | Q2 | Yes | Good |
| T1059.006 | Standalone CPython 3.10.18 execution | Q3 | Yes | Good |
| T1140 | base64 → python deobfuscation | Q4 | Yes | Partial — FP from CI/installers |
| T1041 / T1102 | Telegram Bot API C2 | Q5 | No | Partial — TLS-pinned; host/DNS visibility only |
| T1204 / multiple | Known-bad SHA256 | Q6 | Yes | Good |
| T1622 / anti-analysis | Prompt-injection blob, dlsym, IOPMAssertion no-sleep | — | No | GAP — in-binary; covered only by hash/string + analyst policy |
Validation: 6 CQL queries cover 7 of 8 mapped behaviors. Residual gap: the anti-analysis tradecraft (prompt-injection blob, dlsym dynamic resolution, IOPMAssertion sleep-prevention) generates little discrete EDR telemetry and is addressed by the hash backstop (Q6) plus the analyst-tooling policy in Section 12. Validate Q1's TargetFileName emission and Q2's keychain-read leg in your tenant before promoting to Block.
Hunt Summary Ticket
TITLE : macOS.Gaslight - DPRK Rust backdoor / infostealer (anti-AI prompt injection)
SEVERITY : Critical (nation-state, active, credential theft)
SCOPE : macOS fleet (Apple Silicon arm64 + x86_64)
HYPOTHESIS : Gaslight persists as a com.apple.* LaunchAgent masquerade, harvests
login.keychain-db + browser data via a downloaded CPython 3.10.18,
and exfils over the Telegram Bot API.
QUERIES : Q1 LaunchAgent masquerade | Q2 keychain+recon burst | Q3 standalone CPython
Q4 base64->python | Q5 Telegram C2 | Q6 known SHA256 backstop
DO FIRST : Q1 + Q6 (high conf, low FP) -> block 4 hashes; sweep fleet for the LaunchAgent label
FINDINGS : <populate from hunt>
GAPS : Anti-analysis tradecraft (prompt-injection blob/dlsym/IOPMAssertion) = hash + policy only;
keychain-read + plist-write telemetry tenant-dependent
ACTIONS : Block hashes | enforce notarization (block ad-hoc) | rotate keychain/browser creds | never LLM-triage live sample
OWNER : HuntPack
VERSION : v0.1 - 2026-06-27
Changelog
table() calls now carry an explicit row limit: the default is 200 and truncation is silent, so a capped result was indistinguishable from a complete one. Atomic-IOC sweeps (filters over 5+ hashes or C2 IPs) use limit=max so a wide infection is never silently under-scoped; behavioural hunts use limit=200, where exceeding the cap indicates the query needs tuning. Where present, event names that do not exist in the Falcon data model were corrected (e.g. ServiceInstalled is a Sysmon concept, not a Falcon event; ElfFileWritten is ELFFileWritten) — such queries could never return a row. No detection logic, fields, or IOCs changed.References
| Tier | Source | Used For | Access Date |
|---|---|---|---|
| 1 · Primary | SentinelOne Labs — macOS Gaslight Rust backdoor | Full technical teardown, hashes, TTPs, IOCs | 2026-06-27 |
| 2 · Corrob. | The Hacker News — Gaslight prompt injection | Attribution, C2, infostealer scope | 2026-06-27 |
| 2 · Corrob. | Infosecurity Magazine — macOS Gaslight Rust Backdoor | BONZAI sibling, collection targets | 2026-06-27 |
| 2 · Corrob. | CyberPress — Gaslight backdoor misleads analysts | Deception payload, operator commands, persistence | 2026-06-27 |
Generated 2026-06-27 · HuntPack v0.1 · Defensive content only (hunt / detect / harden). All atomic IOCs trace to the cited sources; no indicators were fabricated.