How Predator has evolved to infiltrate the system and take advantage of vulnerabilities
Christmas came early for us at iVerify in 2024 when we were “gifted” a sample of Cytrox / Intellexas Predators - it was at the top of our wish list! Though it wasn’t the full malware sample, we got our hands on the loader that’s used to install the agent. What follows here is an overview of what we found and a comparative analysis between samples obtained from 2021 and 2023 to show how the malware has evolved and disclose a couple of IOCs that can be helpful in finding this specific version of the malware on a live device. If you saw us at NullCon Goa 2025, this will serve as a nice recap of our presentation, which we’ve linked below.
Slides: Predator_Trust-Broken-at-the-Core.pdf
Recording: https://www.youtube.com/watch?v=1kZsUeV-_UA
Predator in 2021
If you’re already familiar with Predator malware feel free to skip over this paragraph. If you need a quick refresher, read on. If you’re completely new to Predator this blog post from The Citizen Lab provides a great overview.
The 2021 version of Predator is an iOS spyware that infected devices by trying to get users to click on an infection URL that, once opened in Safari, would lead to code execution and installation of the spyware implant and contained a persistence mechanism by using shortcuts.
Upon execution the Spyware would run two processes from:
/private/var/tmp/UserEventAgent
/private/var/tmp/com.apple.WebKit.Networking
This has a couple of benefits for the attacker: 1) The tmp directory is cleared on reboot so any “malware” sample would be automatically removed, 2) the directory is not readable from the application sandbox and the directory is not backed up, 3) if a researcher / forensic examiner does not have the full process path available in telemetry, those process names would not appear suspicious on first look. But on the second look “UserEventAgent” is a very poor choice as this process often appears with a very low PID and only once per process list on a device. Having two of them running at the same time would certainly trigger additional investigation. In case full path information is available any process executing from /private/var/tmp is a clear sign something is wrong on the device.
Additional processes / injections which are spawned could be:
hooker
takePhoto
agent.dylib
inject
The spyware used a configuration directory inside of
/private/var/logs/keybagd
which would contain a couple of configuration files including the decryption keys and server URls.
At the time, Predator was mainly written in Python, which means the sample contained a complete “Python environment” and it shared a lot of the code between Android and iOS.
The sample removed crashlogs it found on the device and it would not infect a device with a locale of “IL” (Israel) which is a very interesting choice given that the headquarters resides in the European Union and not in Israel anymore. What we also found interesting is that the spyware was very eager to share its existence with the device's unified logs upon execution: “predator installed, run it.”
Additional thorough technical blogposts about Predator can be found at Cisco Talos Blog: here and here and a LabsCon talk by Vitor Ventura. Now lets move on to 2023 and a new version of Predator.
The 2023 Version of Predator
September 21, 2023, Apple patched three “exploited in the wild” vulnerabilities in iOS 16.7 and 17.0.1, all attributed by The Citizen Lab and Google TAG to Intellexa. The patched vulnerabilities were:
CVE-2023-41991 - Certificate validation issue (CoreTrust)
CVE-2023-41992 - Local privilege escalation (Kernel)
CVE-2023-41993 - Remote code execution (Safari)
Those vulnerabilities clearly allow code execution via WebKit, run a privilege escalation into the Kernel and then run a spyware implant on the device. The Citizen Lab published information on a loader of the spyware that it found.
The CoreTrust vulnerability has become very useful for the jailbreak community as it made its way into TrollStore v2 and allows for the install of side-loaded applications until iOS 16.61 and 17.0 with almost any entitlements.
CVE-2023-41993 also reappeared as it was reused by Russian threat actors to target Mongolia. Interestingly, the attacker decided not to run an implant even though they clearly could have used the CoreTrust vulnerability and the kernel vulnerability to do it.
Sample Analysis
Our strategy for analyzing the sample was to start with static analysis and follow with dynamic and network analysis. We stuck with static analysis while we were acquiring a device with an applicable iOS version to support the sample (the sample is built for arm64e so an iPhoneXS or higher [A12 chipset] is required).
The first analysis with built-in tools like strings, otool, nm and codesign already revealed quite a lot of information on the sample:
The min iOS version is 16.0 and the build SDK is 16.4.
codesign reveals the entitlements of the binary and the identifier which is “Watcher.”
A full list of entitlements can be found as an appendix to this blog post.
Interestingly, codesign did not show that the sample had multiple signers for the binary, a requirement for the CoreTrust bypass as written by https://x.com/alfiecg_dev in and https://x.com/opa334dev (check out the joint talk about TrollStore at 0x41con 2025).
In this case, this seems to be an error in Apple’s codesign tool. Viewing the code signature with Jonathan Levin’s disarm shows two code signatures.
One seems to be the copy of a legitimate AppStore App the other one is signature we could also see for the Watcher sample:
This also shows us the exact timestamp when the sample was signed, September 7, 2023.
For further analysis we used IDA Pro and Ghidra. The following code snippet is an approximation of the sample’s main function created by manual analysis, decompilation and LLMs.
What we can see here is essentially:
The binary is spawned with 14 command line arguments. Those arguments are copied into local_variables and then the existing arguments are nulled making sure they are not visible anymore in commands like “ps,” as seen in The Citizen Lab report.
After that the binary checks if arg14 contains “watcher.” If it does, it initializes the WatcherSpawner class with the first 13 command lines arguments and “helper,” as well as running cswatcher.spawn() and cswatcher.start() in a CFRunLoop.
If arg14 is not “watcher” but “helper” the sample will initialize the helper class with call to helper.initwithRW. If that is successful, helper.start() will be called in a CFRunLoop.
If there are less than 13 arguments or if the 14th is not “watcher” or “helper” the program will exit with exit(0).
After just reading the main_function, we know that the sample will likely spawn two processes, which are both going to be “watcher” and “helper”. These are not their actual program names but this is how they are referred to.
Predator - 2023 -_main

