-
34c3 preroll music
-
Herald Angel: And now I want to introduce
our first speaker and the topic he's
-
talking about. iOS kernel exploitation
archaeology. A kernel exploit from late
-
2013 early 2014 will be digged out and
analyzed proper archaeology all the
-
digging... digging and analysis is done by
argp here to my left on the stage and give
-
him a big round of applause. And the stage
is yours, thanks.
-
Applause
-
argp: Thanks for the introduction. First
of all, thank you all for being here. As
-
the person that did the introduction told
you this is going to be an archeology talk
-
so I apologize in advance if it's not that
interesting for you. So we'll talk about a
-
bit older stuff rather than new things.
Okay so a bit a few things about myself.
-
Actually, I think from all these things,
the most important are the the Phrack
-
papers, right? So, yeah. Let's ignore all
the other stuff okay? So, what I'm going
-
to talk about. I'm going to talk about the
evasi0n7 kernel exploit. Now evasi0n7 was
-
a jailbreak it was released by the evad3rs
on the 22nd of December 2013. It supported
-
iOS7 to iOS7.1 beta 3. That's not the
7.1 stable release, right? So that's a
-
beta. And this supported all devices at
that time including the iPhone 5s which
-
was the first 64-bit device except the
Apple TV. So, I decided to reverse
-
engineer the kernel exploit of the
jailbreak focused just on that. Because I
-
was really interested, not so much in the
bug itself, which was as we will see not
-
very complicated. But I was really
interested to understand the exploitation
-
techniques that the evad3rs used. So, I
started reversing it, and I understanding
-
it, and at some point I just said I'm just
gonna do a reimplementation of the kernel
-
exploit. So, this talk is basically my
notes on this whole process. And, of
-
course, it's not a jailbreak walkthrough,
right? And I'm going to specifically focus
-
on the various problems I encountered
during this task and how I overcame them.
-
And hopefully it's going to give you some
helpful takeways for if you do iOS kernel
-
research nowadays. Okay, so, the general
outline is I'm going to say a few things
-
about the version 7 to setup the stage.
And then I'm going to explain the kernel
-
bug itself. And, then I'm going to talk in
length about my debugging setup. And, I
-
think that's a very important step that
usually phone or embedded talks
-
exploitation talks don't analyze that
much, and I think it's a really important
-
part. Because usually having a working the
debugging set up is, basically, maybe half
-
the job of doing a reliable exploit. Then
I'm going to do to talk about my
-
reimplementation of the exploit, and
hopefully, at the end, we're gonna have
-
some things to take away or maybe not. We
will see. Okay so it was the evasi0n7
-
jailbreak was released about 4 years ago.
And that's the archaeology in the title.
-
That's ancient history right? And if you
were following the jailbreak community,
-
you might remember this huge drama around
this jailbreak, initially, with geohot and
-
if he was planning or not to release it
before the evad3rs. And who he was
-
planning to sell it to, and some leaked
discussion that he had with some of that
-
he was offering money to buy. And geohot,
his jailbreak supposedly using
-
some of the bugs the evad3rs were using so
this is a huge drama. And then after the
-
evasi0n7 jailbreak released, like maybe a
few hours ago, people realize that if your
-
phone had a Chinese locale then the
jailbreak was installing a piracy app. So,
-
that was basically a third-party app that
-
was taking you to an
app store not operated
-
by Apple but by TaiG that had some pirated
versions of the real applications on the
-
App Store. And, of course, that also
create like a huge drama, this practice.
-
Okay, so a lot of things were said about
the jailbreak at that time and about the
-
TaiG pirate App Store. But what I really
set apart was this tweet. And the really
-
important thing that I like about this
tweet is, that it doesn't really make
-
sense. So he says that we have to decide
to remotely disable the default
-
installation of TaiG in China for further
investigations of the piracy. So that
-
whole thing doesn't make sense. So you
mean, you didn't know what was happening?
-
You didn't bundle it with a jailbreak? Are
you going to disable it for new
-
installations? And then, what does
remotely then mean exactly? So what about
-
the people that already had the apps, the
piracy app. How are you going to disable
-
that? Is that what remotely refers to? So
that's an excellent tweet I think. Okay,
-
so some point after the evasi0n7 jailbreak
was released geohot did a writeup on the
-
userland part of it. So, he analyzed how
the userland part worked and he stopped at
-
the point of gaining root and basically,
he mentioned in his writeup that the
-
evasi0n7 untethered binary, which
basically what was good doing the kernel
-
exploit, was obfuscated. And as we will
see this was indeed the case and as far as
-
I know that's the first jailbreak that
used the deliberate obfuscation. I don't
-
know the reason, I assume it's
partly to hide the the piracy
-
app store that was bundled with it and
maybe partly to hide the bug, the kernel
-
bug, but I'm not sure about the reason.
Now p0sixninja who found as far as I know
-
the bug, the kernel bug did a writeup on
the kernel bug, it's on the iPhone wiki,
-
and he basically describes the bug and he
stops at the point where he gets a crash
-
log from gdb. So he doesn't say anything
about how to exploit it. Okay, so after
-
all these things happened then I decided
to reverse engineer the untethered binary
-
and understand the exploitation techniques
and I was really interested to reverse
-
engineer the obfuscation that the evad3rs
were using, it seemed like an interesting
-
challenge, and... but as I also mentioned
earlier I was really interested to
-
understand the exploitation techniques
that they were using that was more
-
important for me at that time. And,
okay, so the jailbreak was released
-
December 2013 and I started doing that
around February 2014, and I did that while
-
having an actual day job, right, so I was
spending at most two days per week on
-
that. So what was my setup? I had an
iPhone 4, and if you know about iPhone 4s
-
they have a boot ROM bug called limera1n
which basically allows you to load
-
arbitrary kernels, unsigned kernels, on
the device and run them and that basically
-
means that you can very easily
set up kernel debugging. So initially I
-
had an iPhone 4 device with iOS 7.0.6. I
want to remind you that iPhone 4 is ARM32,
-
right. I also had an iPhone 5s with the
same version of iOS and I had that in
-
order to verify all my findings and all my
tests on - to redo my tests on an ARM64
-
device and as I told you - the iPhone 5s
at that time was the only ARM64 device.
-
Actually, I think on the market, I don't
think there was another consumer device
-
with ARM64 at that time. So that's the
exact version of version 7 I was analyzing
-
and of course IDA, gdb, lldb. Now the lols
in this slide they don't actually refer to
-
something funny they actually mean
something very painful and that caused a
-
lot of like sleepless nights, but I'll get
onto that. Okay, a few things about the
-
obfuscation. So, not all the functions of
the entire binary were obfuscated, but
-
some of the important ones were, and those
were the ones that were triggering the bug
-
and they were actually doing heap
manipulation and all the other important
-
things. Now I have been told, I haven't
checked that, but I have been told that
-
later versions remove the obfuscation but
I'm not sure about that, I haven't
-
verified it and I already had my
implementation done at that point so I
-
wasn't that interested to look at that. So
as I mentioned the kernel bug that the
-
evasi0n7 untethered binary was based on
was found by p0sixninja, and basically as
-
far as he says on that iPhone wiki page he
used that six line bash script fuzzer to
-
find it. So as you can see he basically
creates device nodes and, with
-
controlled arguments here like minor and
major numbers. Now in order to get to the
-
point to create device nodes you basically
need to be outside of the application
-
sandbox that exists on iOS and you also
need root privileges and that's what I
-
refer to as the userland part of the
evasi0n7 binary and I'm not going to cover
-
that at all. So I'm gonna start my
analysis from the point on that we have
-
escaped the sandbox, we have obtained
root and now we go to exploit the kernel
-
bug. Now that's code from that version of
the XNU kernel that had the bug. Now this
-
ptsd_open function is called everytime
userland code opens a /dev/ptmx device and
-
then this ptmx_get_ioctl function is
called. Now the important thing here
-
is that dev here is completely
user controlled and then
-
it's passed to this ptmx_get_ioctl
-
function with no checks at all, right, and
then this ptmx_get_ioctl function uses
-
this to index an array without any checks.
So basically the bug's an invalid indexing
-
bug, right, so since we can control that
you can put here whatever. I have here the
-
ptmx_ioctl struct that, okay, this array
here is, so this state struct here is
-
global to the kernel and this
pis_ioctl_list array here is on the kernel
-
heap and it is an array of ptmx_ioctl
structs and that's the PTMX ioctl struct
-
and the important thing here is, that
I'm going to refer to again and again
-
during the talk, is that it has a pointer
to a tty struct as the first element of
-
the structure. Okay, so we control the
index to the array, so what can we do with
-
that? So here as you can see it return
the ptmx_get_ioctl function returns
-
whatever it indexes, right. So, as you can
see here is it assigns this pti variable
-
and then does all kinds of interesting
things, so pti is controllable, tp is
-
controllable here as well after this
dereference here to some controllable
-
value and, I mean in other code parts of
the kernel this is called again and so
-
there are there are a lot of things to
consider when you know the bug and
-
then you try to think how to exploit it.
Okay, one important thing here that I
-
wanted to mention is that this ptmx,
this function here ptmx_get_ioctl also
-
does the allocation of this struct here,
of this tty struct here and that's
-
important because I'm going to use further
on. Okay, another important thing is that
-
you basically, this bug what allows you
to do is you can control the size of this
-
array here, so by, can you see that?
Okay, so by repeatedly open the ptmx
-
device you can grow this array and you can
grow it as you see here by this grow
-
vector that's 16, but it doesn't matter.
What matters is that the size of this
-
array in bytes is controllable by you, the
person who are trying to exploit this bug.
-
Now, for example these are notes from my
exploit so if I did one allocation, if I
-
did one open of this ptmx device then this
array was going into kalloc_64. If I was
-
doing 17 it was going to kalloc_128, if I
was doing 33 opens here it was going to
-
kalloc_192 and so on and so forth. So I
could decide in which kalloc zone I could
-
place the array. If you don't know kalloc
zones, they are basically, you can think
-
them as container, you can think kalloc
zones as containers for heap objects on
-
the kernel heap. All of them can be of
different type but they're, all of them
-
are of the same size, right, so kalloc_64
can have different structures of size 64
-
bytes, but all of them are our size 64
bytes. Okay so I started debugging the
-
untethered binary in userland, that's how
I started. So initially I was using gdb
-
and I found out that nothing worked with
gdb. It was at that point Apple was
-
starting to move from gdb to lldb, so I
don't, maybe that was the reason gdb
-
wasn't tested at all. So when I
say nothing worked I mean that I was
-
placing break points and they weren't
hitting and I was trying like stepping and
-
it was continuing execution and stuff like
that. Sometimes I couldn't even attach the
-
binary. So then I moved to lldb, on lldb
set up with debugserver and things were
-
much better. Now, while I was
experimenting stealing from, just with
-
userland debugging my iPhone 4 device went
to into a recovery loop and I wasn't able
-
to get out of it, so I was forced to do a
clean restore of the device. The problem
-
was that at that time only iOS 7.1 was
signed by Apple, so I couldn't install a
-
version of files that hit the kernel that
hit the bug that I was interested to look
-
at, but on the other hand I couldn't not
restore my device because that was the
-
only device I had at the point I could do
kernel debugging with. So I updated my
-
device to 7.1. As I said just told you 7.1
didn't have a vulnerable kernel
-
to this bug, so what I wanted to do was
basically to boot an iOS 7.1 device with a
-
7.0.6 kernel, and in order to do that I
could use the limera1n bug that allowed me
-
to boot arbitrary kernels and the utility
to do that was redsn0w, right. The problem
-
was that redsn0w only supported up to iOS
6 and it wasn't, it didn't have support
-
for iOS 7 so I left all the other things I
was doing and I started reversing redsn0w
-
to understand how it worked. Redsn0w, if
you don't know it's, it was back then
-
and still is closed source, right, so I
started reversing that to understand how
-
it worked in order to support, for me to
hot patch it, to binary
-
patch it to add support for iOS 7 and I
spent like I don't know maybe a month on
-
that and then I realized that it was, it
wasn't leading me anywhere, I couldn't
-
understand a lot of things about how
redsn0w was implemented, so I I stopped
-
doing that, and at that point I found
opensn0w which was an effort by winocm to
-
implement redsn0w as open source. So, it
seemed to have support for iOS 7 and that
-
was good, I tested that and it was
working. Now my problem was that I
-
couldn't have an arbitrary
length of boot-args. Boot-args are the
-
arguments that you pass to the kernel when
it boots and they are really important in
-
iOS because by passing certain boot-args
to the kernel you can disable sign checks,
-
you can enable kernel debugging, so it's
really important to be able to pass
-
arbitrary length boot-args. And iOS 7.1
was using absurd 9 character so that was
-
the reason opensn0w couldn't support more
So what I ended up doing was I patched
-
iBEC, which is basically the loader
of the kernel, right, that passes boot-
-
args to the kernel when it boots and,
basically I changed the pointer to the
-
boot-args to some other place that had
much more space. So at that point I was
-
able to pass arbitrary-length boot-args to
my kernel. So where we are at last? So I
-
had an iPhone 4 device with iOS 7.1 and I
was using opensn0w to boot the 7.0.6
-
kernel that had the bug that I was
interested to exploit. Now, one side note
-
here is that as I was doing that and I was
trying to add to open snow all the patches
-
to the kernel to enable kernel debugging,
I was reversing the evasi0n7 binary as
-
well. Now, the evasi0n7 binary was trying
also to, after it exploited the kernel
-
it was patching it to enable kernel
debugging, but, so I was just copying
-
their patches, right, and adding them to
opensn0w, but I realized at some point
-
that they missed some check for the debug-
enabled variable and KDP wasn't really
-
working, so the session was established
and it seemed like it was working, but if
-
you tried to actually use the kernel,
the KDP, the kernel debugging setup for
-
to do actual, like to attach debugger to
the kernel and do whatever, like place a
-
breakpoint or step then KDP just froze. So
I added another part that was required on
-
that. Ok, so kernel debugging at last, but
that's not really what happened, because
-
you know breakpoints didn't always work so
you were placing a breakpoint and it
-
wasn't hitting when execution was reaching
there and you were trying to step
-
instructions and the execution just
continues, so you were stepping one
-
instruction it was just like you would
type in continue and if you were taking
-
too long to type an lldb command then KDP
froze and then you had to restart your
-
device, re-establish the kernel debugging
session and start from zero. And if you
-
issue commands too fast then KDB froze
again, so you have to reboot again. It was
-
amazing, it was great time. And now I did
similar stuff with iOS 6 and I distinctly
-
remember that was much easier and kernel
debugging worked much better. And... I
-
mean the issue that comes to everyone's
mind that does that is: do Apple engineers
-
really use KDP for debugging the iOS
kernel or do they use something else?
-
Okay, so now I could debug the evasi0n7
untethered binary both from the userland
-
side and from the kernel side, and that
was good because I was analyzing at run
-
time and at the same time I was reversing
it in IDA, so the obfuscation who... I
-
could do it much faster since I was taking
hints from runtime. So I... at that point
-
things started moving fast and I quickly
found that it was abusing the data by
-
structure to obtain read/write access to
physical memory. I mean that was
-
interesting to me, but I was expecting
something else. I was expecting something
-
like what they did in iOS in the evasi0n6
jailbreak, that they did like a lot of
-
heap manipulation and that's my interest
actually, heap exploitation. So at that
-
point I decided to stop reversing it and
reimplement the exploit the way that I
-
wanted to do it. So obviously that wasn't
work from scratch, it was from everything
-
that I understood up to that point, and
what I really wanted to use was the
-
vm_map_copy structures technique by Dowd
and Mandt and I'm going to explain that in
-
the following slides, how it works.
Okay, so at that point I had the clear
-
understanding of the bug, what it was and
I had the general idea like about how to
-
exploit it and I mean if you've done
that you know then it takes a lot of pen
-
and paper like ideas you develop on paper,
then you go test them and they don't work
-
and then you design them again and then
again and you fail and you despair and
-
then you suddenly have an idea and you
spend like I don't know like two nights
-
stay up until 5:00 in the morning testing
things and they don't work and then you
-
despair again and ad nauseam. But
eventually you get somewhere so let's talk
-
about exploitation now. Now, a few things
to refresh your memory about the bug. So
-
as I said it was an invalid indexing bug.
This pis_ioctl_list array was on the heap
-
and I could control in which kalloc zone
it can go. I can grow it, but once I grow
-
it I cannot shrink it back. Now, that's
code from that ptmx_get_ioctl function, so
-
what... basically what it does it
allocates a new ptmx_ioctl structure and
-
then it uses the index that you provide...
that you control to store the address on
-
the array. Now, this allocation here...
this struct here goes into kalloc.88 and
-
that's useful for the next parts. Okay, a
few things about the technique I wanted to
-
use... about the exploitation technique I
wanted to use. So it's the vm_map_copy
-
technique, it was proposed by Dowd and
Mandt and basically they were spraying the
-
heap with these structs here, the
vm_map_copy structs, and assuming you have
-
like some way to corrupt this struct that
you've sprayed on the heap if you can
-
overwrite this kdata element here, then
basically what you have is a leak of
-
kernel memory other adjacent like next to
the kdata, whatever is below or above the
-
kdata pointer or arbitrary if you put
whatever address you want in there. By
-
overwriting the kalloc_size element here
and then freeing the struct on the heap,
-
you put it on a wrong zone and basically
when you allocate it back, since you put
-
it on on a different size zone, you can
have a heap overflow. So that's a general
-
overview of this technique. So but you
corrupt this struct and you get primitive
-
exploitation primitives. Okay, so what was
the idea I had at that point? The idea
-
was to use the... this pis_ioctl_list
index bug to corrupt this kdata pointer
-
here and to have arbitrarily... Sorry, we
have a relative leak of kernel heap
-
memory, and that would be my first step
towards exploiting the bug. Of course the
-
end goal is to have arbitrary read/write,
right, and of course it was just a fuzzy
-
idea at that point and you know that's
always the goal, but when you study the
-
bug and you see the different code paths
and how the things you affect are used,
-
then you have some maybe not completely
concrete things in your mind, but you know
-
that interesting things can happen, so
that's what I had at that point.
-
Okay, so let's talk about the exploitation
strategies now. So at stage one I sprayed
-
the kernel heap with vm_map_copy structs
and I decided to work on the kalloc.256
-
zone, and the reason for that was
completely arbitrary... was because of all
-
the kernel debugging I have done up to
this point of this entire binary I saw
-
that this kalloc zone was not really used
that much, either by the kernel or by
-
whatever the exploit was doing. So...
that's good because it means that you
-
can... you as an exploiter can have much
better control over the kernel heap if
-
there aren't other things placing
allocations on the zone you work. So I
-
decided to use the kalloc.256 zone and I
avoided of course kalloc.384 because the
-
tty structs were going there and that
would really mess up my heap arrangements.
-
So the first... let me actually... ok. So
what I wanted to do was to do this.
-
So initially you spray the heap with
vm_map_copy structs and you control both
-
their size and their contents, the content
don't matter at this point. So it... just
-
the size matters. So I spray with 256
bytes vm_map_copy structs and then I free
-
every other second one and I create this
kind of pattern like a vm_map_copy and a
-
free slot and a vm_map_copy and a free
slot and then I grow the pis_ioctl_list
-
array to 256 bytes and then it goes into
one of these free slots here. Now, the
-
code for doing that looks something like
that, so what this basically does it
-
sends... it creates this... so if you see
here the out of line mach messages as
-
basically these vm_map_copy structs and...
Their size is 256, their buffer doesn't
-
matter at this point and you just send
them like machs and methods. And then
-
after you've sprayed with them then you
free every second one here... with this
-
loop here. So in order to make this free
slot you just receive this mach out of
-
line messages that correspond to the
vm_map_copy structs. And after you've
-
created the holes you basically grow the
array to 256 bytes. How do you do that? As
-
I mentioned earlier you open the dev ptmx
device a number of times. How many times
-
doesn't matter, like a specific number of
times that I mentioned earlier, that I
-
have noticed grows it 256 bytes. So that's
the arrangement you have at that first
-
stage. Okay, so the second stage is done
on the kalloc.88 zone. So I spray again
-
with vm_map_copy structs and this
time I make them 88 bytes to go to
-
the kalloc.88 zone and then I create again
holes. And then I trigger the bug with an
-
invalid index value and remember that when
you trigger the bug a ptmx_ioctl struct is
-
allocated and this goes to kalloc.88. But
because on kalloc.88 I have created this
-
pattern of used free used free it goes
into one of the free slots. So now I have
-
a ptmx_ioctl struct in one of my free
slots. I don't know where that is but I
-
know that it falls into the pattern,
right, so I trigger the bug and remember
-
that basically you control this index,
right, so since I control the index I
-
point it to the vm_map... to the kdata
element of the vm_map_copy struct that I
-
know is below the free slot that the array
went into. I don't know the address,
-
right, I can't put like an address there,
but I can... I know the relatives... the
-
relative distance in bytes because I
created the pattern... the heap pattern.
-
So let's go to... okay. So it looks like
that. So that's my first stage, right,
-
free, vm_map_copy, ... and this is the
same pattern on the kalloc.88 zone.
-
When you trigger the bug, this ptmx_ioctl
structure is allocated. It goes into one
-
of the free slots, right, and then the bug
itself, which is what we see here is...
-
remember you control the index, so this is
the new allocation that went here, and
-
then it goes and stores the address where
the index tells it to store it. But
-
remember that this is controlled, we
control that, so what I do I point this
-
here relatively to the neighboring
vm_map_copy struct at the kdata field,
-
right. So in this kdata field here of the
vm_map_copy struct I have now this
-
address, right. So that's how the heap
looks like. I have here the code, it's
-
very similar to the first stage that you
spray with vm_map_copy structs of size 88,
-
machs and methods, right, and then you
receive every second one, you create the
-
holes on the 88 zone and then you trigger
the bug here, right. This invalid pis
-
index number here is basically what points
relatively here, right. So I have now the
-
address of this ptmx_ioctl struct which is
an address on the kalloc.88 zone. I have
-
it on the kdata field of this vm_map_copy
struct here. So what I do... I can simply
-
receive these methods and in its content I
can see the address of that slot on the
-
kalloc.88 zone. So that's the code to do
that, I simply receive all the messages
-
and that's my address. Okay, so at this
point I only... what I only have is this
-
address here, right? I have the address of
this heap slot. So, at that point I
-
started looking at other code paths that
this invalid index... what other
-
variables this invalid index was
influencing and I found the code path that
-
was actually giving... was giving me a
write and... But in order to reach that I
-
needed to survive several dereferences,
and what I only knew was just the
-
kalloc.88 address, right? Nothing else. So
I will now walk you through everything
-
that gave me this write. So I clean up the
kalloc.256 zone and I spray it again with
-
vm_map_copy structs and create holes
exactly like the previous step...
-
the first stage. Again, next to the
pis_ioctl_list array I have a vm_map_copy
-
struct, but at this time I... in all the
the vm_map_copy structs I put a payload of
-
the... of this fake ptmx_ioctl address I
have. And remember that the first element
-
of the ptmx_ioctl struct is a pointer to
tty struct and I can use the leaked
-
address I have for this pointer that I
don't know... I didn't know where to point
-
it to. So, the next step was to clean up
the kalloc.88 zone and spray it again, and
-
again I sprayed with vm_map_copy structs,
but at this time at their payload I can
-
put now the fake tty struct that the
ptmx_ioctl struct is pointing to. The
-
problem at that point was that the tty
struct with 256 bytes and kalloc.88 has...
-
the slots are only 88 bytes, so I couldn't
just with the elements of the... just with
-
the first 88 byte elements, I couldn't get
to the path that was giving the write, so
-
I needed to find some other way to host my
fake tty struct. So remember that I
-
couldn't work on any other kalloc zone or
anywhere else because what I only knew was
-
the address of that kalloc.88 zone, I had
nothing else to build on. So at that point
-
I started doing a much more complicated
heap arrangement. So instead of spraying
-
just one thing I was spraying... I was
trying to create a pattern of two
-
controlled things. Now, I couldn't use
vm_map_copy structs for both these slots
-
because the vm_map_copy structs has
a header, right? So it would mess up my
-
fake tty struct. So by reading i0n1c's
kernel heap exploitation slides, I
-
realized that I could spray the heap with
XML properties of length 88 from that
-
AppleJPEGDriver and I could place as a
second controlled object after the
-
vm_map_copy struct these XML properties
which are completely controlled in
-
content, and I could host the second part
of the tty struct there. I mean, it's
-
still not 256 bytes, but what it gives me
is the ability to survive all dereferences
-
to reach the write that I was interested
in. Okay. So, a few things about the
-
tty struct. So that's what I got... I
wanted to create on the kalloc.88 zone,
-
right, so that's the tty struct that the
ptmx_ioctl struct is pointing to. Now,
-
what basically I wanted to do here is I
wanted to point... the final thing was
-
to use this clist struct to control this
element here, c_cs, as a start of the ring
-
buffer for the tty, to give me an
arbitrary write... Sorry, to give me a
-
controlled write. I started playing a bit
with to use it to do arbitrary write, but
-
I found that I wasn't able to do it
because at later stage some other parts of
-
the tty struct were needed that I wasn't
able to control, so I only had two
-
88-slots to host my fake tty struct. So
that wasn't stable. So I was only
-
using that to do a relative write. So
we'll see the code later on, let's go to
-
the heap layout. So that's the third
stage. Again, remember I sprayed the
-
kalloc.256 zone with vm_map_copy structs/
frees, just place my pis_ioctl_list array
-
next to vm_map_copy struct. Remember that
I control the contents of vm_map_copy,
-
right, so I placed in the buffer of
vm_map_copy this ptmx_ioctl address that I
-
know and I point the invalid index that I
control to this ptmx_ioctl... this address
-
that I put here. And what is this address?
It's that leaked address that I got in the
-
previous stage which points to the
kalloc.88 zone. And what's the arrangement
-
of that kalloc.88 zone? It's as I told you a
vm_map_copy followed by an XML properties.
-
vm_map_copy, XML properties... And all
this hosts this fake tty struct, right?
-
All these are the same, I just explained
here how it looks like. So this points to
-
the kdata element here and the rest of
it holds the rest of the... all this is
-
basically the fake tty struct, like the
buffer of the vm_map_copy and then
-
following the XML contents of this heap
allocation. And where do I... this c_cs
-
pointer that I told you that I wanted to
control, where do I point it? I point it
-
relatively again, I don't know any
addresses but I can put it relatively
-
since I know the... since I created this
heap arrangement, I can put it relatively
-
to the size of the kalloc size of the
neighboring vm_map_copy struct. And why do
-
I need this? Because I want to use the
vm_map_copy technique by Mandt and Dowd
-
that I mentioned earlier, so that's the
end goal. So what's the code looks like?
-
Okay, that's the spray of 256, we've seen
that a lot of times, then we have the
-
freeze... wait, no, that's not the freeze.
So that's the allocations of the 256...
-
that's... yeah, I don't have the freeze
here because they don't matter, because we
-
have seen them before. So what I have here
is the spray of the kalloc.88 zone and the
-
important thing here is that... what I
wanted to show you that is that at every
-
step I took two allocations. One is the
vm_map_copy struct here with the machs and
-
methods, and the second part is the XML
properties, which are sprayed on the heap
-
when you open the device driver, the
AppleJPEGDriver. And what are the contents
-
of that XML properties? They're basically
that fake... the second part of the fake
-
tty struct that you have the controlled
c_cs pointer that will give me the
-
relative write. So if you see here, I have
this function setup_fake_tty that
-
basically creates the structs so I don't
have to type all the time, and we are at
-
second stage here, and basically what you
can see here is the creation of the
-
fake tty struct, right? So that's the
different elements of the fake tty as we
-
saw it from the code. And that's the write
offset I wanted to... that I pointed to
-
the kdata field of the neighboring
vm_map_copy struct. So, again, that's how
-
it looks like in the heap. Okay, so after
that, after we have arranged the... we
-
have arranged it this way, we trigger
again the invalid index array bug, but at
-
this time on the slave ptmx device. I was
only doing that on a master ptmx device,
-
but in order to reach that write code path
that I mentioned, you need to get on a
-
slave ptmx device. So that's what happens
here. And then you simply write to the
-
corresponding descriptor and it just
dereferences this c_cs that you controlled
-
and your end... and it writes with
whatever you want to write. And what do I
-
want to write? I want to write a new size
for the vm_map_copy struct... for the
-
kalloc size field of the vm... of the
neighboring vm_map_copy struct, so I can
-
use the Dowd and Mandt technique. So,
putting everything together. So at that
-
point I have a controlled corruption of a
vm_map_copy struct and I can use the
-
primitives to get arbitrary... an
arbitrary leak, so I can leak for example
-
the KSLR-slide and I can do a heap
overflow. Again these are how you can use
-
the primitives that Mandt and Dowd gave
us. Now I also know my location on the
-
kernel heap, and remember that... that's
basically... we found that on the stage...
-
on the first... on the first of stages and
we only... we use only that, like where
-
that ptmx_ioctl struct was stored on the
kernel heap, that's the only thing we
-
knew, that address, in order to
successively build on it, in order to
-
reach like a much more useful primitive.
And the important... the interesting thing
-
here is that everything up to this point
is data only, right? So you haven't
-
injected any code, you haven't done
anything at all that you could be caught
-
somehow by a kernel self-protection
mechanism or these kind of things,
-
everything's data only. So once you reach
that point, how do you get PC control? So
-
since you can use Dowd's and and Mandt's
technique, you can basically do a heap
-
overflow, so you can again do a heap
arrangement, you can place IOKit objects
-
next to vm_map_copy structs where you can
overflow from, and you can corrupt IOKit
-
objects and from there you can have...
also you can do an arbitrary write...
-
read/write, so you can... by the arbitrary
read you can read the vtables of the IOKit
-
objects so you know the KSLR-slide
and you can corrupt it in order to get PC
-
control. Of course getting to a whole
jailbreak from that point is out of the
-
scope of this talk, and... but is not that
hard actually from that point on. And
-
okay, so after doing all that how close
was that exploit to the evasi0n... to the
-
real evasi0n7 kernel exploiter? I'd say it
was pretty far off, but I mean it wasn't
-
my point to recreate it like completely,
but it was my point to play with the heap
-
and to try to do complex heap arrangements
and to see how much I understand the iOS
-
kernel heap, that was the point of this
whole exercise for me. Okay, so some
-
lessons learned. So the real surprising
thing for me at that point was that I
-
couldn't believe that Apple does kernel
debugging by KDB. It was very flaky, it
-
was very unstable as I told you. If you
type commands too fast it froze, if you
-
type commands very slowly it had like a
go-stop timer and froze, I think.
-
there was a claim of something like that
and it's unbeliev... I couldn't believe
-
that the Apple engineers were using this
interface to do kernel debugging. So it
-
was really hard to do anything on the
kernel side of idevices. But of course I
-
don't really mean that you shouldn't mess
with these things, right? I mean, these
-
devices are really interesting and it's
really becoming harder to hack them, but I
-
think it's much more fun and I think the
only takeaway may be that you shouldn't
-
report bugs to Apple at all and if you
need street cred you should just report
-
white elephant bugs now. I mean that's
always good. And I mean this very... this
-
is getting very esoteric, right, there are
not a lot of information and Apple keeps
-
changing stuff and everything is closed
source, I mean, all the important parts
-
are closed source... and I mean, I really
think people that work on that things
-
should share notes as much as possible.
Okay, so these are some of the people I
-
was talking to while doing all this and I
want to mention them, and basically that's
-
all of the material I have and I'm open to
any questions you might have.
-
applause
Herald: Thank you, argp, for the talk. So
-
we have prepared microphones 1, 2, 3 and 4
in the room and we have a Signal Angel, I
-
think. You... when you have questions, you
can give me a hand sign, but I
-
think we start with microphone 2 here in
the front. And please ask questions and no
-
comments, there's time after the talk.
Okay, go ahead.
-
Q: Thanks for the awesome talk.
argp: Thanks.
-
Q: I have a question about heap spraying.
Was your heap spraying really stable? If
-
it is not successful, did it crash the
device?
-
argp: Yeah. So I haven't mentioned it
here, but it was pretty stable I think.
-
It was something like... because I did a
lot of tests for that because it was
-
really interesting for me to know. It was
maybe something like 90%, so 9 out of 10
-
times it worked, but if it didn't work -
yeah, then... yes it crashed the kernel
-
and crashed the device, yeah.
Q: And did you try to return heap into
-
some kind of initial state to start your
exploit from scratch?
-
argp: Yeah, that's true I haven't included
that, but you're right. So the initial
-
step on every spray that I mentioned here
was to spray a lot of objects of the
-
specific size you were targeting in order
to get basically a new page of the kalloc
-
zone, right? So you... so even if as I
told you the kalloc 256 zone wasn't
-
that busy, it's still... there were still
allocations going on it, right? So if you
-
did a lot of initial spraying, you were
making sure that when you're... the
-
allocations that mattered to you we're
made, were on a new page that weren't...
-
wasn't too much noise from other
allocations from the kernel. So yeah,
-
you're right I haven't included that, but
yeah, that happened.
-
Q: Thanks, great.
argp: Thanks.
-
Herald: Then microphone 1, please.
Q: Also thank you for your awesome talk
-
again.
argp: Thanks.
-
Q: My question was nowadays it's way
harder to use vm_copy I think Apple truly
-
deprecated it, it's not possible anymore
that due to security. Do you see hope in
-
reconstructing some function that does the
same or is it totally dead now?
-
argp: Oh, you mean the vm_map_copy
technique?
-
Q: Yes.
argp: No, I think it's completely dead
-
now.
Q: All right. And I recently saw on the
-
iOS logs vulnerabilities that again a
vulnerability in AppleJPEGDriver was
-
found. Do you think... have you looked
into it or...
-
argp: Well, Apple... the AppleJPEGDriver
is one of the 4, I think, IOkit drivers
-
that you can reach from the container
sandbox, right? So that means it's very
-
fast by everyone, Apple included, and
very audited. So I'm not saying that there
-
aren't many... there aren't things there,
like interesting findings, but if there
-
are they're not going to live much longer,
I think.
-
Q: Okay, thank you.
Herald: Thanks for your question and now
-
from the Signal Angel a question from the
Internet.
-
Signal Angel: Yes, I have a question from
the internet. How long did this research
-
take you? You said two weeks in the
beginning, but from begin to end, how many
-
hours about? Because you also said it was
during work?
-
argp: No, it didn't it didn't take two
weeks, no. It took like maybe close to
-
three months or two months and something
like that. So I spent... as I mentioned I
-
spent like a complete month, I think, like
- maybe three weeks, maybe not a complete
-
month just on reversing redsn0w and trying
to get redsn0w to play with iOS7. So I
-
wouldn't count this month in the exploit
part of it, right? So if you're interested
-
just in the kernel exploit part I would
say something like maybe seven weeks,
-
something like that. But just with 2 maybe
3 days per week right, not complete weeks.
-
Herald: Okay, then microphone 1,
please.
-
Q: Congratulations on your talk which was
really interesting, I liked it a lot and
-
my question is if the technique you used
to exploit the bug was in FreeBSD or any
-
other BSD as well?
argp: Oh no, no. I mean, the vm_map_copy
-
struct doesn't exist anywhere else except
the XNU kernel. But I think the
-
interesting takeaway is that you can do
complex heap arrangements if you
-
understand the kernel heep allocator,
right? So this process I described by
-
creating holes and maybe controlling 2
allocations in order to host fake
-
structures that you are able then to use
to get exploitation primitives then that's
-
applicable everywhere, right?
Herald: Okay, then we go to microphone 2
-
again, please.
Q: So I saw one sentence, just not report
-
or... just don't report the bugs. I would
like to understand your thinking behind,
-
because I think this is really important
for companies to know the bugs that they
-
made and yeah, make the products better
and this is really beneficial for
-
researcher because for example Apple they
pay a lot of money for the bugs. What...
-
argp: Okay, yeah, I don't have much to say
on that. I mean, apart from: if all the
-
bugs are fixed then you won't be able to
do this kind of work and it's no fun.
-
Sorry, I don't have anything else to say
on that. Sorry, I don't have anything
-
else, no comment.
Herald: Okay. Signal Angel, do we have
-
another question from the internet? Okay,
then please a big round of applause for
-
our speaker!
argp: Thanks.
-
applause
-
postroll music
-
subtitles created by c3subtitles.de
in the year 2020. Join, and help us!