 Good evening everyone In a few minutes the Nintendo hacking 2016 talk of start This talk will be translated into German and there are English subtitles available Anyway, we've had much further do These are Derek near Wirt and that will the three students have been working on hacking Nintendo platform for a while now And please give them a warm applause Welcome to the translation for the lecture of Nintendo hacking 2016. We are Siri and We are always looking forward to feedback on Twitter. Our hashtag is hashtag C3T and we'll jump right into the translation So welcome to Nintendo hacking 2016. I'll introduce the other people. This is Derek And I can speak to all three of us and say that we are very happy that we are here today That we are allowed to be here and tell you what we have done the last one and a half years I will start with the state of the Wii U I'll start with the ad with the state of the Wii U Failover flows console hacking talk have you maybe seen in 2016 that it doesn't happen so much Until 2015 There was an public exploit And we just wanted more access than just to use That also worked on a ppc with the kernel And use so mode and kernel mode we don't talk about today Because the kernel exploits are a lot more fun We'll just start with the power pc kernel very quickly Has louder standard security things no aslar what does it do to us all for simplicity has 140 syscalls We can't really name them can't really name them at the beginning, but there's a nice thing But it's the nice thing is the The the PL mechanism from the view for dynamic Bibliotheca RPL this is very simple and we can all syscalls are very easy to name It's really important that all the syscalls and save copy in copy out Mechanism to use So we just looked at the syscalls and looked for what we can do What we found That's called an eye control v-hacks or why indirections are difficult It's just a bug in the pck drivers that request syscalls That Means that we have requests from user mode to translate over there speaks to me later So you submit these kind of requests and the kernel We'll use copy ends and the to name from you from user mode to kernel mode And there's just a certain art from requests and like a second in the interaction Inhalted well, they just ignore that for the second time. I'm just going to read it for the second level and just the best Let's look at the relevant part Relevant part I couldn't sorry that we didn't go to the site, but that's not so much more It's called I us packet in the second line. It's kind of pecker in the second line The tiler and ganz oben is this special request entry Buffer size virtual address and what we find would be something like this That's the biggest and the virtual address Ausfilling and the kernel was ganz angenehm is for us Changed the virtual address to the physical Address to the physical address So It's copied and then it goes to user mode and then goes through all the entries and Changed then the physical address Repair it for us. That's just no safe security mechanism. That's the whole system. It doesn't matter that gives us just a writing approach to everything we want. It looks heavy We're going through this conversation, but we also only need one byte to exploit the whole kernel We notice that K effective to physical Inversion function that's just zero input for every mill that we're going to give It's a pretty big chance That there's garbage coming in If we show that on another part of the kernel strategy is that we This is curl handler address And that's one of the last byte We hope that the new address actually So we hope for the best use a lock in site and it's best to go off The other is this It's a jit area No, and it's Mandi, I'm also carl mode ausfilling khanos. That's nice, too. That's it. Look at the Let's look at the relevance for it. That's the relevant structure. Let's see. That's the kernel So we're from under home lesen Okay, the last line in the bottom This entry to K loader call this entire K loader call by there. It's a hex FF 0 What we're doing is the last bytes to overwrite the last seven and what's happened is that now this is called The cisco on these This thing goes on site register 24 28 and we can this is control here and that's Bring it somewhere to spring so I thought it's like this. We exploit it as a k-mode function We can just call iocontrolV to this shifted address and it's all just, and we have one, the assist call ever goes anywhere we want. So, we start out with full four hearts. So the view, it starts with four hearts. It's a remote code execution. There's code output, it's one and a half less. It's quite nice. It's quite nice. We can and need to. But we have to go even deeper and we can do that. Let's look at the IOSU architecture on. IOSU is present as one big L file. It's a big L file, there's a kernel, all the services in it. It's running on Starbucks. It has a hardware thing that doesn't execute around and doesn't have an ASLR either. It's a micro kernel with about 146 cores. What we can see is that the kernel, all the services just spawned at once. Before we actually exploit it, we have to exploit one of these user-mode processes first. We do that too, but we don't talk about it. And to look into the kernel, we again reverse all the assist calls and look for bugs. And what we came up with is called MQhex. What we found out is MQhex, so message Qhex. And apparently it never dies in the two overflows. And it just doesn't fit in the overflows. Let's look at the code again. There's the assist call, it's called createMessageQueue. It's called a buffer. And the number of buffer entries is four bytes. And every buffer entry is four bytes. If you check the address with four bytes, then you see the number of entries with four bytes. The other nice thing is that it just used the number of entries for the maximum number of entries for the maximum number of entries. That's why it's called MQhex. And then we send it to the assist call. So iOS should be reporting that no executable memory is writable. And if you look at the kernel section flex, where you see the kernel text, then you see read execute in kernel. And with this data, you see read write, but that's all over it. Our exploit strategy looks like this. If we look at the relevant parts in iOS kernel, then we see it starts with this low-end address. And it's very convenient for us. There's a system on call. And the addresses before are all valid. So we put a message queue on that starts with minus eight bytes. And this magical hack brings us to the point where we just send two messages and a ARM instruction. And what that does is it ensures that this section is overwritten. And we look at the integer overflow, four times this value, four bytes short, and then you think the kernel is the message queue of eight bytes, but we can put every message in there. That already gives us the iOS kernel mode execution, second heart. And with that, we have complete control over the console. That's very pleasant. That's all the keys except for boot one. We'll look at that later. These keys are unfortunately excluded, as we've already seen. Now we want to make things persistent. The content is only verified during the installation, but not during the booting. So now the binary is verified shortly before the execution. So that we can change the content with the JIT permissions. We basically describe the ROM for a DS game, exploit it with the emulator and get code execution. Also, there is this configuration section that basically says which part should be booted. We can describe the title ID. And if you describe the DS emulator title and the console is restarted, then you just boot it directly into the game. That gives us persistent code execution by a cold boot with complete control over the console. Game over? Yes or no? Half-heart is still left. So as we just saw, the kernel is broken in the meantime. What is missing? I just copied this slide from a slide from another talk. You can see it with the same theme for our slides. Basically, this Stage 2 bootloader with the Boot1 key, this key is still unknown to us. We tried to get it through a side-channel attack, but it didn't look good. So it would be nice to have this key. And the first thing we did was to connect a NAND tracer. Basically, all the traffic was there between the NAND and the Boot1 reads to see what this process reads from the FlashSpeaker. So we see a few nice addresses there. We can compare these with the data system on the FlashSpeaker to see which data is read there. We just played around with a few data on this data system and found out that Boot1 has passed a system.xml file. It doesn't look so safe to pass an XML file in such a temporary part of the boot process. There's a lot of stuff that can go wrong there. So we tried to get it through a side-channel attack. We tried to use a few exploits there, but it didn't really work. So we tried something else. There's Boot1. Sorry. We have Boot0. And this booted Boot1. And we found out that it's the boot that you can re-activate virtual remodeling again. So we can see that it's... We can then see that it reads the boot1 key from the OTP and connects the boot1 key again. And that happens very, very quickly in the process. But it's kept in memory until the things are done, until Boot1 is successfully launched or when a mistake happens. And that means we have to exploit Boot0 to get to the boot1 key. Unfortunately, Boot0 is pretty safe. That's a bit surprising because it's a VU. And the question is, how can we exploit something that doesn't have a bug? The answer is, we have to plug in our own bugs. We're doing this by using the fault injection. Maybe you heard of it. Basically, you introduce an error in the device by playing around on the clock or on the clock or by changing something with electromagnetism. Basically, what you want to have is a mutated instruction or broken register. What you don't want is just a lockup so that the system crashes. That doesn't help that much. So we want to plug in a glitch in Boot0. And to do that, we have to find a nice goal for us. Just a really nice weak point. So let's take a look at what Boot0 actually does. The first thing is, it copes itself in a frame because we don't understand it. And that's nice for us because it's in the frame and it's taken out from there. It copies the Boot1 key in the storage. It switches out the OTP slot. It does a few other things with the flash controller and then reads the Boot1 header or BootOn image. It reads the header to this address first. And then it reads the size of this header field. You do at least a check for the maximum size. And be careful, the header itself is not locked. They don't do any testing of a signature or anything like that. So they use the size and they just use the size and then do a signature verification in Boot1. They check that this image is not broken. They remove this Boot1 code, they remove the key from the frame, they remove the key and then they jump to the entry point for Boot1. So what's the weak point at this point? I mean, if you look at this, you can already say what it is. It's, of course, this size check of the size of this field is there. What we can do is we just write our own modified version of Boot1 in the flash frame with a pretty remarkable size in the header. It reads the header, then it's supposed to do this size check exactly where we want to glitch it. And that's exactly where we want to add the glitch. Finally, we just skip this instruction and basically the size check is by path. And basically the size check is by path. So if we read the Boot1 image with this size, then we have a buffer overflow in it and then we have a few jump instructions at the end so that when it returns from the function, it will finally jump to our own code. Yeah, that's our Boot0 code execution, as we do it. Good. So we have Boot0 code execution in there. We can just dump the Boot1 key out of the frame. We don't actually need an exploit for that. Boot0 is actually pretty safe, right? It's actually pretty safe, but by glitching, it tries to behave properly. But the Boot0 code is then customizable. And the Boot1 image buffer is actually where the Boot0 buffer is so that you can add an overflow. And that works surprisingly stable. So the half of the cases we can work like this. So let's take a look at Boot1 now. Boot1 understands the VU data system. It then loads a firmware image. And the first thing we did is we'll take a look at this XML parser. But unfortunately, it looks pretty safe. But maybe we found a bug. We're not really sure, and we haven't really tried to exploit it yet. After all, it's just the VU. It's just the VU. So that's it for VU. Okay, so much for VU. And I'm going to go over to the network that's going to get out of the 3DS. Hi, everyone. I'm Ned. I made it with the 3DS last year. I'm going to be showing some of the Homebrew side of 3DS where that's at right now. I'm not going to show you how it looks with the Homebrew side because the 3DS last year these people broke the userland kernel and the security processor. They broke the hardware key scrambler and since then they've been kind of mad about this. They released a lot of system updates. And they started bug bounty programs and they've got a lot of bugs patched. But because of the level of exploitation we got last year and we need to find some new exploits. What I want to emphasize here is that what I want to emphasize here is that because we have a game because we have a customer game and because there's more difficult bugs we're going to be able to exploit more bugs. So starting with user space we're going to start with our Homebrew comes from. So already it's pretty good. This is already a huge focus for our community because it's kind of where user space is where you want to run your own custom games and so on. So we have a bunch of game entry points and a bunch of browser exploits and there's a couple limitations to these. But there's a couple limitations and game cards cost money and they cost pretty frequently like the games that are exploited but the games that are somewhat rare and unusual price goes way up and it gets pretty expensive when the browser every time you release a new browser exploit or Nintendo can just just patch it out because if we have a new page the system's on the latest version so they can kind of prove that the system is the latest version so it's sort of looking at this I thought I'd like to look at to see if some titles could be exploitable but I found sound hacks and the basic, like the two probably most obvious things to look at is because it's got JPEG processing and the music player I saw that they're processing actually a lot of formats even their own custom playlist format if they make a single mistake anywhere then it's over I'm not trying to compare with open source optimization to compare so it was pretty promising it was pretty close to about a month I found a bunch of bugs and I was trying to chain together a little logical it really worked really critical so I'm going to demonstrate that here so I actually studied MP3 for like the whole month MPG was like the last day so MPG was the last thing I saw they actually malloc and 256-byte buffer for the song and when they're loaded they see a Unicode they just memcopy they just memcopy the one so that's it so this is pretty great This is pretty cool, this is a pretty big exploit, it's a bit difficult, so it looks like this. We have our name chunk, with which we just want to overflow. We just put A's in, A's in. The next thing that happens is that this gets freed, and this victim chunk that we've overridden, and we're going to write it over here, and it's working again. It's a link, it's a list, I'll show you where everything is right now. And at this point we have a four-bit rate, and we want to get out of there. We'll probably do a stack pivot, so we're going to pivot the stack, there's only one pivot gadget, and I looked at the thumb pivots, they're actually hard, but the thumb pivots didn't support the wide instructions that were all the way up there. Unfortunately, that's one of the arithmetic conditions on it, so basically it was that in order to load all your registers from the condition flags, the condition flags had to satisfy the list. And I remember where we returned from the function there, and I just checked that, like if this pointer is not number three, then in any sense, it wouldn't ever be satisfied. So basically it was that in order to load all your registers from the condition flags, there was a lot of work arounds. The CTF work arounds can always get the heap free list head with a stack address. And on the next one, we're going to just read into it. There's a couple of constraints on this, and the first one is really normal, like this is pretty normal to stack. You have to make sure you keep the stack on the stack. Luckily, this is actually pretty easy, because all you need is a size followed by two null pointers representing a previous result. And now it goes to look there. If one of them goes to look there, then I don't have anything else in the queue, so just write it down on this work. So we mem copy the next stack to the stack, the next stack to the stack against my mem copy. And then Meloq is there for us. And then we're done, because we can do a little, we can mem copy the shell, but then we use an existing exploit that's been around for a long time to overwrite the text section and then the tag section to overwrite. So there's the first heart. So you can't really talk about homebrew without talking about kernel. We want to get access to the most calls, like the three ones actually, like the three ones actually, like the last ones called away from you. So, I guess, the goal is to call some calls that are restricted. And then it would be a memory for like a demo layer. So, it's kind of a, It's kind of a situation here inside the sandbox, you want to find bugs in like pretty restrictive, so it's a lot easier to talk and like what had been done so far, and I learned a lot of attacks on that memory mapping. I didn't see much about memory mapping or anything related to news after free, and I had just got a pretty bad grade on my OS project, because I had a really bad note for it. So I noticed a design flaw when I was working on it, so it's not so much that they couldn't possibly get this right, but when you're designing an API, it's really true for how you do ref counting, so basically whenever the user fetches, a kernel object holds a kernel object on it, and you can use this call that does the correct in-gref, and then it does the right in-gref, and then it does it for you. I was looking at it, and I was thinking, well, like a long time ago kernel actually is using these objects internally. I mean, I spoiled it, but like, I mean, it was like a way back from the user fetches, and they're all following the same thing. I found three of them, and that's all the same. We're now maintaining the reference count, and then some people asked me like advice on kernel hacking. For kernel hacking at home, I definitely said, okay, look here, there's definitely something to get. I'm going to talk a little bit about the timer object. It's a pretty simple kernel API. You can ask the timer there, you can set this timer, you can ask it, it's just a normal synchronization primitive. Like I said, I was looking at it, and I saw it there, and I thought, oh, that's interesting. There's one called Pulse. There's one called Pulse. Because what's happening with this, you set the timer to Pulse, like every year, you're going to get this pulse every year. Everything that's waiting on it gets a signal. And when you get a signal on it, you get the next signal. And it definitely does things with this object that are a bit more complicated than the other modi and the other kernel objects. So I looked at how they did this, how they did this Pulse story. What's actually going on in the code? If you take a look at this, you can see they're doing some pretty good locking. And then what happens here is when the signal goes through these waiting cycles and gets rescheduled, at the end they reset the timer state and just say, okay, we're waiting for the next cycle. And then this also looks pretty good. It looks pretty good. They're locking the scheduler there, but nothing's preventing you from doing this from having a asynchronous close handle. So we take fast tags. And that's it. That's three syscalls. There's a whole bunch of set ups where you don't want to go in, but you put the timer on, set it up, close the handle, close the handle. And if it was in Pulse mode right now, what's nice about this is you can lose the race. It's just a race condition there. And then it happens quite often. And once it was within a second, I didn't think it was optimal. So let's take a look at how we can exploit this whole thing. Basically, it's a little bit more complicated. I'll show you in a second. Here is what happens. So R7 points to my timer object and then it's set free before we get to this chunk here. Then it loads this R0 history there and jumps there. So that I call this use after free. And that's pretty exploitable. When I look at these objects, that's the normal situation. The table shows the real timer table. And wants to call this KTimerReset function. But when we call it free, then the table pointer goes to the next timer object in the kernel. So it's going to point to the next free timer object in the kernel. And what's nice is that it overlaps with the initial timer value. We totally control. But that we have total control. So after the initial value is set, we should be pretty fast in the user space. Because what's actually calling this is in a kernel thread? What it calls in a kernel thread, we have no guarantee that the user process is actually memory mapped. And even if you open the kernel thread, you can't get more than 25% of it. So that's very unstable. Also because it's a kernel thread, we don't want to crash it. But this will just totally break everything and sink thread dies. As long as we return a function to something defined, as long as we're actually in the dry. There's actually another problem. And the kernel commode is mapped to a higher address. And they're negative. And this set timer syscall actually checks if these values are negative. So we need a pretty strict trick that I didn't find. If you set the timer, you can say, one second from now, the pulse should start. Then it adds the current time to the one second. So set timer is the one that does the add for you. Timer actually does this addition. And this overflow is not checked when the timer is set. So we can actually overflow this and then with a schedule that shows back into the past. Here is my eclipsed setup for that. In the middle there, that's the beginning of this place. And then that region on the right side is what the 3DS allows to survive there. That's the pulse period times that we can use. And so what I do is I just put it right there at the end. I set it right there at the end. There's an overflow and the next pulse that I can also control that range. So then I get exactly where I want to go. That's pretty good. That's pretty good. But unfortunately at this point it's pretty solid. At this point it's pretty stable, but we don't know exactly what to give back, what to call. There's no simple function for that. Our negative scheduling stuff is pretty difficult to do for different calls. So I try to find a call that gives me this control. And that's where it gets really, really tricky. If we look at how the memory mapping in 3DS looks, then we can see it in the user space, where the FC RAM is just in the control area. And the kernel also has a view of the heap. So it's a shared mapping. And that means if we can write in there, then it ends up in something we can see as the user. So it's something we can see as the user. This is actually a common instruction on the ARM architecture. And at this point we just put a view table call with an argument. And that means that R0 just contains the address of the object and R1 the address where we want to go. And this B65C is where R1 shows up. We can see the random link list. And when we go down to the add instruction, then we write it to the object. And in this way it looks like this. It's pointing to something in the user space. And we do an alloc twice. We can look at the user space. There's the object. We control the view table. And then we're actually at standard methods that we can use. There we go. OK. There we have the user space and kernel. And this is almost game over. So we have already knocked on different parts of the 3DS. Including the kernels and the software that runs on this security processor. What we didn't look at are the 3DS boot ROMs. Basically there's one boot ROM for every processor. For the ARM 11. And I think there's probably more boot ROMs than the 3DS system on the chip. But we're focusing on these 3DS boot ROMs here. What we know for sure is that this firmware image from FlashSpeicher is something. We also know that this ARM 9 boot ROM does all the interesting things. Because only the ARM 9 boot ROM has access to this entire crypto hardware. And we also know that the boot ROM initializes the key slots. We would like to get those key slots. Unfortunately the boot ROM is disabled before the firmware launches. And the 3DS... They also give a very nice error screen if something is broken. Then you get a error screen. So let's look at how these boot ROMs are protected. Basically there are two registers that we call ConfixusRoot 9 and ConfixusRoot 11. And the boot ROM writes to these registers. And of course it's a one-shot. You can't turn them on again. That's not the VU. And basically if this boot ROM is disabled, then the only half of what you get are two parts of the boot ROM. There's the unprotected part and the unprotected part. You can just dump the unprotected part and you can see the unprotected part. But you can't see the protected part. And all the interesting codes have been stored in this protected part. And if you look at the reset vector, it just jumps directly into the protected part of the boot ROM. So you don't really know what happens there when the 3DS starts. But what you can do is you can look at the unprotected boot ROM code. Who knows, maybe we'll find a bug in there. So first of all, let's see, there are no keys in the unprotected part. All the keys are stored in the protected part. There's a whole bunch of driver codes in there. There are some hardware stuff in the AS Engine, which is kind of interesting. There's also the SPI, which is quite interesting. Because it's a very small chip that's soldered on the Wi-Fi socket. And it's useful for Wi-Fi settings. Other settings that are in there. And when we're used to it, it's interesting for us. And it also includes the ARM exception vector table. And that's a design that you actually have from older or other generations of Nintendo DS. If you don't know the ARM architecture, basically there's an exception vector table there. It's a hard-coded address in the boot ROM. And basically every time something weird or something special happens on the CPU, it jumps to these exceptions. And the reset vector that we just saw, when you're trying to reach from an address, if you're trying to jump to an unprotected board or a data board, then the corresponding vector is triggered. And even if you interrupt it, it jumps to the interrupt request vector. So those are the exception vectors that are hard-coded in the boot ROM. And there's a problem with that. Because as a developer, you don't want to have an exception handler routine in the boot ROM. You want to change the code, after all. What they do is, as a result, they drag all these exceptions out of the boot ROM into another jump table that is in the ARM 9 RAM. It looks like this. What you can see here is that the boot ROM vectors basically just a jump instruction to the actual firmware handler that just jumps into the firmware handler. And when the firmware is running, that's how it looks when the firmware actually runs. But what about the cold boot? You get this. And this looks kind of interesting. It looks pretty interesting, because we have these boot ROM vectors in the ARM 9 RAM storage. But because it's a cold boot, nothing is initialized in the RAM. So that's interesting for us. It's not really a bug, because at some point these things are initialized. But let's shuffle a little bit here and say, let's take a look. We can solve a pretty time-consuming exception, even before the boot ROM is able to solve the whole thing. Yeah, it's probably just crashing. On an exception, it would just jump to an initialized memory. On an exception, it would just jump to an unused memory spring, and there would just be no instruction there. So that's not really useful. But that's a really nice hardware flow. There's a whole bunch of hardware errors in there. That's what we see when we have a memory reboot. And then we looked at what happened. We also found out that some of the RAMs actually weren't really solved with a reboot, and that's in the ARM 9. What we're going to do now is we're going to do a few custom exception vectors in the RAM, and we're going to do an execution flow in the Dharma code. And then we're going to do this here. And that's very interesting. When we're going to need to do that, all we're going to have to do now is to trigger an exception from the chunk to our exception. How can we trigger an exception? How can we trigger an exception? If you look at the exception vector tab, there are a few exceptions that we can trigger. A few hard coded ones. They won't jump to ARM 9 memory. And you can't use the interrupt vector because interrupts were reset, deactivated, and that won't work. What's left over are these four interesting exceptions. They normally don't work. And the fine destruction is pretty rare. It shouldn't really happen. I don't know. It's a really nice use case to do a fall injection again. You can't compare that, and a few modified structures get out, and then it's very likely that there will be an exception output. That's the vector glitch hack. We have a few vectors in the RAM set up, rebooted, glitched, reset it again, let it boot again, and hopefully the damper code was executed and then wrote a copy of the boot ROMs on the memory. It's not so stable, but it works for me. Okay, we got boot ROMs, and Nintendo is losing their life there. Before we look at boot ROMs, I have something for you. A little prologue. In 2014, a FCC document was published. It says that the CPU in Nintendo 2DS changed. That's an interesting sentence. It just says, they changed the security function of the initialization program. That's in the modern installers. The initial ROM is probably the boot ROM, and obviously a huge bug had to be in it. Let's take a look at the boot ROMs. There are a few boot methods. You can download it from NAND. It usually does that. Alternatively, it's also from spy flash. That's wireless, of course. It only starts with signed and encrypted images. It's not a weird development sector that we can exploit. There are two different keys for NAND and not NAND boot methods. Even when stuff is leaked, you can't use it on your console that you bought. Take a look at a small boot walkthrough. It's pretty normal. It looks for a boot device from a company header and an RSA signature. It's just one block. Then the header is hashed and pulled out from the signature and then it's compared. It's a very simple signature verification. The header is safe and loads the company header. It's a pretty simple format. You have a few entries in the header. Take the data from this offset. There's a section that says load this size to this address. We know from Nintendo's past that they like to break RSA signatures. Let's look at how it was done in the last three years. They use RSA signatures in the PKCS standard. It's a standard that says how your signatures look like. They want to use 2048, so 2084 bit version of RSA, which is safe. In the signature we have SHA2 hash. It's coded with ASN1. It's a pretty complex structure. It's similar to the MP3 structure. You have small chunks of data with small headers and the headers have tag bytes and length bytes. It's all ASN1. It tells the parser which hashing algorithm is used. Since SHA2 hash is only 2048, SHA2 hash is just a little bit bigger than SHA2. PKCS says padding and this padding should be deterministic. If we try to forge signatures, it's really hard to forge because this padding is very long. If you compare signatures of different companies, you'll notice that only the hash changes. The rest of the data is always the same for all signatures. For some reason they decided to write a signature parser. The first thing it does is try to read the padding and it's totally messed up. There's a flag byte that tells you if the padding should be checked and if it's checked, it's checked. But if it's two, it just skipped the padding. It also has some really weak and sure that it will not out of bounds. But it doesn't really fit in there. So the next thing they do is this really complicated parser. It's also really simplified. So we know S and 1 have some length fields in there. There's no bounds checking. So eventually we add this length to the signature and then they can also say we passed all the data and that should be the hash. They don't check this length and this pointer is then used to compare the hash to the hash at the end. What you can say is it only checks a few bytes in this signature and this parser is really pretty simple. The ASN parser is really simplified. So what we can do is we can create a perfect signature pointer when the padding is passed the ASN1 data. This last pointer corresponds to the pointer of the calculated hash of the boot ROM. What it actually does is it makes a mem copy or a mem compare with the calculated hash of the boot ROM. This calculated hash will never fail. It will always give a success and that's the CX. So CX is the boot ROM exploit of the 3DS and basically we can signature our own firmware based on all models because the boot ROM can't fix it. That's pretty nice. There's one heart remaining. Something is missing. What we haven't done yet is we have the ARM 11 boot ROM. We would like to have the full capacity but we would like to have it. Theoretically we can do a vector glitch hack because it's based on the same weak point. But now that we can sign our own firmware let's try something. If you look at the unprotected part of the ARM 11 boot ROM you can see that there are a lot of references between our own firmware and our own firmware. Maybe we can overwrite some boot ROM data. The boot ROM they were kind of clever. The ARM 9 boot ROM that actually checks these firmware sections. And they have a blacklist. Unfortunately you can't just overwrite these data sections. But for some reason they forgot to blacklist the boot 11 data region so that we can write on there or on the exception vectors. And with that you can simply dump the boot 11 boot ROM out. That was pretty easy. Now I can tell you something about all these things about the boot ROM. We did that in summer 2015. We could have talked about that last year already but because we are quite friendly hackers we have held back for so long. Nintendo should be grateful to us. Okay, so that was 3DS game over. Here is a picture of Nintendo Switch. Our bodies are ready. Thank you very much. We have 5 minutes for questions. Are there any questions from the internet? No? Hello? Yes, that's one question from the internet. The internet wants to know if we can get DSP code executions soon. Can you repeat the question? It's very hard to understand here. Okay, the internet wants to know if we can get DSP code execution. DSP code execution. Well, the DSP of the DSP has its own firmware and that is a kernel module and basically if you can get your own firmware then you can also get the kernel so that another DSP firmware can do that. Yes, basically you can do that. Okay, people are leaving. People are quietly leaving. There was a question on the microphone 3. Not longer. Does the internet have more questions? Yes, it does. The internet wants to know how you managed the Wii U to get the execution. Well, I don't want to detail how I did it in detail. But there are a few full detection attacks on it. My setup looked like this. It was rather complicated. I had to modify a lot of things on the Wii U Mainboard to get it to work. I guess you have to figure it out yourself. Sorry. Okay, there's a question upstairs. There's a question on the bottom of the page. Well, you said that you broke all the 2DS. Did you show that the 2DS didn't change the boot process? Did you verify that for the first version? Yes, we did. The new 3DS came out. The 2DS came out after the 2DS and the new one is also usable. Basically, all Nintendo DS consoles are the same. Well, we verified that. We don't know what this FCC document means in detail. We got a few really new 2DS from the store. Basically, there's no difference in the boot. Good to know. Thank you. The last question from Microphone 3. Why such a device? Did you want to play it? Or do you just want to see if you can hang it? Personally, I don't have a game on the Wii U. But I don't have any co-op games.