-
rC3 opening music
-
Jiska: Hello everyone and welcome to my
talk, Fuzzing the phone in the iPhone. The
-
phone in the iPhone is the component that
receives SMS, sends SMS, receives phone
-
calls, makes phone calls and also manages
your Internet connection when you are not
-
on Wi-Fi. However, you might now wonder,
what is it exactly? So I'm talking about
-
CommC enter and fuzzing it via the QMI and
ARI interfaces. But this is a bit too
-
technical for most of you. So I will first
introduce you to the concept of fuzzing in
-
general and protocol fuzzing before I dive
into further details. For those of you
-
have not yet heard about the concept of
fuzzing - you can send a lot of random
-
messages and then try to test the security
of an interface with this. And in this
-
video, you can see how I send SMS over a
Frida-based fuzzer with something like 400
-
fuzzcases per second. And then the IMH
receives them, catches them and sends a
-
couple of them also to the smartphone.
Let's start with a motivation and an
-
explanation to the attacker model. So, if
you look into a modern smartphone, you
-
have two components if you want to show it
in a simple way. So first of all, there's
-
the hardware part with a lot of chips. And
then on top of this, there is an operating
-
system and applications. However, it's not
as simple as this because even those chips
-
are so complex that they run their own
little real-time operating systems to
-
preprocess data. So this means that you
can even get code execution on such a
-
chip. And this is usually much easier than
in the operating system itself, because
-
those chips cannot have that many
mitigations. However, so what do you even
-
do if you have code execution in such a
chip, so if you are in a baseband chip,
-
then one escalation strategy from the chip
towards the operating system might be to
-
manipulate traffic in the browser.
However, I don't think that this is the
-
case, because if you look at the Zerodium
price list, then actually the browser
-
exploits are much more expensive. So it's
probably not done like this. And there
-
must be other ways to escalate from this
chip into the operating system. In
-
general, the traffic manipulation is
something that you can always do in
-
wireless transmission or also on the
Internet. So if you look how those systems
-
work these days, so you have something
like the Internet in general that serve
-
websites and so on, and also the core
network of your mobile provider. And there
-
are many, many ways to manipulate traffic,
either if you are a state level actor who
-
is able to have something in the core
network or just by sending around websites
-
or modifying websites. And then there is
the base station subsystem, there might
-
also be dragons. We don't know exactly.
And of course, there are over-the-air
-
transmissions and wireless transmissions
are very special because, if there is
-
something just slightly broken in the
encryption, for example, then it's also
-
possible to manipulate traffic there, if
you have a software defined radio, for
-
example. So all of this could be attacked
to manipulate traffic. And I don't think
-
that for this, one would craft a baseband
exploit. Already in 2014 at the CCC, there
-
have been two talks about a SS7 protocol
which is run in the core network and is
-
actually meant to connect different
mobile carriers to each other. And this
-
can also be used to intercept phone calls,
for example. And this also has been
-
exploited recently. So even though, there
have been some mitigations, etc. since
-
then, it's still exploited for the same
purpose to spy on people. So really,
-
really, really, basement exploits only
exists to escalate from the chip into the
-
operating system. But now the question is,
what are the strategies? So if it's not
-
via the browser, what else could it be? So
the browser really I'm sure it is not,
-
because also you need to have some
traffic and so on, it doesn't really work
-
instantly, you need to visit the website
to replace traffic on a website and so on.
-
There must be something else. So
if you are on the chip with remote code
-
execution and want to go into the
operating system, there is some interface.
-
And this means that something in those
interfaces needs to be exploitable, so
-
that you can escalate the privileges from
the chip into the system. And also, those
-
interfaces are very interesting from a
reverse engineer's perspective. So even if
-
you don't want to attack anything, just
understanding how they work, is also a
-
goal of this work. So, for example, if you
have a baseband debug profile, you can
-
just download it onto your iPhone and then
you open your iDevice syslog, you can
-
already see a lot of management messages
that are exchanged between the chip and
-
the iPhone. And if you have a jailbreak
and Frida, you can even inject packets or
-
modify packets to change the behaviour of
your modem.But if you want to start to
-
work on such a thing, the question is
like, how do you even start? Where do you
-
start? And fuzzing is actually a method
that can be used to understand such an
-
interface. So initially, if you identified
an interface, just to check if it is the
-
correct interface, so, if it really
changes behaviour, if you flip some bytes,
-
but also how powerful this interface is.
So what are the features? What breaks
-
instantly? And if things break, also you
can check if the whole interface has been
-
designed with security in mind. Now, let's
start with an introduction to wireless
-
protocol fuzzing, this will also be a
short rant because the current tooling for
-
fuzzing is usually not made to fuzz a
protocol. So let's start with a very
-
simple fuzzer, a fuzzer that is just an
image parser. So, you browse your
-
smartphone for unicorn pictures or PNGs or
JPEGs, and then you send them to the image
-
parser and in the image parser you might
be able to observe which functions are
-
executed in the form of basic blocks. And
then, during this initialization, the
-
image parser can even report which parts
were executed and you can just go to image
-
again and again with different images and
get this basic block coverage back. In a
-
next step, you can then combine existing
images or flip bits in these images and
-
send them to the image parser and again
observe the coverage, most of the time, it
-
won't generate any new coverage. So you
just say you are not looking into this
-
image in particular, but sometimes you
might get new coverage, like here, and
-
then you add this image to your corpus. So
over time, you can increase your corpus
-
and increase your coverage. Another method
can be, if you know how exactly an image
-
format looks like, so you might know the
JPEG specification and because of this,
-
you could just generate images that are
more or less specification compliant and
-
they look more artificial like this. So
you just generate images and send them to
-
the image parser and at some point you
might observe a crash. So that also
-
depends, again, on your harnessing. Maybe
you can observe basic blocks, maybe you
-
can just observe crashes and then you know
at which image you had a crash. You might
-
even be able to combine these two
approaches just depending on what you know
-
about your input and how you can harness
your target. Now it looks a bit different
-
for a protocol. So, in a protocol, you can
have a very complex state. Let's say you
-
are in an active phone call or just
something like, you receive an SMS. You
-
can actually force the iPhone to receive
SMS, if you have a second iPhone and send
-
SMS. And then during the fuzzing, you can
replace some bits and bytes, like this and
-
then you would have a modification. So
this is a very simple approach and it
-
preserves the state. So no matter how
complex the thing is, that you're
-
currently doing, it's very simple to flip
a bit here and there in an active
-
interaction. But it's also a bit annoying,
because you need to have these active
-
phone calls, etc. So something that's more
efficient is injection. So you would
-
observe certain messages and then just send
them again - and then you don't even need
-
the second phone to make calls, etc., -
you can just send a lot, a lot, a lot of
-
data. And this is the effect, when your
iPhone goes di-di-di-di-dimm or something
-
because of all the notifications and all
the data that is sent. But issue here is,
-
that this does not preserve state. So
there might be actions where the iPhone
-
requests something that is then answered.
So, the iPhone might request, for example,
-
a date and only then the chip would reply
with a date and only then the iPhone would
-
accept a date. But it's still very
interesting to do this. So even though you
-
cannot reach certain states because you
can do this without a SIM card and you can
-
do this very, very fast. So, just to
summarize the issues here: if you fuzz the
-
wireless protocol, you can have very
significant state differences and just
-
injecting packets cannot reach all
states. The fact, that you cannot reach
-
all states also shows in very simple stuff
like a trace replay. So a trace of
-
something that you record. So let's say I
have an active phone call, I record all
-
the packets, and I can also observe the
coverage. So , with Frida, you can observe
-
coverage on an iPhone while the phone call
is active. And then, in a second step, you
-
would do some injection. But the only
thing that you can inject are the packets
-
sent from the basement to the smartphone,
not the opposite direction. And this
-
results usually in much less coverage. So
you are missing a lot of things due to a
-
missing state. And even worse, if you do
the same thing again, you might be in a
-
different state, and you might observe a
different coverage. So you do the exact
-
same thing, but you get different
coverage.So, even replaying recorded
-
messages results in less or inconsistent
coverage. Anyway, let's take a look into
-
an injection example. So, in this video,
you can see how I'm in the Unicorn Network
-
on an iPhone 8, which has obviously 5G,
but also does a lot of fuzzing and in the
-
fuzzing, what is interesting is, that you
might do a lot of states in a combination
-
that are not usually possible, like you
have a lost network connection while you
-
have to confirm a pin or you have a
network connection during this, etc. To
-
summarize my rant, some states cannot be
reached solely by injecting packets. So,
-
even if we have a very good corpus and do
very good mutations, we might miss
-
80% of the code, but we can just fuzz
anyway. But we need to keep in mind, that
-
some stuff is just not fuzzable. We looked
into a lot of wireless protocols and have
-
seen more in the past, so, it's worth to
also consider, which tooling we already
-
had available for fuzzing protocols. The
most advanced tooling, that we have, is
-
Frankenstein and it's built by Jan. So,
what Jan did is, he emulated the firmware
-
and attached it to a virtual modem and
also a Linux host. For this, he first
-
looked into the firmware, that's here, and
we had some partial symbols for this and
-
also some information about registers.
Then, Frankenstein is actually taking a
-
snapshot, that you can see here, including
some of those registers of the modem. And
-
with this, you can build a virtual modem
and fuzz input as if it would come over
-
the air. Then Frankenstein also emulates
the whole firmware, including thread
-
switches. So it gets into very complex
states and it's even attached to a Linux
-
host. So, it also fuzzes a bit of Linux
while actually fuzzing the firmware
-
itself. Now, the issue with this is that
basement firmware is usually 10 times the
-
size of bluetooth firmware or even more,
and we don't have any symbols for this, so
-
it's a lot of work to customize this. And
even if, one would do all those steps and
-
put all the work into this, it's only, so
to say, code execution in the baseband.
-
It's not yet a privilege escalation into
the operating system. The next interesting
-
tooling was built by Steffen and what
Steffen did, he built a fuzzer based on
-
DTrace and AFL. DTrace is a tool that can
provide functional level coverage in the
-
macOS kernel and user space. With some
modifications you can even get basic
-
block coverage in the user space, which is
required for AFL to work. So, in the end,
-
you have AFL or AFL++ as a fuzzer on any
program on macOS. It's even slightly
-
faster than Frida, at least the version
that he used. And he gets a couple of
-
thousand fuzz cases per second, even on a
very old iMac. So, in our lab, we just had
-
an old iMac 2012 for this and it works on
this. But the issue is, that Wi-Fi and
-
Bluetooth, which he fuzzed, are very complex
protocols, so he couldn't find any new
-
bugs with AFL. And also, in the kernel
space, you only get this function level
-
coverage. He still, despite not finding
any bugs in Wi-Fi or Bluetooth, got a CVE,
-
because DTrace also has bugs. So, at least
some funding, but on iOS, this is not
-
supported out of the box. So it might be
possible to get DTrace working with some
-
tweaks, but it's a lot of work. So
probably it's easier to just use Frida in
-
the iOS user space. Also during this, so
while Steffen was building all this very
-
advanced tooling, Wang Yu found issues in
the macOS Bluetooth and Wi-Fi drivers, and
-
so he was very, very successful in
comparison to us. That's really a pity.
-
And I think, what he did, is much better
state modelling, so, of how the messages
-
interact and what is important to reach
certain functions. So what is still left?
-
So, usually fuzzing the baseband means
that you need to modify firmware or also
-
emulate firmware, you need to implement
very complex specifications on a software
-
defined radio if you want to fuzz over the
air or build proof of concepts. And for
-
everything that's somewhat proprietary,
you need to do protocol reverse
-
engineering, so you can spend a lot of
time and money just to do very, very basic
-
research. Or, you can also use Frida, so
you can fuzz with Frida and all you need
-
to do for this is, write a few lines of
code in JavaScript. So I kid you not. The
-
option is Frida. Dennis was the first in
our team who was advised as a thesis
-
student who built a Frida-based fuzzer,
and it's called ToothPicker. It's based on
-
Frizzer and Radamsa. So what it does is,
well, it hooks into these connections or
-
into the protocols of the bluetooth
daemon, you could also think of this upper
-
part here, as one block. So the protocols
are implemented in the Bluetooth daemon,
-
but we want to fuzz certain protocol
handlers. And to increase the coverage, he
-
creates a virtual connection. So a virtual
connection holds a connection and pretends
-
to the Bluetooth daemon that there would
be an active connection to a device. And
-
of course, the chip would then say, I
don't know anything about this connection.
-
So, there are also some abstractions in
here, so that the connection is not
-
terminated. So, that's a very simple tool,
but it really found a lot of bugs and
-
issues and even there were some issues in
the protocols themselves that also apply to
-
macOS. So it's not just iOS bugs, but also
protocol bugs in macOS that Dennis found.
-
And this really got me thinking,
because ToothPicker with only 20
-
fuzz cases per second, so it's really,
really slow and we were still able to find
-
Bluetooth vulnerabilities at this speed.
So, why is this? So first of all, if you
-
try to fuzz Bluetooth over the air, then
the over-the-air connections are
-
terminated after something like five
invalid packets. So, over-the-air fuzzing
-
is really, really inefficient. And with
Frida you can actually patch these
-
functions, so it's gone. Then the
virtual connections are a very important
-
factor. So they are really, really
important for having coverage. It's still
-
a lot of coverage that we missed during
replay and fuzzing. But it's
-
really an advantage compared to the
other fuzzing approaches where you just
-
inject packets. And in addition, there is
an issue here, because if you have a
-
virtual connection, it might be that this
virtual connection triggers behaviour,
-
that you cannot reproduce over the air.
So, that means that everything that you
-
find, you need also to confirm that it
works over the air. At least the
-
inconsistent coverage is also fixed in
ToothPicker, because ToothPicker
-
replays all packets five times in a row.
But the issue here is that it also means
-
that if you have a sequence of packets,
that is like generating a certain bug -
-
so you need multiple packets - this is
nothing that the mutator is aware of and
-
also nothing that's logged properly in
ToothPicker. And because of this, I got a
-
bit anxious. Maybe we missed a
lot of things? So once I got the
-
intuition that we are actually missing
certain state information, I had the idea
-
to replace bytes in active connections.
And this is one part of that you can see
-
on a keyboard, so I'm just replacing bytes
on keyboard input and see what happens.
-
And I let this run for a couple of weeks,
also for different protocols and so on to
-
see, if there are further bugs or not that
we didn't find previously. So here you
-
can see the same for AirPods with SCO and
then they produce crack-sounds for the
-
replace bytes, it's even worse for ACL, so
actual music, because then you can hear
-
very noisy chirps. I let this fuzzer run
for multiple weeks and it didn't find
-
any bugs that ToothPicker hadn't
discovered before. So, I think the reason
-
for this is that I mainly passed in active
connections like the one with the audio
-
or the keyboard, but I only passed a few
active pairings because this requires me
-
to actually perform those pairings by
hand, so, nothing really interesting. The
-
only bad thing that I could produce with
this, but not worth a CVE, is that the
-
sound quality of my AirPods is now a
really, really bad. Well, OK. And also the
-
Broadcom chips on iOS don't check the UART
lengths, but that's not that bad. So, I
-
mean, if you consider that they removed
the write-RAM recently, then you might now
-
still be able to write into the RAM via UART
buffer overflows. But yeah, nothing too
-
interesting. So after all of this, I asked
myself: "What is still left for fuzzing if
-
we cannot find a new Bluetooth or Wi-Fi
bugs?" Well, the iPhone baseband - or
-
actually the iPhone basebands, because
there are two. The first variant of iPhone
-
baseband, that you can get, are Qualcomm
chips and they are in the US devices they
-
use the Qualcomm MSM interface. And this
interface comes with some documentation
-
and there are even open source
implementations for it. So it's something
-
that's probably easy to understand and
easy to fuzz. On the other hand in almost
-
all devices that I had on my table, were
Intel chips. Intel has been recently
-
bought by Apple, at least the part that
does the baseband chips and these are the
-
chips in the European devices, that's
the reason why almost all my devices had
-
Intel chips. And they use a special
protocol. It's called Apple Remote
-
Invocation. And if you search for this on
the Internet, I even checked it like
-
just today, there are no Google hits at
all. So it really hasn't been researched
-
before, at least not publicly. It's
completely undocumented and it's a very
-
custom interface. So it's not even used
for Android. It's really an interface
-
just for Apple. The component that we are
going to fuzz in the following is CommCenter.
-
So CommCenter is the equivalent of, for
example, the Bluetooth or Wi-FI daemon,
-
but for telephony. It's sandboxed as the
user "wireless", but it comes with a lot of
-
XPC interfaces. And this is something
that we will also see later in the
-
fuzzing results. The next part is that
there are two flavors of libraries, so
-
depending on if you have a Qualcomm or an
Intel chip, different libraries will be
-
used before certain actions or data
actually is then processed by the
-
CommCenter itself. So we have a different
code paths here. But all of this runs in
-
user space, and this means that both
libraries can be hooked with Frida and can
-
be fuzzed with Frida. So that's very
interesting. There is still a lot of stuff
-
that goes on in the kernel. So what you
can see here is that QMI and ARI have some
-
management information that is sent to
CommCenter, but they don't contain the
-
raw network or audio data. So they don't
contain your phone call, they don't
-
contain your website that you are opening.
And the next issue is that QMI and ARI
-
are not directly sent over the air, but
what is sent over the air are normal
-
baseband interactions and these generate
QMI and ARI messages. So there's still
-
some section in between, but of course,
there are now two ways: either you have
-
interaction that you can do over the air,
that is causing ARI and QMI messages
-
directly, that are something that causes an
issue in the upper layers. Or you might
-
have this full exploit chain requirement
that you first need to exploit the chip
-
over the air, and then from the chip
break the interface into the CommCenter.
-
Now, QMI, the code has a lot of
assertions. So it's really asserting
-
everything about a protocol, delaying the
TRV format and so on, and if anything goes
-
wrong, it really terminates CommCenter.
So if you just send one invalid packet,
-
CommCenter is terminated. This doesn't
matter a lot because if your protocol is
-
stable and you usually don't send any
invalid packets, then you know an attack
-
is ongoing, so it's valid to terminate
the CommCenter. And furthermore, it
-
doesn't matter a lot to the user. So the
worst thing that happens when CommCenter
-
crashes, for example, while you have an
active phone call, it's just that the
-
phone call gets lost or your LTE
connection is re-established. So you don't
-
really notice it. It just feels like your
Internet connection breaks for a short
-
moment. In contrast, there is the ARI
protoctol, and this is the part that just
-
works very, very, very different. So
whatever it's getting, it just parses it,
-
and it doesn't terminate CommCenter.
So you can send many, many,
-
many fancy things and it just
continues, continues, continues,
-
because the developers were probably very,
very happy once they got their special
-
protocol for Apple working and then they
never touched it again. But what does it
-
look like? So it has a very basic format,
also with some TLS(?), and the first
-
thing that I noticed when I fuzzed it is
that in the iDevice syslog, it always
-
complained about this sequence number
being wrong. So it just said I expected
-
the follow-up sequence number, so and so.
So I started to fix this. And if you open
-
it in IDA, you can see that the range,
that is expected it's between zero and
-
0x7ff hexadecimal. So you know it is
the range and then it gets weird. So the
-
sequence number is spread over three
different bytes in single bits and
-
shifted around and so on. And it's not
even continuous. So very weird code.
-
Probably they just added those
sequence numbers to confirm some race
-
conditions or something. I really don't
know. Or out-of-order packets? Something
-
weird going on there. But I wrote the
code, I fixed the sequence number and
-
then during the replay of packets, I
noticed, well, it doesn't even matter! So
-
no matter if your sequence number is valid
or invalid, parsing continues and even
-
worse, even packets with a wrong sequence
number are parsed. Probably because
-
otherwise there would be too many issues,
because the protocol implementation is too
-
buggy. And there are also a couple of
other things, so, for example, if you sent
-
the first four magic bytes wrong or a
wrong length or something, then the
-
packet is potentially ignored. But parsing
continues and CommCenter is not terminated
-
like in QMI. Since it's a proprietary
protocol, there is currently no tooling
-
available. But, Tobias is working on a
Wireshark dissector and once he finishes
-
his thesis, it will also be publicly
released. So you need to wait a while, but
-
then you will have a tool for this.
Anyway, let's also talk about fuzzing
-
this, so I would not recommend to fuzz
this, because you might brick your device
-
or at least get into weird states. So
just don't do this on your productive
-
iPhone. I mean, obviously, I know what
I'm doing, so, yeah, just fuzzing packets,
-
right? But I'm not so sure about what
exactly I'm doing, so the only direction
-
that I fuzz is from the baseband to the
iPhone here, not the opposite direction.
-
So I hopefully do prevent anything weird
on the chip, right? But the iPhone might
-
still answer with something invalid and
this might confuse the baseband or cause
-
other crashes. And so I actually had to
call for help, like mimimimimi, I broke my
-
iPhone - I mean, just one of my research
devices - but still so it booted into
-
pongoOS but no longer into iOS and it
didn't tell me any debug message that was
-
useful. Well, it turns out, at least
under Qualcomm chips, and that's where
-
this happens, it just boots after a
couple of hours again. But before it's
-
just entering a boot loop and on the
Intel iPhones I also almost bricked an
-
iPhone 8, but luckily it didn't
completely break. So the issue there is if
-
you enable the baseband debug profile,
then it writes a lot of stuff to the ISTP
-
files, so that is some debug format of
Intel, and every few minutes it just
-
creates something like 500MB of data, at
least on the iPhone 8. On the newer
-
iPhones, this debug format is a bit
shorter, so it doesn't create as much
-
data, but still a lot. And if you don't
delete this regularly, then of course
-
your disk will be full and an iPhone
behaves quite strange if it has a full
-
disk. So you can still interact with the
user interface, but you can no longer
-
delete photos because deleting a photo, it
seems, it just needs some file
-
interaction. Also, you can no longer log
in with SSH, which is also an issue
-
because it somehow seems to create a file
when logging in, so you can no longer
-
delete any files. And I was just
rebooting the iPhone after trying a couple
-
of things and luckily it came back and
deleted some files and I was able to log
-
in and removed the baseband logs. But be
careful when doing this. And of course,
-
all the iPhones are very confused from
the fuzzing. So they really lose
-
everything about their identity and
location and they want to be activated
-
again. So here you can see a smartphone
that lost its location and really wants
-
to be activated, activated, activated.
During SMS fuzzing, you might even get
-
Flash messages. And if you click on the
head menu on dark theme, they are
-
displayed black on gray, so probably
nobody ever tested it. Also great if you
-
have a locked iPhone, you can still
display SIM menus and SIM messages on top
-
of the lock. OK, so I guess I have to
revise my first instruction. So fuzz this!
-
Really, really fuzz this! It's a lot of
fun. Maybe just not on your primary
-
device, but you will enjoy fuzzing these
interfaces. But first of all, you
-
obviously need to build a fuzzer, so how
do you build a fuzzer? The first fuzzer
-
that I used was the one that I also used
for Bluetooth that just uses the
-
existing bytestream protocol and then
flips single bits and bytes. So it has
-
this high state-awareness. But it also
means that like some kind of monkey I was
-
just calling myself, writing SMS to
myself, enabling flight mode, everything
-
that you could just imagine. And it's a
very boring task. But it also found very
-
fancy bugs that I couldn't reproduce with
the other fuzzers yet, because it can
-
reach states that just injection of
packets cannot reach. So at least it was
-
quite successful. And when I fuzzed with
this for something like three days and
-
already found a bugs, that's very
different with the Bluetooth fuzzers, so
-
there seemed to be more bugs in
CommCenter. And so I just wrote to Apple
-
PR: "Hey there, I wrote this really,
really ugly 10-lines-of-code fuzzer and
-
see what it found. Awesome, awesome,
awesome! And crash logs are attached. And
-
obviously this is simple to reproduce
because I only fuzzed for three days. Got
-
most of these crashes multiple times.
Yeah. So here you go. Enjoy my fuzzer."
-
And this was probably quite
stupid because it's not that simple. So
-
it's really not easy to reproduce the
crashes. First of all, well, of course
-
this script is so generic that it runs on
all iPhones with an Intel chip, so no
-
matter if I take an iPhone 7 or an iPhone
11, it will just work. But the crash logs
-
that you get are very different depending
on if you fuzz on a pre-A12, so iPhone 7
-
and 8, or on later versions like the iPhone 11
and SE2. So you cannot reproduce the same
-
crash logs that easy. And also it depends
a lot on the SIM. So even on a passive
-
iPhone, if you don't do any phone calls
and so on, you would get different
-
results. So I started my fuzzing actually
with a Singaporean SIM card
-
without any data contract or phone
contract on top of it and already found a
-
couple of things. But it might just
behave very different on just a slightly
-
different configuration. Anyway, let's
listen to a null pointer that it found. And
-
this null pointer has been fixed in iOS
14.2 and it's in the audio controller, so
-
you can hear some loop going on there.
What you can see here is me calling the
-
Deutsche Telekom and so on. So they have
this very important text.
-
Announcement: Guten Tag, und herzlich
willkommen beim Kundenservice der Telekom.
-
jiska: And then I call again and have a
crash. And now let's listen to the crash.
-
Telekom jingle starts playing,
final part loops ten times
-
jiska: Just for the sound effect, I also recorded
another one, so this one is with ALDI TALK.
-
Announcement: Guten Tag, ALDI TALK gibt
die Senkung der Mehrwertsteuer vom ersten...
-
jiska: And now let's listen to a special
offer by ALDI TALK.
-
In 3, 2, 1... di-dimm...
-
Announcement: Guten Tag, ALDI TALK gibt die
Senkung der Mehrwersteuer vom
-
loops ten times
erst-erst-erst-erst-erst-erst-erst-erst-erst-er
-
Jiska: Since his first fuzzing results
were very promising, I decided to use
-
the latest ToothPicker version and extend
it for fuzzing ARI and I called it
-
ICEPicker because the Intel chips are also
called ICE. So I just cloned Dennis'
-
latest ToothPicker alpha, which is very,
very unstable, but this one actually
-
runs on the iPhone locally without any
interaction with Mac OS or Linux. So it
-
doesn't need to exchange any the payload
via USB and also it's using AFL++, which
-
is a much faster mutator than Radamsa.
So from a speed consideration, this is a
-
much better design. However, AFL++ didn't
turn out to be the best fuzzer for
-
protocol, so most of the time is actually
spent trying to brute force the first
-
magic bytes, the first four bytes, because
it tries to shorten inputs. It's also not
-
aware of something like a packet order, so
it was just brute forcing those first four
-
bytes. And well, the next issue is, that
for some reason, if the first four bytes
-
are invalid, the ARI parser slows down a
lot. So I was suddenly down to something
-
like less than 10 fuzz cases per second.
And also there is no awareness of the
-
ICEPicker in this case, of the ARI host
state. So ARI sometimes shuts down this
-
interface, if it thinks that something is
very invalid and the fuzzer will just
-
continue. So I looked into the iDevice
syslog after the fuzzer couldn't find any
-
new coverage for more than six hours.
And I was wondering: "What is the
-
issue here? Is the implementation
wrong or is it the fuzzer?" And it really
-
looks like the fuzzer is producing inputs
that are not good for protocol fuzzing.
-
Of course, this is stuff that you can
optimize, so AFL++ can do a lot here, so
-
you can tell it a bit how the protocol
looks like and also get it to not brute
-
force the first four magic bytes. But for
this I would have to recompile the whole
-
thing. And it was something that compiled
on Dennis' machine, but it didn't compile
-
on my machine , because I had my Xcode
beta in a weird state. And well, of
-
course, some of you now say:
"Just download and install a new Xcode!"
-
But this takes so long that actually
writing the next fuzzer seemed to be.
-
easier. Still, this variant of ICEPicker
was interesting to me because it was the
-
first time when I saw that the fuzzer
initialization works, including
-
coverage and also my replay works across
multiple iPhone versions. So my call was
-
collected on an iPhone SE2, was replayable
on an iPhone 7. So it was not useless in
-
that sense, but I just decided to not
use this configuration. So I just wrote a
-
very simple fuzzer again and I didn't do
the porting of everything to run locally
-
on iOS. I just kept the design a bit
simpler or at least easier to code and had
-
my fuzzer running on Linux and then using
only Frida on iOS. It cannot reproduce all
-
the states and crashes that I observed
with my very first fuzzer, but most
-
crashes could be reproduced. I didn't do
any coverage. I didn't do any smart
-
mutations, just very stupid mutations. And
basically I just did a very blind
-
injection. But this was super fast, so
instead of the 20 fuzz cases per second, I
-
already had something like 400 fuzz cases
per second on an iPhone 7, which was about
-
the same speed or even faster than the
AFL++ variant. And I can at least correct
-
the length field, sequence number and so
on before injecting the payload. Since it
-
doesn't do that great mutations, at
least, I need to collect a good corpus
-
with many SIMSs, many calls. And I'm also
logging the packet order with this. So
-
it's at least aware of a pocket sequence
in the sense of, I can reproduce the
-
sequence later on. I had this fuzzer
running on a couple of iPhones in
-
parallel for multiple weeks, and it found
a lot of interesting crashes. So that's
-
my go-to fuzzer. I still wanted to
confirm that not collecting coverage
-
wasn't an issue, so I also cloned the
publicly released of ToothPicker, which
-
definitely finds new coverage, and it's
using the Radamsa-mutator, which is very,
-
very slow, but it does a bit smarter
mutations, at least in terms of protocol
-
fuzzing. It's still only a aware of
single packets and it's only using the
-
same packets five times in a row to
confirm coverage, etc. And also an issue
-
is that it cannot catch a lot of the
crashes of CommCenter. So it happens
-
quite often that CommCenter crashes. And
then if you cannot catch the crash with
-
Frida and everything crashes, then you
need to start the fuzzer again. But you
-
also need to delete the files in the
corpus that led to the crash because
-
otherwise you would just run into the same
crash very fast. So it needs a lot of
-
babysitting. I also had it running for a
couple of weeks, but sadly, it didn't find
-
any crashes. So at least I can be sure
that fuzzing, much slower, but with
-
coverage, is not any improvement. Still,
the mutations it creates are quite useful,
-
as you can see in the following. So you
can even see this phone numbers scrolling
-
here and so on. So it generated a very
long phone number correctly into some TLV
-
structure here. And that's quite
interesting to see. So this is something
-
that you could not reach by just
flipping bits and bytes.
-
There is one big shortcoming that all of
these fuzzers have, including the initial
-
ToothPicker which is they don't have any kind
of memory sanitization. So the framework
-
that you would usually use in user space
on iOS is the MallocStackLogging
-
framework. I even got this running for
CommCenter, so it's a bit of a command
-
line juggling. But in the end you can
enable MallocStackLogging also for
-
CommCenter. The issue here is that it
increases the memory usage a lot and even
-
if you configure CommCenter to have a
higher memory allowance, it is so high
-
that it's just immediately killed by the
out-of-memory killer. So this doesn't
-
work. Then there is also libgmalloc. It
doesn't exist for iOS, it's just exists on
-
Xcode. I got one of the Xcode libraries
running on one of my iPhones. I have no
-
idea if this is an expected configuration
or not. At least I could execute smaller
-
programs. And then when you use this on
CommCenter, it just crashes with a
-
libgmalloc error on parsing some of the
configuration files very, very early when
-
starting the CommCenter. So all of this
didn't work. And this also means that the
-
fuzzer cannot find certain bug types or
crashes much later when encountering
-
bugs. So all of the fuzzers that I created
are not perfect, but at least they found
-
a lot of different crashes. Let's look
into this. I mean, the first obvious
-
number that you see here is the 42. So I
stopped fuzzing after 42 crashes - at
-
least crashes that I think are individual
crashes and that are not caused by Frida -
-
so I tried to filter out Frida crashes
and this corresponds to the total amount
-
of crashes, but only some of them are
replayable by either one or multiple
-
packets. And for the replayable crashes I
can also check if they were fixed in
-
recent iOS versions or the most recent iOS
14.3 or not. Then I also marked two
-
colors here because there is the Intel
libraries, but there's also the
-
Qualcomm libraries. And for the Qualcomm
libraries, I didn't spend as much time
-
fuzzing, because I have less Qualcomm
phones, but also all the asserts in the
-
code prevent a lot of issues from being
reached. So the libraries themselves have
-
less issues and also within CommCenter,
less of the code that has improper state
-
handling is reached. The location daemon is
marked also with a big grey box here,
-
because the location daemon is similarly to
the CommCenter using some of the raw
-
packet inputs and parses them. So it has
special parsers for Qualcomm and Intel.
-
And it's also an interesting target
because of this. Other than this I got
-
really a lot, a lot, a lot of different
daemons crashing. Some of them, even with
-
replayable behaviour. So, for example,
there is the wireless radio manager daemon
-
that you can just crash via one Intel
packet. But, this has been fixed. And then
-
there is one interesting crash that I
actually got via Qualcomm and Intel
-
libraries. So in the mobile Internet
sharing daemon, this also has been fixed
-
and some of the crashes only happened via
Qualcomm, but I'm not sure if that's like
-
a Qualcomm-specific thing or it's just
randomness of the fuzzer. So the mobile
-
Internet sharing demon has an issue where
it accesses memory at configuration
-
strings, so there's different strings at
this memory address and I found this quite
-
early, but I was not aware of the fact,
that so many other daemons are actually
-
crashing when I fuzz CommCenter. So, I
didn't look into this in the very
-
beginning. And when I reported it to
Apple, they said: "Yeah, yeah, we already
-
know about this and we fixed it and a
beta prior to your report." So certainly
-
nothing that I got a CVE for. Another
interesting crash in the CellMonitor, but
-
only of the Intel library. The CellMonitor
is something that is running passively in
-
the background all the time and it parses,
for example, GSM and UMTS cell
-
information. I already found this on the
Singaporean SIM without any active
-
data plan in my very first round of
fuzzing and reported it back then to
-
Apple. I don't know, if it's triggerable
over the air or not. So I guess it's
-
something that you first need to get code
execution for. And it has been fixed in
-
iOS 14.2. And I wrote a lot of emails with
Apple because I thought, that they didn't
-
fix it. And the reason for this is that
both the GSM cell info and the UMTS cell
-
info function, when they parse data, they
have two different bugs. So I still got
-
crashes in the same functions and I
thought: "OK, same function, still a
-
crash: The bug is not fixed.". But actually,
it's very high quality code and it's just
-
multiple bugs per function. And there is
even one more issue in the CellMonitor,
-
even though I think the remaining bugs are
very simple crashes or nothing that could
-
be exploitable at all, but still hints to
the great code quality. And the same story
-
is, that there're even more bugs to be
fixed. So most of them are probably just
-
stability improvements, but some of them
are still interesting. So, let's see how
-
this goes. So since I told, that it's a
very simple fuzzer, some of you might have
-
already started coding those 10 lines of
code for fuzzing, while I continued talking
-
and grabbed their old iPhones, that they are
willing to lose, if something goes wrong.
-
So, how can we actually build a fuzzer
that is performant and replicates some of
-
the bugs that I found just within a day.
Let's take a look. When you look, Frida
-
fuzzing, a lot of the stuff that you do,
is limited by the processing power of the
-
iPhone. So your iPhone will get very,
very, very hot and it might even drain
-
more battery, than it can get via the USB
port. So it might even discharge while
-
fuzzing. And performance is really key. So
you need to identify bottlenecks.
-
I said ToothPicker or ICEPicker, the
initial version is just 20 fuzz cases per
-
second and you can tune this to something
like 20.000 fuzz cases per second. So, I
-
already told, that I tuned it to something
like 400 or 500 fuzz cases per second,
-
but, why the 20.000? So, initially, a
student of mine, did some fuzzing in a
-
very different parser and said: "On my
iPhone 6S, it's running with 20.000 fuzz
-
cases per second." I was like: "No way, no
way!" But actually, you can do this. So,
-
this depends a lot on the Frida design.
The first variant, how most Frida scripts
-
are written is, that you have some Python
script that runs on Linux or macOS, and it
-
has a couple of functions that you can see
here. So first of all, it has this
-
on_message callback. So, this on_message
callback is something that we need later.
-
And we just register it to our Frida
script, the Frida script, that I'm going
-
to show you in a second. And you load the
script and the script can then even call
-
functions on your iPhone. For this, you
load a second script on your iPhone. So
-
this is JavaScript injected into the iOS
target process and it can, for example,
-
use to send function to send something
back to the on message function. And it
-
can export functions via RPCs. So, you can
then call them. All this happens via JSON.
-
And so it needs serialization and
deserialization, which means you cannot
-
send hex data or binary data directly. So
you have a hex string that you encode into
-
JSON, which is then parsed as binary data
and also it's all via USB. So you also
-
have the speed limitation by USB. And, of
course, if you use the Frida C-bindings
-
locally on the iOS smartphone, it is a bit
faster, but it's still not perfect. So,
-
the more you can prevent from this JSON
part and the USB part, the better. The
-
actual fuzzer looks a bit like this. So,
you are in the libARIServer, so that's the
-
lowest library from the diagram before.
And then you define this inbound message
-
callback function, which has two
arguments, which are the payload and the
-
length. So, this looks a bit cryptic, but
that's basically it. And then you can, but
-
you don't have to, add this interceptor
here because you might want to fix your
-
sequence number or add basic block
coverage to your fuzzer, etc. So, this is also
-
done there. And then you can just call this
inbound message callback of ARI and send
-
ARI payloads. So, this already can be very
different. So, if you now call this via
-
RPC export, via a Python script on your
laptop, you can reach something like 500
-
fuzz cases per second, if you inject SMS,
which are quite processing intensive
-
payload. Or, if you just do the same
thing and if you just run this inbound
-
message callback in a loop, locally with
JavaScript, without any external Python
-
script, then you would get 22.000 fuzz
cases per second on the very same device.
-
So this is the speed difference that the
JSON serialization, deserialization and
-
the USB in between make. So, I did a few
more measurements, and certainly on the
-
iPhone 8, there is a bug that prevents me
from collecting coverage. But, what you
-
can see is, so, the first part here is if
you have just a bit flipper in a loop that
-
calls the target function, you can get
17.000 fuzz cases per second on an iPhone 7.
-
As soon as you start collecting basic
block coverage, not processing it, just
-
collecting, you drop to 250 fuzz cases per
second. So, you need to ask yourself, if
-
your fuzzer gets really that much better
from collecting coverage. And another
-
thing is - that's this line above - so, if you
just print the packet, that you fuzzed or
-
injected and print this via Python to your
laptop, you also have a huge slow down,
-
which is not as large as the coverage
slowdown. But still, you can see every
-
print and every sending off a message in
between the Python script and JavaScript
-
takes a lot of time. Now, if you have this
remote SMS injection that I had before,
-
then you drop to 200 fuzz cases per
second. So it is a blind injection without
-
any coverage. If you collect coverage but
don't process coverage, then you are down
-
to 100 fuzz cases per second. So, for the
initial ToothPicker design, this would be
-
the optimum. But, because the Radamsa
mutator is very slow and because you also
-
need to process the coverage information,
et cetera, that's down to 20 fuzz cases
-
per second. So, this is the comparison
here. And now you can imagine why
-
collecting coverage probably isn't always
useful and why also having your laptop
-
calculating better mutation because it's
easier to write a mutator there, than
-
directly in JavaScript, is not always the
best idea. So let's watch one last demo
-
video. What you can see here, is when you
try to delete SMS, after all of the
-
fuzzing, it really doesn't work neither
via the settings nor via the SMS app. So,
-
you really need to reset your iPhone after
fuzzing it for too long. No other chance
-
than this to delete the messages. With
this, we are already at the end of this
-
talk, but of course, there will be a Q&A
session and if you missed the Q&A session,
-
you can also ask me on Twitter or write me
an email. Thanks for watching!
-
rC3 music
-
Subtitles created by c3subtitles.de
in the year 2020. Join, and help us!