0:00:00.000,0:00:17.760 33C3 preroll music 0:00:17.760,0:00:23.730 Herald: Good evening, everyone. In a few[br]minutes, the Nintendo Hacking 2016 talk 0:00:23.730,0:00:28.470 will start. This talk will will be[br]translated into German, and there are 0:00:28.470,0:00:34.300 English subtitles available. Anyway,[br]without much further ado. These are 0:00:34.300,0:00:38.100 derrek, naehrwert and nedwill. They are[br]three students that have been working on 0:00:38.100,0:00:42.499 hacking Nintendo platforms for a while[br]now, and please give them a warm applause. 0:00:42.499,0:00:54.490 applause 0:00:54.490,0:01:00.890 naehrwert: Hi guys. So, welcome to our[br]talk about Nintendo Hacking 2016. Let me 0:01:00.890,0:01:06.280 quickly introduce the other guys. This is[br]derek, and that's ned, and I think I can 0:01:06.280,0:01:11.210 speak for the three of us to say that I am[br]really happy that you guys are here today 0:01:11.210,0:01:15.250 and we are happy that we can be here today[br]to tell you everything about what we did 0:01:15.250,0:01:22.920 in the past one and a half years. I will[br]start with the state of the Wii U. I hope 0:01:22.920,0:01:29.270 a lot of you guys have seen failOverflow's[br]talk in 2013 about hacking the Wii U. Not 0:01:29.270,0:01:38.530 much happened afterwards, until 2015 there[br]is a public webkit exploit released and 0:01:38.530,0:01:43.640 this time we started looking into the Wii[br]U. And, we wanted more access, right? Than 0:01:43.640,0:01:48.430 just user mode and because there is also[br]the kernel running on a PowerPC and then 0:01:48.430,0:01:54.320 there is this other ARM processor that[br]runs IOSU. Also user mode and kernel mode. 0:01:54.320,0:01:58.470 I am not going to consider the user mode[br]today. Because I think there are currently 0:01:58.470,0:02:05.970 exploits that are way more fun. So, let's[br]start with PowerPC kernel very quick. It 0:02:05.970,0:02:10.139 has all standard basic security measures,[br]though it doesn't have any ASLR which 0:02:10.139,0:02:20.110 makes our lives easier. It has about 140[br]syscalls. And we don't really.. We can't 0:02:20.110,0:02:24.840 really name them from start, right? Kinda[br]need to reverse them. But there's a nice 0:02:24.840,0:02:29.210 thing. So, the Wii U uses this RPL[br]mechanism for dynamic libraries. And 0:02:29.210,0:02:33.500 there's this really nice library. It's[br]called coreinit.rpl and it contains a lot 0:02:33.500,0:02:38.390 of syscalls, shims and symbol names. So we[br]can name all syscalls straight away 0:02:38.390,0:02:44.420 without much hassle and, it is important[br]to know that all the syscalls use the safe 0:02:44.420,0:02:50.120 copy in/copy out mechanism to get data[br]from the user space into the kernel space. 0:02:50.120,0:02:56.330 So we start reversing each syscall and we[br]start looking for bugs And what we came 0:02:56.330,0:03:01.750 out with, at first, this is what we call[br]I/O controlled VHAX Or, why indirections 0:03:01.750,0:03:07.960 are hard. It's actually a bug in the[br]IPCKDriver_SubmitRequest syscall so what 0:03:07.960,0:03:13.950 this syscall is used for is: you want to[br]submit requests from user mode to this 0:03:13.950,0:03:20.220 other processor running which I'm going to[br]talk about later. And, so you submit this 0:03:20.220,0:03:24.930 kind of request structures and the kernel[br]uses copy in to fetch the request 0:03:24.930,0:03:29.260 structure from user mode into kernel mode[br]but there's a certain type of request 0:03:29.260,0:03:35.380 structure which contains an indirection[br]like a second layer, right? And, well, 0:03:35.380,0:03:41.060 they just ignore that for the second level[br]and hope for the best. So, let's look at 0:03:41.060,0:03:45.220 the relevant part. I'm really sorry I'm[br]showing you this code here, but it's not 0:03:45.220,0:03:49.430 much more than that. So, there is[br]something that is called ios packet in the 0:03:49.430,0:03:53.599 second line which is kind of this request[br]that we submit from user mode into kernel 0:03:53.599,0:03:58.351 mode And in the top line there's this[br]special request entry, so it contains a 0:03:58.351,0:04:03.069 physical address, a buffer size and a[br]virtual address. And what we do from user 0:04:03.069,0:04:07.510 mode is we submit it filled out with the[br]virtual address and the size. and the 0:04:07.510,0:04:15.520 kernel does this convenient thing for us.[br]It kind of.. changes the virtual address 0:04:15.520,0:04:21.019 to the physical address. So we can see, it[br]copies in these packets from user mode 0:04:21.019,0:04:25.530 into kernel mode using the safe mechanism[br]and then it goes through all the entries 0:04:25.530,0:04:29.840 and fixes up the physical addresses for us[br]but we can see in this line that it 0:04:29.840,0:04:33.500 doesn't use to the safe mechanism at all[br]it doesn't care about whatever address we 0:04:33.500,0:04:38.620 put in there so this gives us some kind of[br]right primitive to wherever we want 0:04:38.620,0:04:45.780 basically and this looks hard to exploit,[br]right? Because the right kind of going 0:04:45.780,0:04:54.630 through this conversation but we actually[br]only need one byte to exploit the kernel 0:04:54.630,0:05:01.639 and we do this by noting that this[br]KIEffectiveToPhysical conversion function 0:05:01.639,0:05:08.350 actually returns 0 for any garbage input[br]we get and there's a pretty high chance of 0:05:08.350,0:05:14.320 the input to the function to being garbage[br]if we point to any part inside kernel data 0:05:14.320,0:05:19.940 so the strategy here is that we go into[br]syscall handler address table and we 0:05:19.940,0:05:25.020 overwrite the last byte for one particular[br]syscall handler and we hope that the new 0:05:25.020,0:05:29.590 address actually points to some usable[br]gadget so we hope for the best basically 0:05:29.590,0:05:33.910 and the other important thing to note here[br]is that our user mode code is running from 0:05:33.910,0:05:38.230 what we call the JIT area and what's[br]really stupid is that the JIT area is 0:05:38.230,0:05:44.050 actually executable from kernel mode for[br]some reason so that's nice too. Okay, 0:05:44.050,0:05:49.720 let's look at the relevant structures so[br]this is the kernel and we should read this 0:05:49.720,0:05:56.020 from the bottom to the top. Ok, like in[br]the last line the button we see this entry 0:05:56.020,0:06:03.040 to KeLoaderCall and then we can look at[br]the last byte there it's hex F0. And what 0:06:03.040,0:06:11.080 we will do now is overwrite this last byte[br]with 0 and what happens is that now this 0:06:11.080,0:06:16.000 syscall will actually point to this[br]very usable gadget up there where it loads 0:06:16.000,0:06:20.880 this register r28 into the link register[br]and just branches there the nice thing is 0:06:20.880,0:06:28.120 that we control our 28 from user mode so[br]this gives us a way to just jump anywhere 0:06:28.120,0:06:35.800 basically so how do we exploit this. Well,[br]we have our k-mode function there then we 0:06:35.800,0:06:42.430 just call ioctlv to this shifted address[br]and from this point on we have this nice 0:06:42.430,0:06:46.360 syscall that just comes to anywhere we[br]want and then we call it basically and 0:06:46.360,0:06:53.310 this calls our k-mode function. So, the[br]Wii U starts out with full four hearts and 0:06:53.310,0:06:59.710 this gives us PowerPC kernel mode code[br]execution so we subtract one hard and it's 0:06:59.710,0:07:05.570 quite nice but we can and need to go[br]deeper and for that let's look at the IOSU 0:07:05.570,0:07:12.430 architecture. So IOSU is present as one[br]big ELF file and this includes the kernel 0:07:12.430,0:07:18.110 and all the services and it's running on[br]the Starbuck it, has a hardware way to 0:07:18.110,0:07:24.479 enforce no execute and again no ASLR,[br]making our lives easier and it's a 0:07:24.479,0:07:30.590 microkernel design that has about a 140[br]syscalls so another thing to notice that 0:07:30.590,0:07:35.790 the kernel spawns all these services as[br]user mode processes so before we can 0:07:35.790,0:07:40.139 exploit the kernel we actually have to[br]exploit one of these user mode processes 0:07:40.139,0:07:46.280 which we did but i'm not going to talk[br]about and to look into the kernel, we 0:07:46.280,0:07:51.639 began by reversing all of the syscalls and[br]search for bugs and what we came up with 0:07:51.639,0:07:56.400 is called MQHAX or message queue hax it[br]contains another nice bug class that 0:07:56.400,0:08:05.249 apparently never dies. Integer overflows.[br]And let's look at the code again so 0:08:05.249,0:08:09.610 there's this syscall, it's called create[br]message queue you pass it a buffer and a 0:08:09.610,0:08:14.050 number of buffer entries and what they[br]assumed was that each buffer entry is four 0:08:14.050,0:08:18.410 bytes so when they check the address range[br]to just multiply the number of entries 0:08:18.410,0:08:24.361 with four bytes so does anyone see the[br]integer overflow here and then a nice 0:08:24.361,0:08:28.110 thing is that it just to use the number of[br]entries for the maximum number of entries 0:08:28.110,0:08:33.718 for the message queue and our right[br]primitive again is the send message 0:08:33.718,0:08:40.669 syscall. So, I told you about this[br]hardware NX right? So IOSU should be 0:08:40.669,0:08:47.759 enforcing that no executable memory is[br]writeable and if you look at the kernel 0:08:47.759,0:08:52.180 section flags we actually see that[br]KERNEL_TEXT is read execute and 0:08:52.180,0:08:58.789 KERNEL_DATA is read-write but these[br]permissions are all lies. Ok so our 0:08:58.789,0:09:05.199 exploit strategy: well, let's look at the[br]relevant part of the IOSU kernel so we see 0:09:05.199,0:09:10.230 that KERNEL_TEXT starts at this lower[br]address, at hex 0x08120000 and 0:09:10.230,0:09:15.170 conveniently for us there is a syscall[br]there and the addresses before that are 0:09:15.170,0:09:21.089 all valid so we create a message queue,[br]I'm starting at minus eight bytes and this 0:09:21.089,0:09:27.629 magic hex 0x400- whatever-2 number and[br]from this point on we just push two 0:09:27.629,0:09:32.529 messages and then ARM instruction to[br]branch out three and what this does is it 0:09:32.529,0:09:38.499 actually causes the start of text section[br]to be overwritten with branch R3 and let's 0:09:38.499,0:09:43.619 just look at the integer overflow right[br]four times this value truncated to 4 bytes 0:09:43.619,0:09:48.200 gives 8 bytes so what kind of things is[br]that the message queues is only bytes but 0:09:48.200,0:09:54.509 we can just push any messages we want ok[br]so this gives us IOSU kernel-mode 0:09:54.509,0:09:59.560 execution and the nice thing about this is[br]that we actually have full control over 0:09:59.560,0:10:03.871 the console unit now right so we can dump[br]the console's OTP which contains all the 0:10:03.871,0:10:10.209 keys except for boot1 which we will come[br]back to later because unfortunately the 0:10:10.209,0:10:15.869 pieces for boot1 are locked out as we have[br]already seen. And now we want to make 0:10:15.869,0:10:22.199 everything persistent so how do we do[br]that? We find that title content is only 0:10:22.199,0:10:27.179 verified at title install time but never[br]at boot time because at boot time they 0:10:27.179,0:10:31.790 only verify the title binary so what you[br]can do is you can actually start to mess 0:10:31.790,0:10:39.499 with the metadata of titles and overwrite[br]it and what we did was to overwrite the 0:10:39.499,0:10:44.769 ROM for a DS game, exploited the emulator[br]and got user mode code 0:10:44.769,0:10:50.170 execution again and another thing is that[br]the console contains this config file 0:10:50.170,0:10:55.100 which tells it to boot into which[br]title to boot so what you can do is you 0:10:55.100,0:11:00.869 overwrite the title ID with your modified[br]DS emulator title and the next time you 0:11:00.869,0:11:06.970 start up the console it actually boots[br]into the exploited game and yeah so just 0:11:06.970,0:11:11.060 gives us persistent code execution and[br]cold boot with full control over to 0:11:11.060,0:11:17.570 console whatsoever so[br]game over 0:11:17.570,0:11:26.339 applause 0:11:26.339,0:11:33.959 derrek: So, as we just saw, the kernel[br]it's like pretty broken, right? So, what 0:11:33.959,0:11:41.420 is missing and I just copied this slide from[br]failoverflow's talk as you can see we are 0:11:41.420,0:11:49.309 using the same d14 thing for our slides[br]and basically the boot1 key which is the 0:11:49.309,0:11:57.060 second stage bootloader on Wii U and this[br]key is still unknown and they tried to get 0:11:57.060,0:12:05.129 it somehow with some side-channel attacks[br]thing but I think it never worked 0:12:05.129,0:12:12.889 so it would be nice to get this key and[br]the first thing we did was to make a NAND 0:12:12.889,0:12:22.139 tracer so we can basically sniff all the[br]traffic between NAND and boot1 to see what 0:12:22.139,0:12:33.069 boot1 reads from flash and so we get some[br]nice addresses and we could compare this 0:12:33.069,0:12:40.319 with the file system on the / to see what[br]file it is reading and we also kind of 0:12:40.319,0:12:46.740 mess around with some files on this file[br]system and we found out that boot1 0:12:46.740,0:12:53.360 actually parses a file that is called[br]system.xml and I don't know, it doesn't 0:12:53.360,0:13:03.290 really feel safe to parse an XML file in[br]such a really early boot process I mean 0:13:03.290,0:13:11.860 there's a lot of stuff that could go[br]wrong. So, we tried to attack this and we 0:13:11.860,0:13:18.350 tried some blind exploitation stuff but[br]yeah unfortunately it didn't really work 0:13:18.350,0:13:28.899 so let's try something else. So, there's[br]boot1, which of course boots this.. Sorry 0:13:28.899,0:13:37.290 we've got boot0 and this boots boot1 and[br]failoverflow found out that this boot0 0:13:37.290,0:13:42.629 which is a bootrom of the security[br]processor can be re-enabled again in 0:13:42.629,0:13:49.339 virtual Wii mode and you can just dump it[br]so let's look at boot1... boot0 I'm sorry 0:13:49.339,0:13:59.029 and we can see that it reads boot1 key[br]from OTP and then it locks out boot1 key 0:13:59.029,0:14:05.769 forever and this happens really early but[br]it's basically kept in memory all the time 0:14:05.769,0:14:14.790 until it's done until it has launched[br]boot1 or just panicked. So, this means 0:14:14.790,0:14:22.740 that we have to exploit boot0 to get the[br]boot1 key and unfortunately, boot0 is 0:14:22.740,0:14:30.389 pretty safe it's kind of surprising[br]because this is Wii U and basically this 0:14:30.389,0:14:37.649 gives us this question: How can you[br]exploit something that has no bugs? So, 0:14:37.649,0:14:43.860 the answer is we have to introduce our own[br]bugs - laughter - and we're doing this 0:14:43.860,0:14:50.230 by using fault injection and maybe you[br]have heard of it already it's basically 0:14:50.230,0:14:58.410 you introduce an error into device by a[br]glitching the clock, voltage, the reset 0:14:58.410,0:15:04.790 line you can also do electromagnetic[br]injections. There are many ways. But 0:15:04.790,0:15:12.049 basically what you want to get is a[br]mutated instruction, or instruction skip 0:15:12.049,0:15:18.579 or some corrupted registers and what you[br]don't want is just a stupid lock up where 0:15:18.579,0:15:27.790 it just crashes and yeah that's all really[br]useful so we want to glitch boot0 and to 0:15:27.790,0:15:37.069 do this we have to find a nice target like[br]the weak spot of boot0 so let's take a 0:15:37.069,0:15:44.829 look what boot0 does first thing it does[br]is it copies itself to ram for some 0:15:44.829,0:15:49.129 unknown reason I mean there's no good[br]reason to do this but it's nice for us 0:15:49.129,0:15:58.029 because it copies itself to RAM and just[br]executes from there and then it copies the 0:15:58.029,0:16:04.519 boot1 key to memory it locks out the auto[br]key slot initializes some other stuff and 0:16:04.519,0:16:11.579 flash controller and then it starts[br]reading the boot1 image and it does that 0:16:11.579,0:16:22.559 by just reading its header to this address[br]and then they read the size from the 0:16:22.559,0:16:30.639 header field and they also do some max[br]size check on this and please note that 0:16:30.639,0:16:37.990 the header itself is not encrypted and[br]they also don't do any signature 0:16:37.990,0:16:49.869 verification here at this step so they use[br]the size and reads the whole boot1 image 0:16:49.869,0:16:54.939 using size and then they do a real[br]signature verification to make sure that 0:16:54.939,0:17:00.230 the image is not corrupted it then[br]decrypts the boot1 code using the key from 0:17:00.230,0:17:09.010 RAM and then it clears the key and jumps[br]to boot1entry point ok so what is the weak 0:17:09.010,0:17:14.680 spot here and I mean if you look at this[br]you can pretty much already tell what it 0:17:14.680,0:17:24.940 is and of course it's this size check so[br]what we can do is we can write our own 0:17:24.940,0:17:31.500 modified version of boot1 into flash with[br]some really really large size in the 0:17:31.500,0:17:43.660 header so it reads the header and then[br]it's supposed to do a size check and this 0:17:43.660,0:17:50.830 is exactly where we wanted to glitch it[br]and eventually it will just skip the 0:17:50.830,0:17:57.560 instruction or something else happens and[br]then basically the size check is bypassed 0:17:57.560,0:18:03.300 so when it's reading the boot1 image using[br]this size it will actually overflow the 0:18:03.300,0:18:09.180 buffer and we have some jump instructions[br]at the end so when it returns from the 0:18:09.180,0:18:16.730 flash read function it will eventually[br]jump to our code and this is actually 0:18:16.730,0:18:19.820 boot0 code execution 0:18:19.820,0:18:29.680 applause 0:18:29.680,0:18:35.450 ok so we have boot0 code execution and you[br]know we can just dump the boot1 key from 0:18:35.450,0:18:43.430 RAM and we didn't even need an exploit for[br]this right so it's just boot0 is actually 0:18:43.430,0:18:49.600 pretty safe right but when it comes to[br]pitching it's kind of fragile 0:18:49.600,0:18:58.350 because boot0 code is writeable and also[br]the boot1 image buffer is in front of boot0 0:18:58.350,0:19:04.810 buffer so we can just overflow it and also[br]the setup that I had was also surprisingly 0:19:04.810,0:19:11.600 stable so it works like fifty percent of[br]the entire time so let's finally look at 0:19:11.600,0:19:19.490 boot1 and boot1 is able to understand the[br]Wii U file system it uses real file path 0:19:19.490,0:19:24.670 strings to load the firmware image[br]and of course the first 0:19:24.670,0:19:33.370 thing we did was to look at the xml parser[br]and well unfortunately it seems pretty 0:19:33.370,0:19:44.160 safe and yeah but maybe we found a bug[br]we're not really sure and we haven't 0:19:44.160,0:19:49.750 really tried to exploit it. Interest kind[br]of faded out because you know it's after 0:19:49.750,0:20:00.290 all it's just the Wii U so that's it for[br]Wii U and now I will hand over to nedwill. 0:20:00.290,0:20:03.250 He's talking about 3DS 0:20:03.250,0:20:12.020 applause 0:20:12.020,0:20:17.820 nedwill: Hi, everyone, I'm ned. I started 3DS[br]this year and I'm basically a software 0:20:17.820,0:20:22.860 person so I'm going to be showing some of[br]the homebrew side of 3DS where that's at 0:20:22.860,0:20:29.701 right now so just to reiterate from last[br]year these guys broke userland, kernel and 0:20:29.701,0:20:37.060 the security processor they also broke the[br]secret hardware key scrambler and since 0:20:37.060,0:20:44.130 then Nintendo has been kind of mad about[br]this they released a lot of system updates 0:20:44.130,0:20:50.940 and they started a bug bounty program so[br]there's a lot of bugs getting patched but 0:20:50.940,0:20:56.360 because of the amount of the level of[br]exploitation we got last year it's 0:20:56.360,0:21:01.740 actually really easy to find new bugs and[br]exploits so what I want to emphasize here 0:21:01.740,0:21:05.860 is that even though it's like a[br]cat-and-mouse game because we have so much 0:21:05.860,0:21:13.310 control we can exploit more difficult[br]books on the latest firmware so starting 0:21:13.310,0:21:19.480 with user space. This is where all[br]homebrew comes from so already it's pretty 0:21:19.480,0:21:25.040 good like this has always been a huge[br]focus for the homebrew community because 0:21:25.040,0:21:29.190 it's kind of where you know user space is[br]where you want to be running your own 0:21:29.190,0:21:37.380 custom games you know modifying stuff so[br]we have a bunch of game entry points and a 0:21:37.380,0:21:41.930 bunch of browser exploits but there's a[br]couple limitations to leads and that's 0:21:41.930,0:21:50.800 that game carts cost money and they[br]frequently are.. like the games that are 0:21:50.800,0:21:56.600 exploited are usually somewhat rare and[br]unusual and so the price goes way up as 0:21:56.600,0:22:03.870 demand soars and for the browser every[br]time we release a new browser exploit, 0:22:03.870,0:22:10.280 Nintendo can actually enforce that you're[br]on the latest firmware, because before we 0:22:10.280,0:22:16.490 fetch any web page it will check that the[br]system is on the latest version. So, they 0:22:16.490,0:22:23.731 can kind of remotely cut off web browser[br]exploits. So looking at this I thought it 0:22:23.731,0:22:27.570 might be fun to look at if any of the[br]system titles can be exploitable as 0:22:27.570,0:22:36.960 primary entry points and I found something[br]called SOUNDHAX so just the basic like the 0:22:36.960,0:22:42.370 two probably most obvious things to look[br]at are the image loader because it's got 0:22:42.370,0:22:48.020 JPEG parsing and also the music player.[br]But, when I looked at the music player I 0:22:48.020,0:22:52.330 saw that they're parsing actually a lot of[br]formats and maybe even have their own 0:22:52.330,0:23:00.200 custom playlists format and if they make a[br]single mistake anywhere it's it's over so 0:23:00.200,0:23:03.450 then I was trying to compare with like[br]open source implementations I didn't find 0:23:03.450,0:23:10.610 any overlap. It seemed like everything was[br]custom. So that was pretty promising. So, 0:23:10.610,0:23:14.980 over the course of about a month, I found[br]a bunch of bugs and I was trying to like 0:23:14.980,0:23:20.070 chain together little like logical bugs[br]and it wasn't really working and then I 0:23:20.070,0:23:25.860 just found one that was really critical.[br]So, I'm going to demonstrate that here. 0:23:25.860,0:23:29.240 So, actually studied mp3 for the whole[br]month MPEG was like the 0:23:29.240,0:23:36.260 last day so I looked at it and they[br]actually malloc 256 byte buffer for the 0:23:36.260,0:23:43.000 song name and then when they go to load it[br]if they see a unicode BOM marker they just 0:23:43.000,0:23:49.750 memcpy the thing and that tag size is[br]totally controlled so you know that's 0:23:49.750,0:23:56.060 that's it so this is like it was pretty[br]great but it's a few pics place that's a 0:23:56.060,0:24:01.910 little tricky but this is what it looks[br]like so we have our name chunk that we're 0:24:01.910,0:24:08.900 about to overflow and then like I'm a CTF[br]player, so I put A's there and then the 0:24:08.900,0:24:15.210 next thing that happens is this gets freed[br]and so this victim chunk that we have 0:24:15.210,0:24:21.720 overridden it's actually the way the 3DS[br]heap works they actually track they have a 0:24:21.720,0:24:25.880 linked list of what things are currently[br]allocated so this gives us the classical 0:24:25.880,0:24:32.611 heap unlink arbitrary write and so at this[br]point we have a 4-byte write and we want 0:24:32.611,0:24:40.120 to get ROP out of it so we'll probably do[br]a stack pivot so I looked at the binary 0:24:40.120,0:24:47.230 and there's only one pivot gadget and then[br]i looked at the the thumb pivots, there 0:24:47.230,0:24:51.410 are actually a lot but because this CPU[br]was too old didn't support the wide 0:24:51.410,0:24:58.710 instructions where all the pivots come up[br]so unfortunately that one pivot 0:24:58.710,0:25:07.750 instruction has some arithmetic conditions[br]on it specifically it was that in order to 0:25:07.750,0:25:12.170 you know load all your registers from[br]memory the condition flags had to satisfy 0:25:12.170,0:25:18.800 less than and everywhere where we return[br]from the function it had just checked that 0:25:18.800,0:25:23.240 like if this pointer is not null free it[br]and so the comparisons wouldn't ever be 0:25:23.240,0:25:29.980 satisfied because nothing is mapped up in[br]the negative area so of course CTF 0:25:29.980,0:25:38.230 workarounds. We can still do this so I[br]overwrite the heap freelist head with the 0:25:38.230,0:25:43.420 stack address and so on the next malloc we[br]just return that stack address and read 0:25:43.420,0:25:50.820 into it so there's a couple of constraints[br]on this and the first one is really normal 0:25:50.820,0:25:56.151 like this is every pivot to stack heap[br]thing you have to make sure that you have 0:25:56.151,0:26:01.670 a heap chunk on the stack and luckily this[br]is actually pretty easy because all you 0:26:01.670,0:26:07.450 need is a size followed by two null[br]pointers representing next and previous so 0:26:07.450,0:26:11.640 when malloc goes to look there it seems[br]like the size is big enough and then 0:26:11.640,0:26:18.610 nothing else is in the queue so just[br]return this and then this worked so we 0:26:18.610,0:26:24.080 memcpy the next tag to the stack and like[br]we just specify that size and malloc some 0:26:24.080,0:26:31.320 unintelligible for us and then from[br]there we're done because we can just do a 0:26:31.320,0:26:35.430 little little ROP chain, we memcpy the[br]shellcode to the heap and then use an 0:26:35.430,0:26:41.900 existing exploit gspwn which has been[br]around for a long time to override the 0:26:41.900,0:26:52.410 text section and jump there so there's the[br]first heart so you can't really talk about 0:26:52.410,0:26:58.430 homebrew without also talking about kernel[br]because we want to get access to more 0:26:58.430,0:27:03.060 syscalls like the 3DS actually sandboxes a[br]lot of the syscalls away from you and so 0:27:03.060,0:27:09.170 as an attacker, your goal is to call some[br]syscalls that are restricted a really nice 0:27:09.170,0:27:14.060 example would be you want to map some[br]executable memory for like a JIT emulator 0:27:14.060,0:27:20.590 so it's kind of a tricky situation because[br]you're inside the sandbox you want to 0:27:20.590,0:27:26.380 break out you have to find bugs in like[br]pretty restricted syscalls so I looked at 0:27:26.380,0:27:32.240 last year's talk here and like what had[br]been done so far and it seemed like there 0:27:32.240,0:27:36.740 are a lot of attacks on that memory[br]mapping but I didn't see much about the 0:27:36.740,0:27:42.750 sync primitives or anything related to use[br]after free and i had just got a pretty bad 0:27:42.750,0:27:46.640 grade on my OS project because i had a lot[br]of those so I knew this is a good place to 0:27:46.640,0:27:56.090 look so I noticed the design flaw when I[br]was reversing the ref counting so it's not 0:27:56.090,0:28:00.920 so much that they couldn't possibly get[br]this right but generally when you're 0:28:00.920,0:28:05.740 designing an API you want to make it[br]really hard to abuse and this is just not 0:28:05.740,0:28:10.800 really true for how they do ref counting[br]so I'll go ahead and bring these up yeah 0:28:10.800,0:28:18.910 so basically they whenever the user[br]fetches a kernel object to perform some 0:28:18.910,0:28:23.310 operation on it meaning you call this[br]syscall that does something using the 0:28:23.310,0:28:30.150 current object it does the correct inc ref[br]and then dec ref for you but I was looking 0:28:30.150,0:28:33.059 at it and thinking well like a lot of[br]times the kernel actually is using these 0:28:33.059,0:28:38.090 objects internally to do stuff so I mean[br]I spelled it but like I mean I was like a 0:28:38.090,0:28:42.380 week I found like 3 use after frees and[br]they're all following the same pattern. 0:28:42.380,0:28:47.640 The kernel's using an object internally[br]without maintaining the reference count 0:28:47.640,0:28:53.510 correctly and then some people ask me like[br]advice on kernel hacking maybe like at 0:28:53.510,0:28:58.630 home I definitely recommend looking here[br]I'm sure that there's plenty more so the 0:28:58.630,0:29:06.360 one going to talk about today is the the[br]timer object so this is a pretty simple 0:29:06.360,0:29:11.950 API with the kernel you can have it create[br]a timer for you you can set the timer you 0:29:11.950,0:29:18.300 can wait on it it's like a normal[br]synchronization primitive so like I said I 0:29:18.300,0:29:21.020 was looking for these use after frees[br]I saw this I thought it's kind of 0:29:21.020,0:29:27.470 interesting that this one called pulse is[br]here because what's happening with this 0:29:27.470,0:29:35.390 one is when you set the timer to pulse[br]like every period it's signaling 0:29:35.390,0:29:38.660 everything that's waiting on it and then[br]it like resets itself and then if you wait 0:29:38.660,0:29:42.559 on it the next period comes around you get[br]a signal again and so was thinking like 0:29:42.559,0:29:47.990 it's definitely doing some stuff with this[br]object internally that's like a bit more 0:29:47.990,0:29:53.890 complicated than some of the other modes[br]and the other kernel objects so i looked 0:29:53.890,0:29:59.810 at how they did the pulse like you know[br]every every second whatever, when it 0:29:59.810,0:30:06.610 pulses like what's actually getting[br]executed and if you look here they do some 0:30:06.610,0:30:11.370 pretty good locking and then they signal[br]and then what happens here is basically 0:30:11.370,0:30:16.299 when they signal they go through and[br]everyone that was waiting gets rescheduled 0:30:16.299,0:30:22.420 - made runnable - and then at the end they[br]reset the timer state and just say like 0:30:22.420,0:30:28.470 okay everyone that waits on this again has[br]to wait for the next cycle so and then 0:30:28.470,0:30:32.790 this also looks pretty good like they[br]they're locking the scheduler here this 0:30:32.790,0:30:38.670 would work but nothing is preventing you[br]from just closing this from another call 0:30:38.670,0:30:46.809 so I have FASTHAX which is just 3 syscalls[br]and that's it. That's the entire exploit 0:30:46.809,0:30:51.440 there's a lot of setup which we will get[br]to but you just create the timer set it to 0:30:51.440,0:30:57.760 run really fast and then close the handle[br]and then if it was pulsing and you closed 0:30:57.760,0:31:03.950 it it will use after free so what's nice[br]about this is if you lose the race it's 0:31:03.950,0:31:09.510 just the timer is just on schedule you're[br]fine and then it actually happens quite 0:31:09.510,0:31:14.340 often and I didn't even really[br]specifically try to win this to like I 0:31:14.340,0:31:18.740 just.. Once it was within a second I don't[br]worry about those parameters are probably 0:31:18.740,0:31:28.610 not optimal so we should look at how do we[br]exploit this basically this is a little 0:31:28.610,0:31:32.450 bit of a more complicated view of it. I'll[br]show a diagram in a second but this is 0:31:32.450,0:31:37.559 like where the use after free actually[br]happens so like r7 is pointing to my timer 0:31:37.559,0:31:42.760 object and then it was freed before we[br]reach this chunk here and then it's 0:31:42.760,0:31:48.510 loading r7 to r0, loading something from[br]that and then branching to it so that's 0:31:48.510,0:31:54.730 like calling a use after free object. So,[br]this is pretty exploitable on the 3DS 0:31:54.730,0:32:03.970 kernel because they use a slab heap to deal[br]with allocating objects so this is the 0:32:03.970,0:32:09.050 normal situation when that first timer is[br]allocated the vtable is pointing to the 0:32:09.050,0:32:12.930 you know the real KTimer vtable and then[br]it wants to call that timer reset 0:32:12.930,0:32:21.460 function. It's totally fine but when we[br]free it actually, that vtable pointer goes 0:32:21.460,0:32:25.320 to the next free timer object in the[br]kernel so it's actually interpreting that 0:32:25.320,0:32:31.730 struct as a vtable and what's nice is it[br]actually overlaps with the initial timer 0:32:31.730,0:32:38.970 value that we totally control and so it[br]looks like okay we can just set the 0:32:38.970,0:32:44.590 initial timer value you know do this use[br]after free, we're just calling user space 0:32:44.590,0:32:52.580 that's what I thought and then realized it[br]wasn't that easy so because the race like 0:32:52.580,0:32:56.820 it because I was actually calling this is[br]in a kernel thread we actually can't 0:32:56.820,0:33:01.420 guarantee that our user process is[br]actually mapped in memory and in fact it's 0:33:01.420,0:33:07.380 on a different core so even if you open a[br]process in the other core like ran a 0:33:07.380,0:33:12.980 thread there you can't get more than[br]twenty-five percent of the time I think so 0:33:12.980,0:33:17.840 that's just super unstable also because[br]it's a kernel thread we don't necessarily 0:33:17.840,0:33:21.900 want to crash it and we don't like crashes[br]in general but this will just totally 0:33:21.900,0:33:27.760 break everything if the timer like sync[br]thread dies so as long as we return to a 0:33:27.760,0:33:33.860 function do something cleanly, return it[br]will be fine so it sounds like okay all we 0:33:33.860,0:33:38.290 have to do is find some kernel function we[br]can call and we're done but there's 0:33:38.290,0:33:44.070 actually another issue and that's that[br]kernel code is mapped at high addresses 0:33:44.070,0:33:49.370 and these are actually negative and that[br]the set timer syscall actually checks if 0:33:49.370,0:33:57.250 your timer is negative so there's a pretty[br]funny trick I found and that's that when 0:33:57.250,0:34:00.510 you set the timer you're saying like you[br]know start I like one second from now 0:34:00.510,0:34:06.730 start pulsing obviously it's adding like[br]the current time to the one second to know 0:34:06.730,0:34:11.730 like when do i trigger this timer so so[br]SetTimer is the one that does that add for 0:34:11.730,0:34:18.359 you they don't check for overflow when[br]installing it and timer schedule values 0:34:18.359,0:34:26.210 are signed which is also a bit weird so we[br]can overflow and schedule into the past so 0:34:26.210,0:34:32.739 how this looks is that's my like[br]disgusting set up call so what's happening 0:34:32.739,0:34:38.789 is like in the middle that's the start of[br]the 3DS boot and then that range on the 0:34:38.789,0:34:46.129 right is what the 3DS will allow you to[br]pass for your values for the initial and 0:34:46.129,0:34:54.329 like pulse period time and so what I do is[br]I just put it right there at the end and 0:34:54.329,0:35:00.230 then it overflows and then on the next[br]pulse I also control that and that's also 0:35:00.230,0:35:05.509 less than that range so then we can get it[br]to line up on the kernel address we want 0:35:05.509,0:35:13.130 and so that's pretty good. Unfortunately,[br]we're at the end like at this point is 0:35:13.130,0:35:19.309 pretty solid but there isn't like an[br]obvious single thing we can call and it 0:35:19.309,0:35:22.269 seems like maybe you could race a bunch of[br]times and call a bunch of different things 0:35:22.269,0:35:26.359 in the kernel and like you know that's a[br]decent amount of control but because of 0:35:26.359,0:35:32.739 all this weird negative scheduling stuff[br]it's actually pretty hard to do multiple 0:35:32.739,0:35:37.150 calls so I was trying to look for one[br]thing that I can call that will give me 0:35:37.150,0:35:47.049 control and this is where it gets really[br]tricky so if we look at how the memory 0:35:47.049,0:35:54.489 mapping on 3DS works in userspace you can[br]access the FCRAM which is that first range 0:35:54.489,0:36:00.599 up there that's just where you know your[br]heap goes there and then the kernel also 0:36:00.599,0:36:09.039 has a view of this heap it's you know a[br]shared mapping so if we can write one of 0:36:09.039,0:36:13.190 those something in that range into the[br]free pointer and allocate it, it actually 0:36:13.190,0:36:20.160 ends up in something we can see as the[br]user so then I noticed this.. This is 0:36:20.160,0:36:30.099 actually a common instruction prefix in[br]ARM so I jumped here and at this point 0:36:30.099,0:36:35.559 like we just did in C++, a vtable call on[br]the use after free thing with one argument 0:36:35.559,0:36:41.009 so this means that r0 contains the address[br]of the object and r1 contains the address 0:36:41.009,0:36:49.519 of where we just jumped to so that uh like[br]B65C [0xFFF1B65C] is where r1 is pointing 0:36:49.519,0:36:53.290 so this is actually like some random[br]linked lists lookup function but it's 0:36:53.290,0:36:57.829 actually looking down to the add[br]instruction and loading it to r1 and then 0:36:57.829,0:37:05.720 we write that to the object and so at this[br]point it looks like this it's pointing to 0:37:05.720,0:37:11.190 something in user space and then we just[br]alloc two times we can look in user space 0:37:11.190,0:37:16.579 so they put the object there you control[br]the vtable and from there it's pretty much 0:37:16.579,0:37:25.970 standard straightforward thing. So, there[br]we go unintelligible userspace in kernel 0:37:25.970,0:37:31.210 and this is almost game over one more time 0:37:31.210,0:37:39.450 applause 0:37:39.450,0:37:42.000 derrek: So we've broken several parts of 0:37:42.000,0:37:48.920 the 3DS firmware including 3DS kernel and[br]all software that's running on the 0:37:48.920,0:37:55.390 security processor what we haven't looked[br]at yet are the 3DS bootroms and I'm 0:37:55.390,0:38:04.470 basically there's one bootrom for each[br]processor for the ARM 11 and for the ARM 9 0:38:04.470,0:38:10.869 and I think there's probably, there are[br]more bootroms in 3DS system-on-a-chip used 0:38:10.869,0:38:18.220 to for old Nintendo DS mode but we will[br]focus on the 3DS bootroms here and what we 0:38:18.220,0:38:27.670 know is 3DS is somehow loading the[br]firmware image from NAND flash and we also 0:38:27.670,0:38:34.640 know that the ARM9 bootrom does all the[br]interesting stuff because only the ARM9 0:38:34.640,0:38:43.549 has access to the whole crypto hardware[br]like the AES engine, RSA engine we also 0:38:43.549,0:38:53.279 know that the bootrom will initialize the[br]secret keys for the AES key slots and yes 0:38:53.279,0:39:00.769 we would like to get those keys but um[br]unfortunately the bootrom is disabled, it 0:39:00.769,0:39:08.789 disables itself before its launching of[br]the firmware and 3DS bootroms also print 0:39:08.789,0:39:16.330 nice error screens like when the NAND is[br]corrupted or something, it shows an error 0:39:16.330,0:39:23.580 screen so let's look how the bootroms are[br]protected in detail and basically there 0:39:23.580,0:39:30.730 are two registers that we call[br]CFG_SYSPROT9 and CFG_SYSPROT11 and the 0:39:30.730,0:39:37.089 bootrom writes to those registers and of[br]course they are one shot you cannot 0:39:37.089,0:39:44.490 re-enable bootroms again because this is[br]not the Wii U and basically when it's 0:39:44.490,0:39:53.029 disables the bootrom it only disables one[br]half of it so what you get are two parts 0:39:53.029,0:40:01.190 of bootrom there's the unprotected part[br]and protected part you can just dump the 0:40:01.190,0:40:07.739 unprotected part by taking over ARM9 from[br]firmware but you can never see the 0:40:07.739,0:40:14.030 protected part and they were really clever[br]and basically they put all the interesting 0:40:14.030,0:40:20.249 code in the protected part and if you look[br]at the reset vector it just jumps directly 0:40:20.249,0:40:25.680 to protected part of the boot room so as[br]you can't really figure out what is going 0:40:25.680,0:40:32.499 on when the 3DS is starting up but what[br]you can do is you can look at the code 0:40:32.499,0:40:40.989 from the unprotected bootrom and who knows[br]maybe we can find a bug so let's do this. 0:40:40.989,0:40:47.190 First of all of course there are no keys[br]in in the unprotected bootrom, they put 0:40:47.190,0:40:53.989 all the keys in the protected part it's[br]also mainly it's a lot of driver code. 0:40:53.989,0:41:00.059 Talks to some hardware like NAND flash,[br]MMC, AES engine and also to SPI flash 0:41:00.059,0:41:07.539 which is kind of interesting because the[br]SPI flash is some really tiny chip that is 0:41:07.539,0:41:14.509 soldered on the Wi-Fi socket and it's[br]actually used for some Wi-Fi settings and 0:41:14.509,0:41:21.430 other user settings us by old Nintendo DS[br]mode and yeah that's kind of interesting 0:41:21.430,0:41:28.170 uses the SPI flash and it also includes[br]the ARM exception vector table and this is 0:41:28.170,0:41:32.769 actually just design that they have[br]adopted from previous generations of the 0:41:32.769,0:41:41.299 Nintendo DS such as the DSi if you don't[br]know ARM basically, you have something 0:41:41.299,0:41:48.089 that is called an exception vector table[br]and this is located at this hardcoded 0:41:48.089,0:41:55.769 address in bootrom and basically every[br]time when something weird happens or 0:41:55.769,0:42:03.249 something special on the CPU it will jump[br]to those exception vectors like the reset 0:42:03.249,0:42:09.000 vector as we just so or when you're trying[br]to read from an invalid address, it 0:42:09.000,0:42:16.160 returns to the prefetch abort or data[br]abort vector and also when you receive an 0:42:16.160,0:42:25.160 interrupt it will jump to interrupt[br]request vector so those are the exception 0:42:25.160,0:42:29.580 vectors and they're hardcoded in the[br]bootrom and there's kind of a problem with 0:42:29.580,0:42:37.700 that because as a developer you don't want[br]to put the exception in the routines in 0:42:37.700,0:42:45.480 the boot rom, you want to it'd be able to[br]change the code right? So, what they do is 0:42:45.480,0:42:53.839 they just redirect all the exception[br]execution flow from bootrom to another 0:42:53.839,0:43:01.699 jumptable that is located in ARM9 memory[br]so it looks like this. What you can see 0:43:01.699,0:43:06.539 here are the bootrom vectors and it's[br]basically just a jump instruction to the 0:43:06.539,0:43:12.239 RAM vectors and the RAM vectors are also[br]just another jump instruction to the 0:43:12.239,0:43:16.980 actual firmware handler and this is so[br]things look like when the firmware is 0:43:16.980,0:43:26.200 running but what about cold boot well on[br]cold boot you get this and this looks 0:43:26.200,0:43:33.339 kinda interesting because you have the[br]bootrom vectors that still point to ARM9 0:43:33.339,0:43:39.930 memory but since this is cold boot, the[br]RAM is not initialized so this is 0:43:39.930,0:43:45.050 interesting but it is it's not really a[br]bug because at some point the bootrom will 0:43:45.050,0:43:53.700 initialize those RAM vectors so but let's[br]cheat a little bit here and say let's just 0:43:53.700,0:43:59.130 assume we could somehow trigger a really[br]early exception even before the bootrom is 0:43:59.130,0:44:08.729 able to initialize the RAM vectors well[br]probably it was just crash because on 0:44:08.729,0:44:13.519 exception it will just jump to[br]uninitialized memory and there's probably 0:44:13.519,0:44:22.190 no valid instruction there so this is not[br]very useful but there's a really nice 0:44:22.190,0:44:27.960 hardware flaw and we found this by just[br]writing to some memory reboot, and see 0:44:27.960,0:44:35.010 what what happened basically we found out[br]that some RAM is actually not cleared on 0:44:35.010,0:44:42.410 reboot and this also includes ARM9 so the[br]basic idea is we can set up some custom 0:44:42.410,0:44:49.650 exception vectors in RAM that regenerate[br]execution flow to some dumper code so when 0:44:49.650,0:44:55.579 we reboot we get this and this is really[br]interesting because if you look at this 0:44:55.579,0:45:01.469 this means all we need to do now is[br]trigger a really early exception and then 0:45:01.469,0:45:10.039 the bootrom will jump to our dumper code[br]so, how can we trigger an exception? Well 0:45:10.039,0:45:14.489 if you look at here, the exception vector[br]table again there are some exceptions that 0:45:14.489,0:45:20.261 we can trigger like because they are[br]hardcoded like reset and they won't jump 0:45:20.261,0:45:29.200 to ARM9 memory and you also can't use the[br]interrupt vector because interrupts are 0:45:29.200,0:45:39.190 disabled on reset and yeah this won't work[br]so what's left is these 3 here interesting 0:45:39.190,0:45:45.150 exceptions and if you look at those and[br]they normally don't happen right undefined 0:45:45.150,0:45:50.970 instruction is pretty rare and it[br]shouldn't happen so I don't know about 0:45:50.970,0:45:57.839 this reminds me kind of like it's a really[br]nice use case for doing for injection 0:45:57.839,0:46:04.759 again because you can corrupt registers[br]and getting mutated instruction so it's 0:46:04.759,0:46:10.950 really likely that it will trigger an[br]exception so this is the vector glitch 0:46:10.950,0:46:17.200 hack and basically we set up some vectors[br]in RAM, trigger reboot then do some 0:46:17.200,0:46:24.930 glitching magic and then we reset again[br]and let it boot up normally and hopefully 0:46:24.930,0:46:32.170 our dumper code got executed and just[br]wrote a copy of the bootrom in memory so 0:46:32.170,0:46:38.299 we can just dump it. All this stuff is not[br]very stable but it works for me. 0:46:38.299,0:46:48.549 applause 0:46:48.549,0:46:57.990 Wo okay we got the bootrom and Nintendo is[br]losing a life there so before we look at 0:46:57.990,0:47:08.889 the bootrom I have a little problem for[br]you and basically in early 2014 an FCC 0:47:08.889,0:47:15.629 document became public. There it is, and[br]basically it says that Nintendo has changed 0:47:15.629,0:47:21.400 the CPU of the Nintendo 2DS and there's[br]one really interesting sentence that 0:47:21.400,0:47:26.819 basically says, they have changed security[br]function of the initial program loader 0:47:26.819,0:47:33.300 that is installed in each model so the[br]initial program loader is probably bootrom 0:47:33.300,0:47:42.180 so obviously there must be some really[br]huge bug in the bootrom, right? So so 0:47:42.180,0:47:48.680 that's it let's look at the bootrom.[br]Basically there are some boot methods and 0:47:48.680,0:47:52.721 you can boot from NAND, that's what it[br]normally does but alternatively you can 0:47:52.721,0:48:00.839 also boot from SPI flash which is the[br]Wi-Fi flash and it will only boot firmware 0:48:00.839,0:48:08.050 images that are signed and encrypted[br]there's no freaky development backdoor 0:48:08.050,0:48:15.420 that we can exploit it also uses two[br]different sets of keys for NAND and non 0:48:15.420,0:48:21.390 NAND boot methods and also for our retail[br]and dev mode so even when stuff gets 0:48:21.390,0:48:28.150 leaked you cannot use it on your retail[br]console so let's do a small boot walk 0:48:28.150,0:48:34.469 through and it's pretty straightforward[br]actually so the first thing it does is it 0:48:34.469,0:48:41.869 selects a boot device then it loads the[br]firmware header and RSA signature from it 0:48:41.869,0:48:50.959 it's just one block and then it hashes the[br]header and extract the hash from the 0:48:50.959,0:48:58.170 signature and compares it, so basically a[br]basic signature verification header 0:48:58.170,0:49:04.859 verification and then assumes yeah the[br]header is safe and then it starts loading 0:49:04.859,0:49:12.789 the firmware sections and the firmware[br]images are pretty simple format and like 0:49:12.789,0:49:19.930 you have some entries in the header that[br]tells you okay take the data from this 0:49:19.930,0:49:26.849 offset and there there's a section with[br]the size load it to that address. It's 0:49:26.849,0:49:32.729 pretty simple so we know from Nintendos[br]past that they like to mess up RSA 0:49:32.729,0:49:42.220 signature checks so let's look as how RSA[br]is done on 3DS so for the 3DS firmware 0:49:42.220,0:49:51.630 they're using RSA signatures in the PKCS[br]standard PKCS is basically a bunch of 0:49:51.630,0:49:57.500 standards that tell you how your[br]signatures have to look like and they are 0:49:57.500,0:50:11.269 using the 2048-bit version of RSA which is[br]safe and in the signature you have a SHA-2 0:50:11.269,0:50:19.870 hash and this is encoded using ASN.1 and[br]ASN.1 it's some really complex structure 0:50:19.870,0:50:26.009 it's basically it's similar to the mp3[br]structure so you have little chunks of 0:50:26.009,0:50:31.490 data and those chunks have little headers[br]and the headers have tag bytes and length 0:50:31.490,0:50:40.900 bytes and basically this ASN.1 stuff is[br]used to tell the parser which hashing 0:50:40.900,0:50:51.311 algorithm is used and well since the SHA-2[br]hash is only 20 hex [0x20] bytes in size 0:50:51.311,0:50:57.050 you have some remaining space in the[br]signature that you have to fill and PKCS 0:50:57.050,0:51:01.959 says you need a padding and this padding[br]should be deterministic it should only[br] 0:51:01.959,0:51:07.950 contain FF bytes so when you're trying to[br]forge signatures it's it's really 0:51:07.950,0:51:14.489 difficult because of this padding that[br]really long and when you compare the[br] 0:51:14.489,0:51:22.019 signatures of different firmware images[br]you'll actually notice that only the hash 0:51:22.019,0:51:28.269 will change and the rest of the data is[br]always the same for all signatures but 0:51:28.269,0:51:34.729 well for some reason they decided to write[br]a signature parser for this stuff so what 0:51:34.729,0:51:45.860 you get now is RSA the Nintendo way again[br]so the first thing it does is it tries to 0:51:45.860,0:51:53.129 parse the padding and this part is totally[br]messed up like there is a flag byte that 0:51:53.129,0:51:59.129 tells you if the padding should be checked[br]and if it's one then it is checked it 0:51:59.129,0:52:06.910 should be all FF but but if it's two then[br]it will just skip the padding and it also 0:52:06.910,0:52:12.809 has some really weak bounds checking it[br]make sure that it will not when it's 0:52:12.809,0:52:18.859 passing the padding it make sure that it[br]will not go out of bounds but they forget 0:52:18.859,0:52:28.489 to verify that the hash will actually fit[br]in there as well so next thing they do is 0:52:28.489,0:52:35.000 parsing this really complicated ASN.1[br]structure and this process is also really 0:52:35.000,0:52:42.770 simplified so we know ASN.1 has some[br]length fields and there's no bounds 0:52:42.770,0:52:52.800 checking so eventually it will add the[br]length to the current pointer in the 0:52:52.800,0:53:02.300 signature and then they stop parsing and[br]say okay we parsed all the data and now 0:53:02.300,0:53:08.950 there should be the hash and yet they are[br]not checking this length and this pointer 0:53:08.950,0:53:18.430 is used to do the hash comparison so all[br]in all you can say it only checks a few 0:53:18.430,0:53:23.410 bytes in the signature because the padding[br]parser is messed up and also the ASN.1 0:53:23.410,0:53:29.249 parser is really simplified so what we can[br]do is we can bruteforce the perfect 0:53:29.249,0:53:36.909 signature where the final pointer when[br]it's done parsing the padding and the 0:53:36.909,0:53:45.779 ASN.1 data that this final pointer matches[br]the pointer of the calculated hash of 0:53:45.779,0:53:57.359 bootrom so what it does then this it does[br]a mem compare [memory compare] with the 0:53:57.359,0:54:05.481 calculated hash and the calculated hash[br]like and this never fails, right? So it 0:54:05.481,0:54:10.009 will always succeed and this is SIGHAX.[br] 0:54:10.009,0:54:18.210 applause 0:54:18.210,0:54:24.450 So the SIGHAX is a bootrom exploit for 3DS[br]and basically we can sign our own 0:54:24.450,0:54:31.279 firmwares and there are over 60 million[br]vulnerable devices and basically in new 0:54:31.279,0:54:37.259 3DS and 2DS basically all models are[br]affected and of course since this is the 0:54:37.259,0:54:45.709 bootrom, Nintendo can't fix it so that's[br]very nice but that's one heart remaining 0:54:45.709,0:54:54.960 so something is missing what we haven't[br]done yet is we haven't dumped the ARM11 0:54:54.960,0:55:00.019 bootrom. It's probably not really[br]interesting but for sake of completeness 0:55:00.019,0:55:07.759 you would like to get it and in theory we[br]can just do a vector glitch hack again 0:55:07.759,0:55:13.369 because it has the same flaw but know that[br]we can sign our own firmwares let's try 0:55:13.369,0:55:21.450 something else so if you look at the[br]unprotected part of the ARM11 bootrom you 0:55:21.450,0:55:29.059 can see there are a lot of references to[br]ARM11 memory so maybe now that we can sign 0:55:29.059,0:55:33.880 our own firmwares and we can set up our[br]own firmware sections maybe we can 0:55:33.880,0:55:41.979 overwrite some bootrom data so but they're[br]the bootrom developers were kind of clever 0:55:41.979,0:55:49.059 and the ARM9 bootrom checks the firmware[br]sections and they have some kind of 0:55:49.059,0:55:58.359 blacklist and unfortunately you can't just[br]overwrite boot9 data sections sections but 0:55:58.359,0:56:03.709 for some reason they forgot to blacklist[br]all the boot11 data regions so we can just 0:56:03.709,0:56:11.770 overwrite boot11 stack or the exception[br]vectors and well you can dump the ARM11 0:56:11.770,0:56:12.990 bootrom. 0:56:12.990,0:56:21.989 applause 0:56:21.989,0:56:29.520 yeah that was pretty easy and now I get to[br]tell you something, all this stuff about 0:56:29.520,0:56:38.829 the bootrom we did this in summer 2015 so[br]we could have talked about this already 0:56:38.829,0:56:45.880 last year but since we are kind of[br]friendly hackers we held this bug so long 0:56:45.880,0:56:56.660 so yeah Nintendo should be thankful and ok[br]so that's it 3DS is pretty game over and 0:56:56.660,0:57:02.209 here's a picture of Nintendo Switch and[br]our body is ready laughter 0:57:02.209,0:57:16.429 applause 0:57:16.429,0:57:21.499 Herald: Thank you very much there's about[br]five minutes left for questions and are 0:57:21.499,0:57:26.749 there any questions from the internet?[br]No no no okay? 0:57:26.749,0:57:32.069 Signal Angel: Yes there's actually one[br]question from the internet and that is the 0:57:32.069,0:57:41.519 internet wants to know if we can get DSP[br]code execution maybe sometime soon 0:57:41.519,0:57:43.000 Herald: Can you repeat the question? 0:57:43.000,0:57:44.780 yeah very hard to understand here 0:57:44.780,0:57:51.049 Signal Angel: Ok I'm the internet wants to[br]know if we can get a DSP code execution? 0:57:51.049,0:58:02.259 derrek: Yes well the DSP of the 3DS runs[br]its own firmware and that is included in 0:58:02.259,0:58:10.440 some kernel module and basically when you[br]can sign your own firmware you can also 0:58:10.440,0:58:21.519 make it load another DSP firmware[br]so yes you can do this 0:58:21.519,0:58:25.369 Herald: Ok people who are leaving please[br]do so quietly and people entering please 0:58:25.369,0:58:35.369 do so quietly. There was a question on[br]microphone 3 I think but no longer okay. 0:58:35.369,0:58:38.260 Does the internet have more questions? 0:58:38.260,0:58:44.009 Signal Angel: Yes it does. The internet[br]wants to know if you or how you glitch the 0:58:44.009,0:58:48.599 Wii U to get execution 0:58:48.599,0:58:56.729 derrek: Well I don't want to worry how I[br]did it in detail but there are some basic 0:58:56.729,0:59:04.660 fault injection attacks and my setup was[br]I think kind of complicated you had to 0:59:04.660,0:59:11.490 modify a lot of stuff on the Wii U[br]mainboard to get it to work so I guess you 0:59:11.490,0:59:17.260 have to figure out yourself, sorry. 0:59:17.260,0:59:21.109 Herald: Ok there's a question[br]upstairs microphone five I think? 0:59:21.109,0:59:29.920 Mic 7: Seven but it's okay. Yeah well you[br]said that you broke all the 2DS but 0:59:29.920,0:59:36.880 actually you showed that the 2DS changed[br]in the boot process so did you verify that 0:59:36.880,0:59:40.500 that work for the first version as well 0:59:40.500,0:59:47.160 derrek: Yes so the new 3DS was released[br]after the 2DS and the new 3DS is also 0:59:47.160,0:59:54.900 vulnerable and basically all the Nintendo[br]2DS consoles are also also vulnerable as 0:59:54.900,1:00:01.140 well. Yes we did verify this and we don't[br]really know what this FCC document is 1:00:01.140,1:00:12.019 about we got some really new 2DS from[br]store and and basically yes, no difference 1:00:12.019,1:00:16.179 for the bootrom at all,[br]so yes everything is vulnerable. 1:00:16.179,1:00:18.169 Mic 7: Nice to know, thanks. 1:00:18.169,1:00:23.470 derrek: ok[br]applause 1:00:23.470,1:00:25.650 Herald: Final question from microphone 3? 1:00:25.650,1:00:29.390 Mic 3: Yeah just a fun question out of[br]interest when you're going to buy such a 1:00:29.390,1:00:33.880 device do you also plan to play games on[br]it? Or is it just going to check if the 1:00:33.880,1:00:38.730 other kernel works? 1:00:38.730,1:00:42.549 naehrwert: Personally for the[br]Wii U, I own 0 games so 1:00:42.549,1:00:44.199 Mic 3: Great, thanks. 1:00:44.199,1:00:49.519 applause 1:00:49.519,1:00:55.979 I also didn't pirate any so i never[br]played a game on my Wii U. 1:00:55.979,1:01:01.521 33c3 postroll music 1:01:01.521,1:01:20.000 subtitles created by c3subtitles.de[br]in the year 2017. Join, and help us!