-
33C3 preroll music
-
Herald: Good evening, everyone. In a few
minutes, the Nintendo Hacking 2016 talk
-
will start. This talk will will be
translated into German, and there are
-
English subtitles available. Anyway,
without much further ado. These are
-
derrek, naehrwert and nedwill. They are
three students that have been working on
-
hacking Nintendo platforms for a while
now, and please give them a warm applause.
-
applause
-
naehrwert: Hi guys. So, welcome to our
talk about Nintendo Hacking 2016. Let me
-
quickly introduce the other guys. This is
derek, and that's ned, and I think I can
-
speak for the three of us to say that I am
really happy that you guys are here today
-
and we are happy that we can be here today
to tell you everything about what we did
-
in the past one and a half years. I will
start with the state of the Wii U. I hope
-
a lot of you guys have seen failOverflow's
talk in 2013 about hacking the Wii U. Not
-
much happened afterwards, until 2015 there
is a public webkit exploit released and
-
this time we started looking into the Wii
U. And, we wanted more access, right? Than
-
just user mode and because there is also
the kernel running on a PowerPC and then
-
there is this other ARM processor that
runs IOSU. Also user mode and kernel mode.
-
I am not going to consider the user mode
today. Because I think there are currently
-
exploits that are way more fun. So, let's
start with PowerPC kernel very quick. It
-
has all standard basic security measures,
though it doesn't have any ASLR which
-
makes our lives easier. It has about 140
syscalls. And we don't really.. We can't
-
really name them from start, right? Kinda
need to reverse them. But there's a nice
-
thing. So, the Wii U uses this RPL
mechanism for dynamic libraries. And
-
there's this really nice library. It's
called coreinit.rpl and it contains a lot
-
of syscalls, shims and symbol names. So we
can name all syscalls straight away
-
without much hassle and, it is important
to know that all the syscalls use the safe
-
copy in/copy out mechanism to get data
from the user space into the kernel space.
-
So we start reversing each syscall and we
start looking for bugs And what we came
-
out with, at first, this is what we call
I/O controlled VHAX Or, why indirections
-
are hard. It's actually a bug in the
IPCKDriver_SubmitRequest syscall so what
-
this syscall is used for is: you want to
submit requests from user mode to this
-
other processor running which I'm going to
talk about later. And, so you submit this
-
kind of request structures and the kernel
uses copy in to fetch the request
-
structure from user mode into kernel mode
but there's a certain type of request
-
structure which contains an indirection
like a second layer, right? And, well,
-
they just ignore that for the second level
and hope for the best. So, let's look at
-
the relevant part. I'm really sorry I'm
showing you this code here, but it's not
-
much more than that. So, there is
something that is called ios packet in the
-
second line which is kind of this request
that we submit from user mode into kernel
-
mode And in the top line there's this
special request entry, so it contains a
-
physical address, a buffer size and a
virtual address. And what we do from user
-
mode is we submit it filled out with the
virtual address and the size. and the
-
kernel does this convenient thing for us.
It kind of.. changes the virtual address
-
to the physical address. So we can see, it
copies in these packets from user mode
-
into kernel mode using the safe mechanism
and then it goes through all the entries
-
and fixes up the physical addresses for us
but we can see in this line that it
-
doesn't use to the safe mechanism at all
it doesn't care about whatever address we
-
put in there so this gives us some kind of
right primitive to wherever we want
-
basically and this looks hard to exploit,
right? Because the right kind of going
-
through this conversation but we actually
only need one byte to exploit the kernel
-
and we do this by noting that this
KIEffectiveToPhysical conversion function
-
actually returns 0 for any garbage input
we get and there's a pretty high chance of
-
the input to the function to being garbage
if we point to any part inside kernel data
-
so the strategy here is that we go into
syscall handler address table and we
-
overwrite the last byte for one particular
syscall handler and we hope that the new
-
address actually points to some usable
gadget so we hope for the best basically
-
and the other important thing to note here
is that our user mode code is running from
-
what we call the JIT area and what's
really stupid is that the JIT area is
-
actually executable from kernel mode for
some reason so that's nice too. Okay,
-
let's look at the relevant structures so
this is the kernel and we should read this
-
from the bottom to the top. Ok, like in
the last line the button we see this entry
-
to KeLoaderCall and then we can look at
the last byte there it's hex F0. And what
-
we will do now is overwrite this last byte
with 0 and what happens is that now this
-
syscall will actually point to this
very usable gadget up there where it loads
-
this register r28 into the link register
and just branches there the nice thing is
-
that we control our 28 from user mode so
this gives us a way to just jump anywhere
-
basically so how do we exploit this. Well,
we have our k-mode function there then we
-
just call ioctlv to this shifted address
and from this point on we have this nice
-
syscall that just comes to anywhere we
want and then we call it basically and
-
this calls our k-mode function. So, the
Wii U starts out with full four hearts and
-
this gives us PowerPC kernel mode code
execution so we subtract one hard and it's
-
quite nice but we can and need to go
deeper and for that let's look at the IOSU
-
architecture. So IOSU is present as one
big ELF file and this includes the kernel
-
and all the services and it's running on
the Starbuck it, has a hardware way to
-
enforce no execute and again no ASLR,
making our lives easier and it's a
-
microkernel design that has about a 140
syscalls so another thing to notice that
-
the kernel spawns all these services as
user mode processes so before we can
-
exploit the kernel we actually have to
exploit one of these user mode processes
-
which we did but i'm not going to talk
about and to look into the kernel, we
-
began by reversing all of the syscalls and
search for bugs and what we came up with
-
is called MQHAX or message queue hax it
contains another nice bug class that
-
apparently never dies. Integer overflows.
And let's look at the code again so
-
there's this syscall, it's called create
message queue you pass it a buffer and a
-
number of buffer entries and what they
assumed was that each buffer entry is four
-
bytes so when they check the address range
to just multiply the number of entries
-
with four bytes so does anyone see the
integer overflow here and then a nice
-
thing is that it just to use the number of
entries for the maximum number of entries
-
for the message queue and our right
primitive again is the send message
-
syscall. So, I told you about this
hardware NX right? So IOSU should be
-
enforcing that no executable memory is
writeable and if you look at the kernel
-
section flags we actually see that
KERNEL_TEXT is read execute and
-
KERNEL_DATA is read-write but these
permissions are all lies. Ok so our
-
exploit strategy: well, let's look at the
relevant part of the IOSU kernel so we see
-
that KERNEL_TEXT starts at this lower
address, at hex 0x08120000 and
-
conveniently for us there is a syscall
there and the addresses before that are
-
all valid so we create a message queue,
I'm starting at minus eight bytes and this
-
magic hex 0x400- whatever-2 number and
from this point on we just push two
-
messages and then ARM instruction to
branch out three and what this does is it
-
actually causes the start of text section
to be overwritten with branch R3 and let's
-
just look at the integer overflow right
four times this value truncated to 4 bytes
-
gives 8 bytes so what kind of things is
that the message queues is only bytes but
-
we can just push any messages we want ok
so this gives us IOSU kernel-mode
-
execution and the nice thing about this is
that we actually have full control over
-
the console unit now right so we can dump
the console's OTP which contains all the
-
keys except for boot1 which we will come
back to later because unfortunately the
-
pieces for boot1 are locked out as we have
already seen. And now we want to make
-
everything persistent so how do we do
that? We find that title content is only
-
verified at title install time but never
at boot time because at boot time they
-
only verify the title binary so what you
can do is you can actually start to mess
-
with the metadata of titles and overwrite
it and what we did was to overwrite the
-
ROM for a DS game, exploited the emulator
and got user mode code
-
execution again and another thing is that
the console contains this config file
-
which tells it to boot into which
title to boot so what you can do is you
-
overwrite the title ID with your modified
DS emulator title and the next time you
-
start up the console it actually boots
into the exploited game and yeah so just
-
gives us persistent code execution and
cold boot with full control over to
-
console whatsoever so
game over
-
applause
-
derrek: So, as we just saw, the kernel
it's like pretty broken, right? So, what
-
is missing and I just copied this slide from
failoverflow's talk as you can see we are
-
using the same d14 thing for our slides
and basically the boot1 key which is the
-
second stage bootloader on Wii U and this
key is still unknown and they tried to get
-
it somehow with some side-channel attacks
thing but I think it never worked
-
so it would be nice to get this key and
the first thing we did was to make a NAND
-
tracer so we can basically sniff all the
traffic between NAND and boot1 to see what
-
boot1 reads from flash and so we get some
nice addresses and we could compare this
-
with the file system on the / to see what
file it is reading and we also kind of
-
mess around with some files on this file
system and we found out that boot1
-
actually parses a file that is called
system.xml and I don't know, it doesn't
-
really feel safe to parse an XML file in
such a really early boot process I mean
-
there's a lot of stuff that could go
wrong. So, we tried to attack this and we
-
tried some blind exploitation stuff but
yeah unfortunately it didn't really work
-
so let's try something else. So, there's
boot1, which of course boots this.. Sorry
-
we've got boot0 and this boots boot1 and
failoverflow found out that this boot0
-
which is a bootrom of the security
processor can be re-enabled again in
-
virtual Wii mode and you can just dump it
so let's look at boot1... boot0 I'm sorry
-
and we can see that it reads boot1 key
from OTP and then it locks out boot1 key
-
forever and this happens really early but
it's basically kept in memory all the time
-
until it's done until it has launched
boot1 or just panicked. So, this means
-
that we have to exploit boot0 to get the
boot1 key and unfortunately, boot0 is
-
pretty safe it's kind of surprising
because this is Wii U and basically this
-
gives us this question: How can you
exploit something that has no bugs? So,
-
the answer is we have to introduce our own
bugs - laughter - and we're doing this
-
by using fault injection and maybe you
have heard of it already it's basically
-
you introduce an error into device by a
glitching the clock, voltage, the reset
-
line you can also do electromagnetic
injections. There are many ways. But
-
basically what you want to get is a
mutated instruction, or instruction skip
-
or some corrupted registers and what you
don't want is just a stupid lock up where
-
it just crashes and yeah that's all really
useful so we want to glitch boot0 and to
-
do this we have to find a nice target like
the weak spot of boot0 so let's take a
-
look what boot0 does first thing it does
is it copies itself to ram for some
-
unknown reason I mean there's no good
reason to do this but it's nice for us
-
because it copies itself to RAM and just
executes from there and then it copies the
-
boot1 key to memory it locks out the auto
key slot initializes some other stuff and
-
flash controller and then it starts
reading the boot1 image and it does that
-
by just reading its header to this address
and then they read the size from the
-
header field and they also do some max
size check on this and please note that
-
the header itself is not encrypted and
they also don't do any signature
-
verification here at this step so they use
the size and reads the whole boot1 image
-
using size and then they do a real
signature verification to make sure that
-
the image is not corrupted it then
decrypts the boot1 code using the key from
-
RAM and then it clears the key and jumps
to boot1entry point ok so what is the weak
-
spot here and I mean if you look at this
you can pretty much already tell what it
-
is and of course it's this size check so
what we can do is we can write our own
-
modified version of boot1 into flash with
some really really large size in the
-
header so it reads the header and then
it's supposed to do a size check and this
-
is exactly where we wanted to glitch it
and eventually it will just skip the
-
instruction or something else happens and
then basically the size check is bypassed
-
so when it's reading the boot1 image using
this size it will actually overflow the
-
buffer and we have some jump instructions
at the end so when it returns from the
-
flash read function it will eventually
jump to our code and this is actually
-
boot0 code execution
-
applause
-
ok so we have boot0 code execution and you
know we can just dump the boot1 key from
-
RAM and we didn't even need an exploit for
this right so it's just boot0 is actually
-
pretty safe right but when it comes to
pitching it's kind of fragile
-
because boot0 code is writeable and also
the boot1 image buffer is in front of boot0
-
buffer so we can just overflow it and also
the setup that I had was also surprisingly
-
stable so it works like fifty percent of
the entire time so let's finally look at
-
boot1 and boot1 is able to understand the
Wii U file system it uses real file path
-
strings to load the firmware image
and of course the first
-
thing we did was to look at the xml parser
and well unfortunately it seems pretty
-
safe and yeah but maybe we found a bug
we're not really sure and we haven't
-
really tried to exploit it. Interest kind
of faded out because you know it's after
-
all it's just the Wii U so that's it for
Wii U and now I will hand over to nedwill.
-
He's talking about 3DS
-
applause
-
nedwill: Hi, everyone, I'm ned. I started 3DS
this year and I'm basically a software
-
person so I'm going to be showing some of
the homebrew side of 3DS where that's at
-
right now so just to reiterate from last
year these guys broke userland, kernel and
-
the security processor they also broke the
secret hardware key scrambler and since
-
then Nintendo has been kind of mad about
this they released a lot of system updates
-
and they started a bug bounty program so
there's a lot of bugs getting patched but
-
because of the amount of the level of
exploitation we got last year it's
-
actually really easy to find new bugs and
exploits so what I want to emphasize here
-
is that even though it's like a
cat-and-mouse game because we have so much
-
control we can exploit more difficult
books on the latest firmware so starting
-
with user space. This is where all
homebrew comes from so already it's pretty
-
good like this has always been a huge
focus for the homebrew community because
-
it's kind of where you know user space is
where you want to be running your own
-
custom games you know modifying stuff so
we have a bunch of game entry points and a
-
bunch of browser exploits but there's a
couple limitations to leads and that's
-
that game carts cost money and they
frequently are.. like the games that are
-
exploited are usually somewhat rare and
unusual and so the price goes way up as
-
demand soars and for the browser every
time we release a new browser exploit,
-
Nintendo can actually enforce that you're
on the latest firmware, because before we
-
fetch any web page it will check that the
system is on the latest version. So, they
-
can kind of remotely cut off web browser
exploits. So looking at this I thought it
-
might be fun to look at if any of the
system titles can be exploitable as
-
primary entry points and I found something
called SOUNDHAX so just the basic like the
-
two probably most obvious things to look
at are the image loader because it's got
-
JPEG parsing and also the music player.
But, when I looked at the music player I
-
saw that they're parsing actually a lot of
formats and maybe even have their own
-
custom playlists format and if they make a
single mistake anywhere it's it's over so
-
then I was trying to compare with like
open source implementations I didn't find
-
any overlap. It seemed like everything was
custom. So that was pretty promising. So,
-
over the course of about a month, I found
a bunch of bugs and I was trying to like
-
chain together little like logical bugs
and it wasn't really working and then I
-
just found one that was really critical.
So, I'm going to demonstrate that here.
-
So, actually studied mp3 for the whole
month MPEG was like the
-
last day so I looked at it and they
actually malloc 256 byte buffer for the
-
song name and then when they go to load it
if they see a unicode BOM marker they just
-
memcpy the thing and that tag size is
totally controlled so you know that's
-
that's it so this is like it was pretty
great but it's a few pics place that's a
-
little tricky but this is what it looks
like so we have our name chunk that we're
-
about to overflow and then like I'm a CTF
player, so I put A's there and then the
-
next thing that happens is this gets freed
and so this victim chunk that we have
-
overridden it's actually the way the 3DS
heap works they actually track they have a
-
linked list of what things are currently
allocated so this gives us the classical
-
heap unlink arbitrary write and so at this
point we have a 4-byte write and we want
-
to get ROP out of it so we'll probably do
a stack pivot so I looked at the binary
-
and there's only one pivot gadget and then
i looked at the the thumb pivots, there
-
are actually a lot but because this CPU
was too old didn't support the wide
-
instructions where all the pivots come up
so unfortunately that one pivot
-
instruction has some arithmetic conditions
on it specifically it was that in order to
-
you know load all your registers from
memory the condition flags had to satisfy
-
less than and everywhere where we return
from the function it had just checked that
-
like if this pointer is not null free it
and so the comparisons wouldn't ever be
-
satisfied because nothing is mapped up in
the negative area so of course CTF
-
workarounds. We can still do this so I
overwrite the heap freelist head with the
-
stack address and so on the next malloc we
just return that stack address and read
-
into it so there's a couple of constraints
on this and the first one is really normal
-
like this is every pivot to stack heap
thing you have to make sure that you have
-
a heap chunk on the stack and luckily this
is actually pretty easy because all you
-
need is a size followed by two null
pointers representing next and previous so
-
when malloc goes to look there it seems
like the size is big enough and then
-
nothing else is in the queue so just
return this and then this worked so we
-
memcpy the next tag to the stack and like
we just specify that size and malloc some
-
unintelligible for us and then from
there we're done because we can just do a
-
little little ROP chain, we memcpy the
shellcode to the heap and then use an
-
existing exploit gspwn which has been
around for a long time to override the
-
text section and jump there so there's the
first heart so you can't really talk about
-
homebrew without also talking about kernel
because we want to get access to more
-
syscalls like the 3DS actually sandboxes a
lot of the syscalls away from you and so
-
as an attacker, your goal is to call some
syscalls that are restricted a really nice
-
example would be you want to map some
executable memory for like a JIT emulator
-
so it's kind of a tricky situation because
you're inside the sandbox you want to
-
break out you have to find bugs in like
pretty restricted syscalls so I looked at
-
last year's talk here and like what had
been done so far and it seemed like there
-
are a lot of attacks on that memory
mapping but I didn't see much about the
-
sync primitives or anything related to use
after free and i had just got a pretty bad
-
grade on my OS project because i had a lot
of those so I knew this is a good place to
-
look so I noticed the design flaw when I
was reversing the ref counting so it's not
-
so much that they couldn't possibly get
this right but generally when you're
-
designing an API you want to make it
really hard to abuse and this is just not
-
really true for how they do ref counting
so I'll go ahead and bring these up yeah
-
so basically they whenever the user
fetches a kernel object to perform some
-
operation on it meaning you call this
syscall that does something using the
-
current object it does the correct inc ref
and then dec ref for you but I was looking
-
at it and thinking well like a lot of
times the kernel actually is using these
-
objects internally to do stuff so I mean
I spelled it but like I mean I was like a
-
week I found like 3 use after frees and
they're all following the same pattern.
-
The kernel's using an object internally
without maintaining the reference count
-
correctly and then some people ask me like
advice on kernel hacking maybe like at
-
home I definitely recommend looking here
I'm sure that there's plenty more so the
-
one going to talk about today is the the
timer object so this is a pretty simple
-
API with the kernel you can have it create
a timer for you you can set the timer you
-
can wait on it it's like a normal
synchronization primitive so like I said I
-
was looking for these use after frees
I saw this I thought it's kind of
-
interesting that this one called pulse is
here because what's happening with this
-
one is when you set the timer to pulse
like every period it's signaling
-
everything that's waiting on it and then
it like resets itself and then if you wait
-
on it the next period comes around you get
a signal again and so was thinking like
-
it's definitely doing some stuff with this
object internally that's like a bit more
-
complicated than some of the other modes
and the other kernel objects so i looked
-
at how they did the pulse like you know
every every second whatever, when it
-
pulses like what's actually getting
executed and if you look here they do some
-
pretty good locking and then they signal
and then what happens here is basically
-
when they signal they go through and
everyone that was waiting gets rescheduled
-
- made runnable - and then at the end they
reset the timer state and just say like
-
okay everyone that waits on this again has
to wait for the next cycle so and then
-
this also looks pretty good like they
they're locking the scheduler here this
-
would work but nothing is preventing you
from just closing this from another call
-
so I have FASTHAX which is just 3 syscalls
and that's it. That's the entire exploit
-
there's a lot of setup which we will get
to but you just create the timer set it to
-
run really fast and then close the handle
and then if it was pulsing and you closed
-
it it will use after free so what's nice
about this is if you lose the race it's
-
just the timer is just on schedule you're
fine and then it actually happens quite
-
often and I didn't even really
specifically try to win this to like I
-
just.. Once it was within a second I don't
worry about those parameters are probably
-
not optimal so we should look at how do we
exploit this basically this is a little
-
bit of a more complicated view of it. I'll
show a diagram in a second but this is
-
like where the use after free actually
happens so like r7 is pointing to my timer
-
object and then it was freed before we
reach this chunk here and then it's
-
loading r7 to r0, loading something from
that and then branching to it so that's
-
like calling a use after free object. So,
this is pretty exploitable on the 3DS
-
kernel because they use a slab heap to deal
with allocating objects so this is the
-
normal situation when that first timer is
allocated the vtable is pointing to the
-
you know the real KTimer vtable and then
it wants to call that timer reset
-
function. It's totally fine but when we
free it actually, that vtable pointer goes
-
to the next free timer object in the
kernel so it's actually interpreting that
-
struct as a vtable and what's nice is it
actually overlaps with the initial timer
-
value that we totally control and so it
looks like okay we can just set the
-
initial timer value you know do this use
after free, we're just calling user space
-
that's what I thought and then realized it
wasn't that easy so because the race like
-
it because I was actually calling this is
in a kernel thread we actually can't
-
guarantee that our user process is
actually mapped in memory and in fact it's
-
on a different core so even if you open a
process in the other core like ran a
-
thread there you can't get more than
twenty-five percent of the time I think so
-
that's just super unstable also because
it's a kernel thread we don't necessarily
-
want to crash it and we don't like crashes
in general but this will just totally
-
break everything if the timer like sync
thread dies so as long as we return to a
-
function do something cleanly, return it
will be fine so it sounds like okay all we
-
have to do is find some kernel function we
can call and we're done but there's
-
actually another issue and that's that
kernel code is mapped at high addresses
-
and these are actually negative and that
the set timer syscall actually checks if
-
your timer is negative so there's a pretty
funny trick I found and that's that when
-
you set the timer you're saying like you
know start I like one second from now
-
start pulsing obviously it's adding like
the current time to the one second to know
-
like when do i trigger this timer so so
SetTimer is the one that does that add for
-
you they don't check for overflow when
installing it and timer schedule values
-
are signed which is also a bit weird so we
can overflow and schedule into the past so
-
how this looks is that's my like
disgusting set up call so what's happening
-
is like in the middle that's the start of
the 3DS boot and then that range on the
-
right is what the 3DS will allow you to
pass for your values for the initial and
-
like pulse period time and so what I do is
I just put it right there at the end and
-
then it overflows and then on the next
pulse I also control that and that's also
-
less than that range so then we can get it
to line up on the kernel address we want
-
and so that's pretty good. Unfortunately,
we're at the end like at this point is
-
pretty solid but there isn't like an
obvious single thing we can call and it
-
seems like maybe you could race a bunch of
times and call a bunch of different things
-
in the kernel and like you know that's a
decent amount of control but because of
-
all this weird negative scheduling stuff
it's actually pretty hard to do multiple
-
calls so I was trying to look for one
thing that I can call that will give me
-
control and this is where it gets really
tricky so if we look at how the memory
-
mapping on 3DS works in userspace you can
access the FCRAM which is that first range
-
up there that's just where you know your
heap goes there and then the kernel also
-
has a view of this heap it's you know a
shared mapping so if we can write one of
-
those something in that range into the
free pointer and allocate it, it actually
-
ends up in something we can see as the
user so then I noticed this.. This is
-
actually a common instruction prefix in
ARM so I jumped here and at this point
-
like we just did in C++, a vtable call on
the use after free thing with one argument
-
so this means that r0 contains the address
of the object and r1 contains the address
-
of where we just jumped to so that uh like
B65C [0xFFF1B65C] is where r1 is pointing
-
so this is actually like some random
linked lists lookup function but it's
-
actually looking down to the add
instruction and loading it to r1 and then
-
we write that to the object and so at this
point it looks like this it's pointing to
-
something in user space and then we just
alloc two times we can look in user space
-
so they put the object there you control
the vtable and from there it's pretty much
-
standard straightforward thing. So, there
we go unintelligible userspace in kernel
-
and this is almost game over one more time
-
applause
-
derrek: So we've broken several parts of
-
the 3DS firmware including 3DS kernel and
all software that's running on the
-
security processor what we haven't looked
at yet are the 3DS bootroms and I'm
-
basically there's one bootrom for each
processor for the ARM 11 and for the ARM 9
-
and I think there's probably, there are
more bootroms in 3DS system-on-a-chip used
-
to for old Nintendo DS mode but we will
focus on the 3DS bootroms here and what we
-
know is 3DS is somehow loading the
firmware image from NAND flash and we also
-
know that the ARM9 bootrom does all the
interesting stuff because only the ARM9
-
has access to the whole crypto hardware
like the AES engine, RSA engine we also
-
know that the bootrom will initialize the
secret keys for the AES key slots and yes
-
we would like to get those keys but um
unfortunately the bootrom is disabled, it
-
disables itself before its launching of
the firmware and 3DS bootroms also print
-
nice error screens like when the NAND is
corrupted or something, it shows an error
-
screen so let's look how the bootroms are
protected in detail and basically there
-
are two registers that we call
CFG_SYSPROT9 and CFG_SYSPROT11 and the
-
bootrom writes to those registers and of
course they are one shot you cannot
-
re-enable bootroms again because this is
not the Wii U and basically when it's
-
disables the bootrom it only disables one
half of it so what you get are two parts
-
of bootrom there's the unprotected part
and protected part you can just dump the
-
unprotected part by taking over ARM9 from
firmware but you can never see the
-
protected part and they were really clever
and basically they put all the interesting
-
code in the protected part and if you look
at the reset vector it just jumps directly
-
to protected part of the boot room so as
you can't really figure out what is going
-
on when the 3DS is starting up but what
you can do is you can look at the code
-
from the unprotected bootrom and who knows
maybe we can find a bug so let's do this.
-
First of all of course there are no keys
in in the unprotected bootrom, they put
-
all the keys in the protected part it's
also mainly it's a lot of driver code.
-
Talks to some hardware like NAND flash,
MMC, AES engine and also to SPI flash
-
which is kind of interesting because the
SPI flash is some really tiny chip that is
-
soldered on the Wi-Fi socket and it's
actually used for some Wi-Fi settings and
-
other user settings us by old Nintendo DS
mode and yeah that's kind of interesting
-
uses the SPI flash and it also includes
the ARM exception vector table and this is
-
actually just design that they have
adopted from previous generations of the
-
Nintendo DS such as the DSi if you don't
know ARM basically, you have something
-
that is called an exception vector table
and this is located at this hardcoded
-
address in bootrom and basically every
time when something weird happens or
-
something special on the CPU it will jump
to those exception vectors like the reset
-
vector as we just so or when you're trying
to read from an invalid address, it
-
returns to the prefetch abort or data
abort vector and also when you receive an
-
interrupt it will jump to interrupt
request vector so those are the exception
-
vectors and they're hardcoded in the
bootrom and there's kind of a problem with
-
that because as a developer you don't want
to put the exception in the routines in
-
the boot rom, you want to it'd be able to
change the code right? So, what they do is
-
they just redirect all the exception
execution flow from bootrom to another
-
jumptable that is located in ARM9 memory
so it looks like this. What you can see
-
here are the bootrom vectors and it's
basically just a jump instruction to the
-
RAM vectors and the RAM vectors are also
just another jump instruction to the
-
actual firmware handler and this is so
things look like when the firmware is
-
running but what about cold boot well on
cold boot you get this and this looks
-
kinda interesting because you have the
bootrom vectors that still point to ARM9
-
memory but since this is cold boot, the
RAM is not initialized so this is
-
interesting but it is it's not really a
bug because at some point the bootrom will
-
initialize those RAM vectors so but let's
cheat a little bit here and say let's just
-
assume we could somehow trigger a really
early exception even before the bootrom is
-
able to initialize the RAM vectors well
probably it was just crash because on
-
exception it will just jump to
uninitialized memory and there's probably
-
no valid instruction there so this is not
very useful but there's a really nice
-
hardware flaw and we found this by just
writing to some memory reboot, and see
-
what what happened basically we found out
that some RAM is actually not cleared on
-
reboot and this also includes ARM9 so the
basic idea is we can set up some custom
-
exception vectors in RAM that regenerate
execution flow to some dumper code so when
-
we reboot we get this and this is really
interesting because if you look at this
-
this means all we need to do now is
trigger a really early exception and then
-
the bootrom will jump to our dumper code
so, how can we trigger an exception? Well
-
if you look at here, the exception vector
table again there are some exceptions that
-
we can trigger like because they are
hardcoded like reset and they won't jump
-
to ARM9 memory and you also can't use the
interrupt vector because interrupts are
-
disabled on reset and yeah this won't work
so what's left is these 3 here interesting
-
exceptions and if you look at those and
they normally don't happen right undefined
-
instruction is pretty rare and it
shouldn't happen so I don't know about
-
this reminds me kind of like it's a really
nice use case for doing for injection
-
again because you can corrupt registers
and getting mutated instruction so it's
-
really likely that it will trigger an
exception so this is the vector glitch
-
hack and basically we set up some vectors
in RAM, trigger reboot then do some
-
glitching magic and then we reset again
and let it boot up normally and hopefully
-
our dumper code got executed and just
wrote a copy of the bootrom in memory so
-
we can just dump it. All this stuff is not
very stable but it works for me.
-
applause
-
Wo okay we got the bootrom and Nintendo is
losing a life there so before we look at
-
the bootrom I have a little problem for
you and basically in early 2014 an FCC
-
document became public. There it is, and
basically it says that Nintendo has changed
-
the CPU of the Nintendo 2DS and there's
one really interesting sentence that
-
basically says, they have changed security
function of the initial program loader
-
that is installed in each model so the
initial program loader is probably bootrom
-
so obviously there must be some really
huge bug in the bootrom, right? So so
-
that's it let's look at the bootrom.
Basically there are some boot methods and
-
you can boot from NAND, that's what it
normally does but alternatively you can
-
also boot from SPI flash which is the
Wi-Fi flash and it will only boot firmware
-
images that are signed and encrypted
there's no freaky development backdoor
-
that we can exploit it also uses two
different sets of keys for NAND and non
-
NAND boot methods and also for our retail
and dev mode so even when stuff gets
-
leaked you cannot use it on your retail
console so let's do a small boot walk
-
through and it's pretty straightforward
actually so the first thing it does is it
-
selects a boot device then it loads the
firmware header and RSA signature from it
-
it's just one block and then it hashes the
header and extract the hash from the
-
signature and compares it, so basically a
basic signature verification header
-
verification and then assumes yeah the
header is safe and then it starts loading
-
the firmware sections and the firmware
images are pretty simple format and like
-
you have some entries in the header that
tells you okay take the data from this
-
offset and there there's a section with
the size load it to that address. It's
-
pretty simple so we know from Nintendos
past that they like to mess up RSA
-
signature checks so let's look as how RSA
is done on 3DS so for the 3DS firmware
-
they're using RSA signatures in the PKCS
standard PKCS is basically a bunch of
-
standards that tell you how your
signatures have to look like and they are
-
using the 2048-bit version of RSA which is
safe and in the signature you have a SHA-2
-
hash and this is encoded using ASN.1 and
ASN.1 it's some really complex structure
-
it's basically it's similar to the mp3
structure so you have little chunks of
-
data and those chunks have little headers
and the headers have tag bytes and length
-
bytes and basically this ASN.1 stuff is
used to tell the parser which hashing
-
algorithm is used and well since the SHA-2
hash is only 20 hex [0x20] bytes in size
-
you have some remaining space in the
signature that you have to fill and PKCS
-
says you need a padding and this padding
should be deterministic it should only
-
contain FF bytes so when you're trying to
forge signatures it's it's really
-
difficult because of this padding that
really long and when you compare the
-
signatures of different firmware images
you'll actually notice that only the hash
-
will change and the rest of the data is
always the same for all signatures but
-
well for some reason they decided to write
a signature parser for this stuff so what
-
you get now is RSA the Nintendo way again
so the first thing it does is it tries to
-
parse the padding and this part is totally
messed up like there is a flag byte that
-
tells you if the padding should be checked
and if it's one then it is checked it
-
should be all FF but but if it's two then
it will just skip the padding and it also
-
has some really weak bounds checking it
make sure that it will not when it's
-
passing the padding it make sure that it
will not go out of bounds but they forget
-
to verify that the hash will actually fit
in there as well so next thing they do is
-
parsing this really complicated ASN.1
structure and this process is also really
-
simplified so we know ASN.1 has some
length fields and there's no bounds
-
checking so eventually it will add the
length to the current pointer in the
-
signature and then they stop parsing and
say okay we parsed all the data and now
-
there should be the hash and yet they are
not checking this length and this pointer
-
is used to do the hash comparison so all
in all you can say it only checks a few
-
bytes in the signature because the padding
parser is messed up and also the ASN.1
-
parser is really simplified so what we can
do is we can bruteforce the perfect
-
signature where the final pointer when
it's done parsing the padding and the
-
ASN.1 data that this final pointer matches
the pointer of the calculated hash of
-
bootrom so what it does then this it does
a mem compare [memory compare] with the
-
calculated hash and the calculated hash
like and this never fails, right? So it
-
will always succeed and this is SIGHAX.
-
applause
-
So the SIGHAX is a bootrom exploit for 3DS
and basically we can sign our own
-
firmwares and there are over 60 million
vulnerable devices and basically in new
-
3DS and 2DS basically all models are
affected and of course since this is the
-
bootrom, Nintendo can't fix it so that's
very nice but that's one heart remaining
-
so something is missing what we haven't
done yet is we haven't dumped the ARM11
-
bootrom. It's probably not really
interesting but for sake of completeness
-
you would like to get it and in theory we
can just do a vector glitch hack again
-
because it has the same flaw but know that
we can sign our own firmwares let's try
-
something else so if you look at the
unprotected part of the ARM11 bootrom you
-
can see there are a lot of references to
ARM11 memory so maybe now that we can sign
-
our own firmwares and we can set up our
own firmware sections maybe we can
-
overwrite some bootrom data so but they're
the bootrom developers were kind of clever
-
and the ARM9 bootrom checks the firmware
sections and they have some kind of
-
blacklist and unfortunately you can't just
overwrite boot9 data sections sections but
-
for some reason they forgot to blacklist
all the boot11 data regions so we can just
-
overwrite boot11 stack or the exception
vectors and well you can dump the ARM11
-
bootrom.
-
applause
-
yeah that was pretty easy and now I get to
tell you something, all this stuff about
-
the bootrom we did this in summer 2015 so
we could have talked about this already
-
last year but since we are kind of
friendly hackers we held this bug so long
-
so yeah Nintendo should be thankful and ok
so that's it 3DS is pretty game over and
-
here's a picture of Nintendo Switch and
our body is ready laughter
-
applause
-
Herald: Thank you very much there's about
five minutes left for questions and are
-
there any questions from the internet?
No no no okay?
-
Signal Angel: Yes there's actually one
question from the internet and that is the
-
internet wants to know if we can get DSP
code execution maybe sometime soon
-
Herald: Can you repeat the question?
-
yeah very hard to understand here
-
Signal Angel: Ok I'm the internet wants to
know if we can get a DSP code execution?
-
derrek: Yes well the DSP of the 3DS runs
its own firmware and that is included in
-
some kernel module and basically when you
can sign your own firmware you can also
-
make it load another DSP firmware
so yes you can do this
-
Herald: Ok people who are leaving please
do so quietly and people entering please
-
do so quietly. There was a question on
microphone 3 I think but no longer okay.
-
Does the internet have more questions?
-
Signal Angel: Yes it does. The internet
wants to know if you or how you glitch the
-
Wii U to get execution
-
derrek: Well I don't want to worry how I
did it in detail but there are some basic
-
fault injection attacks and my setup was
I think kind of complicated you had to
-
modify a lot of stuff on the Wii U
mainboard to get it to work so I guess you
-
have to figure out yourself, sorry.
-
Herald: Ok there's a question
upstairs microphone five I think?
-
Mic 7: Seven but it's okay. Yeah well you
said that you broke all the 2DS but
-
actually you showed that the 2DS changed
in the boot process so did you verify that
-
that work for the first version as well
-
derrek: Yes so the new 3DS was released
after the 2DS and the new 3DS is also
-
vulnerable and basically all the Nintendo
2DS consoles are also also vulnerable as
-
well. Yes we did verify this and we don't
really know what this FCC document is
-
about we got some really new 2DS from
store and and basically yes, no difference
-
for the bootrom at all,
so yes everything is vulnerable.
-
Mic 7: Nice to know, thanks.
-
derrek: ok
applause
-
Herald: Final question from microphone 3?
-
Mic 3: Yeah just a fun question out of
interest when you're going to buy such a
-
device do you also plan to play games on
it? Or is it just going to check if the
-
other kernel works?
-
naehrwert: Personally for the
Wii U, I own 0 games so
-
Mic 3: Great, thanks.
-
applause
-
I also didn't pirate any so i never
played a game on my Wii U.
-
33c3 postroll music
-
subtitles created by c3subtitles.de
in the year 2017. Join, and help us!
Bar Sch
Dear Subtitle Creators: Please use the Styleguide and the Howtos of c3subtitles:
https://wiki.c3subtitles.de/en:postprocessing:contribute
https://wiki.c3subtitles.de/en:styleguide
Please correct it according to the stylguide.
Bar Sch
Please use https://c3subtitles.de/talk/645/ to work on this talk.