Watcher is the process executed first. On initialization it’s going to evaluate a couple of checks to decide if the sample should continue or not. Those were already described by The Citizen Lab.
Watcher: validation checks:
Predator - 2023 - watcher

If those are unsuccessful, the sample will call report_abort() and exit. If successful, watcher will download (if needed) two additional binaries. After that, it checks if “watcher*”* was already executed before by checking for a file hardcoded in “/private/var/tmp/etherium.txt” If this file is found, “watcher” checks the modification time of the file. If this is older then 45 minutes, the previous “watcher*”* will be killed. Then “watcher” will execute the downloaded binaries. Additionally, it will check if “/private/var/tmp/kusama.txt” exists. If it doesn’t, it will spawn “watcher*”* again. “Watcher’s” spawn path is stored at WatcherPathSecond which is a combination of “/private/var/tmp/” and a path supplied via the command line arguments.
After that, it will spawn the downloaded binaries at helperPath and bitPath. Both are also a combination of a fixed path “/private/var/containers/Bundle/” and an individual path which was passed in via the command line arguments.
Thereafter, “watcher” will start a run_loop and continuously check for the existence of the sample’s binaries, if it’s not there, it will re-execute the download and execute function. “Watcher” will also register a notification for “com.apple.springboard.deviceWillShutDown” and stop and remove all spawned binaries on a registered shutdown. Additionally, “watcher” will monitor the crashlog directory for any newly created crashlog and in case it finds the name “SystemMemory” in one of the files, it will search for the process mmaintenanced and if found kill it.
“Watcher” will also start “helper” which is a second mode of the loader sample we retrieved.
The initialization and start from “helper” will follow a similar process to “watcher.” In contrast, it starts either with “InitWithRW” or with “Init.” In the latter case, it will call a function that is called “:RWTransfer:Get” which should make sure that “helper” gets access to the samples kernel rw methodology.
After “Init,” “helper*”* follow a similar start process to “watcher” which includes monitoring for shutdowns and running a runLoop to check if the file at “/private/var/tmp/kusama.txt" exists. If the file is not present, “helper*”* will stop.
“Helper’s” main functionality is to provide a socket server for other parts of the malware and process their requests. For that it runs a Unix socket located at “/tmp/helper.sock”
Predator - 2023 - helper

Unfortunately, the exact operations that “helper” can execute via the socket are dynamically resolved, so we can’t be certain of all of them.
But here is a list of potential operations:
Predator - 2023 - helper

Keylogger, CameraEnabler and VoIP recording are all operations of the malware that require hooking into other functions. While Keylogger naturally hooks into “kbd”, the latter two are a bit more interesting, because they involve hooks into mediaserverd, a process that is present until iOS 17. While it is thought that mediaserverd needs to be restarted after hooking in, the code in these Predator samples doesn’t include any references to spawning or killing the process. Instead, it focuses on a combination of the NSTaskROPWithoutDeveloperMode, DMHooker and UMHooker functions. As of publishing, we haven’t fully analyzed this code.
Another part of “helper” that hooks into other processes is “Helper::HiddenDot” which hooks into Springboard, but the exact functionality remains unclear for now.
“Helper” will store all VoIP recording in the tmp directory and all files will be named after the following schema: “/private/var/tmp/l/voip_%lu_%u_PART.m4a”
Interesting Behavior / Weird Things
Similar to Predator in 2021, the sample contained leftover artifacts or dead code, and even information about their build environment. E.g.
Or functions such as
that are just empty or unreachable from the current code. The sample also checks if any jailbreak was remounting the root partition, something that has not been publicly demonstrated since the introduction of sealed system volumes in iOS 15. Additionally, it checks for the existence of the “checkra1nd”, which is also not publicly used after iOS 14 and requires an arm64 device on which the malware sample wont be able to execute as it was compiled for both iOS 16 and arm64e devices. The publicly available jailbreak for iOS 15 and higher, based on the checkm8 vulnerability, is palera1n. And palera1n uses palera1nd instead of checkra1nd. In summary any banking application will have better jailbreak detection than this sample, but probably also not necessary as there was no public jailbreak for arm64e devices on iOS 16 at the time.
From the 14 command line arguments we could recover the behavior of six so far.
Predator - 2023 - Command Line Arguments

