How Kaspersky obtained all levels of Operation Triangulation
At first of 2023, due to our Kaspersky Unified Monitoring and Evaluation Platform (KUMA) SIEM system, we seen suspicious community exercise that turned out to be an ongoing assault concentrating on the iPhones and iPads of our colleagues. The second we understood that there was a transparent sample within the connections, and that the units may have been contaminated, we initiated a normal digital forensics and incident response (DFIR) protocol for such circumstances – transferring across the workplace, amassing the units, and inspecting their contents. The final word objective was to find and extract the malware, to search out the purpose of entry (hopefully, a 0-day) and to develop a protocol for scanning the iDevices for lively an infection. That course of was a months-long journey, and on this article we want to summarize it.
First steps
As we talked about in the very first article on Operation Triangulation, the contaminated units that we knew about initially, belonged to Kaspersky staff who labored within the HQ workplace in Moscow. All these units have been linked to the company Wi-Fi community, which allowed us to document and examine the community site visitors. After spending a while investigating with Wireshark, finally we discovered the next:
- Proper earlier than exhibiting the suspicious habits, the units linked to the iMessage servers often liable for receiving messages and downloading attachments;
- After downloading a couple of kilobytes of knowledge that might have been an attachment, the units established a connection to the server backuprabbit[.]com, exchanging knowledge with it over a course of lower than a minute;
- Subsequent, the units linked to one of many following servers for an extended session:
- cloudsponcer[.]com
- snoweeanalytics[.]com
- topographyupdates[.]com
- unlimitedteacup[.]com
- virtuallaughing[.]com
- As soon as the system rebooted, all of the suspicious exercise stopped.
Sadly for us, all of the communications with the servers in query occurred over HTTPS, so we couldn’t recuperate any further particulars from the site visitors.
Machine imaging
Since all of the units have been actually inside hand’s attain, the apparent subsequent step for us was to examine their contents. Sadly, it was a lifeless finish: out there forensics acquisition software program on the time of analysis was based mostly on checkra1n and comparable exploits that didn’t work for contemporary processors working iOS 15 and 16.
Inspecting backups
What we determined to do subsequent was to make use of iTunes backups of the units as an alternative choice to full system photographs. This process needed to be executed with a good quantity of secrecy in order to not scare away the attackers. Since we didn’t know in regards to the precise capabilities of the attackers, we assumed that they have been listening to the microphones of the units, and studying e-mail messages and messenger conversations. So, we needed to organize our conferences in individual, placing the telephones in airplane mode, and typically in Faraday baggage. We used the superb tooling from libimobiledevice to amass the backups, and inspected them by constructing a timeline of occasions with the Mobile Verification Toolkit.
Such a timeline combines file system timestamps with knowledge data extracted from varied system databases. We targeted on the iMessage directories, as a result of we knew that in 2021 Citizen Lab researchers had discovered the notorious FORCEDENTRY exploit by analyzing recordsdata in these directories. We wished our evaluation to be as fruitful – however the attackers behind Operation Triangulation turned out to be very stealthy, and we discovered no indicators of exploits within the backup. We additionally searched it for malware executables, which we have been additionally unable to search out.
We had further knowledge factors – the timestamps of suspicious community exercise. So, we began to search for any repeating occasions within the timeline that occurred across the identical time. In consequence, we discovered what regarded like a brand new indicator: knowledge utilization data mentioning a system course of named “BackupAgent” that ought to not have been executed in any respect – the binary was deprecated years earlier than.
2022–09–13 10:04:11.890351Z Datausage IMTransferAgent/com.apple.datausage.messages (Bundle ID: com.apple.datausage.messages, ID: 127) WIFI IN: 0.0, WIFI OUT: 0.0 – WWAN IN: 76281896.0, WWAN OUT: 100956502.0 2022–09–13 10:04:54.000000Z Manifest Library/SMS/Attachments/65/05 – MediaDomain 2022–09–13 10:05:14.744570Z Datausage BackupAgent (Bundle ID: , ID: 710) WIFI IN: 0.0, WIFI OUT: 0.0 – WWAN IN: 734459.0, WWAN OUT: 287912.0 |
Anomalous exercise from the BackupAgent course of noticed in system logs – we shared this snippet in our first submit on Operation Triangulation
Based mostly on the invention of this anomaly, we wrote a primary model of our triangle_check device. It allowed us to shortly affirm if a tool’s backup contained traces of potential compromise.
Attempting to intercept the malicious iMessage
Wanting additional into the occasion timelines, we found a second weak indicator: modification of an empty SMS attachment listing (one or a number of) previous to knowledge utilization by the BackupAgent course of. Because the listing is modified however accommodates no recordsdata, that often means with a excessive diploma of confidence that the final operation was file deletion: there was an incoming attachment, it will get deleted, and seconds later a course of named BackupAgent is working suspicious networking code.
Because the risk actor behind Operation Triangulation gave the impression to be sensible sufficient to take away the malicious attachment from contaminated units, we determined to try to seize the incoming message through the iMessage supply course of. Whereas searching for a option to intercept iMessages, we discovered this Frida script coded by the Google Mission Zero staff. IIt is designed to run on a Mac, so we took a spare Mac mini and put in Frida on it. We then requested a number of of our focused colleagues to log in to that Mac mini with their Apple IDs. By doing that, we have been capable of monitor and intercept iMessages that they acquired. All that we wanted to do subsequent was to attend till the attackers contaminated one in all our colleagues’ units as soon as once more.
On the identical time, we have been actively monitoring SIEM logs for the traces of suspicious exercise. Quickly sufficient, we detected acquainted community connections that indicated a profitable compromise of a cellphone with a “cloned” iMessage account. Nonetheless, after we checked the iMessage interception logs on the Mac mini, we recognized no traces of messages on the time of an infection. Thus, our system was failing to seize the message that might have contained an exploit (we nonetheless don’t know why it didn’t work), so we began to hunt different methods of capturing the malware.
Good outdated MITM
After the plan to intercept iMessages by way of a Mac system failed, we determined to attempt to decrypt HTTPS communications with the C2 servers beforehand recognized from site visitors evaluation.
To do this, we:
- Arrange a Linux server and put in mitmproxy, an HTTPS interception device;
- Put in a root SSL certificates (that we beforehand generated by way of mitmproxy) on a number of iOS units that have been recognized to be compromised earlier than;
- Put in a Wireguard VPN shopper on these units and configured them to make use of our mitmproxy occasion as a VPN server.
We additionally developed a Telegram bot that will notify us each time one of many monitored units grew to become contaminated:
Sadly, this technique didn’t permit us to intercept HTTPS site visitors of Apple providers (together with iMessage), as iOS implements SSL pinning for this. Thus, we weren’t capable of decrypt iMessage site visitors that got here by way of the VPN.
Catching the JavaScript validator
As soon as the attackers reinfected one of many targets, we regarded within the mitmproxy logs, noticing that it managed to decrypt the C2 server site visitors:
We anticipated the payload that we managed to acquire to be an exploit for iOS. Nonetheless, it was the JavaScript validator, which merely collected details about the sufferer browser and despatched it to the C2 server.
We noticed the contaminated system receiving a payload in response to the validation info despatched to the C2 server. Nonetheless, whereas we have been capable of intercept HTTPS site visitors, we couldn’t decrypt it. That’s as a result of the JS validator implements its personal layer of encryption for C2 communications, utilizing the NaCl library. The encryption algorithm used relies on public-key cryptography. Particularly, to speak with the C2 server, the JS validator:
- Generates a random key pair (consisting of personal and public key);
- Derives a shared key from the generated personal key and the C2 server’s public key;
- Makes use of this shared key to encrypt messages despatched to the C2 server and decrypt those acquired from it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var o = perform (t) { perform u(t) { this.D = nacl.field.keyPair(); this.L = nacl.field.earlier than(t, this.D.secretKey); } u.prototype.encrypt = perform (t, nonce) { return nacl.field.after(t, nonce, this.L); }; u.prototype.decrypt = perform (ciphertext, nonce) { return nacl.field.open.after(ciphertext, nonce, this.L); }; u.prototype.N = perform () { return nacl.randomBytes(nacl.field.nonceLength); }; u.prototype.okay = perform () { return this.D.publicKey; }; return new u(t); }(h.values.R) |
Key technology
With the intention to decrypt the C2 server communications, it’s essential to know the personal key that was randomly generated by the JS validator. Nonetheless, this secret is stored in reminiscence and isn’t despatched to the C2 server. And so we needed to do some further work so as to decrypt the validator’s site visitors.
As demonstrated by the screenshot above, the JS validator generates a random key pair by invoking the nacl.field.keyPair() technique. To decrypt the site visitors, we determined to compromise the method of producing this keypair. Particularly, we coded a tiny mitmproxy add-on that regarded for invocations of the nacl.field.keyPair() technique. It then changed them with one other technique, nacl.field.keyPair.fromSecretKey(), that initializes a keypair from a offered personal key.
As will be noticed from the screenshot above, we hardcoded a personal key into the arguments of this technique, thus backdooring the validator’s encryption scheme. As soon as the backdoored validator was executed on the contaminated system, it grew to become doable to decrypt all communications of the JS validator.
The binary validator and the trace in regards to the attachment
As soon as the attackers reinfected one in all their targets, we have been capable of analyze the payload additional executed by the validator. It turned out to comprise two exploits: one for WebKit and the opposite for the iOS kernel. The final word objective of these two exploits is to launch the binary validator stage on the goal system.
As we described within the article protecting the stealth of Operation Triangulation, the binary validator accommodates a perform that cleans up traces of the malicious iMessage. Particularly, we discovered that this perform makes the next SQL request to the SMS.db database:
SELECT guid FROM attachment WHERE uti == “com.apple.watchface” AND LENGTH(transfer_name) > 32 AND INSTR(transfer_name, CHAR(0x2013)) == 9; |
The situation ‘uti == “com.apple.watchface”‘ gave us one other trace: now it grew to become clear that the malicious attachment is a .watchface file. And so, with a bit bit extra details about the attachment, we deliberate and executed the subsequent try and acquire it.
Exploring iMessage
With the intention to devise one other technique for getting the attachment, we determined to review the method of sending iMessage attachments in higher element. It seems that this course of consists of the next steps:
- The sender generates a random AES key and encrypts the attachment with it;
- The encrypted attachment is uploaded to iCloud;
- The iCloud hyperlink to the encrypted attachment is distributed to the recipient together with the AES key, which is moreover encrypted utilizing the system’s public RSA key.
Thus, to acquire the malicious attachment file, we needed to retrieve two elements:
- The ciphertext of the attachment;
- The AES key used to encrypt it.
It’s fairly easy to acquire the attachment ciphertext, as it’s doable to intercept site visitors to the iCloud servers by way of mitmproxy. Beforehand, we wrote that iOS doesn’t permit decryption of HTTPS site visitors of Apple providers. Nonetheless, iCloud attachment hyperlinks turned out to be an exception to that rule.
On the identical time, the method of acquiring the AES secret is fairly tough. It’s despatched over the iMessage protocol and so can’t be intercepted by way of mitmproxy. Nonetheless, we found a option to recuperate the attachment and to extract this key utilizing bodily entry to the goal system. We prevented iMessage from efficiently downloading the attachment utilizing the iCloud hyperlink, in order that the exploit wouldn’t activate after which delete the attachment, however the AES encryption key could be saved within the SMS.db database.
We determined to alter a couple of bytes within the attachment ciphertext utilizing our mitmproxy add-on. By doing that, we disrupted the method of downloading the attachment ciphertext, and the decryption key was stored within the SMS.db database. We then downloaded an iTunes backup of the contaminated system and extracted the important thing from the database inside this backup. In consequence, we obtained the malicious .watchface attachment despatched by the attackers – that was the start of the exploit chain used to compromise the units.
Getting the implant
After we completed acquiring the exploits utilized by the attackers, all that remained was to get the implant itself. The binary validator is the part liable for downloading and activating the implant payload from the C2 server, and it makes use of a mix of RSA and AES for communications. Once more, the usage of RSA implies that it’s unimaginable to decrypt the implant payload by having solely the ciphertext site visitors.
To change knowledge with the C2 server, the binary validator:
- Generates a random AES key;
- Encrypts the generated AES key with the server’s RSA public key specified within the validator’s configuration;
- Encrypts the message to be despatched to the C2 server with the generated AES key;
- Sends the encrypted message to the C2 server and receives a response from it;
- Decrypts the response with the identical AES key used for encrypting the despatched message.
The validator encrypts all of the packets with the next ARM directions:
E0 03 18 AA MOV X0, X24 2E 1A 00 94 BL serialize_plist A0 04 00 B4 CBZ X0, loc_100006CD4 E1 03 17 AA MOV X1, X23 39 1A 00 94 BL encryptData |
This code first executes the “serialized_plist” perform, which prepares knowledge for sending. After it’s executed, the register X0 factors to the info able to be despatched to the server.
The subsequent perform to be invoked is “encryptData”. It has two arguments: a pointer to the info being encrypted is handed to the X0 register, whereas the X1 register accommodates a plist with configuration knowledge, together with encryption parameters. After the execution of this perform, the X0 register accommodates a pointer to the ciphertext.
As soon as once more, we wanted to compromise the encryption course of to intercept the info from the contaminated system. We determined to switch the decision to the “encryptData” perform with a NOP instruction (1f 20 03 d5). This fashion, the worth of the X0 register is not going to be overwritten with the pointer to the encrypted knowledge, and the validator will ship cleartext knowledge to our VPN server.
Simply as within the case with the JavaScript validator, we patched the code on the fly by extending our mitmproxy add-on:
sig_pattern = re.compile(rb“…xaa…xf9…x94…xaa…x94…xb4…xaa…x94…xb4…xb4…x71…x54…xaa…x70…xd5…xaa…x14”) block_to_nop = sig_pattern.findall(ungzipped)[0] new_block = block_to_nop[:28] + b‘x1fx20x03xd5’ + block_to_nop[32:] ungzipped = ungzipped.substitute(block_to_nop, new_block) |
Snippet of the mitmproxy add-on code that patches the decision to the encryptData perform with a NOP
When the cleartext knowledge reaches our VPN server, we (once more, by way of the mitmproxy add-on) simulate a key change and knowledge encryption and management the worth of the encryption key. In consequence, we efficiently decrypted the info despatched by the C2 server and extracted the physique of the implant.
Acquiring the modules
After reverse engineering the TriangleDB implant, we discovered that it is ready to execute auxiliary modules, which made us need to acquire the module binaries. In our evaluation of the implant, we wrote that module executables are handed to the implant by way of the CRXUpdateRecord and CRXUpdateRunRecord instructions. Thus, so as to get these executables, it was essential to have the ability to decrypt all of the instructions despatched to the C2 server.
Once more, the encryption algorithm was based mostly on RSA, so our actions have been much like these we took to acquire the implant binaries.
This time, nevertheless, we determined to:
- Generate our personal RSA public/personal key pair;
- Substitute the RSA public key from the implant’s configuration with the beforehand generated one.
We did that by including the next code to the mitmproxy add-on:
macho_second_index = find_nth(decompressed_implant, b“xcfxfaxedxfe”, 2) macho_second = decompressed_implant[macho_second_index:] rsa_key, xored_signature_offset, xor_key = extract_rsa_key(macho_second) my_der_key = MY_CERT_DER self.infections[flow.client_conn.peername[0]][“true_device_public_cert”] = rsa_key my_der_key_xored = xor_one_byte_key(my_der_key, xor_key) decompressed_implant[macho_second_index + xored_signature_offset:macho_second_index + xored_signature_offset+796] = my_der_key_xored |
When the implant site visitors reached our VPN server, we:
- Decrypted it with the RSA personal key that we generated;
- Saved the decrypted site visitors;
- Re-encrypted the site visitors with the general public key utilized by the attackers.
This fashion, we have been capable of listen in on all communications carried out by the implant, in addition to acquire the module binaries.
Conclusion
Our journey of investigating Operation Triangulation was fairly prolonged; it took a number of months. Regardless of many ups and downs, we finally managed to acquire all of the levels used on this assault, together with 4 zero-day exploits reported to Apple, two validators, an implant and its modules.
Alongside the best way, we carried out plenty of analysis on iOS internals and got here up with many attention-grabbing methods, such because the one we used for extracting the iMessage attachment.
The primary issue that we encountered throughout our analysis was to take care of the public-key cryptography that was utilized in nearly each stage of the an infection chain. To bypass the encryption, we needed to develop a mitmproxy add-on that patched the malicious levels on the fly and compromised the unique algorithms. Initially, we began with simply 30 strains of code. After we completed extracting the modules, it had about 400 strains – and we undoubtedly didn’t anticipate the add-on’s code to develop that a lot again at the beginning of our enduring journey!