30/06/2016

Extracting Qualcomm's KeyMaster Keys - Breaking Android Full Disk Encryption

After covering a TrustZone kernel vulnerability and exploit in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous blog post, I thought this time it might be interesting to explore some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implications of code-execution within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel. In this blog post, I'll demonstrate how TrustZone kernel code-execution can be used to effectively break Android's Full Disk Encryption (FDE) scheme. We'll also see some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 inherent issues stemming from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 design of Android's FDE scheme, even without any TrustZone vulnerability.

I've been in contact with Qualcomm regarding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue prior to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 release of this post, and have let cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m review cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 blog post. As always, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y've been very helpful and fast to respond. Unfortunately, it seems as though fixing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue is not simple, and might require hardware changes.

If you aren't interested in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 technical details and just want to read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 conclusions - feel free to jump right to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Conclusions" section. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same vein, if you're only interested in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code, jump directly to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Code" section.

[UPDATE: I've made a factual mistake in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original blog post, and have corrected it in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 post below. Apparently Qualcomm are not able to sign firmware images, only OEMs can do so. As such, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y cannot be coerced to create a custom TrustZone image. I apologise for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mistake.]

And now without furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r ado, let's get to it!

Setting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Stage 


A couple of months ago cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 highly-publicised case of Apple vs. FBI brought attention to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 topic of privacy - especially in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 context of mobile devices. Following cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 2015 San Bernardino terrorist attack, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FBI seized a mobile phone belonging to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shooter, Syed Farook, with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 intent to search it for any additional evidence or leads related to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ongoing investigation. However, despite being in possession of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FBI were unable to unlock cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 phone and access its contents.

This may sound puzzling at first. "Surely if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FBI has access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 phone, could cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y not extract cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user data stored on it using forensic tools?". Well, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 answer is not that simple. You see, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device in question was an iPhone 5c, running iOS 9.

As you may well know, starting with iOS 8, Apple has automatically enabled Full Disk Encryption (FDE) using an encryption key which is derived from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user's password. In order to access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FBI would have to crack that encryption. Barring any errors in cryptographic design, this would most probably be achieved by cracking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user's password.

"So why not just brute-force cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 password?". That sounds like a completely valid approach - especially since most users are notoriously bad at choosing strong passwords, even more so when it comes to mobile devices.

However, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 engineers at Apple were not oblivious to this concern when designing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir FDE scheme. In order to try and mitigate this kind of attack, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y've designed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption scheme so that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 generated encryption key is bound to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardware of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device. 

In short, each device has an immutable 256-bit unique key called cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 UID, which is randomly generated and fused into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device's hardware at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 factory. The key is stored in a way which completely prevents access to it using software or firmware (it can only be set as a key for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 AES Engine), meaning that even Apple cannot extract it from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device once it's been set. This device-specific key is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n used in combination with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 provided user's password in order to generate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resulting encryption key used to protect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device. This effectively 'tangles' cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 password and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 UID key.


Apple's FDE KDF
Binding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption key to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device's hardware allows Apple to make cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 job much harder for would-be attackers. It essentially forces attackers to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device for each cracking attempt. This, in turn, allows Apple to introduce a whole array of defences that would make cracking attempts on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device unattractive.

For starters, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key-derivation function shown above is engineered in such a way so that it would take a substantial amount of time to compute on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device. Specifically, Apple chose cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function's parameters so that a single key derivation would take approximately 80 milliseconds. This delay would make cracking short alphanumeric passwords slow (~2 weeks for a 4-character alphanumeric password), and cracking longer passwords completely infeasible.

In order to furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r mitigate brute-force attacks on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device itself, Apple has also introduced an incrementally increasingly delay between subsequent password guesses. On cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 iPhone 5c, this delay was facilitated completely using software. Lastly, Apple has allowed for an option to completely erase all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 information stored on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device after 10 failed password attempts. This configuration, coupled with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 software-induced delays, made cracking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 password on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device itself racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r infeasible as well.


With this in mind, it's a lot more reasonable that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FBI were unable to crack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device's encryption.

Had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y been able to extract cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 UID key, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y could have used as much (specialized) hardware as needed in order to rapidly guess many passwords, which would most probably allow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to eventually guess cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct password. However, seeing as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 UID key cannot be extracted by means of software or firmware, that option is ruled out.

As for cracking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 password on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 software-induced delays between password attempts and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 possibility of obliterating all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device made that option racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r unattractive. That is, unless cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y could bypass cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 software protections... However, this is where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 story gets racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r irrelevant to this blog post, so we'll keep it at that.

If you'd like to read more, you can check out Dan Guido's superb post about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 technical aspects of Apple v. FBI, or Matcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365w Green's great overview on Apple's FDE, or better yet, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 iOS Security Guide.

Going back to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue at hand - we can see that Apple has cleverly designed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir FDE scheme in order to make it very difficult to crack. Android, being cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mature operating system that it is, was not one to lag behind. In fact, Android has also offered full disk encryption, which has been enabled by default since Android 5.0.

So how does Android's FDE scheme fare? Let's find out.

Android Full Disk Encryption


Starting with Android 5.0, Android devices automatically protect all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user's information by enabling full disk encryption.

Android FDE is based on a Linux Kernel subsystem called dm-crypt, which is widely deployed and researched. Off cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bat, this is already good news - dm-crypt has withstood cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 test of time, and as such seems like a great candidate for an FDE implementation. However, while cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption scheme may be robust, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system is only as strong as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key being used to encrypt cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 information. Additionally, mobile devices tend to cause users to choose poorer passwords in general. This means cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key derivation function is hugely important in this setting.

So how is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption key generated?

This process is described in great detail in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 official documentation of Android FDE, and in even greater detail in Nikolay Elenkov's blog, "Android Explorations". In short, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device generates a randomly-chosen 128-bit master key (which we'll refer to as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Device Encryption Key - DEK) and a 128-bit randomly-chosen salt. The DEK is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n protected using an elaborate key derivation scheme, which uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user's provided unlock credentials (PIN/Password/Pattern) in order to derive a key which will ultimately encrypt cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DEK. The encrypted DEK is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n stored on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device, inside a special unencrypted structure called cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "crypto footer".


