-
32C3 preroll music
-
Herald: Okay, welcome to our
last talk in this hall today!
-
It’s about Console Hacking and I guess
that’s the reason why you are here.
-
Console hacking has a long
tradition at our great conference
-
and we have seen lots of funny things.
People doing stuff with Xboxes,
-
Playstations and everything.
-
Okay. Today we got a team which
deals with the Nintendo DS,
-
so give a warm applause
for plutoo, derrek and smea!
-
applause
-
smea: Hi! I’m smea,
this is plutoo, this is derrek,
-
and today we are going to talk to you
about our work on the Nintendo 3DS.
-
So, the way this talk is going to be
structured, is we are just going to
-
go over all the hardware,
organisation, software, like…
-
Just give you a basic overview
about how the system works.
-
And after that we are going to go into
-
basically every layer of
security the system has,
-
and break every one of them.
-
laughter
-
applause
-
Okay. So, as you probably know,
the 3DS, the original Nintendo 3DS
-
was released in 2011. It’s a system
that is kind of underpowered.
-
It’s got, like… It’s got an
ARM11 dual core CPU,
-
268Mhz, it’s got a nice
proprietary GPU, a bit of RAM,
-
you know, the usual. It’s also backwards
compatible with the DS games,
-
which is nice. Then the new 3DS
was released in 2014 and 2015,
-
there was like different regions. And it
was basically just the same console,
-
just some improvements in the
hardware. You’ve got a better CPU,
-
it has got more cores. It’s faster, it has
got more RAM. Basically everywhere.
-
So, it is just the same thing,
it runs the same software, exactly.
-
It has got some exclusive
software, but not much.
-
So, in terms of a hardware overview, this
is what what we are going to talk about
-
looks like; in general. So you
got the top part right here,
-
which is what we are
going to go into first.
-
This is like the ARM11 part.
-
Basically, you’ve got the ARM11,
which is the main CPU. It runs
-
the main operating system. It has
2 cores as I just said, or 4 cores.
-
So, it runs the main operating
system, it runs the games,
-
it runs all the applications.
Basically, it’s just –
-
if you’re doing something on the 3DS
that you can… you can see it happening,
-
it’s happening on that CPU. It has got
access to all of the main memory.
-
So that includes FCRAM,
-
which is 128MB or 256MB,
-
depending on which model it is.
And FCRAM is actually divided
-
into 3 separate regions. So you
first got the Application Region,
-
which contains the currently
running game or application.
-
The System Region, which contains applets,
which are basically tiny applications,
-
which run in the background.
So, that includes the home menu,
-
which is actually always running
in background, and the web browser,
-
which you can actually run at
the same time as your game, so
-
it has to run there. And then you got the
Base Region, which is more interesting.
-
It contains all the system modules
of the operating system,
-
as well as some kernel data,
such as handle tables
-
and MMU tables. So it is kind of sensitive
stuff. And then we got a WRAM,
-
which is tiny and contains all
the kernel code, and, well,
-
most of the kernel structures as well.
So it’s also an interesting target.
-
Then we’ve got the lower part, which
is the ARM9 part of the hardware.
-
So the ARM9 is basically a separate, well…
-
it’s an entirely separate CPU,
which has access to…
-
well… So it runs basically the
same microkernel as the ARM11.
-
It’s mostly the same code,
it has just got some pure features.
-
Mostly it runs a single process,
which is called ‘Process9’,
-
which does everything the ARM9 does.
Beyond that the role of the ARM9 is
-
to broker access to hardware that
might be sensitive in terms of security.
-
So one of the things it does is it
brokers access to all storage media,
-
so that includes the permanent
storage as well as the SD card.
-
And then it does all sorts of crypto
stuff, which is really important,
-
and does that by using hardware, actually.
So there is this hardware key scrambler,
-
which is used to.. to store
secrets in hardware basically.
-
The idea is, you feed
it two separate keys,
-
and it is going to generate a
normal key and feed that directly
-
into the hardware implementation
of the AES algorithm.
-
So that way, we never
actually see the final keys.
-
So that’s something that
is kind of annoying.
-
And then beyond that what you can see is:
the ARM9 has access to all of main memory
-
without much of, well, without any
restrictions. But it has also got
-
its own internal memory which the
ARM11 does not have access to.
-
So the ARM9 internal memory is
where the ARM9 stores all its code,
-
all of its data; and this way we
can’t actually take over the ARM9
-
just from the ARM11 without some kind of
exploit. So it’s basically a security CPU.
-
So this leads us to having
4 layers of security.
-
Basically, you’re first going to have
the ARM11 userland, which is what…
-
well, like your games, your applications,
whatever. On top of that,
-
you’re going to have, well, below
that, I guess, the ARM11 kernel.
-
So that is going to have
full privileges on the ARM11.
-
And then you’re going to have
ARM9 userland, which is ‘Process9’.
-
Beyond that you’ll have ARM9
kernel mode. So that’s in theory.
-
In practice, the microkernel
has a system call,
-
which we call… syscall…
we call it ‘svc backdoor’.
-
Because essentially you feed it a
function pointer and it just executes
-
that function in kernel mode.
So you don’t even need an exploit
-
if you have access to that syscall.
Of course, on the ARM11
-
no application or title or anything
ever has access to that,
-
but on the ARM9 ‘Process9’ actually
has access to it. Which means,
-
that from here we actually…
well, userland and kernel mode
-
are basically the same thing.
When you got userland on the ARM9,
-
you got kernel mode.
So that’s nice.
-
Beyond that, in terms of
cryptography on the system,
-
basically, they went out loud (?). So, anything
that can be signed, is signed.
-
So, that includes the firmware,
that includes every application.
-
Signatures are checked not only
at install time but also at runtime,
-
so that’s something to keep in mind.
-
Same thing: anything that can
be encrypted is encrypted.
-
And anything that can be made, well,
console-specific through cryptography
-
or authentication, such as
internal permanent storage
-
or the data that is stored on
the SD card, or savegames,
-
or extra data for games, this
is all made console-specific.
-
And gamecard-specific in
regards of savegames.
-
So, that’s kind of annoying as well. And,
of course, all this is handled by the ARM9
-
using the hardware… the crypto
hardware, so we got to get through that
-
if we want to do interesting things.
-
So, first we are going to go through the
first layer, which is the ARM11 userland.
-
Basically, getting a full
hold onto the system.
-
So, we first need to find
some kind of entry point.
-
There are problems… well,
there are challenges there.
-
One of the challenges is
that the system implements
-
strict Data Execution Prevention. So,
existing pages will never be read…
-
well, will never be read-write-executable.
It’s all only going to be read-only,
-
or read-writable or read-executable.
There’s no way from a standard application
-
to reprotect or map new pages
that are read-write-executable.
-
Because all of the system
calls are locked out, except for
-
higher privileged system
modules. Another thing is
-
that there is no ASLR, so that is not
a challenge, that’s actually kind of nice.
-
The nice thing here is that we… well,
that makes savegame vulnerabilities
-
totally fair game because, well, we don’t
need an actual scripting environment
-
or any kind of exotic
vulnerability to exploit this.
-
As long as we can get past
DEP somehow. And then,
-
of course, the fact that all
savegames are both encrypted
-
and made specific either to the
gamecard or the game console,
-
in the case of eShop games, is really
annoying for savegame vulnerabilities
-
because basically you can’t use those
as an initial entry point in most cases,
-
because, well, you can’t generate
the right, well, ES MAC,
-
or just… you don’t know the right
cryptography. So, that’s annoying.
-
Thankfully, the 3DS runs Webkit…
-
laughter
-
So, that’s nice.
Can always use that.
-
applause
-
So, Webkit is used in a number of places,
obviously it’s using the main web browser,
-
which you can access from the home menu.
It’s also used in the Youtube application,
-
which is available free on the eShop
and doesn’t use any kind of
-
client side authentication for the server,
so you can just redirect traffic through,
-
like a DNS server for example. Miiverse
applet, other stuff, that also uses it.
-
Slightly more secure, but might be
usable at some point, I don’t know.
-
Anywho, the important part here,
is that it’s not only using webkit,
-
it is using a very old version of webkit.
Basically, they do cherrypick
-
some patches into the version
of webkit they use, but only
-
after we exploit those on release, so it
comes a little too late, most of the time.
-
So yeah, this has been used by multiple
people, most notably yellows8,
-
but it has proven to be a very
efficient, reliable entry point.
-
Beyond that, we got Cubic Ninja as initial
entry point. Cubic Ninja is a game
-
that was released in 2011 on Nintendo
3DS. It is nice, because it actually
-
allows users to share levels
that they make themselves
-
through QR codes; and also it is
really bad at parsing those levels.
-
So what you can do, is just, well,
manufacture your own QR code
-
that is going to crash the game
and give you access. So these are
-
nice initial entry points. So, once we’ve
got this, what we have to remember is
-
that we might be able to crash the game
and may be able to control registers,
-
but we don’t actually have our code
running because of that. So,
-
the obvious solution to
hit this, is to use ROP.
-
For those of you, who are
not familiar with ROP:
-
You build your own fake stack
that lets you return into
-
code snippets that are located right
before return instructions. That way…
-
so this is an example. You can just
-
jump to this kind of instruction,
so ‘pop {r0, pc}’ and then
-
this is going to let you load your own
register value and then it is going to
-
jump to the next instruction that you give
it. So, this is a way of executing code
-
without actually executing code,
which is widely used; so this is like
-
the obvious thing to do. Of course,
ROP is annoying. It is very limiting.
-
It can be enough to actually execute
an exploit to get higher privileges,
-
but overall it is just annoying and very
limiting for homebrew, for example.
-
And of course, as I mentioned earlier, we
don’t have access to any of the system calls
-
that would let us map
read-writable-executable pages.
-
Also, the system does support dynamically
linked libraries, so that might be a way,
-
but these are signed and checked in
places that we can’t access at this point.
-
So, what we’re going to look
at next is the GPU to see
-
if we use that to bypass that.
What you can see here is that
-
the GPU has access not only to
video RAM, but also to FCRAM,
-
which is, if you recall it, main
memory. So, if you look at this,
-
with all the different memory regions,
-
we have got the Application Region
here, which is entirely contained within
-
what the GPU can access within FCRAM.
Of course, the GPU can not actually access
-
all of that FCRAM, so that is kind
of limiting. What we can see here,
-
is that, of course, application code is
within range of the GPU’s level of access.
-
The reason the GPU has access to
FCRAM and Video RAM, through DMA,
-
by the way, is, so that it can access
information such as textures,
-
vertex buffers, this sort of thing.
-
So, it’s actually kind of important. And
the reason it can write to it is because
-
it has to render its data somewhere.
The point is, that we can use this
-
to render data into main memory.
-
And main memory contains application
code. And since the physical layout is
-
actually completely deterministic, and
even if it wasn’t, we could just use the
-
read capabilities of the GPU to
search for what we are looking for.
-
Well, we can use this to overwrite our
current application’s text section
-
and we get code execution
that way, in spite of DEP.
-
Yeah, so this is where
we get code execution…
-
applause
-
We execute our own,
unsigned code, which is very…
-
applause
-
It’s great, but we are still confined
within the application sandbox.
-
So, we bypassed DEP,
we are inside the sandbox.
-
This means we can only access
our current application’s savedata,
-
so if we want to install some kind of
secondary exploit, this is too limiting.
-
We can only access certain services and
system calls, which is also limiting
-
and frustrating. And we can’t alter
memory layout, so we can’t allocate
-
more executable pages
than I mentioned earlier.
-
So, we are still kind
of limited at this point.
-
So, what we are going to do, is look at
what else the GPU can access.
-
And you can see, is that, of course, there
is this entirely separate memory region
-
the GPU can modify.
-
So it can access most of the System
Region. And the System Region contains
-
a few things. It contains the home menu, as
I mentioned, because that is an applet.
-
It contains the internet browser, and it
contains actually a single system module,
-
which is called ‘NS’, which we think stands
for ‘Nintendo Shell’, we don’t really know.
-
So, let’s look at this. First we got
NS code well beyond the GPU cutoff.
-
We got menu code, which is
also well beyond GPU cutoff.
-
But we got the menu’s heap, right here,
well, actually there is separate heaps,
-
these are well within the
GPU’s range, so that’s good.
-
NS unfortunately is still well beyond the
cutoff. All of its data, all of its code.
-
So we apparently can’t get to that.
-
So, then the idea is, to just,
well, okay, so actually…
-
What’s interesting here, is that
the cutoff is right before the end of
-
the System Region, which as we just
saw, has some interesting things, but
-
also excludes all of Base Region,
which also has very interesting things.
-
So, it seems likely that Nintendo knew
about the capabilities of GPU DMA,
-
like the theoretical capabilities, but
they didn’t do anything about it.
-
So, it seems that they probably didn’t
realize what we could do with it,
-
which is a lot.
-
So, basically, we got menu heaps. So
what we do, is… we have a heap, and
-
this is all C++ code. We are just
going to find objects inside the heap
-
and overwrite it. So it’s pretty simple.
Just find an object, that is going to be
-
triggered to some kind of synchronisation
mechanism. In this case, it’s gonna be
-
just ‘Return to Menu’. And we
create some kind of vague vtable
-
and get it to run our own
stack pivot. And then we get…
-
we get ROP execution under
Home menu, which is cool.
-
We still don’t have code execution
in the Home menu, but that’s okay.
-
So, we can do a bunch of stuff from ROP.
-
We can access a new system
service, which is called ‘ns:s’,
-
which is very helpful, because it can
kill any arbitrary process, as well as
-
create new ones. Also it gives us access
to SD card, which most applications
-
actually don’t have. And it lets us
decrypt/dump any title on the system.
-
So any game, even if it uses new
cryptography that Nintendo introduced,
-
we can actually dump that, because
for some reason, well, Home menu
-
apparently needs access to
that. And then we can also
-
access and overwrite all that extra data
used by any application, which is great.
-
So we use this as a base
for running homebrew.
-
Our homebrew launcher is
essentially just a service
-
that runs in the background under Home
menu process. It is written in ROP,
-
which is kind of disgusting, but it works.
laughter
-
The ‘Service’ handles running homebrew,
so the process is very simple. You just
-
kill off the current application, you
spawn a new one, and then you take it over
-
using the GPU DMA access.
And then, what we do is
-
we send all of these new capabilities that
we got through handles to the new process
-
and that gives us some
higher privilege homebrew.
-
It also handles events, such as Home
button, Power button, all that good stuff.
-
Which is nice, because we can actually
run code under any arbitrary application
-
or game, so we can actually modify
these games. We can run ROM hacks.
-
So there has been a bunch of translations
that can be run through this, for games
-
that haven’t come out outside
of Japan, so that’s pretty nice.
-
It’s the same principle, you just
launch the app, you take it over,
-
you pass the code, and then
you jump to it, essentially.
-
All within the confines of
userland, which is nice.
-
So, the other thing is, we can actually
access any game or application’s data
-
because we can run code under
it. So, these things include
-
savegame data for any game. So we
can actually install more convenient
-
secondary entry points, which do not
rely on the browser, which can be
-
patched any moment, or on some old game.
-
So, some examples include ‘Menuhax’
by yellows8, which exploits
-
faulty theme handling code, which
was introduced in firmware 9.0.
-
Which is really nice, because this way,
you can actually just run homebrew
-
right as Home menu is opened,
so right on boot time,
-
which is great. Then you got other games.
Of course you got a Zelda game
-
that’s vulnerable.
audience chuckles
-
This time it wasn’t the
horse’s name, but pretty similar.
-
And then you got other games. We
got tons of entry points at this point.
-
We’re really, literally drowning
in them. So, this is nice.
-
But we forgot about ‘Nintendo Shell’,
right? It’s a very attractive target,
-
for a couple of reasons. For one thing,
it has access the ‘am:u’ service,
-
which can be used to
downgrade any system title.
-
It’s not actually designed to downgrade
titles, the thing is, you can both
-
install and uninstall titles.
So, what happens is,
-
if you uninstall a title, and
then install an older version
-
of that title, you actually
bypass the version check.
-
So, you can just do that to
downgrade any system title
-
and bring back old exploits,
if that is necessary.
-
Assuming you have
access to the service.
-
And of course it’s in a region
that we can partially modify,
-
so it’s an interesting target.
-
Unfortunately, we can’t actually
access its data right now.
-
But maybe we can actually move
it to somewhere, where we can.
-
The idea is, if you were to kill NS, and
then allocate something in it’s place,
-
then run NS again, you can
move it below the cutoff.
-
laughter
-
applause
-
Thanks. But unfortunately
it’s not that simple. That can’t work.
-
The reason being, that we actually need
NS to be running to launch NS again.
-
So that kind of sucks.
-
But… well, no.
Actually we also can’t run
-
a second instance of NS at the same time,
-
so we can’t do that either.
-
But interestingly…
Well, the 3DS has an interesting feature,
-
which is called ‘Safe Mode’. Basically
it’s a second firmware, which is
-
an old version of the
regular one, and that
-
creates a bunch of
copies of system titles.
-
Most of them, anyways. So that gives
it a different ID. So, the idea is,
-
that if it has got a different ID, we
might be able to run it at the same time,
-
because, well, PM might fail
to notice that. Of course it doesn’t.
-
It actually does notice that. So we can’t
run the Safe Mode version of a title
-
at the sime time as the regular
version of the title. But,
-
for some reason, in the case of NS – you
might not be able to see this very well,
-
but we’ve got NS’s regular title right
here, and then we got Safe Mode NS
-
right here. And for some reason
they created a new 3DS version
-
of the Safe Mode version of NS,
though there is no new 3DS version
-
of the original NS. So that
creates a separate title ID
-
which we can run at the same time
as regular NS. So then, the exploit
-
becomes very simple. You keep NS running,
just allocate enough data, that it will be
-
below the cutoff; and then you
just run new 3DS Safe Mode NS.
-
And then it’s within range of the GPU
and you can take it over and have
-
access to everything. So, this is nice.
-
It’s more of an oversight than
a proper exploit, but whatever.
-
So this gives us access to a
bunch of system calls. Mostly
-
service handling system calls,
so we can post our own service,
-
which can be useful for other
exploits that I won’t get into, for
-
impersonating other services
to other system modules.
-
And then we got access to all of
these services, which is great.
-
So we can downgrade
system titles arbitrarily.
-
And this runs in background, which
can always be helpful for homebrew.
-
The only problem is at this point,
it’s still new 3DS only, because
-
it relies on this new 3DS title. But
there are actually ways around that.
-
This was just to show that we can actually
get fairly high levels of privilege,
-
even still just always staying
in userland on the ARM11.
-
And there are other, similar attacks to
that. If you’re interested you can look up
-
‘rohax’, which is a similar
attack in the system module.
-
So, now derrek is going to talk to you
about exploiting the ARM11 kernel.
-
derrek?
applause
-
derrek: So, hi everyone!
-
First, I will give you some
very short inside view
-
of the kernel, and then I will
explain how you can exploit
-
the latest version of the ARM11 kernel.
-
So,
-
this is actually Nintendo’s very
first gaming console kernel.
-
Like on any other older console,
-
there was no kernel. All games
were just running on bare metal.
-
Like there was a kernel for the Wii,
-
like a very small microkernel
running on the security processor,
-
but that wasn’t written by Nintendo.
-
So it’s their very first
gaming console kernel.
-
That kernel is made to be thread safe,
-
so it can run on multiple cores
-
at the same time and there are like
-
130 system calls available.
-
So that’s quite a lot, in my opinion.
-
But usually, if you have gained execution
-
in ARM11 userland, you
only have access to, like,
-
around 50 system calls.
-
And there’s a reason for that, but I’m
going to explain that in a second.
-
So, internally, the kernel
works with C++ objects.
-
So here are some examples
for system calls. So, we have
-
‘CreateSemaphore’, for
example. That will just create
-
a semaphore object in the kernel
-
and it will return a
handle to the userland.
-
And when you want to do any operations
-
on that semaphore, you
have to pass that handle
-
to the kernel, and it will look up
this handle in a handle table
-
to find the original C++ object.
-
Also there are 2 different
kinds of memory allocators.
-
So, we have a memory allocator
for the main memory, which is
-
the FCRAM. And there is also a Slab Heap,
-
where all the C++ objects are stored in.
-
And this Slab Heap is located in FCRAM,
-
which is the ARM11 memory,
-
where all the kernel code and data is in.
-
Also, there’s an IPC system.
-
IPC is ‘inter process communication’.
-
And it basically allows you
to talk to other processes
-
like services,
-
e.g. the GSP service or FS.
-
So, let’s look at the security.
-
So, the kernel is really small.
There are only like 200KB of code,
-
which is pure ARM code. And
there are only like 1000 functions.
-
So, they try to keep
the code size very low
-
and that makes it harder to find bugs.
-
The code size is really small, and
-
you don’t have really much to choose from
-
what to exploit. Also there are no
symbols included in the kernel.
-
Like when you run strings on it, it will
just give you some names of C++ objects,
-
but there are no function
names or something like that.
-
As we have seen earlier
it’s physically isolated
-
in its own memory. Which turned out
- of course - to be a good idea.
-
Otherwise it would have been
overwritable by the CPU eventually.
-
And all objects have a reference counting.
-
So that’s similar to the
C++ shared pointer
-
where every object has a small field
-
like a counter field and everytime
the kernel wants to use an object
-
this counter gets increased.
And everytime the…
-
like when the reference is no longer
needed it will decrease the counter
-
and when the counter reaches Zero it
will automatically delete that object
-
from the Slab Heap. So they are basically
trying to prevent use after freeze.
-
Also I’m not sure if that’s
a security measurement
-
but there are more than 100
panic calls in the kernel
-
and that’s every 10th function
-
- per average. And they have
the syscall access restriction.
-
So you - as I said - you only have
access to like 50 system calls.
-
All the interesting ones are disabled.
-
E.g. you can’t map executable pages.
-
On the other hand there
is no ASLR. But at least
-
they’re trying to change the
memory mapping every time
-
during a larger kernel update.
-
Also there’s no stack protection. And
the Userland is always mapped.
-
So once you’ve got control
over the program counter
-
you can just jump to
-
Userland pages that are
marked as executable.
-
So you don’t have to do ROP in the kernel.
-
It’s pretty nice.
-
But they tried to have
an execution prevention
-
in the kernel that is: they’re
marking executable kernel pages
-
– that is the code – they’re
marking them as executable
-
in their Page Table. So let’s take a look.
-
The highlighted parts in orange
are the kernel code sections.
-
And as you can see like when
looking at the first highlighted line
-
it says ‘virtual address #FFF00’ etc.
-
is mapped to the physical
address 1FF80000.
-
And it is marked as executable
and you only have access to it
-
in Kernel Mode, of course,
and only Read access. Right?
-
So this is correct.
-
But when you look at the second
line of that Page Table dump
-
you will notice that
there is another section
-
which covers the entire AXI WRAM
-
and it’s mapped as Read-Write.
-
So it doesn’t really make sense. Yeah.
-
So basically it’s completely useless.
We have Read-Write access to it.
-
So, to summarize everything,
-
there’s actually no exploitation
protection. Once we found
-
an exploitable bug it’s
pretty likely that we gain
-
code execution in kernel mode.
-
So, let’s find that bug.
-
And I started at looking at the SVC table.
-
So this is kind of the interface
between kernel land and userland.
-
And this shows all system calls
-
that are available in the kernel. So
you have like normal system calls.
-
For memory management you can
map read- and writable pages;
-
you can mirror pages and do
other memory management stuff.
-
And there’s also some
configuration for threads like
-
you can choose which
core should be used for
-
executing the thread and all that stuff.
-
You have a really large range
of synchronization objects
-
like kernel mute tags and
all that stuff. And of course
-
you have IPC requesting, so you can
-
send messages to services. And
there’s a more advanced section
-
like this is used by services mostly,
-
because they have to
respond to your IPC requests.
-
And there’s also Kernel DMA,
cache control, some things.
-
And they have a set of debug system calls.
-
It’s just basic debugging.
You can set breakpoints,
-
read and write process memory.
But you don’t have access to them.
-
Like on retail it’s not actually used.
-
And so one last section
is the Privileged section.
-
And here are all the
interesting system calls
-
that allow you to create processes and
-
map executable memory and all that stuff.
-
Unfortunately, we can’t use the Advanced,
Debug and Privileged system calls.
-
I mean that would require
exploiting some service.
-
And that’s just more work for us.
-
So this leaves us with
the normal system calls.
-
But IPC sounds really interesting.
-
But unfortunately it’s full of panics.
-
Also there’s not much to attack at
synchronization object system calls.
-
So you only have like this
more interesting system call
-
for local memory management. And in
theory there’s a lot that you can mess up.
-
Right? There’s a lot that can possibly
go wrong. And also we have
-
unchecked DMA access!
Like through the GPU.
-
So maybe we can do
something useful with that.
-
Okay, so let’s have a look
at the memory allocator.
-
There are 2 types of memory allocators.
-
First is the regular one. And it’s
just for mapping normal heap
-
like for malloc in C, e.g. And you
have the linear memory allocator
-
that is used for GPU textures, like
-
when memory has to be
physically continuous
-
you use the linear memory allocator.
-
And there’s the FCRAM memory
layout that we saw earlier.
-
You have these 3 regions
and every region has
-
its own set of free pages.
-
So how are they keeping track of them?
-
So you have a region descriptor
which tells us the dimensions like:
-
where does it start, the region,
and its size. And you get also
-
a pointer to the first
free piece of memory
-
in that region. And each
free piece of memory
-
which we call a Memchunk
has a Memchunk header
-
right at the beginning. And
it basically tells the kernel
-
how large that Memchunk
is. And it’s also linked
-
in a Doubly Linked List. So you
have a next and previous pointer
-
pointing to the next and
previous Memchunk headers.
-
It kind of looks like that.
So you have the red parts
-
which are the free Memchunks
and the green parts are memory
-
that is already allocated. So
-
allocation is pretty straightforward.
It’s not really complicated.
-
So the first thing that the
allocator function does:
-
it loads the next free pointer
from the region descriptor.
-
And for regular memory it
just goes through the list
-
following the pointers
and it sums up their size
-
until the requested size is reached.
For linear memory it would just
-
look for a suitable memory chunk to make
sure that the memory is really continuous.
-
So when it found enough memory
it sets the next pointer
-
of the very last Memchunk
to Zero. It will then
-
update the list and also
the next free pointer
-
for the region descriptor
and finally it will return
-
a pointer to the first
Memchunk. So,
-
let’s look at this from
a security perspective.
-
And there’s a problem. They
basically have kernel structures
-
inside the FCRAM!
And that is a problem
-
because we have DMA access
to it through the GPU.
-
And there was an attack by yellows8
-
that is called ‘memchunkhax’.
And what he did
-
is basically: he overwrote
memchunk headers
-
with the GPU DMA
flaw. And then
-
he gained an arbitrary kernel write
-
when it’s deallocating memory. So because
-
next/prev pointers have been modified.
-
So, unfortunately, this
was fixed by Nintendo
-
in system update 9.3 last year,
-
like 1 year ago. And the new kernel will
now verify every memchunk header
-
during allocation. Like its size
and also next/prev pointers.
-
So, in theory, everything has been fixed.
Invalid pointers or invalid sizes
-
will just result in a
kernel panic. In theory.
-
So when you look at the system
call for Controlmemory…
-
we have access to it. It’s one
of the normal system calls.
-
It does basic stuff. You
can map/free RW pages,
-
but not executable of course. And it
takes an address and size as argument.
-
And also an operation code
which tells the kernel what to do:
-
to map or free pages, whatever.
-
So first it does some basic
checks on the address
-
and eventually it will
call a very large function.
-
And I just call that function
kern::controlmemory.
-
So what can kern::controlmemory:
it calls the allocator function
-
and it will just return a
memchunk header pointer
-
– as we have seen earlier. Then it goes
through all of the allocated memchunks
-
and it’s mapping them to user space.
-
And it’s also updating some block
information for KProcess object.
-
So there’s a problem. There’s
obviously a race condition.
-
Like we can overwrite memchunk
headers after they have been allocated.
-
So we could try using the GPU
but it’s really slow, actually,
-
because we would have to ask
the GSP service to read memory
-
and we have to go to this
very large IPC kernel code.
-
And that would be probably too
slow. Allocation is really fast.
-
Let’s dig a little bit deeper.
-
I tried to reconstruct
the source code in C.
-
So this is the first step.
It tries to allocate memory.
-
For this example, it will just
allocate regular memory.
-
So when it found a memchunk
-
which means that it’s not
enough memory is available.
-
It will then execute this
really interesting do-while loop.
-
I know, it’s a lot of code. I’m not
sure that you can actually read it.
-
So let’s go quickly through this code.
-
The pages read from the Memchunk header.
It gets converted to a physical address.
-
And that physical address
gets mapped to userland
-
by mem_map function. And then
it will go to the next memchunk.
-
Here. And it will also update
the userland virtual address.
-
And then it will clear that memory. So
-
what’s wrong here?
-
The problem is they’re mapping
the Memorychunk into userland.
-
And after it has been mapped
they’re accessing it again.
-
And what they access is the next pointer.
-
So we can just overwrite it.
-
When we have 2 threads running we can
-
– from another CPU core –
try to overwrite that pointer.
-
So our goal would be to map
kernel pages to userspace.
-
But there are some problems. It
requires really, really perfect timing.
-
There’s only a very small
time frame to do the overwrite.
-
Also, we need a Memchunk header
structure at the next pointer address…
-
…to do this. To make sure
we get a perfect timing
-
I came up with a kernel
address arbiter oracle.
-
It is actually used for thread
synchronization, we don’t care about it.
-
But it tries to read from address and
returns an error when the address is
-
not accessible by userland. So
we can use that system call
-
to make sure that the memory
has been mapped to userland.
-
And once it has been mapped
we’re trying to overwrite it.
-
So one last problem: we have to
inject a memory chunk error
-
in kernel. I did this
by using the Slab Heap.
-
We can just create some KObject
and set their member variables
-
to create a faked memchunk header.
-
So this is the Slab Heap.
We’ve got C++ objects,
-
vtable pointer and some attributes.
-
So the Slab Heap is basically just
a really large area of C++ objects.
-
And what I did was
I changed the attributes
-
and used them as Memchunk
header. And I am redirecting
-
the next-pointer to that
object and it will map
-
multiple C++ objects to userland.
And that’s really nice because
-
we have vtable pointers, so
we can just overwrite them.
-
And that means that
we gain code execution.
-
So, as a summary, we set
up some kernel objects,
-
change their attributes, request
memory from the kernel;
-
and once it becomes available
we patch the next-pointer,
-
overwrite that mapped
SlabHeap pages and
-
then we call a system call
which closes the handle
-
for the kernel objects that
we created in step one.
-
So it will eventually call
some vtable function
-
and it will just jump to our
modified vtable function.
-
And we got ARM11
Level0 Code Execution!!
-
applause, motivated by smea
-
So, now plutoo will tell us
what nice things you can do
-
once you gained ARM11
Code execution.
-
plutoo: Hey guys! Okay, so… the ARM9.
-
Let’s go.
-
The ARM9 is actually also used
for executing old DS games.
-
So what they do is, they actually,
you could say, reused the ARM9
-
which is their backwards compatibility
processor. They use it
-
as a security processor
when executing 3DS code.
-
And like smea said it’s running
a stripped-down version
-
of the ARM11 kernel. It basically
only does threading sequencation,
-
things like that. And there’s
no MMU. There’s an MPU,
-
8 regions you can configure.
-
You could do no-execute
within those regions etc. but
-
the granularity is not very
nice. And they only have 8.
-
So they basically ran out of space.
And .data+stack is executable
-
as long as you can jump to
it. And .text is writable
-
so that’s bad. Basically whenever you can
-
write code into arbitrary memory
you can just overwrite code.
-
These features – you don’t want
them on a security processor.
-
laughter
-
So let’s go. So it turns out that
-
there have been lots of exploits over
the years and most of them are fixed.
-
And most of them used the
normal command interface.
-
But in this case we’re taking
a different approach. So
-
on the 3DS the memory-mapped
I/O is split up into 3 regions.
-
There’s the ARM9-only I/O: it does crypto,
-
it does DMA engine,
-
things like that. Then there’s
the Shared I/O region.
-
And then, finally, there’s the
ARM11 I/O region which contains
-
the GPU video decoder.
-
Thanks to derrek and smea
we have full ARM11 control.
-
We execute kernel mode.
-
So the question is: can we use
the shared I/O region, somehow,
-
to own the ARM9? So it turns out
-
the interface for reading old
DS cartridges is actually
-
in the shared I/O region.
-
We’re not sure why this is, but
-
they have it there for some
reason. And it’s only the ARM9
-
which is actually using this region.
But ARM11 still has access to it.
-
So when you insert the cartridge
it starts by reading the banner.
-
And it does this by writing this
magic value to CTRL register.
-
And basically it just asks
for 0x200 [hex] bytes.
-
And then there’s this loop.
-
And this Assembler code
is on the right side.
-
You can see it basically waits
for some bits to clear / to set
-
and then they read 4 bytes and
then they wait for another bit.
-
And there’s no range check on the
buffer. But it’s always 200 bytes,
-
so it should be fine.
-
What if we overwrite the
CTRL register from ARM11
-
asking for 0x4000 bytes?
-
Boom!
-
We have a nice buffer overrun.
It’s in the DSS segment but…
-
it’s still nice. And can control the data.
-
So the data actually comes
from the cartridge.
-
We need to make our
own DS cartridge. So,
-
there’s this old device, called the
PassMe. It’s for the original DS,
-
where you basically plug
old DS cartridge in
-
and it basically modifies
the header as its read. So,
-
these are available online for 5 bucks.
-
And then you add an FPGA.
-
I implemented this and it
works, but it’s very gimmicky.
-
I don’t recommend it.
-
And here’s my soldering,
it’s not very nice.
-
This gives us ARM9 code execution
and this works on latest firmware.
-
But we want something better.
Let’s look at the chain of trust.
-
The chain of trust: the idea is of course,
you verify all the code that is running.
-
But you’re basically verifying
everything at load time.
-
The 3DS has the simplest
chain of trust you can have.
-
There’s the Boot ROM at
the start. And then it loads
-
the firmware binary from
NAND and it jumps to it.
-
On the new 3DS they were a bit clever.
-
They added an extra crypto
layer on the ARM9 portion.
-
But it’s actually part
of the firmware binary.
-
We call this ‘ARM9 loader’.
-
So the theory that Nintendo had was:
-
“Let’s add another layer of
crypto, so we change the keys,
-
we introduce new keys,
and they can’t break it”.
-
And they don’t have any worked-out
place to put those keys.
-
So they placed them in NAND!
-
But they’re encrypted with
the per-Console key that’s
-
based on a hash of the OTP
that’s unique for each Console.
-
And then OTP access is
disabled early in the Boot.
-
So later on you can’t dump the OTP
and you can’t figure out the keys.
-
This looks safe, in theory.
So here’s the implementation.
-
So they calculate some hash of the OTP.
They read the key-sector from NAND.
-
And they decrypt the key.
And they put it in a keyslot.
-
It’s basically an isolated memory area.
-
And then they generate
a bunch of sub keys and
-
they verify that the key they loaded
from NAND is the correct one.
-
So even if we were to switch the key
they would detect that and just panic.
-
And then they decrypt the ARM9 binary
and they jump to the entry point.
-
But… they forgot to clear the 0x11 key!
-
So we can just get code execution
later on. And we can just regenerate
-
all those keys! So this
implementation is useless.
-
Okay.
laughs
-
applause
-
And they fixed this because they have
more than 1 key hidden in the NAND.
-
So they took their next key.
-
It’s basically the same idea: you
calculate the same hash, you read
-
the key sector from NAND, you generate
all the previous keys for compatibility,
-
and then you decrypt a
new key, we call it Key#2.
-
And then you decrypt ARM9
binary using the second key.
-
You clear the keyslot, and
you jump to entry point.
-
But they forgot to verify the second key!
audience laughs
-
This is epic fail!
applause
-
So let’s exploit this. ‘ARM9LOADERHAX’.
-
We can change the second key. ARM9
loader will just decrypt the binary
-
to garbage and jump to it.
-
If you look at the encoding
of a ARM Branch instruction:
-
the probability is pretty high that
there will just be a Branch instruction.
-
And just any random data will eventually…
like if you try enough keys,
-
it will eventually become a Branch
instruction to some memory.
-
So if we try a lot of keys, eventually
we will find some garbage
-
that is useful.
-
This is the NAND of the Flash
memory of an unmodified 3DS
-
– a new 3DS. So there’s a small key
section, marked in teal, like, blue.
-
And it contains those keys
that we’re talking about.
-
And then there are 2 firmware partitions.
-
One is used for backup, in
case one gets corrupted;
-
so it doesn’t brick the device, whatever.
-
We installed our custom key.
-
And we installed the largest
firm binary we have
-
in the firm0 partition. And we keep
the one with the vulnerability
-
in the firm1 partition. And
then we put our code payload
-
on top of the firmware0 binary.
-
And then we reboot.
And so what will happen?
-
The Bootrom is executed.
-
It will load the first firmware partition.
-
And it has our code in the end,
but it doesn’t know about it.
-
And then it decrypts it.
And, you see, it looks okay.
-
There’s the ARM9 loader stub in the front;
and then comes the encrypted binary.
-
And then, finally,
there’s our payload.
-
But Bootrom checks the
hash, right? And it fails.
-
So it thinks the partition got corrupted.
-
So it will load the smaller one on top.
You see we have our payload in memory,
-
at Boot. And then it decrypts firmware1
-
which is smaller and it still has ARM9
loader and another encrypted ARM9 binary.
-
And then it jumps to ARM9 loader
because the hash checks out.
-
And then the ARM9 loader will
decrypt our corrupted key
-
from NAND and it will
decrypt this one to garbage
-
and it will jump to it. And
hopefully it jumps to our code.
-
So this gives us ARM9 code
execution from cold Boot.
-
Early, very early. So it turns out we
can actually use this to get some keys
-
that are later not available
because they clear those…
-
they use a certain memory area for seeding
encryption engine to generate keys
-
and the memory is later cleared.
So you can’t regenerate the keys.
-
But with this we can actually
get those 2 keys.
-
They’re called the firmware 6.x save-key
-
and firmware 7.x NCCH-key.
-
That’s a bonus.
-
We talked a bit about the AES engine.
It’s used everywhere for the crypto
-
and it’s used for everything, basically.
-
It supports all the usual
block cipher modes.
-
It has 2 security features: it has
write-only keys. Which is really useful.
-
Like you write a key and then
you can never ever read it back.
-
This means that they can
fill in the keys by the Bootrom
-
and we can’t dump them later.
-
So they can keep the keys secret.
-
Even if we hacked the ARM9, even if we get
code execution we’ll never get the keys.
-
And then there’s the key scrambler.
Which is that the key is actually
-
– it’s an optional thing –
where the actual key is hidden,
-
calculated by a hardware
function, that is never…
-
that we don’t know about. So the key
is actually never exposed to the CPU
-
– the actual key. So we just feed it 2
values, 2 keys and then it generates
-
a new key based on that. And
we don’t know what that key is.
-
So this creates a situation similar to
the isolated SPUs on the PS3
-
where you can ask it to decrypt
stuff, but you don’t get the keys.
-
And if you don’t get the keys,
then… we want the keys!!
-
We want to decrypt things on
our PC because we’re lazy.
-
So there’re 2 keys –
KeyX, KeyY we call them.
-
They’re 128bits and the
normal key is derived
-
as a function of those 2;
and that function is unknown.
-
It’s implemented in hardware, in silicon.
-
So even if we know X and Y we
can’t figure out the normal key
-
and we can’t decrypt things
without asking the 3DS first.
-
But we can poke this hardware engine.
-
The first thing you notice when you
do this is that if you set the N-th bit
-
of the X key and the N+2 bit in
the Y key you get the same result.
-
And in general, you find that
the function that we’re looking for
-
is actually just a function
of one variable where it’s
-
the XOR between the X rotated by 2…
-
so this is rotation, not shift,
and XOR-ed with Y.
-
But we still don’t know the key.
But we want to know keys. So…
-
So step back a little bit.
-
The keyscrambler is used for Mii QR-codes.
-
It’s used for everything, right? So it’s
used for network protocol, called UDS,
-
and it’s used for Download Play – which
is when you download games over WiFi,
-
temporary games. But the
Wii U also supports all of this.
-
But it doesn’t have the
key scrambler in hardware.
-
So the Wii U must be using normal keys.
-
applause
screamed from audience: WHAT?
-
applause
-
So we make a table of the shared keys and
-
these are the 3 keys that
are shared with the Wii U.
-
Who is where the KeyX
and KeyY on the 3DS…
-
where they are set. And 2 of them
have KeyY set by firmware.
-
So we can’t read the keys set by the
Bootrom because it’s locked away
-
and we don’t have it. But can
we still figure out G? Let’s see.
-
So I gave shoutout to shuffle2 and
to fail0verflow who hacked the WiiU
-
and they helped us… or shuffle
helped us extract the Wii U keys.
-
So thank you! Now we have KeyY and
we know the normal key from the Wii U.
-
However, KeyX is still unknown.
-
And if G(t) is ‘bad’ then a
small change in the KeyY
-
will only lead to a small
change in the normal key.
-
It’s bad! So let’s look at the data.
-
So when we flip one bit in the
KeyY we can brute-force all keys
-
similar to the normal key which
is just within a couple of bit flips
-
and we find that it always
results in the normal key
-
with bits flipped at
position either 87 or 88,
-
sometimes 89, but never 86.
-
So this reminds me of an adder
where you had a carry bit
-
being propagated to upper
bits, but never to lower ones.
-
So let’s guess that this is
an adder and let’s try:
-
it’s an adder with a rotation so
we guess that G(t) = (t+C)
-
– some constant C, we don’t know it –
and rotated to the left by 87.
-
And then we plug it in to our original
formula and we don’t know KeyX, remember,
-
because it’s set by Bootrom,
we don’t have it.
-
We don’t know the constant C because
it’s in silicon, it’s in hardware.
-
But if we look at the formula,
and we consider the inequality,
-
where we basically rotate right by 87
-
– we’re basically undoing
the outer rotation.
-
And then we plug in our formula
our guess. And then we get this.
-
And then we subtract C from
both sides. We end up with this.
-
And this is basically… we’re XOR-ing
2 different keys with the same X value
-
rotated to the left by 2.
-
Well if you stare for
this bit you’ll see that
-
if y0 and y1 – which are 2 different
KeyY’s – are equal except for
-
at one bit position then
the XOR is smallest
-
for the one which shares
the same bit value
-
at the position that the
2 Y’s are differing at.
-
It’s actually pretty simple
but it sounds difficult.
-
XOR is Zero if they’re the same
input and One if they’re different.
-
If they’re the same it’s
Zero and it’s smaller.
-
So we actually look
bit-by-bit on this. And
-
we repeat this 128 times. And we
recover all 128 bits of the KeyX.
-
And when we have the KeyX we can
calculate the silicon constant C.
-
So the end result is: the key
scrambler is figured out
-
and we have also the secret Bootrom
KeyX for a couple of keyslots, as a bonus.
-
applause, motivated by smea
-
I didn’t think trough the constants in
the slides because I want this to be
-
an exercise for the listener.
-
When the new 3DS was released
they rushed it, we think,
-
because they left some interesting
commands in the PsPs service. And
-
it included an early version of the NFC
crypto used for the Amiibo figurines.
-
This implementation, the first
one, uses a normal key. And the…
-
the newer one changed it to KeyY.
-
So they accidently gave us one of
these pairs in the firmware images.
-
We don’t need to use the Wii U at all.
-
So anyone who can decrypt
3DS firmware binaries
-
can perform this attack
to get the constants.
-
So anyone out there: Good luck!
-
And now: back to smea, for a summary.
-
applause
-
smea: Right, I’m just gonna conclude
really quickly. So, some take-aways of
-
what we talked about
today: first thing is:
-
it’s all pretty obvious lessons,
but – you know – bare with me
-
Giving access to physical memory to
any application, through GPU or whatever,
-
is dangerous. You should always be
careful about that. Even if you think
-
you’ve protected stuff, there’s probably
gonna be stuff that you forgot. So just,
-
like “you don’t do it or do it right”.
-
Other thing is: Shared I/O is
dangerous if you don’t know
-
what can actually control the I/O, then,
well, again, you should be very careful.
-
Also, only checking your data
before decryption is dangerous,
-
and - both that and not checking the key
when you know that it could possibly
-
be modified by an attacker
is a bad idea. And finally,
-
secrets in hardware are great
unless you give them away, so…
-
don’t do that! laughs
audience laughs*
-
Beyond that we just wanted to talk about
the state of Homebrew really quickly.
-
You might recall, on the - during the
Wii U talk around here
-
2 years ago. And fail0verflow said
that they didn’t think necessarily
-
there was much of a future for console
Homebrew. And there’s definitely
-
an argument for that with
the rise of phones, mostly.
-
Anyone can make an app, can make
a game for any number of devices
-
and sell it to millions of people.
But you know, we disagree.
-
cheers and applause
-
It’s been a year since we started
releasing 3DS homebrew. And
-
– this is supposed to be moving,
but… let’s imagine it’s moving.
-
Well, there in there - like a bunch of
3DS Homebrew. It’s been awesome!
-
We’ve been working on this really hard.
A lot of people had been joining us.
-
It’s a great community effort. And
basically what I want to say is
-
we want more developers.
So if you’d like to join us
-
there is a very… well it’s not
very mature, but it’s maturing,
-
our SDK. And you know what:
reverse-engineering hardware is fun.
-
When we don’t have any documentation,
reverse-engineering software is fun.
-
We can always use more reverse-engineers
and just people who want to make cool shit,
-
so… Yeah, oh… right! Just one more thing.
-
Lately there has been a wave
of patches by Nintendo,
-
of known exploits, which
has been really annoying.
-
So for our Browser Hacks, well,
yellows8’s Browser Hacks,
-
menu hacks, stuff like that…
Yellows8’s been working pretty hard,
-
so he actually brought back browser
hacks, it should have been released
-
about 10 minutes ago.
laughter, applause
-
But we also had ironhax for an
eShop game, a free eShop game,
-
so you could just download it. That was
patched. The thing is, there’s actually
-
a way to download the old version from
the eShop application with some patches.
-
So we’re also releasing that right now!
So basically if you can get Homebrew
-
and get on to the eShop
with a modified patch.
-
That should also be released in about…
well, whenever this is done.
-
So get it as soon as possible,
this is a free game, it will get you
-
Homebrew forever. So just do that.
And also, yellows8 just released
-
a new version of menuhax which
works on latest firmware version.
-
This was also patched like a couple of
weeks or months ago. So, this is all out
-
right now. If you have a 3DS, get it.
If you have friends who have 3DS’s,
-
well, tell them and tell them to get it.
Because it might not last super long.
-
Yeah, so we would like to thank yellows8
who unfortunately can not be here tonight
-
but has been super helpful, has been
doing a ton of work on the 3DS.
-
And honestly, a ton of this could
not have been done without him.
-
And thanks to everyone on the
#3DSDEV Homebrew channel,
-
everyone who is attending tonight.
Thanks for this.
-
And if you have any questions,
I don’t think we have a lot of time,
-
but we’ll accommodate. Thanks!
applause
-
Herald: Thank you for your patience, if
you got questions, please come upfront
-
to these guys, because we have no more
time for structured Q&A. Thank you!
-
postroll music
-
Subtitles created by c3subtitles.de
in the year 2016. Join and help us!
Patrick
please do not do timing before the transcription is finished. Actually, please do not do timing at all, before we tried to do it automatically! it saves a lot of time!