Return to Video

#rC3 - Fuzzing the phone in the iPhone

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

more » « less
Video Language:
English
Duration:
55:12

English subtitles

Revisions