The encrypted disk can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n be decrypted by simply taking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user's provided credentials, passing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key derivation function, and using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 resulting key to decrypt cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stored DEK. Once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DEK is decrypted, it can be used to decrypt user's information.



However, this is where it gets interesting! Just like Apple's FDE scheme, Android FDE seeks to prevent brute-force cracking attacks; both on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device and especially off of it.

Naturally, in order to prevent on-device cracking attacks, Android introduced delays between decryption attempts and an option to wipe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user's information after a few subsequent failed decryption attempts (just like iOS). But what about preventing off-device brute-force attacks? Well, this is achieved by introducing a step in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key derivation scheme which binds cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device's hardware. This binding is performed using Android's Hardware-Backed Keystore - KeyMaster.

KeyMaster


The KeyMaster module is intended to assure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protection of cryptographic keys generated by applications. In order to guarantee that this protection cannot be tampered with, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module runs in a Trusted Execution Environment (TEE), which is completely separate from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android operating system. In keeping with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone terminology, we'll refer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android operating system as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Non-Secure World", and to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TEE as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Secure World".


Put simply, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module can be used to generate encryption keys, and to perform cryptographic operations on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m, without ever revealing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 keys to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Non-Secure World.

Once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 keys are generated in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are encrypted using a hardware-backed encryption key, and returned to Non-Secure World. Whenever cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Non-Secure World wishes to perform an operation using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 generated keys, it must supply cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encrypted "key blob" to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module. The KeyMaster module can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n decrypt cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stored key, use it to perform cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 wanted cryptographic operation, and finally return cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Non-Secure World.

Since this is all done without ever revealing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cryptographic keys used to protect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key blobs to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Non-Secure World, this means that all cryptographic operations performed using key blobs must be handled by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module, directly on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device itself.

With this in mind, let's see exactly how KeyMaster is used in Android's FDE scheme. We'll do so by taking a closer look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardware-bound key derivation function used in Android's FDE scheme. Here's a short schematic detailing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KDF (based on a similar schematic created by Nikolay Elenkov):

Android FDE's KDF

As you can see, in order to bind cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KDF to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardware of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device, an additional field is stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 crypto footer - a KeyMaster-generated key blob. This key blob contains a KeyMaster-encrypted RSA-2048 private key, which is used to sign cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption key in an intermediate step in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KDF - thus requiring cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 use of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module in order to produce cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 intermediate key used decrypt cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DEK in each decryption attempt.

Moreover, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 crypto footer also contains an additional field that doesn't serve any direct purpose in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 decryption process; cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value returned from running scrypt on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final intermediate key (IK3). This value is referred to as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "scrypted_intermediate_key" (Scrypted IK in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 diagram above). It is used to verify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 validity of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 supplied FDE password in case of errors during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 decryption process. This is important since it allows Android to know when a given encryption key is valid but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 disk itself is faulty. However, knowing this value still shouldn't help cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attacker "reverse" it to retrieve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 IK3, so it still can't be used to help attackers aiming to guess cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 password off cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device.

As we've seen, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android FDE's KDF is "bound" to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardware of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 intermediate KeyMaster signature. But how secure is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module? How are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key blobs protected? Unfortunately, this is hard to say. The implementation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module is provided by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoC OEMs and, as such, is completely undocumented (essentially a black-box). We could try and rely on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 official Android documentation, which states that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module: "...offers an opportunity for Android devices to provide hardware-backed, strong security services...". But surely that's not enough.

So... Are you pondering what I'm pondering?

Reversing Qualcomm's KeyMaster


As we've seen in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous blog posts, Qualcomm provides a Trusted Execution Environment called QSEE (Qualcomm Secure Execution Environment). The QSEE environment allows small applications, called "Trustlets", to execute on a dedicated secured processor within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Secure World" of TrustZone. One such QSEE trustlet running in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Secure World" is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application. As we've already seen how to reverse-engineer QSEE trustlets, we can simply apply cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same techniques in order to reverse engineer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module and gain some insight into its inner workings.

First, let's take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android source code which is used to interact with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application. Doing so reveals that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet only supports four different commands:

As we're interested in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 protections guarding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 generated key blobs, let's take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KEYMASTER_SIGN_DATA command. This command receives a previously encrypted key blob and somehow performs an operation using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encapsulated cryptographic key. Ergo, by reverse-engineering this function, we should be able to deduce how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encrypted key blobs are decapsulated by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module.

The command's signature is exactly as you'd imagine - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user provides an encrypted key blob, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signature parameters, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address and length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data to be signed. The trustlet cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n decapsulates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key, calculates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signature, and writes it into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared result buffer.


As luck would have it, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key blob's structure is actually defined in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 supplied header files. Here's what it looks like:


Okay! This is pretty interesting.

First, we can see that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key blob contains cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unencrypted modulus and public exponent of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 generated RSA key. However, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 private exponent seems to be encrypted in some way. Not only that, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 whole key blob's aucá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365nticity is verified by using an HMAC. So where is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption key stored? Where is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HMAC key stored? We'll have to reverse-engineer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module to find out.

Let's take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster trustlet's implementation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KEYMASTER_SIGN_DATA command. The function starts with some boilerplate validations in order to make sure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 supplied parameters are valid. We'll skip those, since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y aren't cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 focus of this post. After verifying all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 parameters, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function maps-in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user-supplied data buffer, so that it will be accessible to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Secure World". Eventually, we reach cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "core" logic of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function:


Okay, we're definitely getting somewhere!

First of all, we can see that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code calls some function which I've taken cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 liberty of calling get_some_kind_of_buffer, and stores cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 results in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 variables buffer_0 and buffer_1. Immediately after retrieving cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se buffers, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 qsee_hmac function in order to calculate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HMAC of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first 0x624 bytes of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user-supplied key blob. This makes sense, since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key blob structure we've seen before is exactly 0x624 bytes (without cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HMAC field).

