So today we have Slava Mikheev talking to us about digging into Xiaomi's tea to get to Chinese money. It's Slava's fifth time speaking at DEF CON, so please welcome him back. Hello, everyone. Thank you for attending the talk. I'm Slava. I have been doing mobile security research at Check Point for many years. Reverse engineering and vulnerability research is my daily work. When I hear the phrase trust zone or a trusted environment, I imagine some secure place on a device where cryptographic keys, passwords, and other security-sensitive information are stored. I imagine that protection is implemented with hardware assistance and major mobile chip manufacturers such as MediaTek and Qualcomm are responsible for the business logic. Thank you. In general, all my assumptions are correct. But in fact, and this surprises me a little, not only chip manufacturers can change the logic of the trusted code running on a smartphone. Device manufacturers such as Xiaomi also have the ability to patch the trusted code and add new items. In my research, I consider the trusted code provided by Xiaomi. And I will show you several vulnerabilities in Xiaomi's trusted environment, which align with an unprivileged Android application to steal money from ordinary people. Well, according to the latest statistics, the Far East and China account for two-thirds of the world's mobile payments. This is about four billion dollars in mobile wallet transactions. Let's zoom in. WeChat Pay and Alipay are the largest players in the Chinese mobile payment industry. Together, they account for about 95% of the all-Chinese payment market. Each of these platforms have over one billion users. So actually, it's enough to hack only one of them to get rich. Today, I focus on WeChat Pay. WeChat Pay is built in Xiaomi devices powered by a MediaTek chip. Why this particular combo? Because Xiaomi is the most popular Chinese smartphone manufacturer. MediaTek is the most popular mobile chip manufacturer in the world. And WeChat Pay is the most popular payment platform in China. Okay, now let's talk about the trusted environment, aka TE. As I mentioned, mobile payment signatures are carried out in the TE. So, as long as TE is safe, so are your payments. On the internet, you can easily find many articles about the TE architecture. So, I note only the key points. TE creates a virtual security world managed by a trusted operating system, which runs the trusted applications. Each trusted application implements a specific security feature and the normal world OS, in our case, this is Android, can send a comment to a trusted app and receive a response. Xiaomi devices powered by Qualcomm chipsets use QC. The trusted OS and MediaTek-based devices uses Kinevi. In both cases, Xiaomi can embed and sign their own trusted applications. On Xiaomi devices, you can easily find trusted apps in the directory window THTA. Each app is represented by an unencrypted binary file. And usually, trusted applications of the Kinevi OS have the MCLF file format. But Xiaomi decided to come up with one of their own. Actually, we don't need even to understand all the format fields, because the initial part of the Xiaomi's trusted app is the ELF file. Trusted applications can have multiple signatures following the magic fields. And the magic fields are the same across all trusted apps on the device. Moreover, they are the same with the apps fields of all other devices. As you see, the version control field is omitted in the trusted apps file format. It means that an attacker can transfer an old version of the trusted application to a device and use it to overwrite the new app file. And the signature of the old trusted app is correct. This app will be successfully loaded by the TE. Knowing this, an attacker can bypass security features and patches of Xiaomi and MediaTek in the trusted applications by downgrading them to an unpatched version. I will use this vulnerability in my POC. Okay. Xiaomi follows the global platform TE client client. This is an API specification which defines the interface between the client application and the trusted environment. This API is implemented in the libte-common-asso library. And we can use this library to access the trusted applications from an Android. But unfortunately, an unprivileged Android application has no permission to communicate with the TE. SLE nooks prevents access to the corresponding driver. And it's possible to work only from a limited number of privileged users, such as DRM and media codec. To bypass, we need to use a vulnerability. And I will show you one a bit later. On this slide, you can see an example of how to call a trusted application from Android. In this case, I sent a comment to the THH admin trusted app. This app expects to receive one input buffer and one output buffer as arguments. And the comment ID will be ignored. Okay. Trusted apps implement TA, invoke comment entry point function. It handles the comment ID and the buffers sent from the Android side. This function is a perfect target for fuzzing commands. I'm doing base vulnerability research. And I use a classic combination of AFL and QEMU emulators to fuzz Xiaomi's trusted applications on Ubuntu machine. A little later, I will show you vulnerability related to mobile payment. Okay. Now we know what the Xiaomi's trusted environment is. Let's talk about payment system. Okay. Modern Xiaomi devices have an embedded mobile payment framework. Named Tencent Sorter. Tencent Sorter provides an API to create, sign, and verify payment packages. Transfer it between a mobile application and a remote backend server. We should pay based on the Tencent Sorter. On this slide, you can see an architecture of the Sorter. And this platform deals with three levels of keys. This is device key. ATTK. Ask. And business key. They are all asymmetric RSA keys. And the device key is generated in the trusted environment before the device leaves the factory. And the ATTK public key is safely transmitted by Xiaomi to the Tencent TAM server. A third-party Android application, such as WeChat, can request to create an application key. In this case, the private ask key will be stored in the TE. And the public ask key and its device signature will be uploaded to the app's backend server, which forwards it further to the TAM server for verification with the device public key. In case if the ask packet is legitimate, a third-party store the application public key on its remote server for future use. For each business scenario, such as logging business or payment business, an app should create a business key. The generation process is the same with the application key generation. To make a payment transaction, an application asks a challenge factor. From its remote server, usually it's a random string as an object for signing. And after user fingerprint authorization, application sends this challenge factor, finger ID, device information, and payment data to the backend server. All this data is signed with the business key in the TE. And the public business key will be used to verify the transaction. Tencent Sauter does not provide TE-related code. Tencent leaves the implementation to the chip or device manufacturer. So, Xiaomi implemented their own Sauter trusted application to store keys and manage key operations. On this slide, you can see a code snippet of the Sauter trusted application. I just listed a few supported comments. To start the sign session, Sauter trusted application exports a comment or function in its sign, which expects to receive business key alias and a challenge factor as argument. And this function creates a session ID by concatenating both the string to a heap-based buffer without checking for overflow. And an attacker can provide arguments of such length that they overflow the heap memory after the session buffer with controlled values. Xiaomi's trusted applications don't have SLR protection, so this vulnerability can be exploited. Okay, now let's get back to the Tencent Sauter itself. On this slide, you can see its implementation on the Xiaomi devices. Sauter server system application, Android application exports, I mean share for public, Sauter service. This Sauter service binds vendor point, microtrust point, hardware point, Sauter system service to communicate with the trusted environment. As I mentioned, an unprivileged Android application has no permission to communicate with the TE directly, but it can use the Sauter service as a proxy. This Java code binds the Sauter service and then calls the vulnerable in its sign function. Okay, so Xiaomi did not implement an Android permission to protect the Sauter API. Now I'll show you a really simple demo. When an unprivileged Android application is disabled, it has an ability to pay in the WeChat. Okay, so on the right side, you see a common line actually is just to show you what is going on. And on the left side, this is a telephone. Okay, so I implemented a simple tool with name Sauter caller. This tool I used just to send a specific comments to the Sauter. This is a trusted application and output will be stored in some files provided in the common line. So first of all, I just want to show you that Sauter, Tencent Sauter is okay. It works and returns some results. For example, using this comment, I asked to generate ask application comment. And after that, and sign it. So we have two results. And also in the Android kernel log, we see that everything is okay. So Tencent Sauter responded to our request. Now I just open an unprivileged Android application. So this is a malware. This application can be downloaded from Play Store. And in moment of launching, I implemented a button block payments. So in this moment, when you press on a block payment, I just sent a used chain of vulnerabilities to break the Tencent Sauter. And it's mean, as you see on the right side, so I tried again to send a comment to the Sauter. And we see the target death. And the same situation in the kernel log. So it means that nothing happened. So we can't open a session with the Tencent Sauter. It means that in this moment, if we're trying to open WeChat application, when we open it, we see that it tries to create a session. Open a session with the Sauter twice actually. But Sauter is dead. And it means that WeChat application does not provide actually button to make a payment. That's all. So it means that a malware application can close the ability to pay in WeChat. Okay. But actually we don't want to block payment. We want to extract a private key. Because key leak completely compromised the Sauter platform. Allowing to unauthorized user to sign fake payment packages. Okay. To steal one of the private keys, I use another vulnerability. This is arbitrary memory read vulnerability in the old version of the Sauter trusted application. If you remember, we can downgrade trusted application on Xiaomi devices. Let's see in the TEC operation argument of the invoke command function, which we used to call Sauter trusted app from Android. The caller can provide up to four arguments, such as a number or a buffer to the trusted application for processing. And the common types are encoded in the param types field. Each trusted application must ensure that the data sent from the insecure site matches the expectation of this app. What happens if a trusted application expects to receive a point or two buffer, but we provide a number? In this case, if this application does not check the type of incoming parameter, so our number will be recognized as a virtual address. And Sauter application will read or write to the memory we specified. Okay. So I found that one of the old versions of the Sauter trusted application lacks checking of incoming parameters. And we can use this to achieve arbitrary memory read. So if we hold the target device in our hand, we can send a command and specify the address we are interested in as the second argument. And in this case, we will see a content of this address in the Android kernel log as shown on the slide. If we don't want to deal with the kernel log and just want to get information from the Android kernel log, we need to send a HasAusKey command and specify the target address again as the second argument. And Sauter trusted application will generate the business key based on the content of the address that we specified. And after that, we can use HasAusKey command many times to find the value, which matches the target address. And the generated key. Okay. So we have read vulnerability. In addition, there is no SLR. So all we need to steal the data is just to shape the heap. Okay. I just want to note here that to force load, for example, private device key, we need to send export as key command to the trusted application. And in this case, this public key will be loaded from the security storage to the heap of the Sauter trusted app. Okay. Now I'll show you, if you see, how to extract device private key. Oops. Okay. Just a second. Okay. So it's already technical. Sorry for this. So I will use the same tools that I implemented. It's really simple tool. Just to provide, to send some information. First of all, we're doing downgrade attack. So we overwrite the new version of the Sauter trusted application with the old one. This is the first step. After that, we send. Send command to export ATK key. This command to ask official public device key. This is the public key. I want to save it in the sum file to validate the transactions. After that, I ask using the export as key command. Give me, please, authentication application key. And signature of authentication key. And again, we store it in specific files. Next step, we use arbitrary read vulnerability to extract private key. Actually, this key is represented by RSA private exponent and RSA modules. And so now we have all the information we need. We extracted private key, public key. Packet. And we just need to validate that our signature is correct. How we can do it? We can use open SSL. So using this command, I just validate that the public key and signature of the original packet is correct. It should be correct because we didn't fix any data. Verify it okay. Next, we're going to patch packet. This is ask packet. Okay. We're going to patch some key, some packet with any data. And after that, we're going to sign this packet with the extracted private key. We can use open SSL here because open SSL doesn't know how to proceed with private exponent and modules. But matrix SSL, no. This is open source to matrix SSL. So we sign packet. And the last one, again, we use an open SSL to validate that the new packet which we fixed is correct and signature is correct. So verify it. It means that we extracted private key. We use it to sign. And actually, it means that we can sign any packet we want. Okay. Thank you. Thank you. To summarize, okay. OEM provided TEEs a very promising area for security research because many security-critical features are implemented by OEMs and not by chip manufacturers. To prove this, we analyzed the Tencent slaughter platform built in the Xiaomi devices and found two ways to attack which attack. One is from an unprivileged Android application. By exploiting the overflow vulnerability. And the second one, by downgrading the sorter trusted app. Okay. Xiaomi has fixed most of the vulnerabilities we reported two months ago. So thank you for your attention. You can find a lot of good security research on our research blog. Thank you.