Apple Patch History

image

This year a1exdandy and I spoke at VolgaCTF and KazHackStan conferences with a talk about Patch Diffing programs written on Objective-C and how to use it to search and find 0-day and 1-day vulnerabilities in Apple products. Video speeches can be viewed at the link, slides (link to our website), and for reading the article, welcome to cat.

Binary Diffing is the process of comparing two executable files in order to find similarities and differences between them. Patch Diffing is a special case of Binary Diffing when a file with vulnerability is compared with a fixed file (file with a patch). This way you can find out what corrections the developer made and understand what the vulnerability was.

A few years ago (namely in 2013), an article was published about Patch Diffing’s programs for Windows, to which we also had a hand. We recommend that you familiarize yourself with it if you are interested in this topic in connection with the Windows OS. In the same article, we will talk about the analysis of programs for apple OS.

How can Binary Diffing and Patch Diffing be useful?

The main task of Binary Diffing is to track what changes have been made to the application. To do this, you need to take the old version and compare it with the new one to see what changes the developer added and how they are implemented.

Let's look at situations in which this may be useful:

  • Program Development Analysis: Comparing the new and old versions, you can understand how the application is developing, what new functionality is added, which is removed and what changes the existing code has undergone.
  • Import existing knowledge: In programs that do not use symbolic information, reverse engineers have to spend much more time both on studying logic and searching for vulnerabilities. But it happens that in some version of the software, developers accidentally or deliberately leave symbolic information. This information can be ported from there to the software version you need. For example, Google Project Zero employees using Binary Diffing were able to get characters for fresh Windows versions of Adobe Reader from older versions for other operating systems, which helped them find vulnerabilities;
  • Real software training: in our opinion, Patch Diffing is a great way to smoothly move from studying small CTF problems to researching real software. Exploring the patch, you can look at the real vulnerability in a large software product with all its features (while knowing for sure that the vulnerability is present in the code). By studying the errors in a product, you can gradually move to the search for the same vulnerabilities. As a bonus, you can try to write exploits for them;
  • Create 1-day exploits: When the developer has already released the patch, you can quickly analyze it, write an exploit for this vulnerability and get a 1-day exploit. At the same time, there is the so-called Patch Gapping – the time between the release of the patch and its direct installation by clients. During this time, a 1-day exploit can work successfully and benefit its author (install updates in a timely manner!) Until everyone installs the patch released by the developers. There are situations when a vulnerability is fixed in a library, but programs still use an outdated version of the library. Here are some interesting examples of Patch Gapping for Chrome and WebKit;
  • Search for 0-day vulnerabilities: No matter how strange it may sound, but analyzing patches, you can find previously unknown vulnerabilities (0-day vulnerabilities). Developers are also mistaken, and therefore, in the process of creating a patch, the vulnerability may not be closed correctly. So, by analyzing a patch, you can find a way around it. For example, Apache Struts developers five times (need a link) fixed the vulnerability, but the patch worked only in its sixth version! In addition, often a developer, clearly fulfilling the task set to him to fix a certain vulnerability, may not notice what is happening in neighboring sections of the code. There could be exactly the same vulnerability nearby, and in case of detection it will be 0-day. It is important to study the pattern of a detected developer error and try to find something similar in the same program. If the developer made a mistake in one place, then the likelihood of repeating the same error somewhere else is high.

There is a myth that hiding vulnerability patch information increases security. However, attackers, as a rule, already have a developed infrastructure for analyzing patches, so they will quickly find the data they are interested in. Hiding vulnerabilities complicates the work of those who are responsible for protecting the system, because without full access to information it is impossible to understand how important this patch is for the company. On this issue, we highly recommend that you read the article "Rashomon of disclosure" from the researcher Halvar Flake, where the situation is viewed from different angles.

Not always discovered vulnerabilities are hidden intentionally. Developers may not attach particular importance to some of the shortcomings of their product and fix them without publicity, like a regular bug.

We are sure that this is not all situations in which you can use Binary Diffing and Patch Diffing, and in the comments you can write your own scripts.

Tools

From theory we gradually move on to practice. Naturally, doing Binary Diffing manually is a crazy undertaking. An extensive toolkit has long been developed, consisting of both standalone programs and plugins for popular binary analyzers: Diaphora, BinDiff, DarunGrim, YaDiff, rizzo, Realyze, Turbodiff, patchdiff2, rematch and others.

