Dear viewer, these subtitles were generated by a machine via the service Trint and therefore are (very) buggy. If you are capable, please help us to create good quality subtitles: https://c3subtitles.de/talk/1309 Thanks!
[Music]
is part of the project check-rein they
investigate jailbreaks for iOS devices
for the iphone i phones are usually
locked down and can't be routed as we
call it but technical users try to get
root access from time to time anyway
there's a continuous cat-and-mouse game
between Apple and people who find J
breaks and Apple fixing them again this
still this jailbreak is a particular one
because it's not fixable whoever will
introduce us to their work and explain
what the problem is and what they found
out please warm round applause for
QWERTY thank you
so today I will be speaking about the
one weird trick that securom hate and
this talk was already given a POC 2019
in occasion of the planned release of
choc rain we had missed a deadline but
it is now available for download and
free use and a check kinda iron a check
crayon I am so I am looking at Tedesco
aka QWERTY and you can find me idling on
IRC that cracks by him in the chat
channel on Twitter you can find me at
Kirti or you a OPG I'm an independent
security researcher with an iOS focus
and my main background is that I've been
hacking iOS and I've been involved in
the iOS hacking scene ever since I
discovered iPhones a decade ago however
today I am here on behalf of more than
just me because this talk would not be
possible without the work that several
people have put in place I want to give
a special shout-out to AXA max which is
the person who published the
vulnerability that we were abusing and
also to little Layla who who added
independently and see Goethe
for the expectation strategies and I
also want to thank the entire check-rein
team because we worked for months on end
to get infrastructure ready in order to
turn such a powerful vulnerability into
easy to use and reliable jailbreak for
everyone and the check-rein team is
composed of an all-stars group of iOS
researchers there's more than just these
but these are the main contributors and
the knowledge base of this group is
pretty impressive and it's possibly the
best team that I've worked on in my
entire lifetime so I think it's really
important to give them a shout out
and I'm very great grateful for what we
achieved and the work we put in thank
you
so we'll start talking about what is
Sakura Sakura is the very first code
that will run on your iPhone once you
turn it on and it's a stripped down
version of iboot which is the the iOS
bootloader and this code is very
important because it's placed into mask
ROM while your phone is being
manufactured and it's basically the most
trusted piece of code that can ever run
on the application processor of your
phone
the goal of Sakura is to fetch an image
from flash storage for the full
bootloader I would block the memory and
jump into it so it's very simple but it
does a bunch of signature validation and
it also provides recovery mechanism
known as DFU which allows you to recover
a phone from a bootable state or just do
a complete restore of the device without
relying on the bootloader to be seen and
you can actually enter this mode by
pressing a special key combination while
the phone is turning on and I'm also
gonna mention the secure boot of bunch
during this talk and I us truly
pioneered the concept of secure but but
it's one of the most long-running issues
in the jogger community the ability to
load unsigned code and it all starts
from the root of trust insecure ROM and
every time you load an image in securom
it will perform validation mechanisms
except on the original iPhone where this
was not the case for images that were
already flashed into storage and as I
mentioned yes this is jailbreaking enemy
number one
and jailbreaks want to bypass these DFU
protocol is a fairly simple protocol
implemented over USB control transfers
and again the goal is to allow device to
get some data from the host and since
this is a stripped-down version of the
bootloader
it's designed to be very simple and
basically there is a special request
that you can send to the device with
some data appended to it and once the
transfer is done you can do a sequence
of other requests which will tell device
to boot into the image that you uploaded
there's however other ways to exit vfu
including early special requests called
DfE abort which will shut down the USB
stack and reentry initialize it from
scratch as I mentioned this protocol is
implemented over USD control transfers
and so I will go through what exactly a
control transfer is and basically it's
used to issue some commands from the
host to the device and you can actually
send data with your request or ask
device to provide you with some data
successful USB enumeration requires
compliance to support a minimum set of
these control transfers and each control
transfer starts with a setup packet
which contains some informations on the
transfer that's about to happen and so
we have a request type which specifies
which direction the data has to go
through the B request which is an index
of what kind of request you're trying to
do and some other fields but in our case
here the most interesting one is W
length because if W length is said to be
nonzero the SATA packet is going to be
followed by a so called data phase
during this data phase the host will
send data in the chunk fashion to device
and again as I mentioned earlier this is
the mechanism that allows your house to
upload files to add the fu device
although if you specify a direction of
in the transfer will actually get data
from the device and again the length of
the maximum length of the transfer is
specified in the W length field here and
when you send this data phase the data
that you want to transfer is going to be
chunked into packets of sizes ranging
from zero bytes to 64 bytes depending on
what USB speed you're running on and it
will send it sequentially once the
transfer is finished a status phase
follows and in this status phase marks
the end D of the control transfer and at
zero length packet is going to be sent
in the iboot USB stack a temporary
buffer is allocated in order to get all
these chunks and the data gets mem
copied in the right place every time
such a chunk is received by your device
USB and EF you work side to side because
as soon as you enter VF you the USB
stack gets turned on and during the turn
on these temporary buffer is going to be
allocated and once the control transfer
is issued a pointer this buffer is going
to be copied in a global variable and
the USB stack will use this global
variable to figure out where to put the
data it just got in memory however when
you accept the fu the USB stack is
turned down and the buffer will get
freed and so we get to the interesting
part which is our bug so essentially
when we do free this buffer the global
variable where of destination of the
data right is not actually moved out
and these actually can cause use after
free type of vulnerability and so I'll
recap the steps to get a trigger for
this so we will have to start a USB
control request that has an Associated
data phase and as the data phase is
being sent out
we will interrupt sending packets and
issue a new USB control request in this
case we will issue a USB DFU abort which
will exit the a few turning off the USB
stack with it and freeing the buffer
after DFU except it will try to load
whatever data was loaded but we don't
send any legitimate valid link data and
so DF you fail the image loading will
fail and VF you will re-enter once the
su is re-entered the USB stack is
available again to be used but we have
our dangling pointer still available and
if we send a data face at this point in
time without an Associated setup packet
the pointer is going to be reused from
the previous setup packet that we sent
during the earlier DFU stage and yeah as
soon as this happens the data is going
to be copied on top of such 3-pounder
and in order to accomplish this we need
some very good control over the USB
stack and so little Lela and sagu does
approach to this was to take an Arduino
with a USB host mode shield in order to
get complete control and axiom access
approach on the other hand was to coerce
the USB stack in my class to diverge
from the specification and abort a
transfer midway and the second approach
is now deterministic but you can
actually do multiple attempts and many
USB stacks you will actually tell you
how much data has been transferred once
you abort her request
and from these you can actually infer
whether the attack was successful or not
so as much as it's not deterministic
we found that we got an implementation
that could get very close to 100%
reliability practically and these are
picture of the initial setup to the test
is out from Sigonella to Leila however
there is a catch if you actually attempt
to follow these steps noting that all
would happen except for two specific
devices
a8 and a9 used on the iPhone 6 and the
iPhone 6s and that because on those two
devices there is actually a bug in the
DfE abort functionality basically the
USB stack has its own task to process
USB transfers and zigu delaila noted
that these two devices do not actually
free the tasks once you turn down the
USB stack and so these structure is
going to be leaked in the heap every
time a DFU abort is done and essentially
this gives us the primitive to overwrite
the contents of our task structure and
once you yield from another task once
you from this task the registers are
going to be saved this structure and
when you schedule this task of the
registers are going to be restored off
of it so the users are free right in
theory would allow direct register
control however this is not the case
because the use of the free right
actually happens on the task structure
of the currently executing task and you
can't actually overwrite the registers
because those are live in the actual
hardware backed registers at a point in
time and when you schedule off they will
actually be saved back to the corrupted
test structure and so your corruption is
going to be erased
however tasks also have an internal
linked list from which the actual next
has to be scheduled is chosen
and so you can actually create a fake
trust structure somewhere else in memory
and with the use of turf rewrite
primitive corrupt this linked list
instead so the next time that the USB
task yells back to the scheduler it will
branch into controlled pointers and by
doing these we actually achieve direct
code execution as the heap on securom is
execute 32-bit roms cannot actually use
this strategy as well as a 7 8 10 8 and
X and a 11 which are the newer SOC so
there is no task structure leak to
abusing this and no crash is triggered
whatsoever because the ROM is a terminus
thick enough that every single time we
exceed vfu and we entered the fu the
heap layout is going to look identical
and the buffer for the transfer is going
to be relegated at the same place every
single time and so we need to find a way
to break out of these determinism in
order to get a proper use after free
scenario where the right will actually
hit something that's not supposed to be
just generic data and so AXA max looked
at the secure ROM heap implementation
and realized that the heap will return
the smallest possible hole available for
a given allocation size and so we can
use this property to do hip feng-shui
and essentially what we really need is
controlled allocation primitives so we
actually send a USB transfer there is
actually an Associated structure
allocated on the heap and you can
actually have multiple USB transfers in
this case there transfers from device to
the host specifically in flight at the
same point in time so for instance if
you request some data from the device
the device is not actually going to
able to reply with the data if the host
doesn't acknowledge that the data was
received and every time you send us at a
packet in such a condition where while
the host is enacting the transfer it
will end up staying around for a while
and this gives us the ability to go man
look and delay this free temporarily
until the stall condition is cleared or
the USB stack is shut down but the issue
here is that we need allocations to
persist across a USB stack teardown and
initialization in order for the heap
shaping to influence the state of the
heap when the buffer is going to be
allocated next and in order to pull this
off a state machine bug in the USB stack
had to be abused and these allowed us to
have persistent allocations that will
never actually get freed and these sorry
okay so and these actually relies on
zero length packets so once you have a
transfer from the device to your host
the tractor will actually send up zero
length packet once the request is
fulfilled or the USB stack has to shut
down and the issue is that if you're
actually shutting down the USB stack the
zero length packet is going to be sent
into the void and it will never be
managed because the pointer of the list
of in-flight transfers is going to be
nulled out later on and this leak can be
triggered conditionally because zero
length packets are actually only sent
upon specific conditions for instance
requests that are not a multiple of 64
bytes will not require zero length
packet from the device and so it's not
actually going to be sent and nothing
will happen so we can actually abuse
these in order to carefully craft the
state of the state of the heap and end
up with an exactly sized hole
which will be the preferred place for
Malik to put the ibuffer next and each
USB request structure will also contain
a pointer to a callback that is going to
be invoked once the structure is freed
and we can actually reallocate a few of
these in place of our old buffer and
once we perform our use after free ride
we will be able to control this function
pointer and get an indirect branch once
we exit the fu next and this strategy
can be successfully used on a 9 X a 10
and 11 and a 10 acts on other devices
however these technique is not actually
usable as every single transfer will end
up leaking if the device is has a in
endpoint that stalled however we can
actually allocate repeatedly and have
the heap almost run out - the size that
we want to have for our next buffer and
this will end up creating a hole of the
exact size at the very end of the heap
and that's going to be preferred by
malloc and so by using this we achieve
what's called checkmate however right
now
all we have is code execution and what
we really want to have is a boot kids of
sorts to continue boot normally rather
than staying in securom and DFU mode and
Joburg device hopefully and so how do we
develop a boot kit well we do have code
execution and we are able to re-enter
into the main function of securom which
will attempt to boot device of a flash
again and eventually the bootloader is
going to boot into the kernel and once
that happens it will try to branch into
its entry point and so our goal then
becomes to patch the kernel at the point
in time at which the kernel is loaded in
memory after it's been validated and
it's still fully readwrite at a point in
time and some of you will know that
the colonel text is not writable during
later points in time so that point in
time is actually quite tricky to reach
especially if you want to support
multiple devices and multiple versions
and Brazilian patch finding strategies
were really useful to have in order to
have a job Rock that's maintainable for
the long term so we ended up going for
what's called the book trampoline which
is the last piece of code of I boot that
is ran before jumping the kernel or
another bootloader and this boot
trampoline will wipe the previous page
bootloader from memory so later stages
can dump the memory and dump the
bootloader that way so researchers can
have access to boot loaders it will also
disable the MMU wipe all the registers
and this actually also touches registers
such as X 18 which due to API
constraints are not used anywhere else
and so we can actually find this
trampoline by looking for a move X 18
zero which is always and
deterministically going to only be in
this boot trampoline and yeah we have
shellcode that will dynamically locate
this and patch it out but however there
is a chicken and egg issue here because
the trampoline will wipe the current
stage bootloader and it has to be
relocated somewhere else in order for it
to not be wiped by itself and so it
there is a reserved region for this but
on secure arm especially the trampoline
sometimes is relocated only before
trying to use it and secure rom being
Ram is not patchable
and we get code execution before any of
these happens so it's actually quite
tricky to modify that trampoline
however we are able to copy ctrl into
SRAM and we can patch the page tables in
order to remap Greenup the range of
memory we serve from for the round
and redirect that to our writable Estrin
and on some devices however there is not
enough free as from to do this but we
can do some strategies such as resizing
the heap or we can actually get more
SRAM to available to us by reserving
more of the l2 cache for it but
realistically we all need to remap a
single page in order to patch the
trampoline as it's a pretty small piece
of code and additionally to this we will
also need some area where we can stash
our shell code however we're still
restricted to the available free SRAM
and we will also need to do a normal
boot which might itself make use of SRAM
in other ways and maybe we could use the
RAM however veeram is not initialized
when securom runs the first level
bootloader has to initialize the RAM
however the first stage bootloader also
has a feature called soft DFU which will
simulate the fu mode but at that point
in time the ramp has already been
initialized and this actually allows you
to upload more data to the device and we
can abuse these to load basically an
arbitrary amount of data in the ram
without having to initialize it
ourselves
and without having to bother with a
bunch of other complications that estrin
poses such as size constraints and the
issue with the RAM however is that I
boot will wipe large portions of it but
we implemented dirty work around which
involves in hooking mid 0 and detecting
whether the range overlaps with our
shellcode and in that case turned the
beads your into an up and it isn't nice
nicest way to pull it off but it works
pretty well across all the devices that
we care about and once we hook the
trampoline and beat 0 we are able to
reach the next trampoline invocation
and on some devices there's actually
multiple bootloader stages and so we
have to reiax acute these hooks for each
stage bootloader that gets loaded and
devices before after 810 only one
bootloader is present after ROM so it's
not strictly required eventually the
current list prepara is prepared and the
trampoline is going to be invoked in
devices before a 10 with el3 secured
monitors entry point is actually going
to be passed to these code rather than
the kernels entry point however in the
arguments that are passed to the secure
monitor we can actually find the entry
point for the kernel itself and we can
actually patch the branch target of the
trampoline so our childhood will be ran
instead of the actual secure monitor or
kernel and we can also pass the original
values to our shell code by preventing
registers from being zeroed out by doing
this we now have the ability to patch
the kernel dynamically a boot time
however we have to support a large
number of devices and version thirds
which means that the only viable
strategy here is going to be patch
finding all our patches dynamically and
since we are hooking code execution
after the trampoline runs we do not
actually have a memo or caching
available to us so this becomes really
problematic really quickly because we
are gonna have to scan the kernel which
is roughly 30 megabytes so it becomes
really slow really fast and we will
actually have to turn the MMU back on
with a fake set of page tables in order
to map the RAM as cashable and the patch
Finder can use this cashable map to find
the patches and that's gonna be a lot
faster and our patch finder will apply a
pretty old-school kernel patch set
because KP p and k TR are which our
kernel integrity machan
are not issues we can patch things that
other jailbirds haven't been able to
patch in several years and so it's
basically like it's ios8 all over again
so we are actually able to allow full
read/write/execute code to be allocated
for user space iOS which is going to be
very interesting for emulator kind of
people which hasn't been available to
jailbreakers for roughly four years now
however kernel patching alone is
actually not going to be enough the
issue is that once the kernel boot we
actually want to keep code execution in
order to prepare the gel working state
because we do want to like install some
apps and tools and SSH daemon for
instance and doing these before the
kernel boots is really tricky as we
would have to implement a file system
driver to solve this issue we figured
out that we could embed the tiny RAM
disk in our shell code and this Ram disk
will hijack code execution once the
kernel starts booting user mode and we
can patch the by stray in order for the
kernel to find this Ram disk and we can
alter the kernel boot arguments in order
to have the kernel use it as a root
filesystem rather than the normal NAND
flash and the end result of this was our
initial patch finder here
and so we started from securom code
execution and we got all the way to el0
user mode code execution however we need
to have a ram disk be really small as
the fu transports are pretty slow and
having to wait several seconds on a data
upload to boot your device is not great
additionally there's copyright concerns
since we should avoid shipping any
proprietary Apple code such as libraries
with such a ram disk and again this is
problematic because it means that we
have no libraries and no dynamic linker
available to us at all so it's required
us to write our own totally legitimate
dynamic linker which doesn't actually do
any dilemma klinken it just mounds the
real file system in a union mount on top
of the RAM disk itself and so once we do
that we have the full set of apple
libraries available to us as well as the
real dynamic linker and at that point in
time we can run real code as PID one
before the init in iOS code launch D is
ever executed the root filesystem at
this point is still read-only and we
would really like to keep it that way
until the user explicitly decides to
change it this is for forensics
applications for instance but we also do
need to drop some extra files in order
to get a shell and allow users to
install package managers if they so wish
and so we need the private bar partition
to be available the issue with that is
that private bar is the partition where
user data is stored and on iPhones user
data is encrypted so that partition is
not going to be accessible until we
enable data protection and launch D is
responsible for doing it
so we need to hook code execution at a
later point in time but still early in
the book process so we keep on Union
mounting and this time around we mount
another disk image on top of user lead
exact which is where system demons are
located on iOS and by doing this we can
override any system demon we chose to
override system status check because it
runs to the right point in time across
multiple iOS versions actually finding
something that reliably ran at the right
point in time was quite tricky for us
and they took as several attempts with
different demons until we settled on
this one and once we had code execution
we can execute back into Vinodh of some
other root filesystem and then we can
just first fully amount user little
execs overlay dmg and at this point in
time the system is saying and we can let
launch the continue booting by just
executing it and we can fart before
doing so or inject our own libraries
into launch D and by doing these code
will still be present at that point in
time we'll have to wait until USB
communications are enabled and we will
wait for the host to upload another disk
image this time containing all the
required utilities for a basic shelter
an SSH daemon and app that allows users
to install a proper jailbreak and we
mount these on slash bin pack and
kickstart the SSH daemon and so the
result is that we can get root a root
shell on any iPhone that's vulnerable to
this on any version
and once spring bird which is the demon
that shows the icons on your phone runs
we are able to add our own check-rein
app and we also have some future plans
for all these and we would like for
these to morph from just a jailbreak
into something like clover which is a
bootloader for max and non Mac devices
PC devices which allows you to do custom
kernel extension loading and also allows
you to dwell booting and boot Linux and
windows on iphone and this is still an
ongoing area of research but we are
coming up with what we call Pongo us
which we only briefly mentioned before
today and it's being officially
announced right now which is a tiny
pre-boot execution context it's a fully
custom OS that was written by the
checkering team specifically designed
for apple birds and it actually allows
you to load modules to it over USB and
they will be loaded and linked against
all the facilities that pongo has
provides and we were actually able to
move the check for internal patcher to
such a module and so this will allow
people to use our infrastructure for
custom stuff and security research and
that was it
thank you
well thank you QWERTY for this
interesting talk we are kind of close in
time so we take questions as much time
as we can get please you know the drill
line up behind the microphones and does
the signal every other thing that if it
is very eager there's a question from
the internet how was this exploit
discovered considering that most recent
exploits used user space is the iboot
still active very search so the specific
bug was found by multiple parties the
person who ended up publishing these bug
xmx
actually found it by D Fink because this
was actually patched by Apple in iboot
because the USB stack is actually shared
between iboot and sakura and there is a
two-year lag between something getting
pushed to iboot and it actually reaching
the semiconductor manufacturing
facilities and being flashed on two
devices so yeah as much as that was
patched it was still good enough for our
purposes and I don't know if they're
sending more bugs in iboot but give it a
shot and kink me if you find anything I
guess okay thank you
there's two questions in front of the
microphones what number is it I thought
it is four I think hi yeah yeah really
good talk I've never seen so much great
work put into this really great job guys
my main question today is what is the
estimated time of arrival for the
check-rein Windows built thanks in
advance so we've been working really
hard on these and currently checkering
is only available for mac OS however the
linux release is really close and
hopefully it's going to come out by the
end of the year the Windows version is
also being worked on really much and we
have
overall achievements already we are able
to put some devices and hopefully that's
gonna come be coming in the next couple
months so there's another question on
microphone for yes roses are red violets
are blue windows check-rein eta um I
mean I just answered this question but
there was a good name nicely done
another question from England maybe
someone was wondering where's the source
code so currently check-rein is closed
source however the team plans on open
sourcing it over time and I believe that
Pongo s is going to be the first thing
that will open source and gradually more
of it will be available we estimate that
over the next year it's going to be
fully open source but yeah you can look
for more updates on my Twitter or on the
official checker on Twitter okay thank
you
our time is over so give them another
big round of applause for this very
interesting
[Applause]
[Music]