But wait! We've already seen cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 qsee_hmac function before - in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Widevine application. Specifically, we know it receives cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following arguments:


The variable that we've called buffer_1 is passed in as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fourth argument to qsee_hmac. This can only mean one thing... It is in fact cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HMAC key!

What about buffer_0? We can already see that it is used in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function do_something_with_keyblob. Not only that, but immediately after calling that function, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 signature is calculated and written to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 destination buffer. However, as we've previously seen, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 private exponent is encrypted in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key blob. Obviously cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 RSA signature cannot be calculated until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 private exponent is decrypted... So what does do_something_with_keyblob do? Let's see:


Aha! Just as we suspected. The function do_something_with_keyblob simply decrypts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 private exponent, using buffer_0 as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption key!

Finally, let's take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function that was used to retrieve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HMAC and encryption keys (now bearing a more appropriate name):


As we can see in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code above, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HMAC key and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption key are both generated using some kind of key derivation function. Each key is generated by invoking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KDF using a pair of hard-coded strings as inputs. The resulting derived key is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application's global buffer, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key is returned to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller. Moreover, if we are to trust cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 provided strings, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 internal key derivation function uses an actual hardware key, called cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SHK, which would no doubt be hard to extract using software...

...But this is all irrelevant! The decapsulation code we have just reverse-engineered has revealed a very important fact.

Instead of creating a scheme which directly uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardware key without ever divulging it to software or firmware, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code above performs cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption and validation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key blobs using keys which are directly available to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone software! Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 keys are also constant - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are directly derived from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SHK (which is fused into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardware) and from two "hard-coded" strings.

Let's take a moment to explore some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implications of this finding.

Conclusions

 

  • The key derivation is not hardware bound. Instead of using a real hardware key which cannot be extracted by software (for example, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SHK), cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application uses a key derived from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SHK and directly available to TrustZone.
  • OEMs can comply with law enforcement to break Full Disk Encryption. Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key is available to TrustZone, OEMs could simply create and sign a TrustZone image which extracts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster keys and flash it to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target device. This would allow law enforcement to easily brute-force cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FDE password off cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 leaked keys.
  • Patching TrustZone vulnerabilities does not necessarily protect you from this issue. Even on patched devices, if an attacker can obtain cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encrypted disk image (e.g. by using forensic tools), cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n "downgrade" cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device to a vulnerable version, extract cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key by exploiting TrustZone, and use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to brute-force cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption. Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key is derived directly from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SHK, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SHK cannot be modified, this renders all down-gradable devices directly vulnerable.
  • Android FDE is only as strong as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel or KeyMaster. Finding a TrustZone kernel vulnerability or a vulnerability in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster trustlet, directly leads to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 disclosure of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster keys, thus enabling off-device attacks on Android FDE.

