 Good evening, everyone. In a few minutes to Nintendo hacking 2016, talk will start. This talk will be translated into German, and there are English subtitles available. Anyway, without much further ado, these are Derek, Nierwirt, and Netwheel. The three students have been working on hacking the Nintendo platform for a while now. And please give them a warm applause. Hi, guys. So we'll come to talk about Nintendo hacking 2016. Let me quickly introduce the other guys. This is Derek, and that's Ned. And I think I can speak for all the three of us to say that I'm really happy that you guys are here today, and we are happy that we can be here today to tell you everything about what we did in the past one and a half years, I guess. So I will start with the state of the Wii U. I hope a lot of you guys have seen the fail-of-flow talk in 2013 about hacking the Wii U. Not much happened afterwards. Until 2015, there is a public web kit exploit released. And about this time, we started looking into the Wii U, and we wanted more access than just user mode. Because there is also the kernel running on the PowerPC, and then there is this other ARM processor that runs IOSU, also user mode and kernel mode. I am not going to consider the user mode today, because I think the kernel exploit is just way more fun. So let's start with PowerPC kernel real quick. It has all standard basic security measures, though it doesn't have any ASLR, which makes our life easier. It has about 146 calls. And we don't really, we can't really name them from start, right? Kind of need to reverse it, but there's a nice thing. So the Wii U uses this RPL mechanism for dynamic libraries. And there's this really nice library. It's called corinnet.rpl. And it contains a lot of syscalls, shims, and symbol names. So we can name all the syscalls straight away without much hassle. And it's important to note that all the syscalls use a save copy and copy out mechanism to get data from the user space into the kernel space. So you start reversing each syscall, and you start looking for bugs. And what we came up with at first is what we call iocontrol-vhacks, or by indirections are hard. It's actually a bug in the IPCK driver submit request syscall. So what this syscall is used for is you want to submit requests from user mode to this other processor running, which I'm going to talk about later. And so you submit these kind of request structures. And the kernel uses copy-in to fetch the request structure from user mode into kernel mode. But there is a certain type of request structure which contains an indirection, like a second layer, right? And well, they just ignored it for the second level and hoped for the best. So let's look at the relevant part. I'm really sorry I'm showing you this code here, but it's not much more than that. So there is something that's called iOS packet in the second line, which is kind of this request that we submit from user mode into kernel mode. And in the top line, there is this special request entry. So it contains a physical address, a buffer size, and a virtual address. And what we do from user mode is we submit, it filled out with the virtual address and the size. And the kernel does this convenient thing for us to kind of change the virtual address to the physical address. So we can see it copies in this packet from user mode into kernel mode using the save mechanism. And then it goes through all the entries and fixes up the physical addresses for us. But we can see in this line that it doesn't use the save mechanism at all. It doesn't care about whatever address we put in there. So this gives us some kind of right primitive to wherever we want, basically. This looks hard to exploit, right? Because the right kind is going through this conversation. But we actually only need one byte to exploit the kernel. And we do this by noting that this Ki effective to physical conversion function actually returns zero for any garbage input we get. And there's a pretty high chance of the input to the function to be in garbage if we point it to any part inside kernel data. So the strategy here is that we go into the syscall hand address table and we overwrite the last byte for one particular syscall handler. And we hope that the new address actually points to some usable gadget. So we hope for the best, basically. And the other important thing to note here is that our user mode code is running from what we call the jid area. And what's really stupid is that the jid area is actually executable from kernel mode for some reason. So that's nice too. Okay, let's look at the relevant structures. So this is the kernel. And we should read this from the bottom to the top. Okay, like in the last line in the bottom, we see this entry to ke loader call. And then we can look at the last byte there. It's hex f zero. And what we will do now is overwrite this last byte with zero. And what happens is that now the syscall will actually point to this very usable gadget up there where it loads this register R28 into the link register and just branches there. And the nice thing is that we control R28 from user mode. So this gives us a way to just jump anywhere, basically. So how do we exploit this? Well, we have our K mode function there. And then we just call iocontrol v to this shifted address. And from this point on, we have this nice syscall that just jumps to anywhere we want. And then we call it basically and this calls our K mode function. So the vue starts out with full four hearts. And this gives us PowerPC-con mode code execution. So we subtract one heart. And it's quite nice, but we can and need to go deeper. And for that, let's look at the iosu architecture. So iosu is present as one big L file. And this includes the kernel and all the services. And it's running on the Starbucks. It has a hardware way to enforce no execute. And again, no ASLR, making our lives easier. And it's a micro kernel design and it has about 146 calls. So another thing to notice is that the kernel spawns all the services as user mode processes. So before we can exploit the kernel, we actually have to exploit one of these user mode processes, which we did, but I'm not going to talk about. And to look into the kernel, we again reverse all of these syscalls in search for bugs. And what we came up with is called mqhacks or message qhacks. It contains another nice bug class that apparently never dies in the turbo flows. And let's look at the code again. So there's the syscalls, it's called create message queue. You pass it a buffer and the number of buffer entries. And what they assumed was that each buffer entry is four bytes. So when they check the address range, they just multiply the number of entries with four bytes. So does anyone see the integer overflow here? And the other nice thing is that they just use the number of entries for the maximum number of entries for the message queue. And our write primitive again is a descent message syscall. So I told you about this hardware NX, right? So iOS should be enforcing that no executable memory is writable. And if you look at the kernel section flex, we actually see that kernel text is read execute and kernel data is read write. But these permissions are all lies, okay? So our exploit strategy. Well, let's look at the relevant part of the ISO kernel. So we see that kernel text starts at this lower address at hex 812. And conveniently for us, there is a syscall there. And the addresses before that are all valid. So we create a message queue starting at minus eight bytes and this magic hex 400 whatever, two number. And from this point on, we just push two messages and then our instruction to branch R3. And what this does is it actually causes the start of the text section to be overwritten, branch R3. And let's just look at the integer overflow, right? Four times this value, truncated to four bytes, gives eight bytes. So what the kernel thinks is that the message queue is only eight bytes, but we can just push any messages we want, okay? So this gives us IRS kernel mode execution. And the nice thing about this is that we actually have full control over the console now, right? So we can dump the console as OTP, which contains all the keys except for boot one, which we will coming back to later because unfortunately the keys for boot one are locked out as we've already seen. And now we wanna make everything persistent. So how do we do that? We find that title content is only verified at title install time, but never at boot time. Because at boot time, they only verify the title binary. So what you can do is you can actually start to mess with the metadata of titles and overwrite it. And what we did was to overwrite the ROM for a DS game, exploited the emulator and got user mode code execution again. And another thing is the console contains this config file, which tells it to boot into which title to boot. So what you can do is you overwrite the title ID with your modified DS emulator title. And the next time you start at the console, it actually boots into the exploited game and yeah. So this gives us persistent code execution and cold boot with full control over the console, whatsoever, so game over. So as we just saw, the kernels are like pretty broken, right? So what is missing? And I just copied this slide from failoverflows talk. As you can see, we are using the same default theme for our slides. And basically the boot one key, which is the second stage boot logger on Wii U, this key is still unknown. And they tried to get it somehow with some side channel attack thing, but I think it never worked. So it would be nice to get this key. And the first thing we did was to make a NAND tracer. So we can basically sniff all the traffic from between NAND and would want to see what boot one reads from flash. And so we get some nice addresses and we could compare this with the file system on this flash to see what file it is reading. And we also kind of messed around with some files on this file system. And we found out that boot one actually parses a file that is called system XML. And I don't know, it doesn't really feel safe to parse an XML file in such a really early boot process. I mean, there's a lot of stuff that could go wrong. So we tried to attack this. We tried some blind exploitation stuff, but yeah, unfortunately it didn't really work. So let's try something else. So there's boot one, which of course boots this, sorry, we've got boot zero and this boots boot one and fail overflow found out that this boot zero, which is the boot room of the security processor can be re-enabled again in virtual remote and you can just dump it. So let's look at boot one, boot serial, sorry. And we can see that it reads the boot one key from OTP and then it locks out boot one key forever. And this happens really early. But it's basically kept in memory all the time until it's done, until it has launched a boot one or just panicked. So this means that we have to exploit boot zero to get the boot one key. And unfortunately, boot zero is pretty safe. It's kind of surprising because this is a Wii U and basically this gives us this question, how can you exploit something that has no bugs? So the answer is we have to introduce our own bugs and we're doing this by using fault injection and maybe you have heard of it already. It's basically you introduce an error into the device by clicking the clock or voltage in the reset line. You can also do electromagnetic fault injections there in many ways. But basically what you want to get is a mutated instruction or an instruction skip or some corrupted registers. And what you don't want is just a stupid lock up where it just crashes. Yeah, that's really useful. So we want to click boot zero. And to do this, we have to find a nice target like the weak spot of boot zero. So let's take a look what boot zero does. The first thing it does is it copies itself to RAM for some unknown reason. I mean, there's no good reason to do this, but it's nice for us because it copies itself to RAM and just executes from there. And then it copies the boot one key to memory. It locks out the OTP slot, initializes some other stuff and flash controller. And then it starts reading the boot one image. And it does that by just reading its header to this address. And then they read the size from the header field and they also do some max size check on this. And please note, the header itself is not encrypted and they also don't do any signature verification here at this step. So they use the size and reach the whole boot one image using the size and then they do a real signature verification and make sure that the image is not corrupted. It then decrypts the boot one code using the key from RAM. And then it clears the key and jumps to boot one entry point. Okay, so what is weak spot here? And I mean, if you look at this, you can pretty much already tell what it is. And of course it's this size check. So what we can do is we can write our own modified version of boot one to flash with some really, really large size in the header. So it reads the header and then it's supposed to do the size check and this is exactly where we want to glitch it and eventually it will just skip the instruction or something else happens and then basically the size check is bypassed. So when it's reading the boot one image using this size, it will actually overflow the buffer and we have some jump instructions at the end. So when it returns from the flash read function, it will eventually jump to our code and this is actually boot zero code execution. Okay, so we have boot zero code execution and we can just dump the boot one key from RAM and we didn't even need an exploit for this, right? So it's just, boot zero is actually pretty safe, right? But when it comes to glitching it's kind of fragile because boot zero code is writable and also boot one image buffer is in front of boot zero buffer so we can just overflow it. And also the setup that I had is surprisingly stable so it works like 50% of the entire time. So let's finally look at boot one and boot one is able to understand the VU file system. It uses real file path strings to load a firmware image and of course the first thing we did was to look at the XML parser and well, unfortunately, it seems pretty safe. But maybe we found a bug, we are not really sure and we haven't really tried to exploit it, interest kind of faded out because you know it's, after all, it's just the VU. So that's it for VU and now I will hand over to Ned Will, he's talking about 3DS. Hi everyone, I'm Ned, I started 3DS this year and I'm basically a software person so I'm gonna be showing some of the homebrew side of 3DS where that's at right now. So just to reiterate from last year, these guys broke user land, kernel and security processor. They also broke the secret hardware key scrambler and since then, Nintendo's been kind of mad about this. They released a lot of system updates and they started a bug bounty program. So there's a lot of bugs getting patched but because of the amount of the level of exploitation we got last year, it's actually really easy to find new bugs and new exploits. So what I wanna emphasize here is that even though it's like a cat and mouse game because we have so much control, we can exploit more difficult bugs on the latest firmware. So starting with user space, this is where all homebrew comes from. So already it's pretty good, like this has always been a huge focus for the homebrew community because it's kind of where user space is where you want to be running your own custom games, modifying stuff. So we have a bunch of game entry points and a bunch of browser exploits but there's a couple of limitations to these and that's that game carts cost money and they frequently like the games that are exploited are usually somewhat rare and unusual and so the price goes way up as demand soars and for the browser every time we release a new browser exploit, Nintendo can actually enforce that you're in the latest firmware because before we fetch any web page, it'll check that the system's on the latest version so they can kind of remotely cut off web browser exploits. So looking at this, I thought it might be fun to look at if any of the system titles could be exploitable as primary entry points and I found something called Sound Hacks. So just the basic, like the two probably most obvious things to look at are the image loader because it's got JPEG parsing and also the music player. But when I looked at the music player, I saw that they're parsing actually a lot of formats and they even have their own custom playlist format and if they make a single mistake anywhere, it's over so then I was trying to compare with like open source implementations. I didn't find any overlap. It seemed like everything was custom so that was pretty promising. So over the course of about a month, I found a bunch of bugs and I was trying to like chain together little like logical bugs and it wasn't really working and then I just found one that was really critical so I'm gonna demonstrate that here. So I actually studied MP3 for like the whole month and PEG was like the last day. So I looked at it and they actually malloc 256-byte buffer for the song name and then when they go to load it, if they see a Unicode bomb marker, they just mem copy the thing and that tag size is totally controlled so you know, that's it. So this is like, this is pretty great but it's a heap exploit so it's a little tricky but this is what it looks like. So we have our name chunk that we're about to overflow and then like I'm a CTF player so I just put A's there and then the next thing that happens is this gets freed and so this victim chunk that we've overridden it's actually the way the 3DS keep works they actually track, they have a linked list of what things are currently allocated so this gives us the classical heap on link arbitrary right and so at this point we have a 4-byte right and we want to get it raw out of it so we'll probably do a stack pivot. So I looked at the binary and there's only one pivot gadget and then I looked at the thumb pivots there's actually a lot but because this CPU was too old didn't support the wide instructions that where all the pivots come up so unfortunately that one pivot instruction has some like arithmetic conditions on it specifically it was that in order to load all your registers from memory the condition flags had to satisfy less than and everywhere where we returned from the function it had just checked that like if this pointer is not null free and so the comparisons wouldn't ever be satisfied because nothing's mapped up in the negative area so of course CTF workarounds we can still do this so I'll overwrite the heap free list head with a stack address and so on the next malloc we just return that stack address and read into it so there's a couple of constraints on this and the first one's really normal like this is every pivot to stack heap thing you have to make sure that you have a heap chunk on the stack luckily this is actually pretty easy because all you need is a size followed by two null pointers representing next and previous so when malloc goes to look there it sees like the size is big enough and then nothing else is in the queue so we'll just return this and then this worked so we mem copy the next tag to the stack and like we just specify that size and malloc's and reads it in for us and then from there we're done because we can just do a little a little rock chain where we mem copy the shell code to the heap and then use an existing exploit GSPone which has been around for a long time to overwrite the text section and jump there so there's the first heart so you can't really talk about homebrew without also talking about kernel because we want to get access to more syscalls like the 3DS actually sandboxes a lot of the syscalls away from you and so as an attacker, well your goal is to call some syscalls that are restricted a really nice example would be you'd want to map some executable memory for like a jit emulator so it's kind of a tricky situation because you're inside the sandbox you want to break out, you have to find bugs in like pretty restricted syscalls so I looked at last year's talk here and like what had been done so far and it seemed like there were a lot of attacks on that memory mapping but I didn't see much about the sync primitives or anything related to use after free and I had just got a pretty bad grade on my OS project because I had a lot of those so I knew this is a good place to look so I noticed the design flaw when I was reversing the ref counting so it's not so much that they couldn't possibly get this right but generally when you're designing an API you want to make it really hard to abuse and this is just not really true for how they do ref counting so I'll go ahead and bring all these up yeah so basically whenever the user fetches a kernel object to perform some operation on it meaning you call a syscall that does something using a kernel object it does the correct in-graph and then decref for you but I was looking at it and I was thinking well like a lot of times the kernel actually is using these objects internally to do stuff so I mean I spoiled it I mean it was like a week I found three user for free and they're all following the same pattern the kernel is using an object internally without maintaining the reference count correctly and then some people ask me advice on kernel hacking maybe at home I definitely recommend looking here I'm sure that there's plenty more so the one I'm gonna talk about today is the timer object so this is a pretty simple API with the kernel you can have it create a timer for you and you can set the timer you can wait on it it's like a normal synchronization primitive so like I said I was looking for these user after freeze I saw this and I thought it's kind of interesting that this one called pulse is here because what's happening with this one is when you set the timer to pulse like every period it's signaling everything that's waiting on it and then it like resets itself and then if you wait on it the next period comes around you signal again and so I was thinking like it's definitely doing some stuff with this object internally that's like a bit more complicated than some of the other modes and the other kernel objects so I looked at how they did the pulse like every second when it pulses like what's actually getting executed and if you look here they do some pretty good locking and then they signal and then what happens here is basically when they signal they go through and everyone that was waiting gets rescheduled made runnable and then at the end they reset the timer state and just say like okay everyone that waits on this again has to wait for the next cycle so and then this also looks pretty good like they're locking the scheduler here and this would work but nothing's preventing you from just closing this from another core so I have fast hacks which is just three syscalls is that that's it that's the entire exploit and there's a lot of setup which we'll get to but you just create the timer set it to run really fast and then close the handle and then if it was pulsing and you closed it it'll use after free so what's nice about this is if you lose the race it just the timer is just unscheduled you're fine and then it actually happens quite often and I didn't even really specifically try to win this too well like I just once it was within a second I didn't worry but those parameters are probably not optimal so we should look at how do we exploit this basically this is a little bit more complicated view of it I'll show a diagram in a second but this is like where the use after free actually happens so like R7's pointing to my timer object and then it was freed before we reached this trunk here and then it's loading R7 to R0 loading something from that and then branching to it so that's like calling a use after free object so this is pretty exploitable on the 3ds kernel because they use a slab heap to deal with allocating the objects so this is the normal situation when that first timer is allocated the vtable is pointing to the real k timer vtable and then it wants to call that timer reset function it's totally fine but when we free it actually the vtable pointer goes to the next freed timer object in the kernel so it's actually interpreting that struct as a vtable and what's nice is it actually overlaps with the initial timer value that we totally control so it looks like okay we could just set the initial timer value you know do this use after free and we're just calling user space that's what I thought and then it realized it wasn't that easy so because of what's actually calling this is in a kernel thread we actually can't guarantee that our user process is actually mapped in memory and in fact it's on a different core so even if you open a process on the other core like ran a thread there you can't get more than 25% of the time I think so that's just super unstable also because it's a kernel thread we don't necessarily want to crash it we don't like crashes in general but this will just totally break everything if the timer like sync thread dies so as long as we return to a function do something cleanly in return it'll be fine so it sounds like okay all we have to do is find some kernel function we can call and we're done but there's actually another issue and that's that kernel code is mapped at high addresses and these are actually negative and the set timer syscall actually checks if your timer is negative so there's a pretty funny trick I found and it's that when you set the timer you're saying like start like one second from now start pulsing obviously it's adding like the current time to the one second to know like when do I trigger this timer so set timer is the one that does that add for you they don't check for overflow when installing it and timer schedule values are signed which is also a bit weird so we can overflow and schedule into the past so how this looks is that's my like disgusting setup call so what's happening is like in the middle that's the start of the 3DS boot and then that range on the right is what the 3DS will allow you to pass for your values for the initial and like pulse period time and so what I do is I just put it right there at the end and then it overflows and then on the next pulse I also control that and that's also less than that range so then we can get it to line up on the kernel address that we want and so that's pretty good unfortunately we're at the end like at this point it's pretty solid but there isn't like an obvious single thing we can call and it seems like well maybe you could race a bunch of times and call a bunch of different things in the kernel and like you know that's a decent amount of control but because of all this weird negative scheduling stuff it's actually pretty hard to do multiple calls so I was trying to look for one thing that I can call that will give me control and this is where it gets really tricky so if we look at how the memory mapping on 3DS works in user space you can access the FC RAM which is that first range up there that's just where your heap goes there and then the kernel also has a view of this heap it's a shared mapping so if we can write one of those something in that range into the free pointer and allocate it it actually ends up in something we can see as the user so then I noticed this this is actually a common instruction prefix in ARM so I jumped here and at this point like we just did a C++ view table call on the use after free thing with one argument so this means that R0 contains the address of the object and R1 contains the address of where we just jumped to so that B65C is where R1's pointing so this is actually some random linked list lookup function but it's actually looking down to the add instruction and loading it to R1 and then we write that to the object and so at this point it looks like this it's pointing to something in user space and then we just alloc two times we can look in user space oh they put the object there you control the V table and from there it's pretty much standard straightforward thing so there we go got full R11 user space in kernel and this is almost game over one more time so we have broken several parts of the 3DS firmware including the 3DS kernel and all software that's running on the security processor what we haven't looked at yet are the 3DS boot ROMs and basically there's one boot ROM for each processor for the R11 and for the R9 and I think there's probably more boot ROMs in the 3DS system on a chip used to old Nintendo DS mode but we will focus on the 3DS boot ROMs here and what we know is they are somehow loading the firmware image from NAND flash and we also know that the R9 boot ROM has all the interesting stuff because only the R9 has access to the whole crypto hardware like AES engine, RSA engine we also know that the boot ROM will initialize the secret keys for the AES key slots and yes we would like to get those keys but unfortunately the boot ROM is disabled it disables itself before it's launching the firmware and 3DS boot ROMs also print nice error screens like when the NAND is corrupted or something it shows an error screen so let's look how the boot ROMs are protected in detail basically there are two registers that we call configs sysprot9 and sysprot11 and the boot ROM writes to those registers and of course they are one shot you cannot re-enable the boot ROMs again because this is not the review and basically when it disables the boot ROM it only disables one half of it so what you get are two parts of boot ROM there's the unprotected part and the protected part you can just dump the unprotected part by taking over a line from firmware but you can never see the protected part and they were really clever and basically they put all the interesting code in the protected part and if you look at the reset vector it just jumps directly to the protected part of the boot ROM so you can't really figure out what is going on when the 3DS is starting up but what you can do is you can look at the code from the unprotected boot ROM and who knows maybe we can find a bug so let's do this first of all of course there are no keys in the unprotected boot ROM they put all the keys in the protected part it's also mainly, it's a lot of driver code it talks to some hardware like NAND flash, MSE, the AS engine and also to a spy flash which is kind of interesting because the spy flash is some really tiny chip that is soldered on the Wi-Fi socket and it's actually used for some Wi-Fi settings and other user settings used by all Nintendo DS mode and that's kind of interesting it uses the spy flash and it also includes the ARM exception vector table and this is actually a design that they have adopted from previous generations of the Nintendo DS such as the DSi if you don't know ARM basically you have something that is called an exception vector table and this is located at this hard-coded address in boot ROM and basically every time when something weird happens or something special on the CPU it will jump to those exception vectors like the reset vector that we just saw or when you're trying to read from an invalid address it will jump to the prefix abort or data abort vector and also when you receive and interrupt it will jump to the interrupt request vector so those are the exception vectors and they are hard-coded in the boot ROM and there's kind of a problem with that because as a developer you don't want to put the exception and the routines in the boot ROM you want to be able to change the code so what they do is they just redirect all the exception execution flow from boot ROM to another jump table that is located in ARM-line memory so it looks like this what you can see here the boot ROM vectors it's basically just a jump instruction to the RAM vectors and the RAM vectors are also just another jump instruction to the actual firmware handler and this is how things look like when the firmware is running but what about cold boot? well, on cold boot you get this and this looks kind of interesting because you have the boot ROM vectors that still point to ARM-line memory but since this is cold boot the RAM is not initialized so this is interesting but it's not really a buck because at some point the boot ROM will initialize those RAM vectors but let's cheat a little bit here and say let's just assume we could somehow trigger a really early exception even before the boot ROM is able to initialize the RAM vectors well, probably it would just crash because on an exception it would just jump to an initialized memory and there's probably no valid instruction there so this is not very useful but there's a really nice hardware flaw we found this by just writing to some memory reboot see what happened and basically we found out that some RAM is actually not cleared on reboot and this also includes ARM-line so the basic idea is we can set up some custom exception vectors in RAM that redirect execution flow to some dumper code so when we reboot we get this and this is really interesting because if you look at this this means all we need to do now is trigger a really early exception and then the boot ROM will jump to our dumper code so how can we trigger an exception? well, if you look at the exception vector table again there are some exceptions that we can trigger because they are hardcoded like reset and they won't jump to online memory and you also can use the interrupt vector because interrupts are disabled on reset and this won't work so what is left is these three interesting exceptions and if you look at those they normally don't happen undefined instruction is very rare it shouldn't happen so I don't know but this reminds me it's a really nice use case for doing fault injection again because you can corrupt register and get mutated instruction so it's really likely that it will trigger an exception so this is the vector glitch hack basically we set up some vectors in RAM trigger reboot then do some glitching magic and then we reset again and let it boot up normally and hopefully the dumper code got executed and then just wrote a copy of the boot ROM in memory so we can just dump it all this stuff is not very stable but it works for me so okay, we got the boot ROM and Nintendo is losing a life there so before we look at the boot ROM I have a little prologue for you and basically in early 2014 an FCC document became public there it is and basically it says that Nintendo has changed the CPU of the Nintendo 2DS and there's one really interesting sentence that basically says they have changed the security function of the initial program loader that is installed in each model so the initial program loader is probably the boot ROM so obviously there must be some really huge bug in the boot ROM, right? So let's look at the boot ROM basically there are some boot methods you can boot from then that's what it normally does but alternatively you can also boot from spy flash which is a Wi-Fi flash and it will only boot firmware images that are signed and encrypted there's no freaky development backdoor that we can exploit it also uses two different set of keys for NAND and non-NAND boot methods and also for retail in dev mode so even when stuff gets leaked you cannot use it on your retail console so let's do a small boot walkthrough it's pretty straightforward actually so the first thing it does is it selects a boot device then it loads the firmware header and the RSA signature from it it's just one block and then it hashes the header and extracts the hash from the signature and compares it so basically basic signature verification header verification and then it assumes the header is safe and then it starts loading the firmware sections and the firmware images are pretty simple to format you have some entries in the header that tells you to take the data from this offset and there's a section with the size loaded to that address it's pretty simple so we know from Nintendo's past that they like to mess up RSA signature checks so let's look at how RSA is done in three years so for the three years firmware they are using RSA signatures in the PKCS standard PKCS is basically a bunch of standards that tell you how your signatures have to look like and they are using the 2048 bit version of RSA which is safe and in the signature you have the SHA2 hash and this is encoded using ASN1 and ASN1 is some really complex structure it's basically similar to the MP3 structure so you have little chunks of data and those chunks have little headers and the headers have tag bytes and length bytes and basically this ASN1 stuff is used to tell the parser which hashing algorithm is used and well since SHA2 hash is only 20 hex bytes in size you have some remaining space in the signature that you have to fill and PKCS says you need padding and this padding should be deterministic it should only contain FF bytes so when you're trying to forge signatures it's really difficult because of this padding that is really long and when you compare signatures of different firmware images you will actually notice that only the hash will change and the rest of the data is always the same for all signatures but well for some reason they decided to write a signature parser for the stuff so what you get now is RSA the Nintendo way again so the first thing it does is it tries to parse the padding and this parser is totally messed up like there's a flag byte that tells you if the padding should be checked and if it's one then it is checked it should be all FF bytes but if it's two then it will just skip the padding and it also has some really weak bounds checking it makes sure that it will not when it's parsing the padding it makes sure that it will not go out of bounds but they forget to verify that the hash will actually fit in there as well so the next thing they do is parsing this really complicated as in one structure and this parser is also really simplified so we know as in one has some length fields and there's no bounds checking so eventually it will add the length to the current pointer in the signature and then they stop parsing and say okay we parsed all the data and now there should be the hash and they are not checking this length and this point is used to do the hash comparison so in all you can say it only checks a few bytes in the signature because the padding parser is messed up and also the as in one parser is really simplified so what we can do is we can prove for us a perfect signature where the final pointer when it's done parsing the padding and the as in one data that this final pointer matches the pointer of the calculated hash of the boot room so what it does then is it does a mem-compare with the calculated hash and the calculated hash like in this never fails right so it will always succeed and this is six hacks so six hacks is a boot room exploit for 3ds and basically we can sign our own firmware and there are over 60 million vulnerable devices and basically in new 3ds and 2ds basically all models are affected and of course since this is the boot room Nintendo can't fix it so that's really nice but there's one hard remaining so something is missing what we haven't done yet is we haven't dumped the ARM 11 boot room it's probably not really interesting but for a sake of completeness you would like to get it and in theory we can just do a vector-clitch hack again because it has the same floor but now that we can sign our own firmware let's try something else so if you look at the unprotected part of the ARM 11 boot room you can see there are a lot of references to ARM 11 memory so maybe now that we can sign our own firmware and we can set up our own firmware sections maybe we can all write some boot room data but the boot room developers were kind of clever and the ARM 9 boot room checks the firmware sections and they have some kind of blacklist and unfortunately you can't just overwrite boot 9 data sections but for some reason they forgot to blacklist all the boot 11 data regions so you can just overwrite boot 11 stack or the exception vectors and well, you can dump the ARM 11 boot room yeah, that was pretty easy and now I get to tell you something all the stuff about the boot room we did this in summer 2015 so we could have talked about this already last year but since we are kind of friendly hackers we hold this bug so long so yeah, Nintendo should be thankful and okay, so that's it three years free game over and here's a picture of Nintendo Switch and our buddy is already thank you very much there's about five minutes left for questions are there any questions from the internet? yes, there's actually one question from the internet and that is the internet wants to know if we can get DSP code execution maybe sometime 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 well, the DSP of the 3DS runs its own firmware and that is included in some kernel module and basically when you can sign your own firmware you can also make it load another DSP firmware so yes, you can do this okay, people who are leaving please do so quietly and people entering also do please do so quietly this was a question on microphone 3 I think but no longer okay does the internet have more questions? yes it does the internet wants to know if you or how you glitch the Wii U to get execution well, I don't want to read how I did it in detail but there are some basic fault injection attacks and my setup was I think kind of complicated you had to modify a lot of stuff on the Wii U main board to get it work so I guess you have to figure out yourself, sorry okay, there's a question upstairs microphone 5 I think 7 but it's okay well, you said that you broke all the 2DS but actually you showed that the 2DS changed in the boot process so did you verify that that worked for the first version as well? yes, so the new 3DS was released after the 2DS and the new 3DS is also vulnerable and basically all the Nintendo 2DS consoles are also vulnerable as well yes, we did verify this and we don't really know what this FCC document is about we got some really new 2DS from the store and basically there's no difference for the boot room at all so yes, everything is vulnerable nice to know, thanks final question for microphone 3 yeah, just a fun question out of interest when you're going to buy such a device do you also plan to play a game on it or is it just going to check how the kernel works? personally, for the Wii U I own zero games great, thanks I also didn't pirate any so I never played a game on my Wii U