image
BinDiff interface.

image
Diaphora Interface

In practice, we mainly use only the first two (they are presented in the screenshots above). Most of the current tools, unfortunately, are either not encouraging with the quality of work, or are completely abandoned. Now there are new tools using ML, but their quality leaves much to be desired, although they have interesting ideas for comparing binary files of different architectures.

I would also like to separately note the recently appeared tools for comparing open-source code in binary files: Pigaios and Karta. This is a very interesting and useful direction. They collect metrics from the source code and then use them to compare functions in binary files. This is very useful in the absence of characters and static linking. The task of these tools is to map functions in one file to functions in another.

Comparison of patches for Apple operating systems

Typically, apple OS applications write in Objective-C. This is an object-oriented extension for C, based on Smalltalk language paradigms with its own runtime.

If we open the program on Objective-C in some binary analyzer (in our case, it is an IDA), we will see something like this: functions in C / C ++ will have abstract names, and functions in Objective-C will be called very beautifully. (We’ll say right away that we don’t consider situations with code obfuscation – this is a separate story.) This makes the reverse engineer easier: it is easy to see which object is called, which method is used, and what arguments it has. Also, this symbolic information greatly simplifies the work with tools for comparing binary files. It allows you to quickly and with a minimum number of errors map functions.

image

When there are no symbols, the tools have to use internal algorithms for analysis, heuristics, etc. Naturally, they do not always work correctly.

Use-cases where patch diffing was very useful

Probably, this presentation (in the format of 45 minutes) and this article would not have been born if Apple had not surprised the world research community several times lately. Let's look at these cases.

Case 1: CVE-2019-8606

In May 2019, iOS 12.3 was released for the iPhone, where they fixed a vulnerability that could be used to install jailbreak. In July of that year, Apple released version 12.4, where the jailbreak started working again: employees accidentally deleted the protective patch. The corrected version was released only after a month: all this time any device on the latest version could be easily subjected to jailbreak’s operations. All this was discovered thanks to patch diffing.

image

Case 2: CVE-2019-7278 and CVE-2019-7286

Personal experience with Patch diffing at the Hack in the Box conference in his report Recreating an iOS 0-day jailbreak out of Apple’s security patches was described by security researcher Stefan Esser. He talked about CVE-2019-7278 and CVE-2019-7286 – they are notable for those that were discovered thanks to the Google Threat Analysis Group during their actual use by attackers (ITW, in the wild). Apple received information about them, but neither they nor the guys from Google revealed technical details. Then Stefan wondered what the attackers were using. We highly recommend that you read his report, as it also talks about the process of comparing kernel and user space components.
Interesting fact: a day or two before Stefan’s speech, Project Zero Ian Beer published a series of articles “A very deep dive into iOS Exploit chains found in the wild”, which somewhat confused the maps for the researcher;)

Case 3: checkm8

Apple devices use two bootloaders: Bootrom and Iboot. The first starts to work as soon as the device turns on. It is in read-only memory and cannot be updated. Iboot is a second-level bootloader that improves authentication that runs in the boot chain.
The peculiarity of the loaders is that they share the code. At the beginning of last year, specialists compared updates for Iboot and found that Apple fixed the vulnerability in the USB stack. Knowing that the same code is used in the non-updated part of Bootrom, they realized that this vulnerability also exists there. Then the development of the checkm8 exploit began. Now all devices based on chips from A5 to A11 (from iPhone 4s to iPhone X) are completely vulnerable, and it is possible to run your own code on them. At the same time, on devices of versions XR and 11, this vulnerability is already closed, and there were no reports of this from Apple.
So, knowing where something was patched and how the code is split, you can find some really cool stuff!

Our story: CVE-2019-8574

image

In May, Apple released a new update for its devices. We looked at the list of fixed vulnerabilities and found the sysdiagnose utility. This program collects diagnostic information from various sources and transfers it to the user in the form of an archive for further analysis, support or a service center. It seemed that it was impossible to influence the way she collects information. The patch description stated that the vulnerability could be used to elevate privileges and is a memory corruption error, which intrigued us even more. And the author of the find himself did not publish any description from himself …

image

You can call sysdiagnose on macOS by pressing Ctrl + Option + Shift +., Or using the sudo sysdiagnose command. On iOS devices, you need to hold down the power key and the volume keys up and down.

