WEBVTT
00:00:00.099 --> 00:00:15.129
34c3 preroll music
00:00:15.129 --> 00:00:19.695
Herald Angel: And now I want to introduce
our first speaker and the topic he's
00:00:19.695 --> 00:00:27.844
talking about. iOS kernel exploitation
archaeology. A kernel exploit from late
00:00:27.844 --> 00:00:35.231
2013 early 2014 will be digged out and
analyzed proper archaeology all the
00:00:35.231 --> 00:00:43.165
digging... digging and analysis is done by
argp here to my left on the stage and give
00:00:43.165 --> 00:00:46.586
him a big round of applause. And the stage
is yours, thanks.
00:00:46.586 --> 00:00:47.882
Applause
00:00:47.882 --> 00:00:58.883
argp: Thanks for the introduction. First
of all, thank you all for being here. As
00:00:58.883 --> 00:01:03.899
the person that did the introduction told
you this is going to be an archeology talk
00:01:03.899 --> 00:01:09.939
so I apologize in advance if it's not that
interesting for you. So we'll talk about a
00:01:09.939 --> 00:01:16.310
bit older stuff rather than new things.
Okay so a bit a few things about myself.
00:01:16.851 --> 00:01:20.923
Actually, I think from all these things,
the most important are the the Phrack
00:01:20.923 --> 00:01:26.830
papers, right? So, yeah. Let's ignore all
the other stuff okay? So, what I'm going
00:01:26.830 --> 00:01:35.059
to talk about. I'm going to talk about the
evasi0n7 kernel exploit. Now evasi0n7 was
00:01:35.059 --> 00:01:42.060
a jailbreak it was released by the evad3rs
on the 22nd of December 2013. It supported
00:01:42.060 --> 00:01:50.210
iOS7 to iOS7.1 beta 3. That's not the
7.1 stable release, right? So that's a
00:01:50.210 --> 00:01:55.759
beta. And this supported all devices at
that time including the iPhone 5s which
00:01:55.759 --> 00:02:03.999
was the first 64-bit device except the
Apple TV. So, I decided to reverse
00:02:03.999 --> 00:02:08.900
engineer the kernel exploit of the
jailbreak focused just on that. Because I
00:02:08.900 --> 00:02:14.170
was really interested, not so much in the
bug itself, which was as we will see not
00:02:14.170 --> 00:02:18.805
very complicated. But I was really
interested to understand the exploitation
00:02:18.805 --> 00:02:25.970
techniques that the evad3rs used. So, I
started reversing it, and I understanding
00:02:25.970 --> 00:02:32.329
it, and at some point I just said I'm just
gonna do a reimplementation of the kernel
00:02:32.329 --> 00:02:37.030
exploit. So, this talk is basically my
notes on this whole process. And, of
00:02:37.030 --> 00:02:42.390
course, it's not a jailbreak walkthrough,
right? And I'm going to specifically focus
00:02:42.390 --> 00:02:50.042
on the various problems I encountered
during this task and how I overcame them.
00:02:50.042 --> 00:02:58.250
And hopefully it's going to give you some
helpful takeways for if you do iOS kernel
00:02:58.250 --> 00:03:05.459
research nowadays. Okay, so, the general
outline is I'm going to say a few things
00:03:05.459 --> 00:03:11.730
about the version 7 to setup the stage.
And then I'm going to explain the kernel
00:03:11.730 --> 00:03:18.971
bug itself. And, then I'm going to talk in
length about my debugging setup. And, I
00:03:18.971 --> 00:03:26.136
think that's a very important step that
usually phone or embedded talks
00:03:26.136 --> 00:03:29.860
exploitation talks don't analyze that
much, and I think it's a really important
00:03:29.860 --> 00:03:36.220
part. Because usually having a working the
debugging set up is, basically, maybe half
00:03:36.220 --> 00:03:41.080
the job of doing a reliable exploit. Then
I'm going to do to talk about my
00:03:41.080 --> 00:03:46.520
reimplementation of the exploit, and
hopefully, at the end, we're gonna have
00:03:46.520 --> 00:03:53.870
some things to take away or maybe not. We
will see. Okay so it was the evasi0n7
00:03:53.870 --> 00:03:59.300
jailbreak was released about 4 years ago.
And that's the archaeology in the title.
00:03:59.300 --> 00:04:04.830
That's ancient history right? And if you
were following the jailbreak community,
00:04:04.830 --> 00:04:12.120
you might remember this huge drama around
this jailbreak, initially, with geohot and
00:04:12.120 --> 00:04:17.160
if he was planning or not to release it
before the evad3rs. And who he was
00:04:17.160 --> 00:04:22.860
planning to sell it to, and some leaked
discussion that he had with some of that
00:04:22.860 --> 00:04:31.070
he was offering money to buy. And geohot,
his jailbreak supposedly using
00:04:31.070 --> 00:04:37.773
some of the bugs the evad3rs were using so
this is a huge drama. And then after the
00:04:37.773 --> 00:04:43.320
evasi0n7 jailbreak released, like maybe a
few hours ago, people realize that if your
00:04:43.320 --> 00:04:54.220
phone had a Chinese locale then the
jailbreak was installing a piracy app. So,
00:04:54.220 --> 00:04:57.440
that was basically a third-party app that
00:04:57.440 --> 00:05:00.660
was taking you to an
app store not operated
00:05:00.660 --> 00:05:05.210
by Apple but by TaiG that had some pirated
versions of the real applications on the
00:05:05.210 --> 00:05:12.700
App Store. And, of course, that also
create like a huge drama, this practice.
00:05:13.695 --> 00:05:17.660
Okay, so a lot of things were said about
the jailbreak at that time and about the
00:05:17.660 --> 00:05:23.820
TaiG pirate App Store. But what I really
set apart was this tweet. And the really
00:05:23.820 --> 00:05:28.030
important thing that I like about this
tweet is, that it doesn't really make
00:05:28.030 --> 00:05:31.430
sense. So he says that we have to decide
to remotely disable the default
00:05:31.430 --> 00:05:35.285
installation of TaiG in China for further
investigations of the piracy. So that
00:05:35.285 --> 00:05:40.740
whole thing doesn't make sense. So you
mean, you didn't know what was happening?
00:05:40.740 --> 00:05:45.490
You didn't bundle it with a jailbreak? Are
you going to disable it for new
00:05:45.490 --> 00:05:50.040
installations? And then, what does
remotely then mean exactly? So what about
00:05:50.040 --> 00:05:56.290
the people that already had the apps, the
piracy app. How are you going to disable
00:05:56.290 --> 00:06:04.520
that? Is that what remotely refers to? So
that's an excellent tweet I think. Okay,
00:06:04.520 --> 00:06:11.370
so some point after the evasi0n7 jailbreak
was released geohot did a writeup on the
00:06:11.370 --> 00:06:19.151
userland part of it. So, he analyzed how
the userland part worked and he stopped at
00:06:19.151 --> 00:06:27.690
the point of gaining root and basically,
he mentioned in his writeup that the
00:06:27.690 --> 00:06:33.185
evasi0n7 untethered binary, which
basically what was good doing the kernel
00:06:33.185 --> 00:06:40.260
exploit, was obfuscated. And as we will
see this was indeed the case and as far as
00:06:40.260 --> 00:06:46.038
I know that's the first jailbreak that
used the deliberate obfuscation. I don't
00:06:46.038 --> 00:06:51.330
know the reason, I assume it's
partly to hide the the piracy
00:06:51.330 --> 00:06:57.243
app store that was bundled with it and
maybe partly to hide the bug, the kernel
00:06:57.243 --> 00:07:07.370
bug, but I'm not sure about the reason.
Now p0sixninja who found as far as I know
00:07:07.370 --> 00:07:12.120
the bug, the kernel bug did a writeup on
the kernel bug, it's on the iPhone wiki,
00:07:12.120 --> 00:07:17.630
and he basically describes the bug and he
stops at the point where he gets a crash
00:07:17.630 --> 00:07:25.530
log from gdb. So he doesn't say anything
about how to exploit it. Okay, so after
00:07:25.530 --> 00:07:31.250
all these things happened then I decided
to reverse engineer the untethered binary
00:07:31.250 --> 00:07:37.180
and understand the exploitation techniques
and I was really interested to reverse
00:07:37.180 --> 00:07:41.289
engineer the obfuscation that the evad3rs
were using, it seemed like an interesting
00:07:41.289 --> 00:07:46.250
challenge, and... but as I also mentioned
earlier I was really interested to
00:07:46.250 --> 00:07:49.795
understand the exploitation techniques
that they were using that was more
00:07:49.795 --> 00:07:58.510
important for me at that time. And,
okay, so the jailbreak was released
00:07:58.510 --> 00:08:06.337
December 2013 and I started doing that
around February 2014, and I did that while
00:08:06.337 --> 00:08:10.310
having an actual day job, right, so I was
spending at most two days per week on
00:08:10.310 --> 00:08:20.360
that. So what was my setup? I had an
iPhone 4, and if you know about iPhone 4s
00:08:20.360 --> 00:08:25.570
they have a boot ROM bug called limera1n
which basically allows you to load
00:08:25.570 --> 00:08:31.520
arbitrary kernels, unsigned kernels, on
the device and run them and that basically
00:08:31.520 --> 00:08:38.049
means that you can very easily
set up kernel debugging. So initially I
00:08:38.049 --> 00:08:46.026
had an iPhone 4 device with iOS 7.0.6. I
want to remind you that iPhone 4 is ARM32,
00:08:46.026 --> 00:08:52.990
right. I also had an iPhone 5s with the
same version of iOS and I had that in
00:08:52.990 --> 00:09:00.269
order to verify all my findings and all my
tests on - to redo my tests on an ARM64
00:09:00.269 --> 00:09:06.279
device and as I told you - the iPhone 5s
at that time was the only ARM64 device.
00:09:06.279 --> 00:09:10.480
Actually, I think on the market, I don't
think there was another consumer device
00:09:10.480 --> 00:09:19.240
with ARM64 at that time. So that's the
exact version of version 7 I was analyzing
00:09:19.240 --> 00:09:26.269
and of course IDA, gdb, lldb. Now the lols
in this slide they don't actually refer to
00:09:26.269 --> 00:09:30.639
something funny they actually mean
something very painful and that caused a
00:09:30.639 --> 00:09:37.090
lot of like sleepless nights, but I'll get
onto that. Okay, a few things about the
00:09:37.090 --> 00:09:44.310
obfuscation. So, not all the functions of
the entire binary were obfuscated, but
00:09:44.310 --> 00:09:51.980
some of the important ones were, and those
were the ones that were triggering the bug
00:09:51.980 --> 00:09:56.930
and they were actually doing heap
manipulation and all the other important
00:09:56.930 --> 00:10:01.180
things. Now I have been told, I haven't
checked that, but I have been told that
00:10:01.180 --> 00:10:05.256
later versions remove the obfuscation but
I'm not sure about that, I haven't
00:10:05.256 --> 00:10:09.769
verified it and I already had my
implementation done at that point so I
00:10:09.769 --> 00:10:20.170
wasn't that interested to look at that. So
as I mentioned the kernel bug that the
00:10:20.170 --> 00:10:26.733
evasi0n7 untethered binary was based on
was found by p0sixninja, and basically as
00:10:26.733 --> 00:10:34.040
far as he says on that iPhone wiki page he
used that six line bash script fuzzer to
00:10:34.040 --> 00:10:41.840
find it. So as you can see he basically
creates device nodes and, with
00:10:41.840 --> 00:10:50.439
controlled arguments here like minor and
major numbers. Now in order to get to the
00:10:50.439 --> 00:10:57.100
point to create device nodes you basically
need to be outside of the application
00:10:57.100 --> 00:11:04.329
sandbox that exists on iOS and you also
need root privileges and that's what I
00:11:04.329 --> 00:11:08.224
refer to as the userland part of the
evasi0n7 binary and I'm not going to cover
00:11:08.224 --> 00:11:14.810
that at all. So I'm gonna start my
analysis from the point on that we have
00:11:14.810 --> 00:11:19.321
escaped the sandbox, we have obtained
root and now we go to exploit the kernel
00:11:19.321 --> 00:11:29.268
bug. Now that's code from that version of
the XNU kernel that had the bug. Now this
00:11:29.268 --> 00:11:39.533
ptsd_open function is called everytime
userland code opens a /dev/ptmx device and
00:11:39.533 --> 00:11:43.936
then this ptmx_get_ioctl function is
called. Now the important thing here
00:11:43.936 --> 00:11:46.779
is that dev here is completely
user controlled and then
00:11:46.779 --> 00:11:49.023
it's passed to this ptmx_get_ioctl
00:11:49.023 --> 00:11:54.759
function with no checks at all, right, and
then this ptmx_get_ioctl function uses
00:11:54.759 --> 00:11:59.949
this to index an array without any checks.
So basically the bug's an invalid indexing
00:11:59.949 --> 00:12:05.618
bug, right, so since we can control that
you can put here whatever. I have here the
00:12:05.618 --> 00:12:14.365
ptmx_ioctl struct that, okay, this array
here is, so this state struct here is
00:12:14.365 --> 00:12:21.790
global to the kernel and this
pis_ioctl_list array here is on the kernel
00:12:21.790 --> 00:12:30.418
heap and it is an array of ptmx_ioctl
structs and that's the PTMX ioctl struct
00:12:30.418 --> 00:12:35.610
and the important thing here is, that
I'm going to refer to again and again
00:12:35.610 --> 00:12:41.289
during the talk, is that it has a pointer
to a tty struct as the first element of
00:12:41.289 --> 00:12:50.680
the structure. Okay, so we control the
index to the array, so what can we do with
00:12:50.680 --> 00:12:57.349
that? So here as you can see it return
the ptmx_get_ioctl function returns
00:12:57.349 --> 00:13:04.961
whatever it indexes, right. So, as you can
see here is it assigns this pti variable
00:13:04.961 --> 00:13:10.682
and then does all kinds of interesting
things, so pti is controllable, tp is
00:13:10.682 --> 00:13:14.163
controllable here as well after this
dereference here to some controllable
00:13:14.163 --> 00:13:21.449
value and, I mean in other code parts of
the kernel this is called again and so
00:13:21.449 --> 00:13:26.980
there are there are a lot of things to
consider when you know the bug and
00:13:26.980 --> 00:13:33.788
then you try to think how to exploit it.
Okay, one important thing here that I
00:13:33.788 --> 00:13:44.380
wanted to mention is that this ptmx,
this function here ptmx_get_ioctl also
00:13:44.380 --> 00:13:51.850
does the allocation of this struct here,
of this tty struct here and that's
00:13:51.850 --> 00:14:00.282
important because I'm going to use further
on. Okay, another important thing is that
00:14:00.282 --> 00:14:05.934
you basically, this bug what allows you
to do is you can control the size of this
00:14:05.934 --> 00:14:14.602
array here, so by, can you see that?
Okay, so by repeatedly open the ptmx
00:14:14.602 --> 00:14:21.824
device you can grow this array and you can
grow it as you see here by this grow
00:14:21.824 --> 00:14:29.830
vector that's 16, but it doesn't matter.
What matters is that the size of this
00:14:29.830 --> 00:14:38.299
array in bytes is controllable by you, the
person who are trying to exploit this bug.
00:14:38.299 --> 00:14:44.679
Now, for example these are notes from my
exploit so if I did one allocation, if I
00:14:44.679 --> 00:14:51.239
did one open of this ptmx device then this
array was going into kalloc_64. If I was
00:14:51.239 --> 00:14:59.089
doing 17 it was going to kalloc_128, if I
was doing 33 opens here it was going to
00:14:59.089 --> 00:15:06.709
kalloc_192 and so on and so forth. So I
could decide in which kalloc zone I could
00:15:06.709 --> 00:15:14.009
place the array. If you don't know kalloc
zones, they are basically, you can think
00:15:14.009 --> 00:15:20.829
them as container, you can think kalloc
zones as containers for heap objects on
00:15:20.829 --> 00:15:26.579
the kernel heap. All of them can be of
different type but they're, all of them
00:15:26.579 --> 00:15:33.265
are of the same size, right, so kalloc_64
can have different structures of size 64
00:15:33.265 --> 00:15:43.258
bytes, but all of them are our size 64
bytes. Okay so I started debugging the
00:15:43.260 --> 00:15:49.936
untethered binary in userland, that's how
I started. So initially I was using gdb
00:15:49.936 --> 00:15:57.889
and I found out that nothing worked with
gdb. It was at that point Apple was
00:15:57.889 --> 00:16:01.641
starting to move from gdb to lldb, so I
don't, maybe that was the reason gdb
00:16:01.641 --> 00:16:05.960
wasn't tested at all. So when I
say nothing worked I mean that I was
00:16:05.960 --> 00:16:11.799
placing break points and they weren't
hitting and I was trying like stepping and
00:16:11.799 --> 00:16:16.269
it was continuing execution and stuff like
that. Sometimes I couldn't even attach the
00:16:16.269 --> 00:16:23.534
binary. So then I moved to lldb, on lldb
set up with debugserver and things were
00:16:23.534 --> 00:16:29.489
much better. Now, while I was
experimenting stealing from, just with
00:16:29.489 --> 00:16:35.436
userland debugging my iPhone 4 device went
to into a recovery loop and I wasn't able
00:16:35.436 --> 00:16:46.339
to get out of it, so I was forced to do a
clean restore of the device. The problem
00:16:46.339 --> 00:16:51.749
was that at that time only iOS 7.1 was
signed by Apple, so I couldn't install a
00:16:51.749 --> 00:16:55.889
version of files that hit the kernel that
hit the bug that I was interested to look
00:16:55.889 --> 00:16:59.610
at, but on the other hand I couldn't not
restore my device because that was the
00:16:59.610 --> 00:17:05.240
only device I had at the point I could do
kernel debugging with. So I updated my
00:17:05.240 --> 00:17:11.805
device to 7.1. As I said just told you 7.1
didn't have a vulnerable kernel
00:17:11.805 --> 00:17:22.208
to this bug, so what I wanted to do was
basically to boot an iOS 7.1 device with a
00:17:22.208 --> 00:17:27.990
7.0.6 kernel, and in order to do that I
could use the limera1n bug that allowed me
00:17:27.990 --> 00:17:32.854
to boot arbitrary kernels and the utility
to do that was redsn0w, right. The problem
00:17:32.854 --> 00:17:40.400
was that redsn0w only supported up to iOS
6 and it wasn't, it didn't have support
00:17:40.400 --> 00:17:46.100
for iOS 7 so I left all the other things I
was doing and I started reversing redsn0w
00:17:46.100 --> 00:17:51.530
to understand how it worked. Redsn0w, if
you don't know it's, it was back then
00:17:51.530 --> 00:17:55.740
and still is closed source, right, so I
started reversing that to understand how
00:17:55.740 --> 00:18:00.875
it worked in order to support, for me to
hot patch it, to binary
00:18:00.875 --> 00:18:06.646
patch it to add support for iOS 7 and I
spent like I don't know maybe a month on
00:18:06.646 --> 00:18:11.699
that and then I realized that it was, it
wasn't leading me anywhere, I couldn't
00:18:11.699 --> 00:18:17.029
understand a lot of things about how
redsn0w was implemented, so I I stopped
00:18:17.029 --> 00:18:25.700
doing that, and at that point I found
opensn0w which was an effort by winocm to
00:18:25.700 --> 00:18:32.160
implement redsn0w as open source. So, it
seemed to have support for iOS 7 and that
00:18:32.160 --> 00:18:40.120
was good, I tested that and it was
working. Now my problem was that I
00:18:40.120 --> 00:18:44.460
couldn't have an arbitrary
length of boot-args. Boot-args are the
00:18:44.460 --> 00:18:48.590
arguments that you pass to the kernel when
it boots and they are really important in
00:18:48.590 --> 00:18:57.630
iOS because by passing certain boot-args
to the kernel you can disable sign checks,
00:18:57.630 --> 00:19:02.320
you can enable kernel debugging, so it's
really important to be able to pass
00:19:02.320 --> 00:19:09.470
arbitrary length boot-args. And iOS 7.1
was using absurd 9 character so that was
00:19:09.470 --> 00:19:15.726
the reason opensn0w couldn't support more
So what I ended up doing was I patched
00:19:15.726 --> 00:19:22.556
iBEC, which is basically the loader
of the kernel, right, that passes boot-
00:19:22.556 --> 00:19:29.935
args to the kernel when it boots and,
basically I changed the pointer to the
00:19:29.935 --> 00:19:35.571
boot-args to some other place that had
much more space. So at that point I was
00:19:35.571 --> 00:19:41.619
able to pass arbitrary-length boot-args to
my kernel. So where we are at last? So I
00:19:41.619 --> 00:19:50.358
had an iPhone 4 device with iOS 7.1 and I
was using opensn0w to boot the 7.0.6
00:19:50.358 --> 00:19:56.795
kernel that had the bug that I was
interested to exploit. Now, one side note
00:19:56.795 --> 00:20:04.161
here is that as I was doing that and I was
trying to add to open snow all the patches
00:20:04.161 --> 00:20:09.762
to the kernel to enable kernel debugging,
I was reversing the evasi0n7 binary as
00:20:09.762 --> 00:20:15.217
well. Now, the evasi0n7 binary was trying
also to, after it exploited the kernel
00:20:15.217 --> 00:20:19.799
it was patching it to enable kernel
debugging, but, so I was just copying
00:20:19.799 --> 00:20:23.740
their patches, right, and adding them to
opensn0w, but I realized at some point
00:20:23.740 --> 00:20:29.919
that they missed some check for the debug-
enabled variable and KDP wasn't really
00:20:29.919 --> 00:20:35.919
working, so the session was established
and it seemed like it was working, but if
00:20:35.919 --> 00:20:40.934
you tried to actually use the kernel,
the KDP, the kernel debugging setup for
00:20:40.934 --> 00:20:45.470
to do actual, like to attach debugger to
the kernel and do whatever, like place a
00:20:45.470 --> 00:20:54.241
breakpoint or step then KDP just froze. So
I added another part that was required on
00:20:54.241 --> 00:21:02.730
that. Ok, so kernel debugging at last, but
that's not really what happened, because
00:21:02.730 --> 00:21:07.981
you know breakpoints didn't always work so
you were placing a breakpoint and it
00:21:07.981 --> 00:21:12.708
wasn't hitting when execution was reaching
there and you were trying to step
00:21:12.708 --> 00:21:17.340
instructions and the execution just
continues, so you were stepping one
00:21:17.340 --> 00:21:21.210
instruction it was just like you would
type in continue and if you were taking
00:21:21.210 --> 00:21:26.755
too long to type an lldb command then KDP
froze and then you had to restart your
00:21:26.755 --> 00:21:33.261
device, re-establish the kernel debugging
session and start from zero. And if you
00:21:33.261 --> 00:21:37.951
issue commands too fast then KDB froze
again, so you have to reboot again. It was
00:21:37.951 --> 00:21:47.320
amazing, it was great time. And now I did
similar stuff with iOS 6 and I distinctly
00:21:47.320 --> 00:21:53.110
remember that was much easier and kernel
debugging worked much better. And... I
00:21:53.110 --> 00:21:58.669
mean the issue that comes to everyone's
mind that does that is: do Apple engineers
00:21:58.669 --> 00:22:05.580
really use KDP for debugging the iOS
kernel or do they use something else?
00:22:06.240 --> 00:22:15.330
Okay, so now I could debug the evasi0n7
untethered binary both from the userland
00:22:15.330 --> 00:22:23.130
side and from the kernel side, and that
was good because I was analyzing at run
00:22:23.130 --> 00:22:31.730
time and at the same time I was reversing
it in IDA, so the obfuscation who... I
00:22:31.730 --> 00:22:38.480
could do it much faster since I was taking
hints from runtime. So I... at that point
00:22:38.480 --> 00:22:42.860
things started moving fast and I quickly
found that it was abusing the data by
00:22:42.860 --> 00:22:49.179
structure to obtain read/write access to
physical memory. I mean that was
00:22:49.179 --> 00:22:52.940
interesting to me, but I was expecting
something else. I was expecting something
00:22:52.940 --> 00:22:58.389
like what they did in iOS in the evasi0n6
jailbreak, that they did like a lot of
00:22:58.389 --> 00:23:04.387
heap manipulation and that's my interest
actually, heap exploitation. So at that
00:23:04.387 --> 00:23:10.370
point I decided to stop reversing it and
reimplement the exploit the way that I
00:23:10.370 --> 00:23:16.190
wanted to do it. So obviously that wasn't
work from scratch, it was from everything
00:23:16.190 --> 00:23:20.330
that I understood up to that point, and
what I really wanted to use was the
00:23:20.330 --> 00:23:25.410
vm_map_copy structures technique by Dowd
and Mandt and I'm going to explain that in
00:23:25.410 --> 00:23:31.669
the following slides, how it works.
Okay, so at that point I had the clear
00:23:31.669 --> 00:23:37.090
understanding of the bug, what it was and
I had the general idea like about how to
00:23:37.090 --> 00:23:41.779
exploit it and I mean if you've done
that you know then it takes a lot of pen
00:23:41.779 --> 00:23:47.980
and paper like ideas you develop on paper,
then you go test them and they don't work
00:23:47.980 --> 00:23:53.409
and then you design them again and then
again and you fail and you despair and
00:23:53.409 --> 00:23:58.289
then you suddenly have an idea and you
spend like I don't know like two nights
00:23:58.289 --> 00:24:04.029
stay up until 5:00 in the morning testing
things and they don't work and then you
00:24:04.029 --> 00:24:10.700
despair again and ad nauseam. But
eventually you get somewhere so let's talk
00:24:10.700 --> 00:24:18.630
about exploitation now. Now, a few things
to refresh your memory about the bug. So
00:24:18.630 --> 00:24:26.200
as I said it was an invalid indexing bug.
This pis_ioctl_list array was on the heap
00:24:26.200 --> 00:24:32.760
and I could control in which kalloc zone
it can go. I can grow it, but once I grow
00:24:32.760 --> 00:24:42.700
it I cannot shrink it back. Now, that's
code from that ptmx_get_ioctl function, so
00:24:42.700 --> 00:24:46.760
what... basically what it does it
allocates a new ptmx_ioctl structure and
00:24:46.760 --> 00:24:53.294
then it uses the index that you provide...
that you control to store the address on
00:24:53.294 --> 00:25:01.090
the array. Now, this allocation here...
this struct here goes into kalloc.88 and
00:25:01.090 --> 00:25:07.895
that's useful for the next parts. Okay, a
few things about the technique I wanted to
00:25:07.895 --> 00:25:13.000
use... about the exploitation technique I
wanted to use. So it's the vm_map_copy
00:25:13.000 --> 00:25:19.160
technique, it was proposed by Dowd and
Mandt and basically they were spraying the
00:25:19.160 --> 00:25:24.779
heap with these structs here, the
vm_map_copy structs, and assuming you have
00:25:24.779 --> 00:25:31.250
like some way to corrupt this struct that
you've sprayed on the heap if you can
00:25:31.250 --> 00:25:39.299
overwrite this kdata element here, then
basically what you have is a leak of
00:25:39.299 --> 00:25:44.669
kernel memory other adjacent like next to
the kdata, whatever is below or above the
00:25:44.669 --> 00:25:49.941
kdata pointer or arbitrary if you put
whatever address you want in there. By
00:25:49.941 --> 00:25:58.019
overwriting the kalloc_size element here
and then freeing the struct on the heap,
00:25:58.019 --> 00:26:03.909
you put it on a wrong zone and basically
when you allocate it back, since you put
00:26:03.909 --> 00:26:10.157
it on on a different size zone, you can
have a heap overflow. So that's a general
00:26:10.157 --> 00:26:14.021
overview of this technique. So but you
corrupt this struct and you get primitive
00:26:14.021 --> 00:26:21.840
exploitation primitives. Okay, so what was
the idea I had at that point? The idea
00:26:21.840 --> 00:26:28.659
was to use the... this pis_ioctl_list
index bug to corrupt this kdata pointer
00:26:28.659 --> 00:26:38.370
here and to have arbitrarily... Sorry, we
have a relative leak of kernel heap
00:26:38.370 --> 00:26:44.760
memory, and that would be my first step
towards exploiting the bug. Of course the
00:26:44.760 --> 00:26:52.480
end goal is to have arbitrary read/write,
right, and of course it was just a fuzzy
00:26:52.480 --> 00:26:56.269
idea at that point and you know that's
always the goal, but when you study the
00:26:56.269 --> 00:27:03.620
bug and you see the different code paths
and how the things you affect are used,
00:27:03.620 --> 00:27:08.330
then you have some maybe not completely
concrete things in your mind, but you know
00:27:08.330 --> 00:27:14.234
that interesting things can happen, so
that's what I had at that point.
00:27:14.234 --> 00:27:23.871
Okay, so let's talk about the exploitation
strategies now. So at stage one I sprayed
00:27:23.871 --> 00:27:31.399
the kernel heap with vm_map_copy structs
and I decided to work on the kalloc.256
00:27:31.399 --> 00:27:36.279
zone, and the reason for that was
completely arbitrary... was because of all
00:27:36.279 --> 00:27:40.590
the kernel debugging I have done up to
this point of this entire binary I saw
00:27:40.590 --> 00:27:45.860
that this kalloc zone was not really used
that much, either by the kernel or by
00:27:45.860 --> 00:27:51.970
whatever the exploit was doing. So...
that's good because it means that you
00:27:51.970 --> 00:27:55.950
can... you as an exploiter can have much
better control over the kernel heap if
00:27:55.950 --> 00:28:04.701
there aren't other things placing
allocations on the zone you work. So I
00:28:04.701 --> 00:28:12.610
decided to use the kalloc.256 zone and I
avoided of course kalloc.384 because the
00:28:12.610 --> 00:28:20.559
tty structs were going there and that
would really mess up my heap arrangements.
00:28:20.559 --> 00:28:30.286
So the first... let me actually... ok. So
what I wanted to do was to do this.
00:28:30.286 --> 00:28:37.249
So initially you spray the heap with
vm_map_copy structs and you control both
00:28:37.249 --> 00:28:41.820
their size and their contents, the content
don't matter at this point. So it... just
00:28:41.820 --> 00:28:48.419
the size matters. So I spray with 256
bytes vm_map_copy structs and then I free
00:28:48.419 --> 00:28:53.131
every other second one and I create this
kind of pattern like a vm_map_copy and a
00:28:53.131 --> 00:28:59.210
free slot and a vm_map_copy and a free
slot and then I grow the pis_ioctl_list
00:28:59.210 --> 00:29:08.620
array to 256 bytes and then it goes into
one of these free slots here. Now, the
00:29:08.620 --> 00:29:14.990
code for doing that looks something like
that, so what this basically does it
00:29:14.990 --> 00:29:24.509
sends... it creates this... so if you see
here the out of line mach messages as
00:29:24.509 --> 00:29:31.570
basically these vm_map_copy structs and...
Their size is 256, their buffer doesn't
00:29:31.570 --> 00:29:37.950
matter at this point and you just send
them like machs and methods. And then
00:29:37.950 --> 00:29:42.990
after you've sprayed with them then you
free every second one here... with this
00:29:42.990 --> 00:29:51.779
loop here. So in order to make this free
slot you just receive this mach out of
00:29:51.779 --> 00:29:58.027
line messages that correspond to the
vm_map_copy structs. And after you've
00:29:58.027 --> 00:30:04.519
created the holes you basically grow the
array to 256 bytes. How do you do that? As
00:30:04.519 --> 00:30:12.010
I mentioned earlier you open the dev ptmx
device a number of times. How many times
00:30:12.010 --> 00:30:18.429
doesn't matter, like a specific number of
times that I mentioned earlier, that I
00:30:18.429 --> 00:30:26.370
have noticed grows it 256 bytes. So that's
the arrangement you have at that first
00:30:26.370 --> 00:30:35.520
stage. Okay, so the second stage is done
on the kalloc.88 zone. So I spray again
00:30:35.520 --> 00:30:41.640
with vm_map_copy structs and this
time I make them 88 bytes to go to
00:30:41.640 --> 00:30:50.570
the kalloc.88 zone and then I create again
holes. And then I trigger the bug with an
00:30:50.570 --> 00:30:56.250
invalid index value and remember that when
you trigger the bug a ptmx_ioctl struct is
00:30:56.250 --> 00:31:01.610
allocated and this goes to kalloc.88. But
because on kalloc.88 I have created this
00:31:01.610 --> 00:31:06.840
pattern of used free used free it goes
into one of the free slots. So now I have
00:31:06.840 --> 00:31:13.620
a ptmx_ioctl struct in one of my free
slots. I don't know where that is but I
00:31:13.620 --> 00:31:23.089
know that it falls into the pattern,
right, so I trigger the bug and remember
00:31:23.089 --> 00:31:29.200
that basically you control this index,
right, so since I control the index I
00:31:29.200 --> 00:31:35.270
point it to the vm_map... to the kdata
element of the vm_map_copy struct that I
00:31:35.270 --> 00:31:39.809
know is below the free slot that the array
went into. I don't know the address,
00:31:39.809 --> 00:31:46.950
right, I can't put like an address there,
but I can... I know the relatives... the
00:31:46.950 --> 00:31:52.330
relative distance in bytes because I
created the pattern... the heap pattern.
00:31:52.330 --> 00:31:58.289
So let's go to... okay. So it looks like
that. So that's my first stage, right,
00:31:58.289 --> 00:32:02.594
free, vm_map_copy, ... and this is the
same pattern on the kalloc.88 zone.
00:32:02.594 --> 00:32:08.000
When you trigger the bug, this ptmx_ioctl
structure is allocated. It goes into one
00:32:08.000 --> 00:32:16.590
of the free slots, right, and then the bug
itself, which is what we see here is...
00:32:16.590 --> 00:32:21.340
remember you control the index, so this is
the new allocation that went here, and
00:32:21.340 --> 00:32:27.210
then it goes and stores the address where
the index tells it to store it. But
00:32:27.210 --> 00:32:31.499
remember that this is controlled, we
control that, so what I do I point this
00:32:31.499 --> 00:32:36.809
here relatively to the neighboring
vm_map_copy struct at the kdata field,
00:32:36.809 --> 00:32:42.465
right. So in this kdata field here of the
vm_map_copy struct I have now this
00:32:42.465 --> 00:32:52.740
address, right. So that's how the heap
looks like. I have here the code, it's
00:32:52.740 --> 00:33:00.660
very similar to the first stage that you
spray with vm_map_copy structs of size 88,
00:33:00.660 --> 00:33:05.919
machs and methods, right, and then you
receive every second one, you create the
00:33:05.919 --> 00:33:15.909
holes on the 88 zone and then you trigger
the bug here, right. This invalid pis
00:33:15.909 --> 00:33:29.610
index number here is basically what points
relatively here, right. So I have now the
00:33:29.610 --> 00:33:37.179
address of this ptmx_ioctl struct which is
an address on the kalloc.88 zone. I have
00:33:37.179 --> 00:33:42.669
it on the kdata field of this vm_map_copy
struct here. So what I do... I can simply
00:33:42.669 --> 00:33:51.350
receive these methods and in its content I
can see the address of that slot on the
00:33:51.350 --> 00:34:00.539
kalloc.88 zone. So that's the code to do
that, I simply receive all the messages
00:34:00.539 --> 00:34:12.080
and that's my address. Okay, so at this
point I only... what I only have is this
00:34:12.080 --> 00:34:21.500
address here, right? I have the address of
this heap slot. So, at that point I
00:34:21.500 --> 00:34:28.699
started looking at other code paths that
this invalid index... what other
00:34:28.699 --> 00:34:34.595
variables this invalid index was
influencing and I found the code path that
00:34:34.595 --> 00:34:40.270
was actually giving... was giving me a
write and... But in order to reach that I
00:34:40.270 --> 00:34:45.570
needed to survive several dereferences,
and what I only knew was just the
00:34:45.570 --> 00:34:50.790
kalloc.88 address, right? Nothing else. So
I will now walk you through everything
00:34:50.790 --> 00:35:00.710
that gave me this write. So I clean up the
kalloc.256 zone and I spray it again with
00:35:00.710 --> 00:35:06.384
vm_map_copy structs and create holes
exactly like the previous step...
00:35:06.384 --> 00:35:15.073
the first stage. Again, next to the
pis_ioctl_list array I have a vm_map_copy
00:35:15.073 --> 00:35:23.110
struct, but at this time I... in all the
the vm_map_copy structs I put a payload of
00:35:23.110 --> 00:35:29.890
the... of this fake ptmx_ioctl address I
have. And remember that the first element
00:35:29.890 --> 00:35:40.250
of the ptmx_ioctl struct is a pointer to
tty struct and I can use the leaked
00:35:40.250 --> 00:35:44.860
address I have for this pointer that I
don't know... I didn't know where to point
00:35:44.860 --> 00:35:52.880
it to. So, the next step was to clean up
the kalloc.88 zone and spray it again, and
00:35:52.880 --> 00:35:58.650
again I sprayed with vm_map_copy structs,
but at this time at their payload I can
00:35:58.650 --> 00:36:07.231
put now the fake tty struct that the
ptmx_ioctl struct is pointing to. The
00:36:07.231 --> 00:36:15.780
problem at that point was that the tty
struct with 256 bytes and kalloc.88 has...
00:36:15.780 --> 00:36:22.480
the slots are only 88 bytes, so I couldn't
just with the elements of the... just with
00:36:22.480 --> 00:36:29.311
the first 88 byte elements, I couldn't get
to the path that was giving the write, so
00:36:29.311 --> 00:36:44.730
I needed to find some other way to host my
fake tty struct. So remember that I
00:36:44.730 --> 00:36:50.730
couldn't work on any other kalloc zone or
anywhere else because what I only knew was
00:36:50.730 --> 00:36:59.207
the address of that kalloc.88 zone, I had
nothing else to build on. So at that point
00:36:59.207 --> 00:37:07.070
I started doing a much more complicated
heap arrangement. So instead of spraying
00:37:07.070 --> 00:37:15.830
just one thing I was spraying... I was
trying to create a pattern of two
00:37:15.830 --> 00:37:20.480
controlled things. Now, I couldn't use
vm_map_copy structs for both these slots
00:37:20.480 --> 00:37:24.930
because the vm_map_copy structs has
a header, right? So it would mess up my
00:37:24.930 --> 00:37:34.390
fake tty struct. So by reading i0n1c's
kernel heap exploitation slides, I
00:37:34.390 --> 00:37:40.828
realized that I could spray the heap with
XML properties of length 88 from that
00:37:40.828 --> 00:37:48.411
AppleJPEGDriver and I could place as a
second controlled object after the
00:37:48.411 --> 00:37:53.130
vm_map_copy struct these XML properties
which are completely controlled in
00:37:53.130 --> 00:37:58.190
content, and I could host the second part
of the tty struct there. I mean, it's
00:37:58.190 --> 00:38:06.190
still not 256 bytes, but what it gives me
is the ability to survive all dereferences
00:38:06.190 --> 00:38:14.430
to reach the write that I was interested
in. Okay. So, a few things about the
00:38:14.430 --> 00:38:20.080
tty struct. So that's what I got... I
wanted to create on the kalloc.88 zone,
00:38:20.080 --> 00:38:28.051
right, so that's the tty struct that the
ptmx_ioctl struct is pointing to. Now,
00:38:28.051 --> 00:38:38.230
what basically I wanted to do here is I
wanted to point... the final thing was
00:38:38.230 --> 00:38:45.610
to use this clist struct to control this
element here, c_cs, as a start of the ring
00:38:45.610 --> 00:38:50.609
buffer for the tty, to give me an
arbitrary write... Sorry, to give me a
00:38:50.609 --> 00:38:56.500
controlled write. I started playing a bit
with to use it to do arbitrary write, but
00:38:56.500 --> 00:39:04.340
I found that I wasn't able to do it
because at later stage some other parts of
00:39:04.340 --> 00:39:09.957
the tty struct were needed that I wasn't
able to control, so I only had two
00:39:09.957 --> 00:39:17.500
88-slots to host my fake tty struct. So
that wasn't stable. So I was only
00:39:17.500 --> 00:39:25.660
using that to do a relative write. So
we'll see the code later on, let's go to
00:39:25.660 --> 00:39:32.430
the heap layout. So that's the third
stage. Again, remember I sprayed the
00:39:32.430 --> 00:39:38.940
kalloc.256 zone with vm_map_copy structs/
frees, just place my pis_ioctl_list array
00:39:38.940 --> 00:39:43.150
next to vm_map_copy struct. Remember that
I control the contents of vm_map_copy,
00:39:43.150 --> 00:39:52.270
right, so I placed in the buffer of
vm_map_copy this ptmx_ioctl address that I
00:39:52.270 --> 00:39:59.650
know and I point the invalid index that I
control to this ptmx_ioctl... this address
00:39:59.650 --> 00:40:03.830
that I put here. And what is this address?
It's that leaked address that I got in the
00:40:03.830 --> 00:40:11.550
previous stage which points to the
kalloc.88 zone. And what's the arrangement
00:40:11.550 --> 00:40:16.780
of that kalloc.88 zone? It's as I told you a
vm_map_copy followed by an XML properties.
00:40:16.780 --> 00:40:21.170
vm_map_copy, XML properties... And all
this hosts this fake tty struct, right?
00:40:21.170 --> 00:40:28.160
All these are the same, I just explained
here how it looks like. So this points to
00:40:28.160 --> 00:40:35.090
the kdata element here and the rest of
it holds the rest of the... all this is
00:40:35.090 --> 00:40:39.660
basically the fake tty struct, like the
buffer of the vm_map_copy and then
00:40:39.660 --> 00:40:47.370
following the XML contents of this heap
allocation. And where do I... this c_cs
00:40:47.370 --> 00:40:53.045
pointer that I told you that I wanted to
control, where do I point it? I point it
00:40:53.045 --> 00:40:56.572
relatively again, I don't know any
addresses but I can put it relatively
00:40:56.572 --> 00:41:02.420
since I know the... since I created this
heap arrangement, I can put it relatively
00:41:02.420 --> 00:41:07.380
to the size of the kalloc size of the
neighboring vm_map_copy struct. And why do
00:41:07.380 --> 00:41:13.720
I need this? Because I want to use the
vm_map_copy technique by Mandt and Dowd
00:41:13.720 --> 00:41:20.060
that I mentioned earlier, so that's the
end goal. So what's the code looks like?
00:41:20.060 --> 00:41:25.910
Okay, that's the spray of 256, we've seen
that a lot of times, then we have the
00:41:25.910 --> 00:41:34.004
freeze... wait, no, that's not the freeze.
So that's the allocations of the 256...
00:41:34.004 --> 00:41:37.864
that's... yeah, I don't have the freeze
here because they don't matter, because we
00:41:37.864 --> 00:41:42.880
have seen them before. So what I have here
is the spray of the kalloc.88 zone and the
00:41:42.880 --> 00:41:46.720
important thing here is that... what I
wanted to show you that is that at every
00:41:46.720 --> 00:41:53.510
step I took two allocations. One is the
vm_map_copy struct here with the machs and
00:41:53.510 --> 00:42:00.840
methods, and the second part is the XML
properties, which are sprayed on the heap
00:42:00.840 --> 00:42:09.920
when you open the device driver, the
AppleJPEGDriver. And what are the contents
00:42:09.920 --> 00:42:15.590
of that XML properties? They're basically
that fake... the second part of the fake
00:42:15.590 --> 00:42:20.282
tty struct that you have the controlled
c_cs pointer that will give me the
00:42:20.282 --> 00:42:27.438
relative write. So if you see here, I have
this function setup_fake_tty that
00:42:27.438 --> 00:42:33.230
basically creates the structs so I don't
have to type all the time, and we are at
00:42:33.230 --> 00:42:37.740
second stage here, and basically what you
can see here is the creation of the
00:42:37.740 --> 00:42:41.770
fake tty struct, right? So that's the
different elements of the fake tty as we
00:42:41.770 --> 00:42:47.690
saw it from the code. And that's the write
offset I wanted to... that I pointed to
00:42:47.690 --> 00:42:54.050
the kdata field of the neighboring
vm_map_copy struct. So, again, that's how
00:42:54.050 --> 00:43:02.360
it looks like in the heap. Okay, so after
that, after we have arranged the... we
00:43:02.360 --> 00:43:08.780
have arranged it this way, we trigger
again the invalid index array bug, but at
00:43:08.780 --> 00:43:13.920
this time on the slave ptmx device. I was
only doing that on a master ptmx device,
00:43:13.920 --> 00:43:18.070
but in order to reach that write code path
that I mentioned, you need to get on a
00:43:18.070 --> 00:43:24.080
slave ptmx device. So that's what happens
here. And then you simply write to the
00:43:24.080 --> 00:43:29.830
corresponding descriptor and it just
dereferences this c_cs that you controlled
00:43:29.830 --> 00:43:33.860
and your end... and it writes with
whatever you want to write. And what do I
00:43:33.860 --> 00:43:39.010
want to write? I want to write a new size
for the vm_map_copy struct... for the
00:43:39.010 --> 00:43:42.841
kalloc size field of the vm... of the
neighboring vm_map_copy struct, so I can
00:43:42.841 --> 00:43:52.730
use the Dowd and Mandt technique. So,
putting everything together. So at that
00:43:52.730 --> 00:43:57.410
point I have a controlled corruption of a
vm_map_copy struct and I can use the
00:43:57.410 --> 00:44:04.000
primitives to get arbitrary... an
arbitrary leak, so I can leak for example
00:44:04.000 --> 00:44:10.230
the KSLR-slide and I can do a heap
overflow. Again these are how you can use
00:44:10.230 --> 00:44:18.580
the primitives that Mandt and Dowd gave
us. Now I also know my location on the
00:44:18.580 --> 00:44:24.610
kernel heap, and remember that... that's
basically... we found that on the stage...
00:44:24.610 --> 00:44:29.380
on the first... on the first of stages and
we only... we use only that, like where
00:44:29.380 --> 00:44:36.580
that ptmx_ioctl struct was stored on the
kernel heap, that's the only thing we
00:44:36.580 --> 00:44:41.770
knew, that address, in order to
successively build on it, in order to
00:44:41.770 --> 00:44:47.200
reach like a much more useful primitive.
And the important... the interesting thing
00:44:47.200 --> 00:44:50.690
here is that everything up to this point
is data only, right? So you haven't
00:44:50.690 --> 00:44:55.090
injected any code, you haven't done
anything at all that you could be caught
00:44:55.090 --> 00:45:00.850
somehow by a kernel self-protection
mechanism or these kind of things,
00:45:00.850 --> 00:45:10.310
everything's data only. So once you reach
that point, how do you get PC control? So
00:45:10.310 --> 00:45:18.400
since you can use Dowd's and and Mandt's
technique, you can basically do a heap
00:45:18.400 --> 00:45:23.480
overflow, so you can again do a heap
arrangement, you can place IOKit objects
00:45:23.480 --> 00:45:31.000
next to vm_map_copy structs where you can
overflow from, and you can corrupt IOKit
00:45:31.000 --> 00:45:36.840
objects and from there you can have...
also you can do an arbitrary write...
00:45:36.840 --> 00:45:43.470
read/write, so you can... by the arbitrary
read you can read the vtables of the IOKit
00:45:43.470 --> 00:45:48.650
objects so you know the KSLR-slide
and you can corrupt it in order to get PC
00:45:48.650 --> 00:45:55.500
control. Of course getting to a whole
jailbreak from that point is out of the
00:45:55.500 --> 00:46:01.030
scope of this talk, and... but is not that
hard actually from that point on. And
00:46:01.030 --> 00:46:09.551
okay, so after doing all that how close
was that exploit to the evasi0n... to the
00:46:09.551 --> 00:46:15.660
real evasi0n7 kernel exploiter? I'd say it
was pretty far off, but I mean it wasn't
00:46:15.660 --> 00:46:22.040
my point to recreate it like completely,
but it was my point to play with the heap
00:46:22.040 --> 00:46:29.260
and to try to do complex heap arrangements
and to see how much I understand the iOS
00:46:29.260 --> 00:46:36.730
kernel heap, that was the point of this
whole exercise for me. Okay, so some
00:46:36.730 --> 00:46:44.290
lessons learned. So the real surprising
thing for me at that point was that I
00:46:44.290 --> 00:46:52.760
couldn't believe that Apple does kernel
debugging by KDB. It was very flaky, it
00:46:52.760 --> 00:46:57.630
was very unstable as I told you. If you
type commands too fast it froze, if you
00:46:57.630 --> 00:47:03.430
type commands very slowly it had like a
go-stop timer and froze, I think.
00:47:03.430 --> 00:47:08.280
there was a claim of something like that
and it's unbeliev... I couldn't believe
00:47:08.280 --> 00:47:14.670
that the Apple engineers were using this
interface to do kernel debugging. So it
00:47:14.670 --> 00:47:23.730
was really hard to do anything on the
kernel side of idevices. But of course I
00:47:23.730 --> 00:47:27.280
don't really mean that you shouldn't mess
with these things, right? I mean, these
00:47:27.280 --> 00:47:31.941
devices are really interesting and it's
really becoming harder to hack them, but I
00:47:31.941 --> 00:47:37.070
think it's much more fun and I think the
only takeaway may be that you shouldn't
00:47:37.070 --> 00:47:41.310
report bugs to Apple at all and if you
need street cred you should just report
00:47:41.310 --> 00:47:48.060
white elephant bugs now. I mean that's
always good. And I mean this very... this
00:47:48.060 --> 00:47:52.220
is getting very esoteric, right, there are
not a lot of information and Apple keeps
00:47:52.220 --> 00:47:55.690
changing stuff and everything is closed
source, I mean, all the important parts
00:47:55.690 --> 00:48:01.110
are closed source... and I mean, I really
think people that work on that things
00:48:01.110 --> 00:48:08.240
should share notes as much as possible.
Okay, so these are some of the people I
00:48:08.240 --> 00:48:15.190
was talking to while doing all this and I
want to mention them, and basically that's
00:48:15.190 --> 00:48:21.570
all of the material I have and I'm open to
any questions you might have.
00:48:21.570 --> 00:48:32.850
applause
Herald: Thank you, argp, for the talk. So
00:48:32.850 --> 00:48:42.831
we have prepared microphones 1, 2, 3 and 4
in the room and we have a Signal Angel, I
00:48:42.831 --> 00:48:50.870
think. You... when you have questions, you
can give me a hand sign, but I
00:48:50.870 --> 00:48:58.050
think we start with microphone 2 here in
the front. And please ask questions and no
00:48:58.050 --> 00:49:01.510
comments, there's time after the talk.
Okay, go ahead.
00:49:01.510 --> 00:49:03.830
Q: Thanks for the awesome talk.
argp: Thanks.
00:49:03.830 --> 00:49:11.960
Q: I have a question about heap spraying.
Was your heap spraying really stable? If
00:49:11.960 --> 00:49:17.080
it is not successful, did it crash the
device?
00:49:17.080 --> 00:49:21.850
argp: Yeah. So I haven't mentioned it
here, but it was pretty stable I think.
00:49:21.850 --> 00:49:25.130
It was something like... because I did a
lot of tests for that because it was
00:49:25.130 --> 00:49:31.480
really interesting for me to know. It was
maybe something like 90%, so 9 out of 10
00:49:31.480 --> 00:49:35.141
times it worked, but if it didn't work -
yeah, then... yes it crashed the kernel
00:49:35.141 --> 00:49:40.250
and crashed the device, yeah.
Q: And did you try to return heap into
00:49:40.250 --> 00:49:44.990
some kind of initial state to start your
exploit from scratch?
00:49:44.990 --> 00:49:50.230
argp: Yeah, that's true I haven't included
that, but you're right. So the initial
00:49:50.230 --> 00:49:56.860
step on every spray that I mentioned here
was to spray a lot of objects of the
00:49:56.860 --> 00:50:01.740
specific size you were targeting in order
to get basically a new page of the kalloc
00:50:01.740 --> 00:50:07.120
zone, right? So you... so even if as I
told you the kalloc 256 zone wasn't
00:50:07.120 --> 00:50:11.220
that busy, it's still... there were still
allocations going on it, right? So if you
00:50:11.220 --> 00:50:16.390
did a lot of initial spraying, you were
making sure that when you're... the
00:50:16.390 --> 00:50:21.690
allocations that mattered to you we're
made, were on a new page that weren't...
00:50:21.690 --> 00:50:24.110
wasn't too much noise from other
allocations from the kernel. So yeah,
00:50:24.110 --> 00:50:26.930
you're right I haven't included that, but
yeah, that happened.
00:50:26.930 --> 00:50:29.900
Q: Thanks, great.
argp: Thanks.
00:50:29.900 --> 00:50:36.200
Herald: Then microphone 1, please.
Q: Also thank you for your awesome talk
00:50:36.200 --> 00:50:37.710
again.
argp: Thanks.
00:50:37.710 --> 00:50:43.609
Q: My question was nowadays it's way
harder to use vm_copy I think Apple truly
00:50:43.609 --> 00:50:49.480
deprecated it, it's not possible anymore
that due to security. Do you see hope in
00:50:49.480 --> 00:50:54.560
reconstructing some function that does the
same or is it totally dead now?
00:50:54.560 --> 00:50:57.780
argp: Oh, you mean the vm_map_copy
technique?
00:50:57.780 --> 00:51:00.740
Q: Yes.
argp: No, I think it's completely dead
00:51:00.740 --> 00:51:03.940
now.
Q: All right. And I recently saw on the
00:51:03.940 --> 00:51:10.310
iOS logs vulnerabilities that again a
vulnerability in AppleJPEGDriver was
00:51:10.310 --> 00:51:15.060
found. Do you think... have you looked
into it or...
00:51:15.060 --> 00:51:20.050
argp: Well, Apple... the AppleJPEGDriver
is one of the 4, I think, IOkit drivers
00:51:20.050 --> 00:51:25.820
that you can reach from the container
sandbox, right? So that means it's very
00:51:25.820 --> 00:51:31.260
fast by everyone, Apple included, and
very audited. So I'm not saying that there
00:51:31.260 --> 00:51:36.170
aren't many... there aren't things there,
like interesting findings, but if there
00:51:36.170 --> 00:51:38.640
are they're not going to live much longer,
I think.
00:51:38.640 --> 00:51:41.680
Q: Okay, thank you.
Herald: Thanks for your question and now
00:51:41.680 --> 00:51:45.000
from the Signal Angel a question from the
Internet.
00:51:45.000 --> 00:51:48.650
Signal Angel: Yes, I have a question from
the internet. How long did this research
00:51:48.650 --> 00:51:52.800
take you? You said two weeks in the
beginning, but from begin to end, how many
00:51:52.800 --> 00:51:55.430
hours about? Because you also said it was
during work?
00:51:55.430 --> 00:51:59.750
argp: No, it didn't it didn't take two
weeks, no. It took like maybe close to
00:51:59.750 --> 00:52:05.030
three months or two months and something
like that. So I spent... as I mentioned I
00:52:05.030 --> 00:52:09.190
spent like a complete month, I think, like
- maybe three weeks, maybe not a complete
00:52:09.190 --> 00:52:16.560
month just on reversing redsn0w and trying
to get redsn0w to play with iOS7. So I
00:52:16.560 --> 00:52:21.790
wouldn't count this month in the exploit
part of it, right? So if you're interested
00:52:21.790 --> 00:52:29.000
just in the kernel exploit part I would
say something like maybe seven weeks,
00:52:29.000 --> 00:52:36.170
something like that. But just with 2 maybe
3 days per week right, not complete weeks.
00:52:36.170 --> 00:52:40.240
Herald: Okay, then microphone 1,
please.
00:52:40.240 --> 00:52:45.740
Q: Congratulations on your talk which was
really interesting, I liked it a lot and
00:52:45.740 --> 00:52:51.090
my question is if the technique you used
to exploit the bug was in FreeBSD or any
00:52:51.090 --> 00:52:56.320
other BSD as well?
argp: Oh no, no. I mean, the vm_map_copy
00:52:56.320 --> 00:53:02.900
struct doesn't exist anywhere else except
the XNU kernel. But I think the
00:53:02.900 --> 00:53:06.921
interesting takeaway is that you can do
complex heap arrangements if you
00:53:06.921 --> 00:53:13.960
understand the kernel heep allocator,
right? So this process I described by
00:53:13.960 --> 00:53:18.740
creating holes and maybe controlling 2
allocations in order to host fake
00:53:18.740 --> 00:53:24.630
structures that you are able then to use
to get exploitation primitives then that's
00:53:24.630 --> 00:53:30.740
applicable everywhere, right?
Herald: Okay, then we go to microphone 2
00:53:30.740 --> 00:53:35.810
again, please.
Q: So I saw one sentence, just not report
00:53:35.810 --> 00:53:42.830
or... just don't report the bugs. I would
like to understand your thinking behind,
00:53:42.830 --> 00:53:48.980
because I think this is really important
for companies to know the bugs that they
00:53:48.980 --> 00:53:54.800
made and yeah, make the products better
and this is really beneficial for
00:53:54.800 --> 00:54:00.950
researcher because for example Apple they
pay a lot of money for the bugs. What...
00:54:00.950 --> 00:54:07.050
argp: Okay, yeah, I don't have much to say
on that. I mean, apart from: if all the
00:54:07.050 --> 00:54:11.030
bugs are fixed then you won't be able to
do this kind of work and it's no fun.
00:54:11.030 --> 00:54:17.760
Sorry, I don't have anything else to say
on that. Sorry, I don't have anything
00:54:17.760 --> 00:54:23.140
else, no comment.
Herald: Okay. Signal Angel, do we have
00:54:23.140 --> 00:54:31.310
another question from the internet? Okay,
then please a big round of applause for
00:54:31.310 --> 00:54:33.539
our speaker!
argp: Thanks.
00:54:33.539 --> 00:54:35.233
applause
00:54:35.233 --> 00:54:39.864
postroll music
00:54:39.864 --> 00:54:57.000
subtitles created by c3subtitles.de
in the year 2020. Join, and help us!