# Sinking macOS Pirate Ships with Elastic Behavior Detections

Pirated UltraEdit loads unsigned libConfigurer64.dylib that drops hidden Khepri backdoor and a masqueraded launch agent for persistence on macOS.

- Payout: Real-world hack
- Severity: high
- Program: UltraEdit
- Analysis by: Colson Wilhoit
- Disclosed: 2024-03-15
- Write-up quality: 6/10
- Original: https://www.elastic.co/security-labs/threat-command/sinking-macos-pirate-ships
- Library page: https://bugbountylibrary.com/r/blog%3Aelastic-co-security-labs-threat-command-sinking-macos-pirate-ships
- Tags: area:os domain:desktop impact:internal-access impact:rce kind:incident platform:threat-intel sev:high technique:source-review vuln:misconfiguration

**Target:** macOS application bundle (pirated UltraEdit .dmg)
**Root cause:** The pirated UltraEdit app was altered to load an unsigned third-party dylib (libConfigurer64.dylib) at launch, which acts as a dropper for follow-on payloads.
**Steps:**
1. Victim runs pirated UltraEdit from a mounted .dmg; app immediately loads unsigned `libConfigurer64.dylib` from Contents.
2. Dylib downloads and executes `/private/tmp/.test` (Khepri backdoor) and `/Users/Shared/.fseventsd`.
3. `.test` executes with process arguments pointing to a non-default SSH binary path to blend in.
4. `.fseventsd` installs a masqueraded `com.apple*.plist` launch agent (runatload/keepalive) referencing a hidden executable in `/Users/Shared`.
5. `.fseventsd` downloads a third-stage hidden payload into `/tmp/`.
**How found:** Detection engineering exercise: analysts observed the unsigned dylib load as the only non-system library in Elastic Analyzer, then traced child processes and persistence events to build behavior-based EQL rules.
**Exploitation:** Pirated app distribution via .dmg; on launch the unsigned dylib drops a Khepri post-exploitation backdoor giving full remote access, plus a launch agent for persistence and a downloader for further payloads.
**Insight:** Pirated/cracked app bundles are a distribution vector: hunt for unsigned dylibs loaded from /Volumes/*.app or /Applications/*.app by unsigned processes, and for hidden dot-prefixed Mach-O binaries executing from /tmp or /Users/Shared.

## Proof of concept (copied exactly from the original report)

**EQL rule for unsigned dylib load**

```
library where event.action == "load" and dll.path : 
("/Volumes/*.app/Contents/*", "/Applications/*.app/Contents/*") 
and dll.code_signature.exists == false
```

**EQL rule for hidden binary in temp dir**

```
process where event.type == "start" and event.action == "exec" and 
process.executable : ("/private/tmp/*", "/tmp/*") and 
process.name : ".*" and (process.code_signature.exists == false or 
process.code_signature.trusted == false)
```

**EQL rule for masqueraded plist persistence**

```
file where event.type != "deletion" and 
 file.name : "*com.apple*.plist" and
 file.path :
 ("/System/Library/LaunchAgents/*", 
 "/Library/LaunchAgents/*",
 "/Users/*/Library/LaunchAgents/*",
 "/System/Library/LaunchDaemons/*",
 "/Library/LaunchDaemons/*") and
(process.code_signature.trusted == false or 
process.code_signature.exists == false)
```