Patch Diffing Apple in practice

If you want to Patch Diffing Apple devices, you need to get two versions of the update (old and new). On macOS, you can analyze files in the Software Update Catalog. This method does not always help, as Apple removes some updates. Updates can also be found in the / Library / Updates directory. You can find firmware for iOS devices on ipsw.me.
For macOS, you need to extract executable files, library files, frameworks, and the kernel using the Suspicious Package utility.
For iOS devices, things are a little more complicated. The update itself is a ZIP archive. In this archive you need to find the kernelcache file: inside is the kernel and its extension. However, before analysis, you need to convert the file to Mach-O format. This can be done using the utilities img4tool, joker, jtool2 and others.
User-land-component firmware can be found in the largest DMG-image: it contains the root system and executable files. However, if you look at shared libraries and frameworks, they will not be there. The fact is that to optimize the space they are placed in dyld_shared_cache. This file contains all the libraries on the iPhone and takes up more than 1 gigabyte, which complicates its analysis. If you need to download a separate part of the ipsw file, use the ipsw utility (https://github.com/blacktop/ipsw).

Patchdifting CVE-2019-8574

To study patch CVE-2019-8574, we get a file from Library / Updates and extract two sysdiagnose executable files (old and new) using the Suspicious Package, and then check for updates through utilities for comparing binary codes, for example, Diaphora or BinDiff (they are much better than hex editor).

How the patch works

For x86_64 architecture, we found only one changed function. There are more changes in ARM, but they are minor.

image

The problem was the method [SDTask start]: it added a new check. In the figure you can see how a call to some isAppleInternal function occurs and the presence of the substring / usr / local in some path is checked.

image

As stated earlier, sysdiagnose collects information from various sources. Sources can be either files (for example, an event log), or the output of some information commands (for example, listing processes or threads using ps) – such tasks are stored in sysdiagnose as SDTask objects. Method [SDTask start] starts the execution of tasks. In the figure below you can see the code in which all tasks are formed. All paths of executable files and their arguments are written directly in the program, and there are tasks from various directories, including / usr / local.

image![](./assets/8.png)

Thus, prior to installing the patch, any task could be performed regardless of where the executable file is located. After installing the patch, the isAppleInternal function is called, which checks whether the device is an internal test device of Apple. If this is an internal device, then the task is performed in a standard way, and if it is a client, then the presence of the substring / usr / local / in the path of the task executable file is checked. If a substring is found, the task will not be completed.

Recall that in the description of the vulnerability it was said that this is a memory corruption violation, but in the patch we did not notice anything like it … In our opinion, this is a well and stably exploited logical vulnerability.

How to exploit it

To exploit the vulnerability, you must perform the following steps:
Create any executable file (binary or shell script) that sysdiagnose launches from / usr / local / bin, and put our payload there. The list of valid files is given below. It is important that the brew package manager is installed on the system: it allows the user to create files in / usr / local / without elevating privileges.

It is necessary to call sysdiagnose. In this case, our payload will be executed with root user rights, and its output will be placed in the archive, which forms sysdiagnose. This way we get privilege escalation. However, running sysdiagnose itself requires elevated privileges. But, as mentioned above, sysdiagnose can also be launched using a keyboard shortcut, and this works even from the macOS lock screen.
This vulnerability can be used to create various malicious programs.

/ usr / local / bin / airplayutil
/ usr / local / bin / amstool
/ usr / local / bin / apsclient
/ usr / local / bin / audioDeviceDump
/ usr / local / bin / cdcontexttool
/ usr / local / bin / cddebug
/ usr / local / bin / cdknowledgetool
/ usr / local / bin / dastool
/ usr / local / bin / idstool
/ usr / local / bin / imtool
/ usr / local / bin / keystorectl
/ usr / local / bin / pmtool
/ usr / local / bin / xcpm
/ usr / local / efi / bin / efi-perf

Interestingly, other vulnerabilities could be associated with the brew package manager, or rather with the ability to write to / usr / local / without privileges.

Output

With this study, we would like to show the importance and criticality of patch diffing not only for attackers, but also to increase the security of software products. Unfortunately, the patch can not only close the vulnerability, but also play into the hands of the attacker.
Nevertheless, this approach allows not only to study known vulnerabilities, but also to search for new ones like them. Therefore, we believe that patch diffing is a must have for every researcher.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *