tag:blogger.com,1999:blog-2029700426505953971.post7126667581278688733..comments2017-07-18T17:10:19.934+03:00Comments on Bits, Please!: Exploring Qualcomm's Secure Execution Environmentlaginimainebhttp://www.blogger.com/profile/00867710965331025912noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-2029700426505953971.post-83860149327812230132017-06-18T22:45:01.004+03:002017-06-18T22:45:01.004+03:00Hi CrazyGalaxy,
I didn't do anything fancy - ...Hi CrazyGalaxy,<br /><br />I didn't do anything fancy - I simply used OpenSSL's RSA_public_decrypt (https://www.openssl.org/docs/man1.1.0/crypto/RSA_public_decrypt.html) for the "decryption".<br /><br />To get OpenSSL to load the public key, I did write a small PyCrypto script to define the public key from the parameters (e,N) using RSA.construct (https://www.dlitz.net/software/pycrypto/api/current/Crypto.PublicKey.RSA-module.html#construct), and then saved them to a PEM.<br /><br />All the best,<br />Gal. laginimainebhttps://www.blogger.com/profile/00867710965331025912noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-37282591327283337382017-05-04T21:17:53.922+03:002017-05-04T21:17:53.922+03:00Could you share the script to "decrypt" ...Could you share the script to "decrypt" the 2048-bit signature blob?<br />I searched the Internet but most of them work on certificates with certain formats, rather than raw-data parameters.CrazyGalaxyhttps://www.blogger.com/profile/09637205807262584535noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-58677913429391115672017-03-23T00:44:29.423+02:002017-03-23T00:44:29.423+02:00I didn't, but you can save the blob from the m...I didn't, but you can save the blob from the match index until the end of the file, and asn1parse will stop at the end of the ASN1 data.laginimainebhttps://www.blogger.com/profile/00867710965331025912noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-19340942088641874242017-03-22T20:52:26.512+02:002017-03-22T20:52:26.512+02:00Cool post!
"So let's search for these tw...Cool post!<br /><br />"So let's search for these two bytes in the ".mdt" and save each found blob into a file."<br /><br />How could you know the length of these blobs?CrazyGalaxyhttps://www.blogger.com/profile/09637205807262584535noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-5474181514085616782016-07-15T18:57:13.476+03:002016-07-15T18:57:13.476+03:00Thank you! I think the easiest way is to disassemb...Thank you! I think the easiest way is to disassemble the first function (func_0) and look for the function the returns a function pointer. That function pointer points to the entry function. Alternately, you can just search for the Widevine commands (such as PRDiag*) and work backwards from there using XREFs.laginimainebhttps://www.blogger.com/profile/00867710965331025912noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-939447217426315032016-06-21T05:38:28.276+03:002016-06-21T05:38:28.276+03:00Awesome post!
I am trying to follow your post an...Awesome post! <br /><br />I am trying to follow your post and reverse widevine trustlet(and if needed libQSEECom.so for the loading part).<br />Is there a easy way to locate the entry function for the trustlet being loaded? Do I have to look at the libQSEECom.so ?<br /><br />Thanks in advancemindbl0werhttps://www.blogger.com/profile/14603170490324070101noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-43279397056990907142016-06-19T17:59:16.059+03:002016-06-19T17:59:16.059+03:00Hi Jose,
Sorry for the late response! I missed yo...Hi Jose,<br /><br />Sorry for the late response! I missed your response.<br /><br />I didn't look at public TEEs yet, but I might get around to it (for example, Trusty TEE looks like it could be interesting...)<br /><br />Also, I haven't spoken in any conference yet (and have nothing planned up ahead). Mainly because the conferences happen to coincide with the exam period :)<br /><br />All the best,<br />Gal.laginimainebhttps://www.blogger.com/profile/00867710965331025912noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-37894501907417813482016-06-17T16:36:17.316+03:002016-06-17T16:36:17.316+03:00Hi Gal (my name is Jose, I use yours so I think is...Hi Gal (my name is Jose, I use yours so I think is fair you to know mine),<br /><br />You do not have to apologize, you did not know it and, probably, some readers have learnt a little more about crypto ;)<br /><br />Perfect, everything clear now! Maybe, you will find interesting this article: https://www.cs.cornell.edu/courses/cs5430/2015sp/notes/rsa_sign_vs_dec.php<br /><br />Look for vulnerabilities on non-public things is quite exciting, but have you try to check how good is the implementation of public TEEs such OP-TEE?<br /><br />Will you participate at any security conference to talk about this?<br /><br />Thank you,<br />Regardsjotahttps://www.blogger.com/profile/08615015479109041198noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-30277866497336980382016-06-17T14:36:40.221+03:002016-06-17T14:36:40.221+03:00Hi Jota,
Sorry, just wanted to write a full expla...Hi Jota,<br /><br />Sorry, just wanted to write a full explanation just in case other people find it useful. Anyway, I agree, writing math in a blog post is pretty hard :)<br /><br />As for the actual value that is signed - it's actually special version of HMAC-SHA256 (w/ a different i_pad and o_pad) over all the block files' data, concatenated. But you can outright ignore that and still find the signature block.<br /><br />Here are a couple of facts:<br />1. The signature is 2048 bits long, while the HMAC-SHA256 is only 256 bits long.<br />2. The signature uses PKCS#1 v1.5 padding<br /><br />If we simply use RSA-public-decrypt w/ the appropriate padding on each 2048-bit block, we'll get a 2048 bit result. For each randomly-chosen block, the resulting block's bits will be roughly uniformly distributed (since RSA is a trapdoor permutation). But we know that in the signature blob the first 2048-256 bits will be zero (remember this is after removing the padding). The chances of that happening in uniformly distributed message is negligibly small 2^(-1792).<br /><br />So all TryDecrypt does is iterate over each block, use "RSA public decrypt" w/ the appropriate padding, and check if the resulting block starts with a bunch of leading zeros.laginimainebhttps://www.blogger.com/profile/00867710965331025912noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-64162311300471504412016-06-17T13:40:35.937+03:002016-06-17T13:40:35.937+03:00Hi Gal,
Thank you by your quick response. I know ...Hi Gal,<br /><br />Thank you by your quick response. I know what involves RSA cryptography, part of my daily job is related with crypto issues. The thing was that this was the first time I read the concept of encryption when you want to refer to signing, but I agree is just terminology.<br /><br />I know a forum is not the best place to write maths...jajaja but I suppose you wanted to write (the ' was left):<br /><br /> (m^e) mod N = m' is public-encryption and (m'^d) mod N is private-decryption<br />&&<br /> (m^d) mod N = m' is private-encryption and (m'^e) mod N is public-decryption<br /><br />Therefore, what I understand is that when you write "we try to "decrypt" a blob using our public key" what you are looking for is a hash value. Because what has been "encrypted/signed" should be a hash value. That's the way signing process works. <br /><br />Then, what is the output of your TryDecrypt function, the hash value of some of the blocks? How did you choose the m message along the .mdt binary to perform the "decryption"?<br /><br />Thank you<br />Regardsjotahttps://www.blogger.com/profile/08615015479109041198noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-41625709252517513572016-06-17T12:19:36.801+03:002016-06-17T12:19:36.801+03:00Thank you!
As for you question - the main problem...Thank you!<br /><br />As for you question - the main problem here is terminology regarding RSA.<br /><br />First, the mathematical definition of RSA is a trapdoor permutation family. Let's say we have the public exponent e, private exponent d and modulus N.<br /><br />Now, for each message m in Zn*, applying m' = (m^e) mod N is a onto one-to-one mapping into Zn*. Recall that we chosen e,d such that e*d = 1 (mod phi(N)). This means that by applying the permutation (m' ^ d) mod N = ((m^e) ^ d) mod N = (m ^ (e*d mod phi (N))) mod N = m (mod N).<br /><br />So applying the reverse permutation allowed us to retrieve the original message m.<br /><br />Now - people often refer to RSA as an encryption scheme. It isn't (because it's not CPA-secure, as it's completely deterministic). But you *could* think of it as encryption in the sense that after permuting a message with the public exponent, it's hard to retrieve the message without knowing the private exponent.<br /><br />In that sense, we can say that the operation (m^e) mod N is public-encryption and (m^d) mod N is private-decryption.<br /><br />The inverse is also true (since RSA is symmetric with regards to e,d). So we could say that (m^d) mod N is private-encryption and (m^e) mod N is public-decryption.<br /><br />Next comes an important primitive that is often used with RSA - signing. Imagine you have a message and would like to guarantee it was produced *only* by someone who knows the private exponent. You could do this by applying the permutation using the private exponent - that is, for each message m, produce (m^d) mod N. We just called this operation "private-encryption" in the previous paragraph, but when using RSA as a signature scheme, we could call this operation "signing".<br /><br />So... how is this useful at all? Well, someone with the public exponent can apply "public-decryption" on the message, and by the commutativity of multiplication: (m' ^ d) mod N = ((m^d) ^ e) mod N = (m ^ (d*e mod phi (N))) mod N = (e*d mod phi (N))) mod N = m (mod N). So anyone with the public key can use this to retrieve the message m from the signature. We'll call this operation "verify".<br /><br />Finally, if we already have a signature block produced using the private exponent, and we know the signed message has some unique structure, we can scan each block and attempt to perform RSA-verification ("public-decryption") on every block. This will produce some message m' - if it matches the structure we know, it is (other than a negligible probability) our signature block.<br /><br />Cheers,<br />Gal.laginimainebhttps://www.blogger.com/profile/00867710965331025912noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-1913551554923612352016-06-17T11:05:17.248+03:002016-06-17T11:05:17.248+03:00Hi, great post!
I got lost in the signature recove...Hi, great post!<br />I got lost in the signature recover phase. You wrote:<br /><br />"Normally, the private key is used to produce a signature and the public key can be used to recover the signed data"<br />Please, could you explain me how you recover the signed data with the public key? It's the first time I heard about it.<br /><br />Later on you wrote:<br /><br />"This means that if we try to "decrypt" a blob using our public key[...]"<br />What do you want to mean by "decrypt"? Again, it's the first time I heard about using a public key RSA to decrypt data. <br /><br />I do not understand quite well your process of looking for the signature, what does trydec function do? <br />Could not you to try to do it by brute force? Sign-hash blob files with several hash functions and the public key and then looking for the result on the .mdt binary data?<br /><br />Maybe the problem is that I am a mathematician (...XD) trying to get your work. <br /><br />Thank you again and waiting for more post!jotahttps://www.blogger.com/profile/08615015479109041198noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-33189321419561777472016-06-06T10:22:03.361+03:002016-06-06T10:22:03.361+03:00Great post!
Could this exploit be used on a snapd...Great post! <br />Could this exploit be used on a snapdragon 820? Or is it only limited to the 800 and the 810?Albano Nunezhttps://www.blogger.com/profile/06194942117450101785noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-32395371410663679282016-05-31T01:39:11.348+03:002016-05-31T01:39:11.348+03:00Very good! Enjoyed reading it, looking forward to ...Very good! Enjoyed reading it, looking forward to new posts.<br /><br />Cheers.ETraudhttps://www.blogger.com/profile/14189172369730338344noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-2056353366733417192016-05-11T17:57:08.039+03:002016-05-11T17:57:08.039+03:00Thank you Eric, It means a lot to me!
More posts ...Thank you Eric, It means a lot to me!<br /><br />More posts coming soon :)<br /><br />laginimainebhttps://www.blogger.com/profile/00867710965331025912noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-48752455726169067292016-05-11T10:35:41.108+03:002016-05-11T10:35:41.108+03:00Just wanted to drop a note and say: you have done ...Just wanted to drop a note and say: you have done some really great work here.<br /><br /> I actually needed to implement some signing verification tools for Qualcomm's mdt/mbn format very recently. While I have a full set of docs from them it was actually reading through this article that got me most of the information I needed instead :)<br /><br />It is funny how reversers often know more about the nitty gritty details of a company's product than they themselves seem to.<br /><br />I have also been enjoying the follow up articles on exploitation immensely. Keep up the great work!Eric Montihttps://www.blogger.com/profile/14198057058153642599noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-50484780954073939972016-05-04T21:17:53.820+03:002016-05-04T21:17:53.820+03:00Gal, thank you for that shout out. That means a lo...Gal, thank you for that shout out. That means a lot! I love reading your articles, I learn so much from your explanations and examples. Glad that I am able to contribute something to you and your readers. Keep it up, I look forward to the next exploit :)Ghassan Idrisshttps://www.blogger.com/profile/09270334858820145846noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-11388950784180615682016-05-02T13:00:22.109+03:002016-05-02T13:00:22.109+03:00Great :D Thanks all you guys for all the help and ...Great :D Thanks all you guys for all the help and sources. I waiting for the next post.Madushan Nishanthahttps://www.blogger.com/profile/01904428627732530957noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-15315395598614604882016-05-02T01:44:39.369+03:002016-05-02T01:44:39.369+03:00Ghassan -
Just wanted to say thank you for wrapp...Ghassan - <br /><br />Just wanted to say thank you for wrapping the exploit in an LKM! Great work. The code is really clean and well-written. Kudos :)<br /><br />Gal.laginimainebhttps://www.blogger.com/profile/00867710965331025912noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-14001317537490192332016-05-02T01:36:39.260+03:002016-05-02T01:36:39.260+03:00Hi Madushan,
First of all, thank you! Glad you en...Hi Madushan,<br /><br />First of all, thank you! Glad you enjoyed the post.<br /><br />I totally forgot about the "standalone" version of the older TZ exploit. In any case, I just cleaned it up a little bit and put it up on github, here: https://github.com/laginimaineb/standalone_msm8974<br /><br />It relies on the previous kernel exploit (https://github.com/laginimaineb/cve-2014-4322/tree/master/Feud/jni) to get kernel code execution, and then dynamically finds the needed kernel symbols and does all the work without needing a kernel module.<br /><br />You should definitely check out Ghassan's version as well! I just found out about it, but looking at the code it looks very clean and easy to use.<br /><br />As for your second question - you are absolutely correct. QSEE does not have sufficient privileges in order to blow a QFuse, which means we'll need to go further than just exploiting QSEE - you'll see all the details in tomorrow's blog post :)<br /><br />Finally, as shuffle2 mentioned below - yes, I am using 010editor on Linux (which I highly recommend! It's a fantastic tool).<br /><br />Cheers,<br />Gal.laginimainebhttps://www.blogger.com/profile/00867710965331025912noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-58075981498093478962016-04-28T04:44:51.755+03:002016-04-28T04:44:51.755+03:00The hex-editor looks like 010 editor, probably run...The hex-editor looks like 010 editor, probably running on linux.shuffle2https://www.blogger.com/profile/08201827125412664984noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-89039455218654903072016-04-28T00:51:06.671+03:002016-04-28T00:51:06.671+03:00I have re-written his original zero-write exploit ...I have re-written his original zero-write exploit as a standalone kernel module here: https://github.com/ghassani/qc-tz-es-activated-exploitGhassan Idrisshttps://www.blogger.com/profile/09270334858820145846noreply@blogger.comtag:blogger.com,1999:blog-2029700426505953971.post-74455722649010135542016-04-27T13:15:35.188+03:002016-04-27T13:15:35.188+03:00Great post as always!
I'm waiting for the next...Great post as always!<br />I'm waiting for the next post and in the meanwhile I hope you get some time to release the code for standalone version (without the kernel modification) of the older trustzone exploit :).<br /><br />As I understand from the post, trustlets execute in a separate usermode inside QSEE. Can exploiting a trustlet lead to possible bootloader unlock? Since it's just a QSEE usermode application the possibly don't have access privileged instructions like blowing a qfuse right? <br /><br />PS: can I know the hex editor you are using? :)Madushan Nishanthahttps://www.blogger.com/profile/01904428627732530957noreply@blogger.com