Joker
joker
is now built-in to Jtool2 when used with --analyze
on any kernelcache
Joker
is a quick and dirty iOS kernelcache handling utility I've written to assist in my reverse engineering. Apple tries their damn hardest to make reversing the kernel as hard as possible: With every release, more symbols are stripped. The kernelcache, being prelinked, requires less symbols to begin with (and tables in memory, as all LINKEDIT segments, are jettisoned). And - let's not forget - the kernelcache is encrypted. 32-bit kernelcaches can be decrypted thanks to the holy work by @xerub and others, but no 64-bit kernelcache keys exist (publicly), and the only way to "see" the kernel is by dumping it.
This hasn't stopped jailbreakers in the past, and will hopefully not stop us in the future. joker
is another humble contribution I can provide to the community, and to all reversers out there. It uses the same machlib as its sibling jtool
, and the two in fact can finally play well together (see below)
The tool is primarily designed for iOS (naturally), but since the XNU data structures are pretty much identical, it works pretty well with some switches (-m
, -s
) on the OS X kernel, as well.
Usage Examples
Basic
With no arguments, joker
will strive to explain itself:
Zephyr:JTool morpheus$ joker
Usage: joker [-j] [-MmaSsKk] _filename_
_filename_ should be a decrypted iOS kernelcache, or kernel dump.
-m: dump Mach Traps and MIG tables (NEW)
-a: dump everything
-k: dump kexts
-K: kextract [kext_bundle_id_or_name_shown_in_-k|all]
-S: dump sysctls
-s: dump UNIX syscalls
-j: Jtool compatible output (to companion file)
2.2.1 (w/64 kextraction, MIG) Stable version (and kextraction on 64-bit!)
Tested on ARMv7/s 3.x-9.21b1, and ARM64 8.x/9.21b1
With just a filename, it will provide you with a brief identification of the file in question, by looking at the LC_SOURCE_VERSION. It will also print the sysent table address.
Zephyr:JTool morpheus$ joker ~/Documents/iOS/9b/kernel.9b.4S.decrypted
Source Version: 3216.0.0.1.15
This is iOS 9.x, or later
Found iOS 8+ sysent table @3eb684 (Addr: 0x803ec684)
32-bit
Since 32-bit kernelcaches can be obtained in entirety, before LINKEDIT
and PRELINK_INFO
are removed, joker
can both list as well as extract kexts (what I call 'kextract'):
Zephyr:JTool morpheus$ joker -k ~/Documents/iOS/9b/kernel.9b.4S.decrypted | more
Source Version: 3216.0.0.1.15
This is iOS 9.x, or later
Found iOS 8+ sysent table @3eb684 (Addr: 0x803ec684)
Processing kexts
OFFSET: 1095000
0x804ba000: Mach Kernel Pseudoextension (com.apple.kpi.mach)
0x804bc000: Unsupported Pseudoextension (com.apple.kpi.unsupported)
0x804bf000: Private Pseudoextension (com.apple.kpi.private)
0x804c5000: I/O Kit Pseudoextension (com.apple.kpi.iokit)
0x804df000: Libkern Pseudoextension (com.apple.kpi.libkern)
..
0x810d2000: tlsnke (com.apple.nke.tls)
0x810da000: AppleDiagnosticDataAccessReadOnly (com.apple.driver.AppleDiagnosticDataAccessReadOnly)
0x810dd000: AppleA5IOP (com.apple.driver.AppleA5IOP)
Got 171 kexts
To extract, simply specify the name of the kext , not the bundle ID (annoying because of spaces, I know - but I'll add that in later)
# First locate kext Zephyr:JTool morpheus$ joker -k ~/Documents/iOS/9b/kernel.9b.4S.decrypted | grep sandbox 0x80e50000: Seatbelt sandbox policy (com.apple.security.sandbox) # Now extract Zephyr:JTool morpheus$ joker -e "Seatbelt sandbox policy" ~/Documents/iOS/9b/kernel.9b.4S.decrypted Source Version: 3216.0.0.1.15 This is iOS 9.x, or later Found iOS 8+ sysent table @3eb684 (Addr: 0x803ec684) Processing kexts Attempting to kextract Seatbelt sandbox policy Found Seatbelt sandbox policy at load address: 80e50000, offset: e05000 Extracted Seatbelt sandbox policy # extracted kext will be dropped to same directory Zephyr:JTool morpheus$ ls -l Seatbelt\ sandbox\ policy -rw-rw-rw- 1 morpheus staff 499712 Aug 7 16:56 Seatbelt sandbox policy Zephyr:JTool morpheus$ file !$ file Seatbelt\ sandbox\ policy Seatbelt sandbox policy: Mach-O kext bundle arm# BackEndBilly from the forum noted that extraction by name fails on "/" in name, # (and messy with lots of spaces) so this is now easier, by bundle ID, as of v2.1.1: bash-3.2# ./joker -k ~/Documents/iOS/9b/kernel.9b.4S.decrypted | grep MobileFil 0x80728000: AppleMobileFileIntegrity (com.apple.driver.AppleMobileFileIntegrity) bash-3.2# ./joker -K com.apple.driver.AppleMobileFileIntegrity ~/Documents/iOS/9b/kernel.9b.4S.decrypted This is a 32-bit kernel from iOS 9.x, or later (3216.0.0.1.15) Found iOS 8+ sysent table @3eb684 (Addr: 0x803ec684) Processing kexts Attempting to kextract com.apple.driver.AppleMobileFileIntegrity Found com.apple.driver.AppleMobileFileIntegrity at load address: 80728000, offset: 6dd000 Extracted com.apple.driver.AppleMobileFileIntegrity bash-3.2# file com.apple.driver.AppleMobileFileIntegrity com.apple.driver.AppleMobileFileIntegrity: Mach-O kext bundle arm
Note that the kernelcache you see in OS X (shoved deep in
32 and 64-bit (OS X too!)
Using -s
will get you a full dump of the __sysctl_set
section. This is useful because the sysctl descriptors have plenty of useful kernel addresses - both of the variables behind the sysctl as well as any handlers:
# especially designed to be grep(1) friendly - you can get your sysctl + 6 lines Zephyr:JTool morpheus$ joker -s ~/Documents/iOS/9b/kernel.9b.4S.decrypted | grep -A 6 vnode_enfor 0x80411fc0: security.mac.vnode_enforce Description: Enforce MAC policy on vnode operations Handler: 0x802b5171 Format: IU Parent: 0x80414b90 Arg1: 80406028 Arg2: 0x0
Oh, and - this works on OS X kernels too.
Hands down the most useful symbolication is via "-m", which symbolicates Mach traps and UN*X syscalls. joker
will automatically suppress enosys and "old" syscalls which don't really do anything, but will nonetheless provide you with the addresses:
Zephyr:JTool morpheus$ joker -a ~/Documents/iOS/9b/kernel.9b.4S.decrypted | more Source Version: 3216.0.0.1.15 This is iOS 9.x, or later ARM Exception Vector is at file offset @0xc6000 (Addr: 0x800c7000) Found iOS 8+ sysent table @3eb684 (Addr: 0x803ec684) Syscalls at address 0x803ec684 Suppressing enosys (0xffffffff802c14bd) and old (0xffffffff802c14cd) 1. exit 802a0f48 T 2. fork 802a5734 T 3. read 802c14e8 T 4. write 802c1924 T 5. open 800f5344 T 6. close 80290e68 T 7. wait4 802a288c T 9. link 800f5c70 T 10. unlink 800f5d24 T .. 490. netagent_trigger 80152f38 T 491. stack_snapshot_with_config 80287fc4 T 493. grab_pgo_data 80303030 T Zephyr:JTool morpheus$$ joker -m -m -d ~/Documents/iOS/9b/13A4254v.bin | more This is a 64-bit Kernel Source Version: 3216.0.0.1.15 This is iOS 9.x, or later Syscalls at address 0xffffff8005ef60c0 Sysent offset in file (for patching purposes): 4f20c0 Suppressing enosys (0xffffff8005d73640) and old (0xffffff8005d73620) 1.. exit 0xffffff8005d49f5c 2.. fork 0xffffff8005d4f338 3.. read 0xffffff8005d73668 .. 489.. mremap_encrypted 0xffffff8005d5111c 490.. netagent_trigger 0xffffff8005bac3f4 491.. stack_snapshot_with_config 0xffffff8005d29a98 493.. grab_pgo_data 0xffffff8005dc91b0 # Unexpected bonus - also works on OS X kernels :-) Zephyr:JTool morpheus$ joker -m /System/Library/Kernels/kernel | grep mmap This is a 64-bit Kernel # Albeit not as useful since most symbols are still exported (and there's the KDK) 197.. mmap 0xffffff80007c8990 Zephyr:JTool morpheus$ jtool -S /System/Library/Kernels/kernel | grep mmap | grep 8990 ffffff80007c8990 T _mmap
jtool interoperability:
The latest and greatest feature (besides 64-bit) is JTool support - the latter can now work with "companion files", which are simply text files which follow a simple convention (0xaddress:symbol:comment
). You can use the new -j
to auto-create that file
Zephyr:JTool morpheus$ joker -j -m ~/Documents/iOS/9b/13A4254v.bin This is a 64-bit Kernel Source Version: 3216.0.0.1.15 This is iOS 9.x, or later Opened companion File: /Users/morpheus/Documents/iOS/9b/13A4254v.bin.ARM64.397D09B8-4B9B-3771-ACEE-7143647BD873 Opening companion file Syscalls at address 0xffffff8005ef60c0 Sysent offset in file (for patching purposes): 4f20c0 Suppressing enosys (0xffffff8005d73640) and old (0xffffff8005d73620) Output written to /Users/morpheus/Documents/iOS/9b/13A4254v.bin.ARM64.397D09B8-4B9B-3771-ACEE-7143647BD873 in Jtool-compatible format. Run jtool with --jtooldir . or set JTOOLDIR= # File format is crude, I'll admit, but it makes it all the more easier for manual editing Zephyr:JTool morpheus$ head -5 /Users/morpheus/Documents/iOS/9b/13A4254v.bin.ARM64.397D09B8-4B9B-3771-ACEE-7143647BD873 0xffffff8005d49f5c:exit 0xffffff8005d4f338:fork 0xffffff8005d73668:read 0xffffff8005d73d40:write 0xffffff8005b33e44:open # We can now use jtool, since the companion file was created for us - and use symbols from it as we disassemble! Zephyr:JTool morpheus$ jtool -d stack_snapshot_with_config ~/Documents/iOS/9b/13A4254v.bin Opened companion File: 13A4254v.bin.ARM64.397D09B8-4B9B-3771-ACEE-7143647BD873 Disassembling from file offset 0x325a98, Address 0xffffff8005d29a98 to next symbol stack_snapshot_with_config: ffffff8005d29a98 STP X22, X21, [SP,#-48]! ffffff8005d29a9c STP X20, X19, [SP,#16] ffffff8005d29aa0 STP X29, X30, [SP,#32] ffffff8005d29aa4 ADD X29, SP, #32; R29 = SP + 0x20 ffffff8005d29aa8 SUB X31, X31, #64 ffffff8005d29aac MOV X19, X1 ffffff8005d29ab0 MOV X20, X0 ffffff8005d29ab4 BL _kauth_cred_get ; 0xffffff8005d2f300 ffffff8005d29ab8 MOV X21, X0 ffffff8005d29abc ADD X8, X21, #1; ..R8 = R21 (0x0) + 0x1 = 0x1 ffffff8005d29ac0 CMP X8, #1 ffffff8005d29ac4 B.HI 0xffffff8005d29ae0 ; 0xffffff8005d29ae0 ffffff8005d29ac8 ADRP X8, 390; ->R8 = 0xffffff8005eaf000 ffffff8005d29acc ADD X8, X8, #1478; ..R8 = R8 (0xffffff8005eaf000) + 0x5c6 = 0xffffff8005eaf5c6 "kauth_cred_getuid" ffffff8005d29ad0 STP X8, X21, [SP,#0] ffffff8005d29ad4 ADRP x0, 390; ->R0 = 0xffffff8005eaf000 ffffff8005d29ad8 ADD X0, X0, #1454; ..R0 = R0 (0xffffff8005eaf000) + 0x5ae = 0xffffff8005eaf5ae ""%s: bad credential %p"" ffffff8005d29adc BL _panic ; 0xffffff8005a2b960 ; _panic("%s: bad credential %p", arg2, arg3); ...
This is especially useful since IDA pro 6.5, for all its amazing features (and hefty price tag) provides this helpful notification when loading a kernel dump :
Mach Traps
lso, Mach traps are back - task_for_pid
is especially useful (to apply the tfp0
patch, which brings back the kernel_task
to userland.
$ ./joker -m /System/Library/Kernels/kernel.3247 This is a 64-bit kernel from OS X 10.11, or later (3247.1.78.0.0) mach_trap_table offset in file/memory (for patching purposes): 0x801900/ffffff8000a01900 Kern invalid should be ffffff8000309000. Ignoring those 10 _kernelrpc_mach_vm_allocate_trap ffffff80002dde60 - 12 _kernelrpc_mach_vm_deallocate_trap ffffff80002ddf10 - 14 _kernelrpc_mach_vm_protect_trap ffffff80002ddfb0 - .. 93 mk_timer_arm_trap ffffff80002f5410 - 94 mk_timer_cancel_trap ffffff80002f54f0 - 100 iokit_user_client_trap ffffff80008e52d0 - # On OS X, the above are actually exported, so you can # verify joker's got it right $ jtool -S !$ | grep ffffff80008e52d0 jtool -S /System/Library/Kernels/kernel.3247 | grep ffffff80008e52d0 ffffff80008e52d0 T _iokit_user_client_trap
MIG Tables
Mach uses messages, and message serialization uses MIG. The Mach Interface Generator generates the boilerplate code required for parsing messages, and - as can be expected - leave easily recognizable patterns all over the place. joker
now recognizes the dispatch tables left behind (mig_e
), and proceeds to symbolicate the functions as well.
Note that the functions symbolicated are the proxies - the actual functions that do the work are called from these. But it's fairly simple to figure out, because the proxies basically call the message check functions, then the ...internal ones.
This is primarily useful for iOS, of course, but all the symbols are stripped there. So the ..internal pattern can be more readily seen with the OS X xnu, wherein the internal functions are exported (but the mig ones from the tables aren't:
host_priv_subsystem is @0xffffff8000a02a90! 0: host_get_boot_info_mig_wrapper: ffffff800032ea60 (400) .. _host_subsystem is @0xffffff8000a030d8! 0: host_info_mig_wrapper: ffffff8000332300 (200) 19: mach_vm_page_info_mig_wrapper: ffffff8000338cd0 (4819) ..# Note joker can detected if Apple updates their defs Warning: This kernel is newer than joker is (224 < 227)! mach_port_subsystem is @0xffffff8000a03558! 0: mach_port_names_mig_wrapper: ffffff80003346b0 (3200) task_subsystem is @0xffffff8000a04728! 0: task_create_mig_wrapper: ffffff800033fec0 (3400) .. 41: task_swap_mach_voucher_mig_wrapper: ffffff8000342c50 (3441) thread_act_subsystem is @0xffffff8000a04dd8! 0: thread_terminate_mig_wrapper: ffffff8000342f30 (3600) 26: thread_set_mach_voucher_mig_wrapper: ffffff8000344d40 (3626) 27: thread_swap_mach_voucher_mig_wrapper: ffffff8000344ee0 (3627) # Unfortunately, jtool doesn't do x86, so use otool: $ otool -tV /System//Library/Kernels/kernel.3247 |grep -A 100 ffffff8000344ee0 ffffff8000344ee0 pushq %rbp ffffff8000344ee1 movq %rsp, %rbp ffffff8000344ee4 pushq %r15 ffffff8000344ee6 pushq %r14 ffffff8000344ee8 pushq %r13 ffffff8000344eea pushq %r12 ... ffffff8000344ee0 pushq %rbp ffffff8000344ee1 movq %rsp, %rbp ffffff8000344ee4 pushq %r15 .. ffffff8000344fe3 movq %r12, %rsi ffffff8000344fe6 callq _thread_swap_mach_voucher
Again, note I use x86_64 here just to illustrate the idea because you can see the internal function is _thread_swap_mach_voucher, which means joker got the MIG dispatch correctly. To get this on iOS, by cross-correlating ARM64 and x86_64 assembly it's trivial to symbolicate the rest..
Version 3.0β1!
With iOS 10 and OS X 12 out, and the kernel segment layout modified, it's time for an improved joker! v3.0 is worthy of a major number increment, because it features integration with my machlib (the engine of disarm and jtool), which allows joker
to disassemble in order to find functions! Presently I've implemented matching for the "low hanging fruit" (functions taking in strings), but this can be expanded for complex cases and smart pattern matching.
You might be wondering if joker hasn't lost its raison d'être, with Apple (intentionally/accidentally) providing a decrypted kernelcache. I believe it hasn't - namely:
- kexts are still fused in tight - so you need
-k/-K
- Mach Traps & MIG, syscalls and sysctls aren't exported - so you need
-m
,-s
and-S
respectively. I've updated the syscall table, btw, for all 520 syscalls, and almost all MIGs. - A lot of other interesting symbols aren't exported. XNU has O(20k) symbols, of which iOS XNU only exports O(4k) - those needed by kexts
Decompilation is not the usual functionality you'd want, and is also a bit slow. So try -j
and let it take its time. You'll see:
morpheus@Zephyr (~/Documents/iOS/10) % joker -j xnu.3757.j99a 13:00 This is a 64-bit kernel from iOS 10.x, or later (3757.0.0.0.0) Opened companion File: xnu.3757.j99a.ARM64.9612A9D5-FA9B-3663-ADD0-C1852BE6674B Opening companion file Got 4498 syms Looking for _secure_monitor ... Found _secure_monitor at offset 0x7aec Looking for _start_cpu ... Found _start_cpu at offset 0x7018 Auto-Disassembling __TEXT_EXEC.__text from 0xfffffff00747c000 to find rest This may take a little while, but you only need to do this once Disassembling from file offset 0x78000, Address 0xfffffff00747c000 GOT PE_Parse_boot_argn: 0xfffffff0078db018 GOT lck_grp_alloc_init: 0xfffffff0074ac1b4 GOT OSKextLog: 0xfffffff00783bf48 GOT lck_grp_init: 0xfffffff0074ac1b4 GOT PE_get_default: 0xfffffff0078db608 GOT __ZN9IOService15publishResourceEPKcP8OSObject: 0xfffffff007874e88 GOT __ZN8OSSymbol17withCStringNoCopyEPKc: 0xfffffff007849c28 GOT __ZN9IOService15publishResourceEPKcP8OSObject: 0xfffffff007849c28 GOT __ZN9IOService15publishResourceEPKcP8OSObject: 0xfffffff007874e88 GOT IOLog! 0xfffffff00785b5ec ARM Exception Vector is at file offset @0x7b000 (Addr: 0xfffffff00747f000) Output written to xnu.3757.j99a.ARM64.9612A9D5-FA9B-3663-ADD0-C1852BE6674B in Jtool-compatible format. Run jtool with --jtooldir . or set JTOOLDIR= # Note that now function starts are also auto imported into companion file.. morpheus@Zephyr (~/Documents/iOS/10) % wc -l xnu.3757.j99a.ARM64.9612A9D5-FA9B-3663-ADD0-C1852BE6674B 13:03 10791 xnu.3757.j99a.ARM64.9612A9D5-FA9B-3663-ADD0-C1852BE6674B # All these go into companion file, of course, and you can verify those which ARE exported, like IOLog: morpheus@Zephyr (~/Documents/iOS/10) % jtool -S xnu.3757.j99a| grep IOLog 13:04 Opened companion File: ./xnu.3757.j99a.ARM64.9612A9D5-FA9B-3663-ADD0-C1852BE6674B Loading symbols... fffffff00785b5ec T _IOLog # Matches! fffffff00785b680 T _IOLogv
In some cases (notable, PE_parse_boot_argn), joker
is more accurate than the actual symbol table, since the exported symbol is a wrapper over the real implementation, which is the one used frequently. If you want more symbols supported, let me know via the website forum, please.
Joker 3.0 also does MACF policies - presently only for Sandbox.kext , as AMFI's is now loaded in code (but *does* do AMFI as well in dumps). This gets the new hooks in Sandbox 570 (which I've highlighted below) and looks like this:
Zephyr:Sierra morpheus$ joker /tmp/161.com.apple.security.sandbox.kext Found policy at 0xfffffff0055a05d0 Policy name: Sandbox Full name of policy: Seatbelt sandbox policy Flags: 0 Ops: fffffff0055a0620 mpo_cred_check_label_update_execve: 0xfffffff00552a34c .. mpo_mount_check_snapshot_create: 0xfffffff005520970 mpo_check_snapshot_delete: 0xfffffff005520a08 mpo_vnode_check_clone: 0xfffffff005520aa0 mpo_proc_check_get_cs_info: 0xfffffff005520c68 # The Hedgehog hook :-) mpo_proc_check_set_cs_info: 0xfffffff005520d1c mpo_iokit_check_hid_control: 0xfffffff005520d98 .. com.apple.security.sandbox(570.0.0.0.0)(570.0.0.0.0)
Other enhancements in 3.0 are JTOOLDIR=...
so you can extract to elsehwere than /tmp, and a couple of really exciting features (like the auto-detection of IOUserClients), but that won't be out until the final version. The 2nd Beta adds detection of secure monitor (SMC) and the ARM exception vector, long missing in 64-bit
I use joker
extensively (and exclusively, for lack of IDA) when writing my notes from iOS/OSX, now in its third year, and I hope you find it useful.
Version 3.0β2!
joker
now auto-symbolicates stubs in kexts!!! (most) stubs point to exported symbols in the kernel proper, and thanks to AAPL we now have those exports! joker
auto follows the disassembly of stubs, e.g.
fffffff00552fa64 ADRP X16, 113 ; ->R16 = 0xfffffff0055a0000 fffffff00552fa68 LDR X16, [X16, #0] ; -R16 = *(R16 + 0) = *(0xfffffff0055a0000) = 0xfffffff007843ae4 ... ?.. fffffff00552fa6c BR X16 ; 0xfffffff007843ae4
As you can see, machlib
can follow the registers, and figure out the addresses. So, if the symbol for what's in X16 is exported, you can find it easily:
morpheus@Zephyr (~)$ jtool -S ~/Documents/iOS/10/xnu.3705.j99a | grep fffffff007843ae4
fffffff007843ae4 T _IOFree
But.. why should you need to do this yourself? joker
now does this automatically!
morpheus@Zephyr (~)$ joker -K com.apple.security.sandbox ~/Documents/iOS/10/xnu.3705.j99a This is a 64-bit kernel from iOS 10.x, or later (3705.0.0.2.3) ARM Exception Vector is at file offset @0x7b000 (Addr: 0xfffffff00747f000) Found com.apple.security.sandbox at load address: 551c000, offset: 1a8c000 Writing kext out to /tmp/com.apple.security.sandbox.kext Symbolicating stubs for com.apple.security.sandbox from off 0x13a64 # Note that there are still symbols that are not exported by XNU, but ARE linked from stubs Unable to resolve kernel symbol at fffffff0040e4e84 .. Symbolicated stubs to /tmp/com.apple.security.sandbox.kext.ARM64.00066DE6-8BDC-36E0-90CD-A872522D821 morpheus@Zephyr (~)$ cat /tmp/com.apple.security.sandbox.kext.ARM64.00066DE6-8BDC-36E0-90CD-A872522D8211 fffffff00552fa64:_IOFree.stub fffffff00552fa70:_IOMalloc.stub .. fffffff00552faac:_PE_i_can_has_debugger.stub ... fffffff00552fff8:_sock_gettype.stub morpheus@Zephyr (~)$ jtool -d /tmp/com.apple.security.sandbox.kext | grep "^; _panic" Opened companion File: /tmp/com.apple.security.sandbox.kext.ARM64.00066DE6-8BDC-36E0-90CD-A872522D8211 Loading symbols... Disassembling from file offset 0x770, Address 0xfffffff00551c770 ; _panic.stub("released collection's reference to profile"); ; _panic.stub("cannot register builtin profile with no name"); ; _panic.stub("failed to initialize platform sandbox"); ; _panic.stub("unexpected filter type"); ; _panic.stub("sfree on invalid allocation at %p"0xfe); ; _panic.stub("no profile to evaluate"); ; _panic.stub("%s: matchlen (%zu) > pathlen (%zu)\n""(null)"); ; _panic.stub("%s: failed to allocating matching dict""(null)"); ; _panic.stub("%s: failed to lookup AMFI service\n""(null)"); ; _panic.stub("failed to allocate OSSymbol for string \"%s\"""(null)");
Version 3.0β3!
Minor but useful change: If you feed joker an uncompressed (decrypted) kernelcache it will still complain, but will extract the KPP Mach-O at its end for you to
Version 3.0β3!
- Split Kexts (iOS 10b2+)
Version 3.1

Version 3.2
morpheus@Zephyr (~/Documents/Work/JTool) % ./joker -j ~/Downloads/kernelcache.release.n66
Feeding me a compressed kernelcache, eh? That's fine, now. I can decompress! (Type -dec _file_ if you want to save to file)!
Compressed Size: 12537772, Uncompressed: 24854528. Unknown (CRC?): 0x95944450, Unknown 1: 0x1
btw, KPP is at 12538208 (0xbf5160)..And I saved it for you in /tmp/kpp
Got kernel at 437
This is a 64-bit kernel from iOS 10.x (b7+), or later (3789.32.1.0.0)
Opened companion File: /Users/morpheus/Downloads/kernelcache.release.n66.ARM64.977182E2-2525-386E-8808-457275346A3E
Opening companion file
Found _secure_monitor at offset 0x7b0c, Addr: 0xfffffff007087b0c
Found _start_cpu at offset 0x7018, Addr: 0xfffffff007087018
Auto-Disassembling __TEXT_EXEC.__text from 0xfffffff007080000 to find rest..
This may take a little while, but you only need to do this once
Disassembling from file offset 0x7c000, Address 0xfffffff007080000
GOT zinit: 0xfffffff0070e5700
GOT PE_Parse_boot_argn: 0xfffffff0074e5a40
GOT zp_factor: 0xfffffff007556340
GOT PE_Parse_boot_argn: 0xfffffff0074e5a40
GOT zp_scale: 0xfffffff007556344
fffffff007585568:vm objects zone
fffffff0075711f0:vm object hash entries zone
fffffff007570cd0:maps zone
fffffff007570b10:Reserved VM map entries zone
fffffff007570cc0:VM map copies zone
fffffff007570b18:VM map holes zone
fffffff00758ad60:pmap zone
fffffff007588bb0:vm pages array zone
fffffff007588bb8:vm pages zone
GOT lck_grp_alloc_init: 0xfffffff0070b23a8
fffffff007570a90:mem_obj_control zone
fffffff007570a70:device node pager structures zone
fffffff007556338:waitq sets zone
fffffff007537300:ipc spaces zone
fffffff0075372d0:ipc ports zone
fffffff0075372d8:ipc port sets zone
fffffff0075372c0:ipc kmsgs zone
fffffff007538428:ipc vouchers zone
fffffff007538420:ipc voucher attr controls zone
fffffff007537150:ipc task importance zone
... you get the idea
Version 3.99
- Not 4.0 because I still don't have USerClients working - Updated for iOS 11 β (Still not tested on MacOS 13, but should work) - Sandbox decomp likely broken (haven't tested, but there are more operation names , like dynamic-code-generation...I know, I'll fix it)
morpheus@Chimera (~/Documents/Work/JTool) %./joker.universal -s ~/Downloads/kernelcache.release.ipad4
Feeding me a compressed kernelcache, eh? That's fine, now. I can decompress! (Type -dec _file_ if you want to save to file)!
Compressed Size: 12693336, Uncompressed: 24969216. Unknown (CRC?): 0xc809f8d1, Unknown 1: 0x1
btw, KPP is at 12693775 (0xc1b10f)..And I saved it for you in /tmp/kpp
Got kernel at 440
This is a 64-bit kernel from iOS 11.x (b1+), or later (4397.0.0.2.4)
#
# Note also - as apparently two new Mach traps
# KPP updated (haven't checked yet, so not sure it will defeat Luca's bypass, but nice AAPL are trying)
#
...
186.. thread_selfcounts 0xfffffff0071a6c7c
..
375.. kevent_id 0xfffffff0073cb0d0
...
520.. terminate_with_payload 0xfffffff0073efdac
521.. abort_with_payload 0xfffffff0073d9410
522.. necp_session_open 0xfffffff0072465e8
523.. necp_session_actrion 0xfffffff00724c538
524.. setattrlistat 0xfffffff0071ae720
525.. net_qos_guideline 0xfffffff0072d85c4
526.. fmount 0xfffffff0071cf0a0
527.. ntp_adjtime 0xfffffff007466ba4
528.. ntp_gettime 0xfffffff007466a30
529.. os_fault_with_payload 0xfffffff0073d9468
Version 4.0
Ok. So user clients are working :-) Specifically, here's how to use this:
When kextract™ing an extension, joker
will produce a companion file. The major change is that it now also scans __DATA_CONST.__const
(where IO objects are) to find plenty of references back into the main kernel. It symbolicates all of those, and this gets you the IO*
and OS*
methods when you follow up with a jtool --jtooldir ... -d ..
on the kext (remember to get the right dir for the companion file). It also detects the common structure with the layout of function pointers , which can then be identified as the IOExternalMethodDispatch
struct.
I DO NOT provide you user client names (yet). But I do provide a simple user_client_x_method_y format, like so:
grep user_client /tmp/com.apple.iokit.IOMobileGraphicsFamily.kext.ARM64.0BC46AA3-A18A-3109-AE4E-25B7C3951924 | head -5
0xfffffff006b19afc:user_client_1_method_0
0xfffffff006b19b1c:user_client_1_method_58
0xfffffff006b19b40:user_client_1_method_3
0xfffffff006b19b88:user_client_1_method_4
0xfffffff006b19bc4:user_client_1_method_5
so you get the idea.
IF YOU WOULD LIKE TO HELP submit the names of UserClient methods you find through The forum , and future versions of Joker will provide those hard coded. But with 150+ drivers, I can't do this unless people help.
Download
Right here (Universal: OSX 64, iOS 32/64, and Linux 64)Source Caveat: Won't compile without machlib.
ChangeLog
v3.99 - update and minor fix for iOS 11β1
v3.2 - decompilation now successfully gets all zones by decompiling zinit and tracking the return value to globals
v3.1 - works on compressed kernelcaches (not iPhone 7 bvx2 (LZFSE), but classic complzss)
v3.0 - kext support, split kext, MACF Policies, and preliminary sandbox decomp
-- Minor fix to specify output dir for kextraction, as JOKER_DIR=
-- validation on memem in case signature can't be found..
v2.3 - Almost fully integrated with MachLib - Correctly identifies all kexts, even in a dump
v2.2.1 - kextraction on 64 bit works! Can also ID the kexts, despite absence of __PRELINK_INFO. Use "all" for all kexts.
v2.1.1 - preliminary kextraction from a 64 bit dump (sans __PRELINK_INFO), and fix for Billy's Bug
v2.1 - (re)Added Mach trap table, MIG subsystems (+150 symbols!)
v2.0 - jtool integration (write to companion file)
Greets
Finger
License, etc
Use it at will. You have my blessing, and I won't complain. A nice thank you would be appreciate if you find it useful, as well as feature requests, if you have any.
joker
is open source, so you can see the patterns in the kernelcache it locks on in order to its work. Machlib (its dependency) isn't, but I can license the latter if you're interested.