
all right hello everyone um so today i will speak about uh jump back to 2016 ios jailbreaking um so yeah first of all who am i so my name is tommy turkic i'm 16 years old and i'm interested in ios jailbreaking since i started hacking which was about three years ago or so and in fact i actually started hacking um because of ios jailbreaking i i was always kind of interested in ios type of stuff however i only started working on ios about a year ago and this is due to the fact that i was actually working on small cdf challenges and stuff like that and i actually spoke here last year um and this year i actually got invited and i
really appreciate the invitation so um yeah so this is the agenda for uh today so basically first of all i'm going to give a really really short introduction to ios jailbreaking and then we're going to move on to the main parts which is the r2 box and the um some few patches to escalate privileges so um basically what is an ios jailbreak well so for the most people it's actually cydia which is actually just a package manager where you can actually install tweaks from and so that way you it allows the user to to customize their iphones or ipads and if you download some tweaks from cydia you can modify your springboard which is the home screen of the iphone
and this is actually a lot more behind the scenes and i actually wanted to learn more about this and so this is why i kind of started with um with ios jailbreaks um and today i will actually cover a 32-bit ios jailbreak so there will be no software hardware mitigations such as kpp ktrr pack etc which newer jailbreaks actually have to deal with so that also means that we can actually patch the tag segment so as we all know zero days are expensive most of the jailbreaks are rely on already um published vulnerabilities and so in these days once we have the vulnerability exploited what we actually want to set up some read-write primitives to uh perform
further patches and so ios actually builds around message passing and in ios java breaking access to the tosport zero or or the pid 0 is a holy grail because that is the kernel pretty much and if you have a send right to your port that means you can actually modify so you can read write its virtual memory and obviously if you can read and write the kernel memory you can apply further patches now obviously apple knows this and they want to protect the user from having access to the pid 0 and there is a call for tasks for pit 0 which will get you a send right if it is allowed but obviously passing argument 0 will return an error
and so we can see there is a comment in the code uh so if p equals to zero then an error is returned no matter who's going so um yeah we can see there is also some hard coded checks in inside the code codebase and uh we can patch this for example by uh uh in assembly checking for the comparator and instead of zero we're gonna set to for example 0xff and uh so with the access uh to the um or having sent back to the kernel we can read and write arbitrary bytes as i explained previously and many utilities needs this uh thus repeat zero patch for example newer jailbreaks uh use this in order to set boot nons so that the
user can actually downgrade or upgrade to an unsigned ios version if other issues are not present and for example i made a very basic tool called vm read write which actually um does what the name suggests it's reads and writes uh the kernel memory if uh it actually have the toss for p0 patch enabled and so this is how my tool looks it's very very simple but it's actually useful and also i actually made use of during the jailbreak development so um yeah once we have sent right uh to the kernel task and we can write its memory we can actually escalate privileges and uh the main goal of this talk is to actually achieve root
so escalating privileges and there are a bunch more things to do if we want to install cydia spawn ssh and so on we would need to escape the sandbox patch amfi remount the root file system and so on but i won't get into that in today's talk so yeah this is pretty much our plan for the jailbreak so we're gonna first make use of the info leak then the memory caption and then we're gonna make use of other stuff such as read write primitives and some patches uh so before anything i just want to mention that uh as far as i know this is and was the first um spider jailbreak that was actually used in the real
wild and um they actually attacked uh this ahmed human rights defender and he actually received an sms text uh with a link and there was actually a trap a one-click rce and uh he didn't actually clicked on the link instead he actually sent to a group who analyzed the link and they realized that this was such an exploit and uh i won't get into the webkit or the persistence because they actually had persistent exploits as well uh but rather only the two bugs which they are used which is the infolec and the memory corruption so this is the kernel info leak and it's actually really really simple they have a function and they forget to check the length uh variable
which we can see there and uh so pretty much that way we can actually press an arbitrary number and we can if we can read back uh we can leak some kernel stack which will be obviously the case and in order to exploit this we need to craft a special dictionary and so this is how the dictionary look like so first we have the magic number and this is actually needed in order to the function to accept our dictionary otherwise it will actually decline it then we have a dictionary with two entries then we have a three byte aaa plus a null termination and then we have our big size number and at least eight bytes for our big num
big number and in a normal case scenario you would be only be able to read these eight bytes back but uh obviously that's not the case at this point and once we have our melissa's dictionary set up what we actually want to do is uh read those data back uh in order to leak the bytes for us and we're going to do this using io kit and if you don't know what is io kit i'm just gonna not gonna get into that but just gonna say that it's pretty much used for ios kernel and user space communication um yeah it's enough for that and but basically you can actually read these bytes back using iokit
and uh we look for the aaa property and we're going to read from there and this is the full kslr defeat good now i don't know whether can you see clearly or not but it's actually really simple it's just like 50 lines of code i just want decided to throw it in here just to show that it in indeed it is very simple and running the program will result us with some debug messages that we can actually see the leaked address where the function returned from and uh taking the address and applies applying some calculations we can get the kernel base and so how we're going to do it well we're going to have the
array which is the buffery plus we're going to add the the offset to it to actually have it in the ninth position because foreign is 36 some some mats and uh then we're gonna uh mask it to one megabyte because it's always uh gonna end with with five zeros and we're gonna add just by one page because it starts at what 8000 one thousand so um yeah and after this we actually have uh the kernel base and if you still want to calculate the case or slide then it's really simple what you want to do is take away the base address which is 8000 1000 and you will have the kernel aslr side so yeah we can see
that this is the kernel base and this is uh the kernel side so this is the memory caption bug and this is actually a kernel user for free and this is due to a dangling of a string pointer in ossen serialized binary and so that means that again we will need to craft a special dictionary in order to exploit this vulnerability so um but before that i actually want to explain how the bug occurs so basically we have a setting index macro uh predefined for us and what what's interesting in here is that it will actually save our objects to an object array um and yeah pretty much there is a special case in here
uh which called k of a serialized object which what it does is actually will uh call o retaining an object and so what that means is we'll actually add one reference to the object so the object can be freed when uh the when the count drops to zero but we can actually make it live again with the code to retain and so uh exactly what happens here is there is an o string to a symbol cost which will actually call o release which will free the um object save to the objects array which was just saved there and so we we can see there is the o release call and uh there is the call if you remember
from case serialize object so we can actually relocate the data with our custom data and we can call actually or retain on it which makes it a uaf scenario and again for this we need to make a special dictionary as well so we're going to start by the magic again and then we have a dictionary now with three entries and we're going to start by triggering the o string the location where we actually cost it to another symbol and then we have uh the payload or pretty much where we're gonna replace uh the dangling read table pointer and so this is the payload uh with some random zero exported ones and then now we're gonna call
the retain on the object so now it became now once we trigger the bug it will the kernel will actually crash because it will try to jump to an invalid address however if you actually run it it will result such that the fault address is 0x41 but we do not actually control the program counter and so in order to do that we actually need to craft a fake v table and so we can see the retable pointer is pretty much a pointer to a weak table where there are function pointers and so what we're going to do is we're going to craft a fake way table where uh instead of retaining we can actually point to our
militia cup b table which can hold pretty much any value and i decided to place 42 there for for the record and um yeah so pretty much but in order to pull this off what we actually need to do uh have is a control data and kernel memory at the no at a known location and there are a few ways to put control data to kernel memory from user land and training set is actually using a different technique but there are a few few ways as i said so uh i'm actually focusing on mac message at this point and mac messages use ipc and we can actually send or receive using a mac message call
and there is no mac message sender receive instead there is an option which where we can specify whether we want to send the message or receive the message and so pretty much this is how sending your message works um visually so we have task 1 and we want to send to dos 2. what we're going to do is well we're going to send it to the kernel the kernel will allocate some space for the data and they will send it to you task 2 and when the toster receives it the kernel will free its space and wait for another message to reallocate or it will stay there completely freed so basically i think you already guessed
it what we'll what we will do we're gonna send uh again but instead now we're not going to receive it and so our data will stay in actually in the kernel so that way we can actually have control data in kernel memory where we actually send from user space and so he string can actually be achieved by sending a bunch of data but not actually receiving them so we can see that if you not receive it will actually stay in the kernel and also we can do here feng shui uh by sending a bunch of data and only receiving a few so we send a bunch of like for example aaa and we only receive a few we actually eventually
poked holes around the heap but yeah and uh so going on with our technique what we're gonna what we are going to do we are going to allocate a mac port with macbook write receive and so we actually will have this and write to it and we're going to send a message to it in my case i'm going to send 0x42 to it and instead of receiving i choose not to and however now we left with one little problem and that is that okay we can actually send some data to the kernel but we don't know where the data will end up however uh when we are doing the info leak part we're making a use of a call to i or just re-enter
you get property and the make command carries a map message pointer so eventually we'll send a mac message as well and it will actually free it but if we send our message at the right point in time we can actually relocate with our message so again the good thing about this is that we actually leaked this address while we're actually leaking other addresses and so the versions i tested is always ending with b8 so um if you're actually jailbreaking we can actually read from this address and this is actually sometimes it's really good to actually have an already jailbreaking device to actually develop a jar break so yeah we can see uh this is where i
actually make use of my vm breed write tool where i actually got got that data and i started to read from it and eventually i saw my message appear in in the kernel heap and so i what we can do now is actually we craft our payload in such way that i will actually point here so yeah as i said we need to curve the payload uh with the messages rest and after that we actually have uh control over the program counter and so yeah we can see uh we actually do control the program counter if you do like this and uh yeah so we can actually now start um patching and uh however uh we actually
have control over the program counter but when whenever we call this trigger uaf function or to your the uaf it will actually panic the device and we need a way to keep the kernel alive because obviously in order to jailbreak it you have to keep the kernel alive and apply patches in the runtime and uh we can actually do that by replacing uh retain with a legitimate function and uh yeah so that function will um be always serialized serialized and this is how the final payload should look like so we have the address of uh copying then we have some address from the stack and then we have our real address of the payload as some values and again the gadget
and so this is how the os serialized serialized gadget looks like so first of all we actually do control r0 so at this point in time we're gonna control r3 as well and then we're going to control r1 as well because again we control r0 and lastly we're going to control r12 as well which is really good because we actually have a branch to r12 which means that we actually can have an executive primitive and this is how my payload actually looks like so again i have the address for copying from my payload and have some random data then we actually have the payload pointer which is the message where we send and you notice that i actually take away
some bytes and this is due to the fact that it's not exactly located at the address where we actually send the message it will be a bit below but um we can actually locate that um again if you're jailbroken it's really really easy just a simple matter of reading from the address and uh then we have our gadget which will be the always serialized serialized gadget again so yeah i actually just kind of rush it but um yeah this is how it looks and uh so once we have that the kernel will stay alive so we actually need now to set up the read write primitives and i'm again i'm using the same gadgets as the shrine and using
so um we are going to make use of some clock services and for the read primitive we're going to make use of the battery clock so um basically we're going to design the payload in such way that it will contain pointers to handler functions and when we actually call the callback functions the payload will replace the gata ttr handlers and get the ttr uh will actually point to our buff rttr cpx so yeah we can see that what it will do is actually reach from r0 to r0 so it's perfect for our read primitive and again for execute informative we're going to make use of the clock service and we're going to replace now instead of real time clock get a ttr
function and we will replace it with the always serialized serializer serialize function which i actually explained earlier but it's used for uh for our executive primitive because we can actually have arguments and uh yeah we're gonna branch to our control address and this is how the payload uh will look like uh it will rely on some on the on this gadget so we we're gonna have the uh some bytes of random data to make it uh to make it executable and then we actually have two arguments and we have the adjust what we actually want to execute and in order to actually execute the code or the address we actually need to place some bytes before the first
argument and after that we actually after we have actually have the executive primitive setup a right primitive is really really simple uh all we actually need is just the right gadget because we can actually execute the gadget using our executive primitive and so there is this uh right gadget which we're gonna make use of so pretty much we have a store instruction which we're gonna we're gonna store whatever inside r1 which we actually control to our zero plus zero xc but we're gonna take away zero c uh so 12 from address so it will be actually correct where we're going to actually store uh the value or the data and so basically the post exploitation
part which is actually not tied specifically to these exploit or these bugs um the this can be applied to pretty much 32 bits or um yeah any other jailbreaks um and yeah so first of all we're going to actually patch b map because at the mmu level pages are actually read execute and are not read write execute execute except for jit pages for mobile suffering and there are usually three levels of page tables and uh in order to actually patch this which is this is realistically not even a patch uh to actually get the pin of dress what we are actually going to do is get the address of the pmap printer and we're gonna check
for page entries and block entries and in case if it's a page entry what we're gonna do is uh a physical address uh is actually another set of dtes so we're gonna loop one more time and unset the bits and in case it's a block entry we're gonna do is just simply unset the bits so yeah and after setting all the bits pages can be uh read write execute and now we can uh perform further patches and uh so this basically this is the task for p0 patch which again to uh this is needed in order to have a send right to the kernel task and once we have basically our right primitive uh we can
pretty much patch really really easily um to allow zero as an argument uh thus for pit call and we can actually after we actually have this right uh vm right we can actually patch pretty much any other thing and so we're gonna actually patch only three compress it it's actually really really simple to patch for costs for pit zero but again uh on newer uh devices and newer versions uh this is actually not really possible anymore due to the fact that apple introduced kpp and ktrr and pack and basically all the other stuff and so but yeah we're gonna focus on the 32b only so yeah this is the paycheck and uh so we can see there is the comparison
which i actually showed earlier uh with the zero whether if pids equals to zero if it is it will just branch an error and so we actually want to patch this to compare within our value like ff once we have that what we actually want to do is actually we want to patch the posix check uh which is again a really really simple uh just a comparison to r0 with zero i'm going to patch that as well and then we have actually have the mac pro check and uh again if you just just pretty much dig around you you easily find this place and you you can actually patch uh this comparison as well and pretty much after this we can have
uh send right to the kernel tasks so we can actually use the vm read and vm write calls so we can actually write the kernel memory and now we can actually escalate privileges which as i said was pretty much the main idea of this talk and yeah so there are other ways to patch it and you can either like null out the check and move out all these checks or you can actually skip the check which i actually did so pretty much we can see it's actually a branch to ab370 and uh what what we actually want to do because that's actually the if case so what we want to do is dig around and
find uh at the end of the uh the checks and we got we want to brush there so basically um once we found that what we actually want to do is uh write uh the new address the branch address instead so um the offset so instead it's actually gonna branch after the uh if check so we can see how it looks like so it's gonna branch here and uh uh this is how it looks in the hex editor so it's actually e009 the offset and so pretty much we're gonna patch this with four zero e0 and you actually have to calculate the offsets and uh you can then really easily um get with the hex to arm side which is
really really helpful in this case because you can really really easily get what you actually need to put there so yeah um this is after the patch we can see it's a completely different address and it's just gonna pretty much skip the fks and so we can actually after this we can of course attribute id so yeah we can see this is the first case the original where it's actually not patched and it just goes uh goes to the if checks and this is the patch where it's a completely different address it's 3de and they will just pretty much just keep the if case and after running uh uh this the dispatch we can actually call
setup id with zero so after that we actually escalated privileges and so yeah there you go and we can see that uh i actually have uid 501 first which is mobile which is actually normal in in ios which well we are actually in normal his and after that we can see um i'm actually uid 0 which means i'm actually root and also if you don't believe me you can see the code is actually i'm calling get you id so um yeah and if you're actually interested in this project or just want to get the source code or just try it out you can actually get this on my github it's actually called broke and so yeah
you can go ahead and download it and uh yeah and lastly i actually want to give a huge shout out to all these people because this project or the talk wouldn't be possible without them so um yeah i want to give them a big shout out to kwerty saguza jn doc benjamin ibisburgs uh ben and billy ellis because they really really helped me um while i was doing this and they yeah they they were really nice people so yeah and now if you actually have any questions i believe uh you can actually ask on discord i think but i'm not really sure but uh you can always tweet me at tomitake or at ion0uido so yeah
thank you for your attention