Jonathan Levin recently released the QiLin, a toolkit, whose aim is to "alleviate the
jailbreak enthusiast or security researcher from the nooks and crannies of post-exploitation, and
to standardize jailbreaking in a way which will be as forward compatible as possible." The toolkit is used in his LiberiOS and LiberTv jailbreak - the former of which is based on Ian Beer's aysnc_wake.
At the time of writing this post, I couldn't find a step-by-step tutorial on how to get started with QiLin. So I decided to quickly add some notes on doing just that.
Environment Setup
Here are some steps to get started:
- Download/open Xcode
- Download Ian Beer's async_wake project(see previous link)
- Download the QiLin object files(see previous link). You need qilin.o as well as sha1.o/sha256.o
- Save the .h file from the QiLin wiki to a file.(eg QiLin.h)
- Open the async_wake project downloaded in step 2 and add the QiLin object files downloaded in step 3 to the project.
Adding QiLin object files - Drag and drop the QiLin.h file saved in step 4 to the project. Now is also a good time to add the iOSBinpack and tar utilities. Note the tar utility is apart of the binpack. At this point, your project should look like the following:
QiLin header and utilities |
Trying to build the project at this point will fail. Let's fix that. Before proceeding, ensure you are signed into Xcode and then update the Build Identifier by navigating to General -> Identity -> Build Identifier.
You most likely will end up with an error indicating that sha256.o does not contain bitcode. Navigate to Build Settings and toggle off Enable Bitcode.
You most likely will end up with an error indicating that sha256.o does not contain bitcode. Navigate to Build Settings and toggle off Enable Bitcode.
Disable bitcode |
Duplicate methods |
LiberiOS
With the environment up and running, we can now delve into the toolkit. First off, the writeup(linked earlier) does provide an idea of which methods to call, but let's have a look at LiberiOS to see how it uses the toolkit. We will then use that as a guide for our purposes.
LiberiOS first calls doIt() which initializes the toolkit with a call to initQiLin(). The method takes the both the kernel task port and kernel base as arguments.
init QiLin |
Once initialized, the _go() method is called and this is where the magic happens:
jtool -d _go LiberiOS | grep BL
Disassembling from file offset 0xe0e4, Address 0x10000e0e4 to next function, mmapped 0x120f46000
10000e0f4 BL _rootifyMe ; 0x10000d544
10000e118 BL libSystem.B.dylib::_printf ; 0x100013aec
10000e120 BL libSystem.B.dylib::_getpid ; 0x1000138b8
10000e124 BL _getProcStructForPid ; 0x10000b234
10000e128 BL _ShaiHulud2ProcessAtAddr ; 0x10000b854
10000e14c BL libSystem.B.dylib::_fopen ; 0x100013870
10000e170 BL libSystem.B.dylib::_fprintf ; 0x10001387c
10000e184 BL Foundation::_NSLog ; 0x100013738
10000e188 BL _platformizeMe ; 0x10000bfb0
10000e1b4 BL _borrowEntitlementsFromDonor ; 0x10000de0c
10000e1c4 BL libSystem.B.dylib::_sleep ; 0x100013b70
10000e1d8 BL _entitleMe ; 0x10000d28c
10000e1e0 BL libSystem.B.dylib::_getpid ; 0x1000138b8
10000e1f4 BL _entitlePidWithKernelEnts ; 0x10000c904
10000e200 BL libSystem.B.dylib::_sleep ; 0x100013b70
10000e208 BL _remountRootFS ; 0x100009c64
10000e210 BL _castrateAmfid ; 0x10000ac24
10000e234 BLR X8 ; 0x24107ff7e64028f0
10000e25c BL _unpackBinariesToPath ; 0x10000da98
10000e264 BL _disableAutoUpdates ; 0x100009f10
10000e288 BL libSystem.B.dylib::_copyfile ; 0x100013840
10000e2a4 BL libSystem.B.dylib::_mkdir ; 0x100013a2c
10000e2e4 BL _execCommand ; 0x10000d7cc
10000e310 BL _spawnAndPlatformize ; 0x10000dfa8
10000e344 BL _spawnAndPlatformize ; 0x10000dfa8
10000e370 BLR X8 ; 0x24107ff7e6402910
10000e374 BL libSystem.B.dylib::_getpid ; 0x1000138b8
10000e378 BL _getProcStructForPid ; 0x10000b234
10000e380 BL _ShaiHuludProcessAtAddr ; 0x10000b99c
The QiLin writeup already has an explanation for what most of the methods do. But even so, just looking at the above list and the IDA disassembly, it's pretty straightforward what is going on. Keep in mind, you might not be interested in including all of the advertised functionality e.g. disableAutoUpdates()/sendStatToJ() in your jailbreak.
Ok, so all we need to do is call those methods - from the toolkit - in our project and we are done. Post exploitation has never been easier!
QiLin Toolkit
As mentioned earlier, the first step in using the toolkit is calling the initQiLin (mach_port_t TFP0, uint64_t KernelBase) method. The method takes tfp0(task_for_pid0) i.e. SEND right to the kernel task as well as the kernel base. async_wake already provides tfp0 via the get_kernel_memory_rw() method. So all we need to determine is the kernel base. Determining the kernel base involves searching kernel memory for the magic bytes 0xfeedfacf.
Determining kernel base |
One frequently asked question is how do I determine the kernel base. I used the following code - taken from the Coalfire-Research Labs project:
iOS kernelcache
As an aside, you can obtain the kernel by navigating to ipsw and selecting your device. Once downloaded, change the extension to .zip and unzip it. The kernelcache will be labeled kernelcache.release.iphone<x>. This file has been compressed and must therefore be decompressed before any analysis can occur. You can use lzssdec for this, but the easier option is using joker.
// Code lifted from https://github.com/Coalfire-Research/iOS-11.1.2-15B202-Jailbreak
extern uint64_t find_port_via_kmem_read(mach_port_name_t port);
uint64_t dump_kernel(mach_port_t tfp0)
{
// ok, where the f*ck is the kernel
// uint64_t kernel_base = 0xfffffff00760a0a0; //15B202 on iPhone 6s
mach_port_t self = mach_host_self();
uint64_t port_addr = find_port_via_kmem_read(self);
uint64_t search_addr = rk64(port_addr + 0x68); //KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT
search_addr &= 0xFFFFFFFFFFFFF000;
printf("[+]\tGoing backwards until magic seen....\n");
while (1)
{
if (rk32(search_addr) == 0xfeedfacf)
{
printf("[+]\tOk, looks like we've found the beginning of the kernel!\n");
printf("[+]\tKERNEL IS AT 0x%llx\n", search_addr);
return search_addr;
} else {
search_addr-=0x1000;
}
}
}
// End lift
iOS kernelcache
As an aside, you can obtain the kernel by navigating to ipsw and selecting your device. Once downloaded, change the extension to .zip and unzip it. The kernelcache will be labeled kernelcache.release.iphone<x>. This file has been compressed and must therefore be decompressed before any analysis can occur. You can use lzssdec for this, but the easier option is using joker.
Decompressing kernelcache |
Show Me Code
Before we actually write any code, let's look at the overall flow:
And with that, the actual code(jbme() snippet) then looks like:
Once executed you should end up with your shell :
The good thing about the toolkit, is that you can view what is happening during each method call - which is very helpful to say the least.
QiLin Notes
While using the toolkit, you may notice that not all exported functions are included in the .h file. To fix that, simply determine the arguments of the function you are interested in - using your favorite disassembler - and then update the .h file. For example, to include the unpackBinariesToPath method, determine the arguments:
And then update the QiLin.h file:
Before we actually write any code, let's look at the overall flow:
Jailbreak flow |
mach_port_t tfp0 = get_kernel_memory_rw();
printf("tfp0: %x\n", tfp0);
/*- Determine kernel_base -*/
uint64_t kernel_base = 0;
kernel_base = dump_kernel(tfp0);
/*- Initialize QiLin toolkit -*/
qInit = initQiLin(tfp0, kernel_base);
/*- Get root privs -*/
printf("[+]\tCalling rootifyMe.....!\n");
rootMe = rootifyMe();
/*- Unsandbox -*/
printf("[+]\tUnsandboxing.....!\n");
uint64_t origCreds = ShaiHuludMe(0);
printf("[+]\tPlatformizing.....!\n");
/*- PlatformizeMe -*/
platformizeMe();
/*- Get Entitlements -*/
printf("[+]\tBorrowing Creds.....!\n");
uint64_t origEnt = borrowEntitlementsFromDonor("/usr/bin/sysdiagnose","-u");
sleep(3);
sleep(1);
/*- Remount / -rw -*/
printf("[+]\tRemount Root file system.....!\n");
remountRootFS();
/*- Kill amfid-*/
printf("[+]\tCastrate AMFID.....!\n");
amfid = castrateAmfid();
if(amfid){
printf("[+]\tFAILED to Castrate AMFID.....!\n");
}else{
/*- Unpack tools -*/
unpackBinariesToPath("binpack64-256.tar", "/jb", "tar");
/*- Get your shell -*/
copyfile("/jailbreak/etc/motd", "/etc/motd", 0, 0xA);
mkdir("/etc/dropbear", 0755);
execCommand("/jb/usr/local/bin/dropbear", "-R", "--shell", "/jb/bin/bash", 0, 0, 0);
/*- Go back into the sandbox-*/
pid_t myPid = getpid();
uint64_t myProcStruct = getProcStructForPid(myPid);
ShaiHuludProcessAtAddr(myProcStruct,origEnt);
}
Once executed you should end up with your shell :
shell access |
QiLin debug info |
While using the toolkit, you may notice that not all exported functions are included in the .h file. To fix that, simply determine the arguments of the function you are interested in - using your favorite disassembler - and then update the .h file. For example, to include the unpackBinariesToPath method, determine the arguments:
unpackBinariesToPath function arguments |
Update QiLin header file |
Conclusion
With the advent of the QiLin toolkit, post exploitation has never been easier. Thanks to Jonathan Levin for this awesome kit. This should be enough to get you up and running.
Have fun!!!!
UPDATE: Just thought I would add that the following calls can be replaced by unShaiHuludMe (as soon as the object file is updated)
The method has already been added to the header file:
Additionally, prior to calling the above block that puts you back in the sandbox, you should check the return value from the call to borrowEntitlementsFromDonor.
Oh and its NOT async_wait it's async_wake. Don't ask how I missed that :) Thanks for pointing that. out.
UPDATE: Just thought I would add that the following calls can be replaced by unShaiHuludMe (as soon as the object file is updated)
/*- Go back into the sandbox-*/
pid_t myPid = getpid();
uint64_t myProcStruct = getProcStructForPid(myPid);
ShaiHuludProcessAtAddr(myProcStruct,origEnt);
The method has already been added to the header file:
unShaiHuludMe in current QiLin.h |
Oh and its NOT async_wait it's async_wake. Don't ask how I missed that :) Thanks for pointing that. out.
I'm totally with you (I think) until I try to find the duplicated function "_go". I cannot find it in the methods of QiLin.h.
ReplyDeleteAt the time of build I get the following build errors:
async_wake_ios Group
Unused Entity Issue Group
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/kmem.c:164:12: Unused variable 'val'
Semantic Issue Group
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/kmem.c:278:7: Code will never be executed
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/arm64_state.h:47:3: Unknown type name 'arm_state_hdr_t'; did you mean 'x86_state_hdr_t'?
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/kdbg.c:13:10: In file included from /Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/kdbg.c:13:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator11.2.sdk/usr/include/mach/i386/thread_status.h:161:30: 'x86_state_hdr_t' declared here
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/arm64_state.h:94:3: Unknown type name 'arm_state_hdr_t'; did you mean 'x86_state_hdr_t'?
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/kdbg.c:13:10: In file included from /Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/kdbg.c:13:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator11.2.sdk/usr/include/mach/i386/thread_status.h:161:30: 'x86_state_hdr_t' declared here
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/arm64_state.h:125:3: Unknown type name 'arm_state_hdr_t'; did you mean 'x86_state_hdr_t'?
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/kdbg.c:13:10: In file included from /Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/kdbg.c:13:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator11.2.sdk/usr/include/mach/i386/thread_status.h:161:30: 'x86_state_hdr_t' declared here
Format String Issue Group
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/async_wake.c:574:65: Format specifies type 'unsigned long' but the argument has type 'mach_port_context_t' (aka 'unsigned long long')
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/async_wake.c:579:51: Format specifies type 'long' but the argument has type 'mach_port_context_t' (aka 'unsigned long long')
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/async_wake.c:619:65: Format specifies type 'unsigned long' but the argument has type 'mach_port_context_t' (aka 'unsigned long long')
/Users/geraldtodd/Desktop/Custom Jailbreak/Libraries/async_wake_ios/async_wake_ios/async_wake.c:624:63: Format specifies type 'long' but the argument has type 'mach_port_context_t' (aka 'unsigned long long')
Thanks for any help, I'm learning a lot (I hope)
Gerald
Hey,
DeleteThanks for reading :).
So the _go method is found in the qilin.o file. So open the file in your favorite disassembler(Hopper, IDA, jtool, binja etc) and then navigate to the exported functions tab....
where do i get the tar file from? how do i find the _go methods?
ReplyDeleteThe tar binary can be found in the iOSBinpack(/usr/bin).
DeleteNot sure I follow the second question. The go method is found in the qilin.o object file. Grab your favourite disassembler and look at the exported methods....
When I attempt this, i'm able to jailbreak and open an ssh shell. However, the ssh session refuses to terminate cleanly. Upon further inspection it seems like the dropbear processes refuse to terminate when they are spawned from my jalibreaking app. Using LiberiOS, dropbear launches and terminates as expected. What would cause this behavior?
ReplyDeleteI can kill dropbear by sending it SIGKILL, but it should not be ignoring sigterm
Fixed Error Uploading Video to Youtube From iPhone
ReplyDeleteWelcome to ufabet online gambling site. Ufabet provides its customers with a safe way to play gambling games. All risky legal issues can be played anywhere, anytime. Just have a mobile or a pc, it can play casino games. The online bingo has always been ufabet open for a long time. Customers receive bonuses from ufabet Instant service 24 Hr. ufabet By the staff with knowledge of the web gambling directly, you can play it in the quality of the web ufabet not just the web. Online gambling alone Customers can watch live sports from abroad through our web directly. Faster than the rituals. You can enjoy the full range of sports games at 5% discount every month, and win some great prizes. Register now and apply for a FREE 20% bonus!
ReplyDeletePlease register at www.ufa-th.com 24 Hr.
Love it keep it
ReplyDeleteThe Xmod Games Hacking APK software
8ball pool unlimited guideline Hack28 without Xmodgames 29
I recently came across your blog and have been reading along. I thought I would leave my first comment. I don’t know what to say except that I have enjoyed reading. Nice blog, I will keep visiting this blog very often.
ReplyDeleteJudi Bola
Hey, great blog, but I don’t understand how to add your site in my reader. Can you Help me please?
ReplyDeleteเว็บยูฟ่าเบท
Creating your own iOS 11/12 jailbreak is a complex and intricate process that requires advanced knowledge and expertise in software development and iOS security. Godaddy Coupon Jailbreaking refers to the process of removing software restrictions imposed by Apple on iOS devices
ReplyDeleteExploring the iOS 11.1.2 Jailbreak journey with the QiLin Toolkit offers tech enthusiasts a unique experience. Just as we navigate the intricacies of mobile devices, it's equally crucial to stay updated on Advancements in Dental Technology. Ensure your digital escapades are complemented by a well-cared-for smile, blending the thrill of tech exploration with the precision of modern oral care.
ReplyDelete