During my communication with Qualcomm I voiced concerns about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 usage of a software-accessible key derived from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SHK. I suggested using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SHK (or anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r hardware key) directly. As far as I know, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SHK cannot be extracted from software, and is only available to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cryptographic processors (similarly to Apple's UID). Therefore, using it would thwart any attempt at off-device brute force attacks (barring cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 use of specialized hardware to extract cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 key).

However, reality is not that simple. The SHK is used for many different purposes. Allowing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user to directly encrypt data using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SHK would compromise those use-cases. Not only that, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application is widely used in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android operating-system. Modifying its behaviour could "break" applications which rely on it. Lastly, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current design of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application doesn't differentiate between requests which use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application for Android FDE and ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r requests for different use-cases. This makes it harder to incorporate a fix which only modifies cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application. 

Regardless, I believe this issue underscores cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 need for a solution that entangles cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 full disk encryption key with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device's hardware in a way which cannot be bypassed using software. Perhaps that means redesigning cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 FDE's KDF. Perhaps this can be addressed using additional hardware. I think this is something Google and OEMs should definitely get togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r and think about.

Extracting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster Keys

 

Now that we've set our sights on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster keys, we are still left with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 challenge of extracting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 keys directly from TrustZone.

Previously on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 zero-to-TrustZone series of blog posts, we've discovered an exploit which allowed us to achieve code-execution within QSEE, namely, within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Widevine DRM application. However, is that enough?

Perhaps we could read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 keys directly from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster trustlet's memory from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 context of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hijacked Widevine trustlet? Unfortunately, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 answer is no. Any attempt to access a different QSEE application's memory causes an XPU violation, and subsequently crashes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 violating trustlet (even when switching to a kernel context). What about calling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same KDF used by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster module to generate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 keys from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 context of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Widevine trustlet? Unfortunately cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 answer is no once again. The KDF is only present in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application's code segment, and QSEE applications cannot modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own code or allocate new executable pages.

Luckily, we've also previously discovered an additional privilege escalation from QSEE to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel. Surely code execution within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel would allow us to hijack any QSEE application! Then, once we control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application, we can simply use it to leak cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HMAC and encryption keys and call it a day.

Recall that in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous blog post we reverse-engineered cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mechanism behind cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 invocation of system calls in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel. Doing so revealed that most system-calls are invoked indirectly by using a set of globally-stored pointers, each of which pointing to a different table of supported system-calls. Each system-call table simply contained a bunch of consecutive 64-bit entries; a 32-bit value representing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 syscall number, followed by a 32-bit pointer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 syscall handler function itself. Here is one such table:


Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se tables are used by all QSEE trustlets, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y could serve as a highly convenient entry point in order to hijack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code execution within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application!

All we would need to do is to overwrite a system-call handler entry in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 table, and point it to a function of our own. Then, once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application invokes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 target system-call, it would execute our own handler instead of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original one! This also enables us not to worry about restoring execution after executing our code, which is a nice added bonus. 

But cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re's a tiny snag - in order to direct cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 handler at a function of our own, we need some way to allocate a chunk of code which will be globally available in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Secure World". This is because, as mentioned above, different QSEE applications cannot access each ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r's memory segments. This renders our previous method of overwriting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code segments of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Widevine application useless in this case. However, as we've seen in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 past, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone Kernel's code segments (which are accessible to all QSEE application when executing in kernel context) are protected using a special hardware component called an XPU. Therefore, even when running within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel and disabling access protection faults in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ARM MMU, we are still unable to modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m.

This is where some brute-force comes in handy... I've written a small snippet of code that quickly iterates over all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone Kernel's code segments, and attempts to modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is any (mistakenly?) XPU-unprotected region, we will surely find it. Indeed, after iterating through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code segments, one racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r large segment, ranging from addresses 0xFE806000 to 0xFE810000, appeared to be unprotected!

Since we don't want to disrupt cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 regular operation of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel, it would be wise to find a small code-cave in that region, or a small chunk of code that would be harmless to overwrite. Searching around for a bit reveals a small bunch of logging strings in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 segment - surely we can overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m without any adverse effects:

Now that we have a modifiable code cave in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel, we can proceed to write a small stub that, when called, will exfiltrate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster keys directly from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster trustlet's memory!

Lastly, we need a simple way to cause cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application to execute cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hijacked system-call. Remember, we can easily send commands to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application which, in turn, will cause cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application to call quite a few system-calls. Reviewing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster's key-generation command reveals that one good candidate to hijack would be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "qsee_hmac" system-call:

KeyMaster's "Generate Key" Flow
Where qsee_hmac's signature is:


This is a good candidate for a few reasons:
  1. The "data" argument that's passed in is a buffer that's shared with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 non-secure world. This means whatever we write to it can easily retrieved after returning from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Secure World".
  2. The qsee_hmac function is not called very often, so hijacking it for a couple of seconds would probably be harmless.
  3. The function receives cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HMAC key as one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 arguments. This saves us cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 need to find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application's address dynamically and calculate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 addresses of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 keys in memory.
Finally, all our shellcode would have to do is to read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 HMAC and encryption keys from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application's global buffer (at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 locations we saw earlier on), and "leak" cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared buffer. After returning from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command request, we could cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n simply fish-out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 leaked keys from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared buffer. Here's a small snippet of THUMB assembly that does just that:

Shellcode which leaks KeyMaster Keys

Putting it all togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r


Finally, we have all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pieces of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 puzzle. All we need to do in order to extract cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster keys is to:
  • Enable cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DACR in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel to allow us to modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code cave.
  • Write a small shellcode stub in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code cave which reads cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 keys from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster application.
  • Hijack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "qsee_hmac" system-call and point it at our shellcode stub.
  • Call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster's key-generation command, causing it to trigger cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 poisoned system-call and exfiltrate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 keys into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared buffer.
  • Read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 leaked keys from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shared buffer. 
Here's a diagram detailing all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se steps:

The Code


Finally, as always, I've provided cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 full source code for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack described above. The code builds upon cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two previously disclosed issues in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 zero-to-TrustZone series, and allows you to leak cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster keys directly from your device! After successfully executing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KeyMaster keys should be printed to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 console, like so:



You can find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 full source code of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit here:

https://github.com/laginimaineb/ExtractKeyMaster

I've also written a set of python scripts which can be used to brute-force Android full disk encryption off cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device. You can find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 scripts here:

https://github.com/laginimaineb/android_fde_bruteforce

Simply invoke cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 python script fde_bruteforce.py using:
  • The crypto footer from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device
  • The leaked KeyMaster keys
  • The word-list containing possible passwords
Currently, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 script simply enumerates each password from a given word-list, and attempts to match cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption result with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "scrypted intermediate key" stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 crypto footer. That is, it passes each word in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 word-list through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android FDE KDF, scrypts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result, and compares it to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 crypto footer. Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation is fully in python, it is racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r slow... However, those seeking speed could port it to a much faster platform, such as hashcat/oclHashcat.

Here's what it looks like after running it on my own Nexus 6, encrypted using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 password "secret":


Lastly, I've also written a script which can be used to decrypt already-generated KeyMaster key blobs. If you simply have a KeyMaster key blob that you'd like to decrypt using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 leaked keys, you can do so by invoking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 script km_keymaster.py, like so:


Final Thoughts

Full disk encryption is used world-wide, and can sometimes be instrumental to ensuring cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 privacy of people's most intimate pieces of information. As such, I believe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 encryption scheme should be designed to be as "bullet-proof" as possible, against all types of adversaries. As we've seen, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current encryption scheme is far from bullet-proof, and can be hacked by an adversary or even broken by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 OEMs cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365mselves (if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are coerced to comply with law enforcement).

I hope that by shedding light on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 subject, this research will motivate OEMs and Google to come togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r and think of a more robust solution for FDE. I realise that in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android ecosystem this is harder to guarantee, due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 multitude of OEMs. However, I believe a concentrated effort on both sides can help cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next generation of Android devices be truly "uncrackable".

15/06/2016

TrustZone Kernel Privilege Escalation (CVE-2016-2431)

In this blog post we'll continue our journey from zero permissions to code execution in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel. Having previously elevated our privileges to QSEE, we are left with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 task of exploiting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel itself.

"Why?", I hear you ask.

Well... There are quite a few interesting things we can do solely from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 context of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel. To name a few:
  • We could hijack any QSEE application directly, thus exposing all of it's internal secrets. For example, we could directly extract cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stored real-life fingerprint or various secret encryption keys (more on this in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next blog post!).
  • We could disable cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardware protections provided by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SoC's XPUs, allowing us to read and write directly to all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 DRAM. This includes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory used by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 peripherals on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 board (such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 modem).
  • As we've previously seen, we could blow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 QFuses responsible for various device features. In certain cases, this could allow us to unlock a locked bootloader (depending on how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lock is implemented).
So now that we've set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stage, let's start by surveying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface!


05/05/2016

War of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Worlds - Hijacking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Linux Kernel from QSEE

After seeing a full QSEE vulnerability and exploit in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous blog post, I thought it might be nice to see some QSEE shellcode in action.

As we've previously discussed, QSEE is extremely privileged - not only can it interact directly with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel and access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hardware-secured TrustZone file-system (SFS), but it also has some direct form of access to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system's memory.

In this blog post we'll see how we can make use of this direct memory access in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Secure World" in order to hijack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Linux Kernel running in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World", without even requiring a kernel vulnerability.



02/05/2016

QSEE privilege escalation vulnerability and exploit (CVE-2015-6639)

In this blog post we'll discover and exploit a vulnerability which will allow us to gain code execution within Qualcomm's Secure Execution Environment (QSEE). I've responsibly disclosed this vulnerability to Google and it has been fixed - for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exact timeline, see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Timeline" section below.

 The QSEE Attack Surface

 

As we've seen in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous blog post, Qualcomm's TrustZone implementation enables cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World" operating system to load trusted applications (called trustlets) into a user-space environment within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Secure World", called QSEE.

This service is provided to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World" by sending specific SMC calls which are handled by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Secure World" kernel. However, since SMC calls cannot be invoked from user-mode, all communication between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World" and a trustlet must pass through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World" operating system's kernel.

Having said that, regular user-space processes within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World" sometimes need to communicate with trustlets which provide specific services to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. For example, when playing a DRM protected media file, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process in charge of handling media within Android, "mediaserver", must communicate with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 appropriate DRM trustlet in order to decrypt and render cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 viewed media file. Similarly, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process in charge of handling cryptographic keys, "keystore",  needs to be able to communicate with a special trustlet ("keymaster") which provides secure storage and operation on cryptographic keys.

So if communicating with trustlets requires cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ability to issue SMCs, and this cannot be done from user-mode, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n how do cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se processes actually communicate with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlets?

The answer is by using a Linux kernel device, called "qseecom", which enables user-space processes to perform a wide range of TrustZone-related operations, such as loading trustlets into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 secure environment and communicating with loaded trustlets.



However! Although necessary, this is very dangerous; communication with TrustZone exposes a large (!) attack surface - if any trustlet that can be loaded on a particular device contains a vulnerability, we can exploit it in order to gain code execution within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trusted execution environment. Moreover, since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trusted execution environment has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ability to map-in and write to all physical memory belonging to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World", it can also be used in order to infect cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World" operating system's kernel without cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re even being a vulnerability in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel (simply by directly modifying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel's code from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Secure World").

Because of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 dangers outlined above, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access to this device is restricted to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 minimal set of processes that require it. A previous dive into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 permissions required in order to access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 driver has shown that only four processes are able to access "qseecom":
  • surfaceflinger (running with "system" user-ID)
  • drmserver (running with "drm" user-ID)
  • mediaserver (running with "media" user-ID)
  • keystore (running with "keystore" user-ID)

This means that if we manage to get a hold of any of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se four processes, we would cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n be able to directly attack any trustlet of our choice, directly bypassing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Linux kernel in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 process! In fact, this is exactly what we'll do - but we'll get to that later in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 series.

For this blog post, let's assume that we already have code-execution within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "mediaserver" process, thus allowing us to directly focus on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 attack surface provided by trustlets. Here's an illustration to help visualise cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 path of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit chain we'll cover during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 series and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 focus of this post:



Vulnerability Scope


I haven't been able to confirm cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exact scope of this issue. I've statically checked quite a few devices (such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Droid Turbo, Nexus 6, Moto X 2nd Gen), and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were all vulnerable. In fact, I believe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue was very wide-spread, and may have affected most Qualcomm-based devices at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time.

So why was this issue so prevalent? As we'll see shortly, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability is contained in a trustlet and so does not rely on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel (which tends to change substantially between SoCs), but racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r on code which is designed to be able to execute in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same manner on many different devices. As such, all devices containing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet were made vulnerable, regardless of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir SoC.

Also note that on some devices cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerable code was present but appeared slightly different (it may have been an older version of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same code).  Those devices are also vulnerable, although cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 indicators and strings you might search for could be slightly different. This means that if you're searching for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exact strings mentioned in this post and don't find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m, don't be dissuaded! Instead, reverse-engineer cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tools from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous blog post, and check for yourself.

Enter Widevine


Previously, we decided to focus our research efforts on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "widevine" trustlet, which enables playback of DRM encrypted media using Widevine's DRM platform. This trustlet seems like a good candidate since it is moderately complex (~125KB) and very wide-spread (according to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir website, it is available on over 2 billion devices).

After assembling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 raw trustlet, we are left with an ELF file, waiting to be analysed. Let's start by taking a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function registered by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet in order to handle incoming commands:



As we can see, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first 32-bit value in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command is used to specify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command code, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 high-word of which is used to sort cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 commands into four different categories.

Taking a peek at each of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 category-handling functions reveals that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 categories are quite rich - all in all, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are about 70 different supported commands - great! However, going over 70 different commands would be a pretty lengthy process - perhaps we can find a shortcut that'll point us in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 right direction? For example, maybe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re's a category of commands that were accidentally left in even though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y're not used on production devices?

Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 libraries which are used to interact with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlets are also proprietary, we can't look through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source code to find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 answers. Instead, I wrote a small IDAPython script to lookup all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 references to "QSEECom_send_cmd", cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function used to send commands to trustlets, and check what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "command-code" value is for each reference. Then I simply grouped cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 results into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 categories above, producing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following results:


So... Nobody is using 5X commands. Suspicious!

Sifting through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 functions in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 5X category, we reach cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following command:



Pretty straight-forward: copies cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data from our request buffer into a "malloc"-ed buffer (note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length field here is not controlled by us, but is derived from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real buffer length passed to QSEOS). Then, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function's flow diverges according to a flag in our request buffer. Let's follow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 flow leading to "PRDiagVerifyProvisioning":



Finally, we found a vulnerability!

After some simple validation (such as checking that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first DWORD in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command buffer is indeed zero), cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function checks cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fourth DWORD in our crafted command buffer. As we can see above, setting that value to zero will lead us to a code-path in which a fully-controlled copy is performed from our command buffer into some global buffer, using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 third DWORD as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length argument. Since this code-path only performs cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerable memcpy and nothing else, it is much more convenient to deal with (since it doesn't have unwanted side-effects), so we'll stick to this code-path (racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one above it, which seems more complex).

Moreover, you might be wondering what is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "global buffer" that's referred to in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function above. After all, it looks a little strange - it isn't passed in to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function at any point, by is simply referred to "magically", by using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 register R9.

Remember how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlets that we analysed in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous blog post had a large read-write data segment? This is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data segment in which all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 modifiable data of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet is stored - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global variables. In order to quickly access this segment from any location in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code, Qualcomm decided to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 platform-specific R9 register as a "global register" whose value is never modified, and which always points to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 beginning of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 aforementioned segment. According to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ARM AAPCS, this is actually valid behaviour:


What now?


Now that we have a primitive, it's time to try and understand which pieces of data are controllable by our overflow. Again, using a short IDAPython script, we can search for all references to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "global buffer" (R9) which reside after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflown buffer's start address (that is, after offset 0x10FC). Here are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 results:


Disappointingly, nearly all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se functions don't perform any "meaningful" operations of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 controllable pieces of data. Specifically, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vast majority of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se functions simply store file-system paths in those memory locations, which imply no obvious way to hijack control flow.

Primitive Technology


Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re aren't any function pointers or immediate ways to manipulate control flow directly after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflown buffer, we'll need to upgrade our buffer overflow primitive into a stronger primitive before we can gain code execution.

Going through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 list of functions above, we come across interesting block of data referred to by several functions:

As you can see above, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block of 0x32 DWORDs, starting at offset 0x169C, are used to store "sessions".  Whenever a client sends commands to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Widevine trustlet, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y must first create a new "session", and all subsequent operations are performed using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 specific session identifier issued during cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 session's creation. This is needed, for example, in order to allow more than a single application to decrypt DRM content at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same time while having completely different internal states.

In any case, as luck would have it, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sessions are complex structures - hinting that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y may be used in order to subtly introduce side-effects in our favour. They are also within our line-of-fire, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are stored at an offset greater than that of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflown buffer. But, unfortunately, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 0x32 DWORD block mentioned above only stores cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointers to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se session objects, not cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 objects cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365mselves. This means that if we want to overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se values, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y must point to addresses which are accessible from QSEE (ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, trying to access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m will simply result in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet crashing).


Finding Ourselves


In order to craft legal session pointers, we'll need to find out where our trustlet is loaded. Exploring cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 relevant code reveals that QSEOS goes to great lengths in order to protect trustlets from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World". This is done by creating a special memory region, referred to as "secapp-region", from which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet's memory segments are carved. This area is also protected by an MPU, which prevents cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World" from accessing it in any way (attempting to access those physical addresses from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World" causes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device to reset).

On cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r hand, trustlets reside within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 secure region and can obviously access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own memory segments. Not only that, but in fact trustlets can access all allocated memory within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "secapp" region, even memory belonging to ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r trustlets! However, any attempt to access unallocated memory within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 region results in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet immediately crashing.

...Sounds like we're beginning to form a plan!

We can use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflow primitive in order to overwrite a session pointer to a location within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "secapp" region. Now, we can find a command which causes a read attempt using our poisoned session pointer. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet crashes after issuing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command, we guessed wrong (in that case, we can simply reload cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet). Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, we found an allocated page in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "secapp" region.


But... How do we know which trustlet that page belongs to?

We already have a way to differentiate between allocated and unallocated pages. Now, we need some way to distinguish between pages based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir contents.

Here's an idea - let's look for a function that behaves differently based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 read value in a cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 session pointer:


Okay! This function tries to access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data at session_pointer + 0xDA. If that value is equal to one, it will return cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value 24, ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, it will return 35.

This is just like finding a good watermelon; by "tapping" on various memory locations and listening to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "sound" cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y make, we can deduce something about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir contents. Now we just need to give our trustlet a unique "sound" that we can identify by tapping on it.

Since we can only listen to differences between one and non-one values, let's mark our trustlet by creating a unique pattern containing ones and zeros within it. For example, here's a pattern which doesn't occur in any ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r trustlet:


Now, we can simply write this pattern to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet's data segment by using over overflow primitive, effectively giving it its own distinct "sound".

Finally, we can repeat cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following strategy until we find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet:
  • Randomly tap a memory location in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "secapp" region:
    • If it sounds "hollow" (i.e., cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet crashes) - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re's nothing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re, so reload our trustlet
    • Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, tap cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sequence of locations within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 page which should contain our distinct marking pattern. If it sounds like cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pattern above, we found our trustlet

Of course, inspecting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocation scheme used by QSEOS could allow us to speed things furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r by only checking relevant memory locations. For example, QSEOS seems to allocate trustlets consecutively, meaning that simply scanning from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "secapp" region to its beginning using increments of half cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet's size will guarantee a successful match.


A (messy) write primitive


Now that we have a way to find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 secure region, we are able to craft "valid" session pointers, which point to locations within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet. Next up, we need to find a way to create a write primitive. So... are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re any functions which write controllable data into a session pointer?

Surprisingly, nearly all functions that do write data to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 session pointer do not allow for arbitrary control over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data being written. Nonecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365less, one function looks like it could be of some help:

This function generates a random DWORD to be used as a "nonce", cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n checks if enough time elapsed since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous time it was called. If so, it adds cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 random value to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 session pointer by calling "addNonceToCache".

First of all, since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "time" field is saved in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global buffer after our overflown buffer, we can easily clear it using our overflow primitive, thus removing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time limitation and allowing us to call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function as frequently as we'd like. Also, note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 generated nonce's random value is written into a buffer which is returned to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user - this means that after a nonce is generated, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 caller also learns cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nonce.

Let's take a peek at how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nonces are stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 session pointer:


So cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re's an array of 16 nonces in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 session object - starting at offset 0x88. Whenever a nonce is added, all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous nonce values are "rolled over" one position to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 right (discarding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last nonce), and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 new nonce is written into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first location in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nonce array.

See where we're going with this? This is actually a pretty powerful write primitive (albeit a little messy)!

Whenever we want to write a value to a specific location, we can simply set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 session pointer to point to that location (minus cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 offset of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nonces array). Then, we can start generating nonces, until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least-significant byte (this is a little-endian machine) in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 generated nonce matches cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 byte we would like to write. Then, once we get a match, we can increment cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 session pointer by one, generate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next byte, and so forth.



This allows us to generate any arbitrary value with an expectancy of only 256 nonce-generation calls per byte (since this is a geometric random variable). But at what cost?

Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 values in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nonce cache are "rotated" after every call, this means that we mess-up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 15 DWORDs after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last written memory location. We'll have to work our way around that when we design cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit.

 Writing an exploit

We finally have enough primitives to craft a full exploit! All we need to do is find a value that we can overwrite using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 messy write primitive, which will allow us to hijack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 control flow of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 application.

Let's take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function in charge of handling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "6X" category of commands:



As you can see, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function calls cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 requested commands by using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command ID specified as an index into an array stored in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 global buffer. Each supported command is represented by a 12-byte entry in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array, containing four pieces of information:
  • The command code (32-bits)
  • A pointer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 handling function itself (32-bits)
  • The minimal input length (16-bits)
  • The minimal output length (16-bits)

If this information is valid, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function pointer is executed, passing in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user's input buffer as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first argument and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 output buffer as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second argument.

If we choose an innocuous 6X command, we can overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 corresponding entry in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 array above so that its function pointer will be directed at any piece of code we'd like to execute. Then, simply calling this command will cause cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet to execute cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code at our controlled memory location. Great!

We should be wary, however, not to choose a function which lies directly before an "important" command that we might need later. This is because our messy write primitive will destroy cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following 15 DWORDs (or racá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next 5 array entries). Let's take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function which populates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entries in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 command array:


There are six consecutive entries corresponding to unused functions. Therefore, if we choose to overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entry directly before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m, we'll stay out of trouble.

 

Universal Shellcode Machine


Although we can now hijack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 control flow, we still can't quite execute arbitrary code within QSEE yet. The regular course of action at point would probably be to find a stack-pivot gadget and write a short ROP chain which will enable us to allocate shellcode - however, since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlets' code segments aren't writeable, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel doesn't expose any system call to QSEE to allow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocation of new executable pages, we are left with no way to create executable shellcode.

So does this mean we need to write all our logic as a ROP chain? That would be extremely inconvenient (even with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 aid of automatic "ROP"-compilers), and might even not be possible if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ROP gadgets in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet are not Turing-Complete.

Luckily, after some careful consideration, we can actually avoid cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 need to write longer ROP chain. If we think of our shellcode as a Turing Machine, we would like to create a "Universal Turing Machine" (or simulator), which will enable us to execute any given shellcode as if it were running completely within QSEE.

Given a piece of code, we can easily simulate all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 control-flow and logic in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World", simply by executing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code fully in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World". But what about operations which behave differently in a QSEE-context? If we think about it, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are only a few such operations:
  • Reading and writing memory
  • Calling system calls exposed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel
These operations must execute within QSEE. However, we can actually execute both of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se operations in QSEE by writing one small ROP chain!

All we need is a single ROP chain which will:
  • Hijack control flow to a separate stack
  • Prepare arguments for a function call
  • Call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 wanted QSEE function
  • Return cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 result to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user and restore execution in QSEE
As you can see, all this chain do is to enable us to execute any given QSEE function using any supplied arguments. But how can we use it to simulate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 special operations?

Well, since all system-calls in QSEE have matching calling-stubs in each trustlet, we can use our ROP chain to execute any system call with ease. As for memory accesses - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is an abundance of QSEE functions which can be used as read and write gadgets. Hence, both operations are simple to execute using our short ROP chain.

This leaves us with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following model:


This also means that executing arbitrary shellcode in QSEE doesn't require any engineering effort! All cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shellcode developer needs to do is to delegate memory accesses and system calls to specific APIs exposed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit. The rest of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 shellcode's logic can remain unchanged and execute completely in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Normal World". We'll see an example of some shellcode using this model shortly.

Finding a stack pivot


In order to execute a ROP chain, we need to find a convenient stack-pivot gadget. When dealing with large or medium-sized applications, this is not a daunting task - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is simply enough code for us to find at least one gadget that we can use.

However, since we're only dealing with ~125KB of code, we might not be that lucky. Not only that, but at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 point at which we hijack cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 control flow, we only have control over cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 registers R0 and R1, which point to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 input and output buffers, respectively.

After fully disassembling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet's code we are faced with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 harsh truth - it seems as though cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no usable stack pivot using our controlled registers. So what can we do?

Recall that ARM opcodes can be decoded in more than one way, depending on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 T bit in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CPSR. When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bit is set, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 processor is executing in "Thumb" mode, in which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 instruction length is 16-bits. Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 processor is in "ARM" mode, with an instruction length of 32-bits.

We can easily switch between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se modes by using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least-significant bit of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PC register when performing a jump. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least-significant bit is set, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 T bit will be set, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 processor will switch to "Thumb" mode. Ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise, it will switch to ARM mode.

Looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 trustlet's code - it seems to contain mostly "Thumb" instructions. But perhaps if we were to forcibly decode cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 instructions as if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were "ARM" instructions, we'd be able to find a hidden stack pivot which was not visible beforehand.

Indeed, that is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case! Searching through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ARM opcodes reveals a very convenient stack-pivot:


By executing this opcode, we will be able to fully control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack pointer, program counter and ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r registers by using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 values stored in R0 - which, as we saw above, points to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fully user-controlled input buffer. Great!

As for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rest of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ROP chain - it is pretty standard. In order to execute a function and return all we need to do is build a short chain which:
  • Sets cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 low registers (R0-R3) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack arguments to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function's arguments
  • Set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 link register to point to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rest of our chain
  • Jump to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function's start address
  • When control is returned via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 crafted LR value, store cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 return value in user-accessible memory location, such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 supplied output buffer
  • Restore cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 stack pointer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 original location and return to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 location from which control was originally hijacked
You can find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 complete ROP chain and gadgets in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 provided exploit code, but I imagine it's exactly what you'd expect.

Putting it all togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r


At long last, we have all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pieces needed to create a fully functional exploit. Here's a short run-down of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit's stages:
  • Find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Widevine application by repeatedly "tapping" cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 secapp region and "listening"
  • Create a "messy" write gadget using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nonce-generation command
  • Overwrite an unused 6X command entry using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 write gadget to direct it to a stack-pivot
  • Execute any arbitrary code using a small ROP chain under cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Universal Shellcode Machine"



The Exploit


As always, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 full exploit code is available here:

https://github.com/laginimaineb/cve-2015-6639

I've also included a sample shellcode using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 model described earlier. The shellcode reads a file from TrustZone's secure file-system - SFS. This file-system is encrypted using a special hardware key which should be inaccessible to software running on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device - you can read more about it here. Regardless, running within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "Secure World" allows us to access SFS fully, and even extract critical encryption keys, such as those used to decrypt DRM content.

In fact, this is all it takes:


Also, please note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are quite a few small details that I did not go into in this blog post (for brevity’s sake, and to keep it interesting). However, every single detail is documented in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit's code. So by all means, if you have any unanswered questions regarding cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit, I encourage you to take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code and documentation.

What's next?


Although we have full code-execution within QSEE, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are still some things beyond our reach. Specifically, we are limited only to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 API provided by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 system-calls exposed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel. For example, if we were looking to unlock a bootloader, we would probably need to be able to blow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device's QFuses. This is, understandably, not possible from QSEE.

With that in mind, in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next blog post, we'll attempt to furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r elevate our privileges from QSEE to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel!

Timeline 

  • 27.09.2015 - Vulnerability disclosed
  • 27.09.2015 - Initial response from Google
  • 01.10.2015 - PoC sent to Google
  • 14.12.2015 - Vulnerability fixed, patch distributed

I would also like to mention that on 19.10.2015 I was notified by Google that this issue has already been internally discovered and reported by Qualcomm. However, for some reason, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fix was not applied to Nexus devices.

Moreover, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are quite a few firmware images for ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r devices (such as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Droid Turbo) that I've downloaded from that same time period that appeared to still contain cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability! This suggests that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re may have been a hiccup when internally reporting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability or when applying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fix.

Regardless, as Google has included cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bulletin on 14.12.2015, any OEMs that may have missed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 opportunity to patch cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issue beforehand, got anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r reminder.

26/04/2016

Exploring Qualcomm's Secure Execution Environment

Welcome to a new series of blog posts!

In this series, we'll dive once more into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 world of TrustZone, and explore a new chain of vulnerabilities and corresponding exploits which will allow us to elevate privileges from zero permissions to code execution in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel.

This may sound familiar to those of you who have read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous series - but let me reassure you; this series will be much more exciting!

First of all, this exploit chain features a privilege escalation which is universal across all Android versions and phones (and which requires zero permissions) and a TrustZone exploit which affects a very wide variety of devices. Secondly, we will dive deep into an as-of-yet unexplored operating system - QSEE - Qualcomm's Secure Execution Environment. Lastly, we'll see some interesting TrustZone payloads, such as directly extracting a real fingerprint from TrustZone's encrypted file-system.

In case you would like to follow along with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 symbols and disassembled binaries, I will be using my own Nexus 6 throughout this series, with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following fingerprint:
    google/shamu/shamu:5.1.1/LMY48M/2167285:user/release-keys 

You can find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exact factory image here.

 

10/02/2016

Unlocking cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Motorola Bootloader

In this blog post, we'll explore cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Motorola bootloader on recent Qualcomm Snapdragon devices. Our goal will be to unlock cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bootloader of a Moto X (2nd Gen), by using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TrustZone kernel code execution vulnerability from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous blog posts. Note that although we will show cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 complete unlocking process for this specific device, it should be general enough to work at-least for most modern Motorola devices.

Why Motorola?


After reporting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous TrustZone kernel privilege escalation to Qualcomm, I was gifted a shiny new Moto X. However... There was one little snag - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y accidentally sent me a locked device. This was a completely honest mistake, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y did offer many times to unlock cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device - but where's cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fun in that? So without furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r ado, let's dive into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Motorola bootloader and see what it takes to unlock it.


24/01/2016

Android privilege escalation to mediaserver from zero permissions (CVE-2014-7920 + CVE-2014-7921)

In this blog post we'll go over two vulnerabilities I discovered which, when combined, enable arbitrary code execution within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 "mediaserver" process from any context, requiring no permissions whatsoever.

 

How bad is it?


The first vulnerability (CVE-2014-7921) was present in all Android version from 4.0.3 onwards. The second vulnerability (CVE-2014-7920) was present in all Android versions from 2.2 (!). Also, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se vulnerabilities are not vendor specific and were present in all Android devices. Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first vulnerability is only needed to bypass ASLR, and ASLR is only present (in a meaningful form) from Android 4.1 onwards, this means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se vulnerabilities allow code execution within "mediaserver" on any Android device starting from version 2.2.

Although I reported both vulnerabilities in mid October 2014, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were unfortunately only fixed much later (see "Timeline" for full description, below) - in Android version 5.1!  This means that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are many devices out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re which are still vulnerable to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se issues, so please take care.
 
You can find cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 actual patches here. The patches were pushed to AOSP five months after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerabilities were reported.

That said, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android security team was very pleasant to work with, and with ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r vulnerabilities I reported later on, were much more responsive and managed to solve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 issues within a shorter time-frame.