The Evolution of Predator
In a two-year span, we can see that Predator malware has been completely rewritten. The new version is built on top of native code instead of the Python-based variant in 2021. It looks a bit more professional than the previous version, but there are still a lot of similarities. The sample starts multiple processes executing again from the tmp directory and the application directories and contains multiple hooking functions. Unfortunately, the exact process names and domains are dynamically configured via the program arguments so we have no exact IOCs to work off of, but it’s very probable that the process names themselves would be named after operating system processes. That’s something we already saw in the 2021version (in contrast to Pegasus at the time).
The sample we investigated did not contain any persistence module, but that doesn’t mean there isn’t one as it could be just dynamically loaded when needed. The developers also learned from The Citizen Lab’s report in 2021 and logged a bit less and started to monitor shutdown.log so they are not kept there anymore, but there is still plenty of behavior that can be detected.
Detecting Predator 2023
We’ll include a list of IOCs for this specific sample, although the detection of most of the IOCs will be unfeasible for most tools. We could not find any IOCs that would persist in a backup, so post-mortem analysis or the use of MVT will not be fruitful. Most of these IOCs (such as the processes executing from tmp) are easy to detect if the data is present (e.g. in a Sysdiagnose), but it requires data capture at the time of infection or closely after, so it’s possible to check any old sysdiagnose for potential infections. The included file-based IOCs can be checked by MTD applications or jailbreak detection frameworks and we encourage them to include them. As written above the loader will spawn two binaries from the “/private/var/containers/Bundle/” directory. Unfortunately we dont know the exact path. So we did not include this in the IOC File. But in case you find two suspicious processes executing from there it’s worth investigating. Similarly we did not include exact IOC for the voip recordings which were stored in /private/var/tmp/l/ as their file names would be generated on demand. But the directory itself would already be suspicious. /private/var/tmp does not normally contain a subdirectory that is called “l” (small “L”).
The sample also contained a couple of log messages:
Those log messages should be descriptive enough to find traces of this specific version of Predator.
If you do find an infected device or you received an Apple Threat Notification - please reach out so we can help investigate!
Further Research
We are far from being done with analyzing this sample, and some of the functions described here might contain other interesting techniques. We’ll continue to publish updates with interesting takeaways as we find them to help enable the community’s research into this strain of malware in the hopes of making everyone safer.
Outlook
We can clearly see that Predator evolved since 2021. The malware was completely rewritten and used very advanced vulnerabilities to both infiltrate the system and run the implant. The CoreTrust bypass fueled third-party AppStores such as TrollStore and allowed a lot of research. But the implant itself still looks a bit sloppy - lots of dead code, unused functions, references to GitHub and still logging, not even mentioning the OPSEC. Even though we only had the loader, we’re not seeing critical components we would expect to find with any advanced desktop malware such as packers and encrypted components stripping off any symbols. The malware would be pretty easily caught by most EDR or AV systems. Frankly, for the price Intellexa is charging, we would have expected a lot more.
It seems like Intellexa is solely relying on the closed nature of the iOS ecosystem, which makes it more difficult for researchers to get insight into system activity and find malicious processes and/or files. There is no way a traditional AV, MTD app or MDM could find this on a device as they all lack access to the data. You need forensic sources such as backups, sysdiagnose, network telemetry and more to discover them, and all of those are guarded by heavy user interactions and hardly automized, so it creates this interesting dichotomy where on the one hand you have a more secure environment but on the other hand for the attacks that do make it through the defenses, like Predator and Pegasus, it also challenges the security analysts doing their best to try and defend those devices by blindfolding them. Even the most basic endpoint security framework for iOS with process telemetry, file listings and crashlog monitoring would have allowed for automated detection of both iterations of Predator - that’s at the top of our Christmas list for this year!
Appendix A: IOCs
ile-paths:
/private/var/tmp/kusama.txt
/private/var/tmp/etherium.txt
/private/var/tmp/helper.sock
/tmp/helper.sock
/tmp/etherium.txt
/tmp/kusama.txt
/private/var/tmp/l
/tmp/l
file-names:
kusama.txt
etherium.txt
helper.sock
log-strings:
Can't initialize TaskROP
Successfully got TaskROP running!
UMHooker has been destroyed
Can't initialize UMHooker
Hook 1 triggered! location:
Appendix B: Predator 2023: List of Entitlements
Appendix C: Downloadable File
https://welcome.iverify.io/hubfs/2025_Predator_2023.stix2
More Blogs
Get Our Latest Blog Posts Delivered Straight to Your Inbox
Subscribe to our blog to receive the latest research and industry trends delivered straight to your inbox. Our blog content covers sophisticated mobile threats, unpatched vulnerabilities, smishing, and the latest industry news to keep you informed and secure.