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!