Despite being a relatively new project, vphone is a game changer in the world of iOS research. It democratizes this niche domain, which was until so recently dominated by the likes of Corellium and/or jailbreaks. The former, being a private company, required a research budget, whereas the latter are all but extinct since the days of iOS 16.5. If that's not already radical enough, vphone also provides an emulated SEP, and - relevant to our previous posts, an ability to peer into TXM and SPTM.
Setting up vphone is relatively straightforward, but we find that it leaves much to be desired before truly providing a fully working research environment. This post addresses what we believe are ways to improve the environment. From presenting an alternative to the aging iosbinpack, to carefully controlling the precise patches applied.
cbv and the case of the better binpack
Our regular readers might recall our post on cbv, a simple tool to edit a Mach-O binary and change its LC_BUILD_VERSION. Apple has provided a similar functionality in its vtool(1).
In that post, the main reason for introducing the tool was in order to port iOS binaries to macOS - so that they can be debugged and traced in a more welcoming environment. With the introduction of vphone, however, cbv gets newfound purpose for working in the opposite direction.
The choice of CLI binaries on iOS is extremely limited, and those that do exist - ps(1), df(1), mount(8), and the like - wouldn't have been there if not for sysdiagnose(1). By contrast, macOS has a rich environment with numerous useful utilities, which - being POSIX-compatible - offer a familiar interface for researchers familiar with the UNIX CLI.
The existing "binpack" offered in vphone is very dated, going as far back to Jonathan Levin's version for iOS 11, wherein he actually compiled "The Best of Apple's Open Source" (ibid.) to recreate every single tool. Most tools are still functional. But, aas can be expected, in the nearly a decade which followed some tools were updated, and brand new ones introduced.
The existing code we provided for cbv (or, for those who prefer, Apple's vtool(1)), does work in converting back to iOS. This, of course, is subject to re-signing and (when necessary) re-entitling the binary. Private entitlements are not an issue, since that is taken care of by the vphone patching.
There is, however, a hitch in the conversion process. Binaries on MacOS dependent on frameworks will have an LC_LIBRARY_PATH with the full framework path - including the "bundle" form of Versions/.... For example, the useful vim(1) editor:
DFFenders@...(~) % ARCH=arm64e disarm -L `which vim` | grep Fram
LC 14: LC_LOAD_WEAK_DYLIB /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compat ver 45.0.0, current ver 2685.60.104)
LC 15: LC_LOAD_WEAK_DYLIB /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices (compat ver 1.0.0, current ver 1226.0.0)
LC 18: LC_LOAD_DYLIB /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compat ver 300.0.0, current ver 5026.5.4)
LC 21: LC_LOAD_WEAK_DYLIB /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compat ver 150.0.0, current ver 5026.5.4)
Leaving aside for the moment some framework differences (above, AppKit.framework, which is not found on iOS), a direct application of the existing cbv wouldn't work, because frameworks on iOS are "flat", and dont have the Versions/../ subdirectories.
This can be fixed on a case by case basis manually, by patching out the Versions/.. and making the frameworks flat again. Of course, this is not really scalable for the numerous binaries we aim to port, so it's easier to build it in to the cbv code, like so:
For fear of upsetting Apple, we cannot provide a binpack of our own - but - since our readers likely have Macs, this handy script recreates the entire environment of macOS on your vphone:
A working scp (or an scp workaround)
Vphone provides a working dropbear, which allows SSH. Transferring files in an out of the vphone, however, requires a trick. For lack of sftp-server, scp(1) won't work, and so files have to be moved in and out by a crude command line:
## output the file into the write end of a pipe,# then have ssh read from it, and effectively connect# it to the read end of "cat" on the device. This will# still prompt you for the "alpine" password, but that won't# affect the copy operation#Dffenders@... $ cat $file | ssh -p 22222 root@vphone "/iosbinpack64/cat > /tmp/$file"
This can be made into a simple script, which can be used without bothering to make the actual scp work:
Alternatively, you can copy over /usr/libexec/sftp-server (requires patching its OpenDirectory.framework dependency).
Direct editing of the Disk.img
Vphone VMs use Apple's Virtualization.framework, and its disk images follow the same format - raw img files, which are a block-by-block map of the entire disk. This makes it easy to edit the image from outside the vphone environment, with some limitations:
- The /var partition, as user-data, is (virtual-)SEP encrypted with a class D key, and therefore cannot be read by the host.
- The rest of the image (that is, directories under / but not under /var) is mounted read-only.
Kernel Patching
The documentation for vphone lists several "patch levels" that can be selected, but does not provide much choice over individual patches. This can prove challenging for researchers who may want to selectively control which patches are applied, and/or apply patches of their own.
Discussion of patches
Using disarm --diff, it's easy enough to get a "bindiff" style list of patches. This feature is currently limited only to files with the same LC_UUID (since otherwise the differences will run into the thousands or more), which makes it perfect for comparing two versions of the same file, pre and post patches. The following shows the example patches detected in this way on the iOS 26.3 vphone:
morpheus@Mistr4l (~/vphone-cli/vphone-cli-26.3) %disarm --diff kernelcache vm/iPhone17,3_26.3_23D127_Restore/kernelcache.research.vphone600
Diffing kernelcache and vm/iPhone17,3_26.3_23D127_Restore/kernelcache.research.vphone600 (Experimental..)
kernelcache: This is an IM4P... with a BVX2 payload@0x23... Uncompressed 44089344 bytes
vm/iPhone17,3_26.3_23D127_Restore/kernelcache.research.vphone600: This is an IM4P... with a BVX2 payload@0x36... Uncompressed 44089344 bytes
-- Files have same UUID (DBA60317-A1B7-24BE-2FC2-4E4EFAFC2D5A)
__DATA_CONST:0x68ab48: 0x0 != 0x1
__DATA_CONST:0x74a5a0: 0xfffffe0007ac17d8 != 0xfffffe0008080d0c
__DATA_CONST:0x74a5a8: 0xfffffe0007c76320 != 0xfffffe0007c76244
__DATA_CONST:0x74a5b0: 0x20000800000007 != 0xc000300000001
__DATA_CONST:0xa62db0: 0xfffffe0007ac1720 != 0xfffffe00093d2ce4
__DATA_CONST:0xa63368: 0xfffffe00093d04d4 != 0xfffffe00093bb63c
__DATA_CONST:0xa63370: 0xfffffe00093d04d4 != 0xfffffe00093bb4f0
__DATA_CONST:0xa63378: 0xfffffe00093d04d4 != 0xfffffe00093bb3a4
__DATA_CONST:0xa63380: 0xfffffe00093d04d4 != 0xfffffe00093bb258
__DATA_CONST:0xa63388: 0xfffffe00093d04d4 != 0xfffffe00093bb10c
__DATA_CONST:0xa63390: 0xfffffe00093d04d4 != 0xfffffe00093bafb8
__DATA_CONST:0xa63398: 0xfffffe00093d04d4 != 0xfffffe00093bae6c
__DATA_CONST:0xa633a0: 0xfffffe00093d04d4 != 0xfffffe00093bad14
__DATA_CONST:0xa633a8: 0xfffffe00093d04d4 != 0xfffffe00093babc8
__DATA_CONST:0xa633b0: 0xfffffe00093d04d4 != 0xfffffe00093baa7c
__DATA_CONST:0xa634c8: 0xfffffe00093d04d4 != 0xfffffe00093b9110
__DATA_CONST:0xa634e8: 0xfffffe00093d04d4 != 0xfffffe00093b86bc
__DATA_CONST:0xa634f0: 0xfffffe00093d04d4 != 0xfffffe00093b8498
__DATA_CONST:0xa63500: 0xfffffe00093d04d4 != 0xfffffe00093b804c
__DATA_CONST:0xa63510: 0xfffffe00093d04d4 != 0xfffffe00093b7ef4
__DATA_CONST:0xa63518: 0xfffffe00093d04d4 != 0xfffffe00093b7c28
__DATA_CONST:0xa63520: 0xfffffe00093d04d4 != 0xfffffe00093b7aa4
__DATA_CONST:0xa63528: 0xfffffe00093d04d4 != 0xfffffe00093b7720
__DATA_CONST:0xa63530: 0xfffffe00093d04d4 != 0xfffffe00093d116c
__DATA_CONST:0xa63538: 0xfffffe00093d04d4 != 0xfffffe00093b7560
__DATA_CONST:0xa63540: 0xfffffe00093d04d4 != 0xfffffe00093b7404
__DATA_CONST:0xa63548: 0xfffffe00093d04d4 != 0xfffffe00093b711c
__DATA_CONST:0xa63560: 0xfffffe00093d04d4 != 0xfffffe00093b6a5c
__DATA_CONST:0xa63568: 0xfffffe00093d04d4 != 0xfffffe00093b68d8
__DATA_CONST:0xa63578: 0xfffffe00093d04d4 != 0xfffffe00093b6690
__DATA_CONST:0xa63590: 0xfffffe00093d04d4 != 0xfffffe00093b6538
__DATA_CONST:0xa635b8: 0xfffffe00093d04d4 != 0xfffffe00093b5fd8
__DATA_CONST:0xa635c0: 0xfffffe00093d04d4 != 0xfffffe00093b5e54
__DATA_CONST:0xa635c8: 0xfffffe00093d04d4 != 0xfffffe00093b5bec
__DATA_CONST:0xa635d0: 0xfffffe00093d04d4 != 0xfffffe00093b5958
__DATA_CONST:0xa635d8: 0xfffffe00093d04d4 != 0xfffffe00093b5800
__DATA_CONST:0xa635e0: 0xfffffe00093d04d4 != 0xfffffe00093b56a8
__DATA_CONST:0xa635e8: 0xfffffe00093d04d4 != 0xfffffe00093b5540
__DATA_CONST:0xa635f0: 0xfffffe00093d04d4 != 0xfffffe00093b53d8
__DATA_CONST:0xa635f8: 0xfffffe00093d04d4 != 0xfffffe00093b5100
__DATA_CONST:0xa63700: 0xfffffe00093d04d4 != 0xfffffe00093b3b18
__TEXT_EXEC: 0xfffffe0007ac02b8: 0x52800000 MOVZ W0, #0 0x00000000 DCD 0x0
__TEXT_EXEC: 0xfffffe0007ac02bc: 0x142e3835 B 0xb8e0d4 0x00000000 DCD 0x0
...
.. Shellcode inserted by vphone's patcher ..
...
__TEXT_EXEC: 0xfffffe0007ac19b0: 0x1402fa31 B 0xbe8c4 0x00000000 DCD 0x0
__TEXT_EXEC: 0xfffffe0007ac19b4: 0x00000000 DCD 0x0 0x00000000 DCD 0x0
##
##
##
__TEXT_EXEC: 0xfffffe0007b10400: 0xeb1f03ff CMPsr X31, X31 0xeb00013f CMPsr X9, X0
__TEXT_EXEC: 0xfffffe0007b10404: 0x540001c0 B.EQ 0x38 0x540001c0 B.EQ 0x38
##
##
##
__TEXT_EXEC: 0xfffffe0007b12100: 0x14000015 B 0x54 0x540002a1 B.NE 0x54
__TEXT_EXEC: 0xfffffe0007b12104: 0x52816a48 MOVZ W8, #2898 0x52816a48 MOVZ W8, #2898
##
##
__TEXT_EXEC: 0xfffffe0007bb8bf8: 0xd503201f NOP 0x36180076 TBZ W22, #3 0xc
__TEXT_EXEC: 0xfffffe0007bb8bfc: 0x52800017 MOVZ W23, #0 0x52800017 MOVZ W23, #0
##
##
__TEXT_EXEC: 0xfffffe0007bd0ac8: 0x1400000a B 0x28 0x54000141 B.NE 0x28
__TEXT_EXEC: 0xfffffe0007bd0acc: 0x37b00128 TBNZ W8, #22 0x24 0x37b00128 TBNZ W8, #22 0x24
##
##
##
__TEXT_EXEC: 0xfffffe0007cb5108: 0xd503201f NOP 0x37280e3c TBNZ W28, #5 0x1c4
__TEXT_EXEC: 0xfffffe0007cb510c: 0x39415368 LDRB W8, [X27, #84] 0x39415368 LDRB W8, [X27, #84]
##
##
##
__TEXT_EXEC: 0xfffffe0007cb5138: 0x9101c208 ADD X8, X16, #112 0x9101c208 ADD X8, X16, #112
__TEXT_EXEC: 0xfffffe0007cb513c: 0xaa1f03e8 MOVr X8, X31 0x39400508 LDRB W8, [X8, #1]
##
##
##
__TEXT_EXEC: 0xfffffe0007cb74e8: 0xd503201f NOP 0x97ffaaac BL 0xfffffffffffeaab0
__TEXT_EXEC: 0xfffffe0007cb74ec: 0xaa1a03e0 MOVr X0, X26 0xaa1a03e0 MOVr X0, X26
##
##
##
__TEXT_EXEC: 0xfffffe0007f7b988: 0xd73f0911 BLRAA X8 0xd73f0911 BLRAA X8
__TEXT_EXEC: 0xfffffe0007f7b98c: 0xd503201f NOP 0x35001340 CBNZ W0, 0x268
__TEXT_EXEC: 0xfffffe0007fb4f68: 0xd503201f NOP 0x34fffda8 CBZ W8, 0xffffffffffffffb4
__TEXT_EXEC: 0xfffffe0007fb4f6c: 0xb9400e88 LDRi W8, [X20, #12] 0xb9400e88 LDRi W8, [X20, #12]
__TEXT_EXEC: 0xfffffe0007fb4f70: 0xd503201f NOP 0x34fffd68 CBZ W8, 0xffffffffffffffac
__TEXT_EXEC: 0xfffffe0007fb4f74: 0xd2800008 MOVZ X8, #0 0xd2800008 MOVZ X8, #0
__TEXT_EXEC: 0xfffffe0007fd1318: 0xf90003ff STRi XZR, [X31] 0xf90003ff STRi XZR, [X31]
__TEXT_EXEC: 0xfffffe0007fd131c: 0xd503201f NOP 0x34000c97 CBZ W23, 0x190
__TEXT_EXEC: 0xfffffe00080083a8: 0xd503201f NOP 0x37000748 TBNZ W8, #0 0xe8
__TEXT_EXEC: 0xfffffe00080083ac: 0xa9507bfd LDP X29, X30, [X31, #256] 0xa9507bfd LDP X29, X30, [X31, #256]
__TEXT_EXEC: 0xfffffe000805fed0: 0x14000011 B 0x44 0x97ef28d2 BL 0xffffffffffbca348
__TEXT_EXEC: 0xfffffe000805fed4: 0x34000200 CBZ W0, 0x40 0x34000200 CBZ W0, 0x40
__TEXT_EXEC: 0xfffffe000806df38: 0xd503201f NOP 0xb40040e0 CBZ X0, 0x81c
__TEXT_EXEC: 0xfffffe000806df3c: 0x97fd665d BL 0xfffffffffff59974 0x97fd665d BL 0xfffffffffff59974
__TEXT_EXEC: 0xfffffe000806df40: 0xd503201f NOP 0x34004134 CBZ W20, 0x824
__TEXT_EXEC: 0xfffffe000806df44: 0x528002c0 MOVZ W0, #22 0x528002c0 MOVZ W0, #22
__TEXT_EXEC: 0xfffffe00080705f0: 0xd2800000 MOVZ X0, #0 0xd503237f PACIBSP
__TEXT_EXEC: 0xfffffe00080705f4: 0xd65f03c0 RET 0xa9bc5ff8 STP X24, X23, [X31, #-64]!
__TEXT_EXEC: 0xfffffe000807fd60: 0xeb00001f CMPsr X0, X0 0xeb10011f CMPsr X8, X16
__TEXT_EXEC: 0xfffffe000807fd64: 0x54000640 B.EQ 0xc8 0x54000640 B.EQ 0xc8
__TEXT_EXEC: 0xfffffe0008240c20: 0x1a9f17fc CSET W28, NE (@@TODO on inv cond) 0x1a9f17fc CSET W28, NE (@@TODO on inv cond)
__TEXT_EXEC: 0xfffffe0008240c24: 0xd503201f NOP 0x37101578 TBNZ W24, #2 0x2ac
__TEXT_EXEC: 0xfffffe0008264640: 0x94023af3 BL 0x8ebcc 0x94023af3 BL 0x8ebcc
__TEXT_EXEC: 0xfffffe0008264644: 0x1400001d B 0x74 0x340003a0 CBZ W0, 0x74
__TEXT_EXEC: 0xfffffe00082d4db8: 0xd2800020 MOVZ X0, #1 0x90ffa608 ADRP X8, #-2880
__TEXT_EXEC: 0xfffffe00082d4dbc: 0xd65f03c0 RET 0xb40000e0 CBZ X0, 0x1c
__TEXT_EXEC: 0xfffffe000836e460: 0x7200011f TST W8, #0x1 0x7200011f TST W8, #0x1
__TEXT_EXEC: 0xfffffe000836e464: 0x52800016 MOVZ W22, #0 0x1a8913f6 CSEL W22, W31, W9, NE
__TEXT_EXEC: 0xfffffe0008645b10: 0xd2800020 MOVZ X0, #1 0xd503237f PACIBSP
__TEXT_EXEC: 0xfffffe0008645b14: 0xb4000042 CBZ X2, 0x8 0xd100c3ff SUBi SP, SP, #48
__TEXT_EXEC: 0xfffffe0008645b18: 0xf9000040 STRi X0, [X2] 0xa9014ff4 STP X20, X19, [X31, #16]
__TEXT_EXEC: 0xfffffe0008645b1c: 0xd65f03c0 RET 0xa9027bfd STP X29, X30, [X31, #32]
__TEXT_EXEC: 0xfffffe000864a8c8: 0x17e6799f B 0xffffffffff99e67c 0x17e6799f B 0xffffffffff99e67c
__TEXT_EXEC: 0xfffffe000864a8cc: 0x52800000 MOVZ W0, #0 0xd503237f PACIBSP
__TEXT_EXEC: 0xfffffe000864a8d0: 0xd65f03c0 RET 0xd10603ff SUBi SP, SP, #384
__TEXT_EXEC: 0xfffffe000864a8d4: 0xa9126ffc STP X28, X27, [X31, #288] 0xa9126ffc STP X28, X27, [X31, #288]
__TEXT_EXEC: 0xfffffe000864e388: 0x97ed6f2b BL 0xffffffffffb5bcac 0x97ed6f2b BL 0xffffffffffb5bcac
__TEXT_EXEC: 0xfffffe000864e38c: 0x17d1c7cb B 0xffffffffff471f2c 0x52800020 MOVZ W0, #1
__TEXT_EXEC: 0xfffffe000864e580: 0x17d1ca60 B 0xffffffffff472980 0x17ffff84 B 0xfffffffffffffe10
__TEXT_EXEC: 0xfffffe000864e584: 0x52800000 MOVZ W0, #0 0x52800000 MOVZ W0, #0
__TEXT_EXEC: 0xfffffe000864e588: 0x17d1ca5e B 0xffffffffff472978 0x17ffff82 B 0xfffffffffffffe08
__TEXT_EXEC: 0xfffffe000864e58c: 0x940068c3 BL 0x1a30c 0x940068c3 BL 0x1a30c
__TEXT_EXEC: 0xfffffe0008652860: 0x6b00001f CMPsr W0, W0 0x7100081f CMPi W0, #2
__TEXT_EXEC: 0xfffffe0008652864: 0x540005e1 B.NE 0xbc 0x540005e1 B.NE 0xbc
__TEXT_EXEC: 0xfffffe0008653370: 0x52800020 MOVZ W0, #1 0x97e6ce34 BL 0xffffffffff9b38d0
__TEXT_EXEC: 0xfffffe0008653374: 0x34000080 CBZ W0, 0x10 0x34000080 CBZ W0, 0x10
__TEXT_EXEC: 0xfffffe0008653378: 0xaa1403e0 MOVr X0, X20 0xaa1403e0 MOVr X0, X20
__TEXT_EXEC: 0xfffffe000865337c: 0x52800020 MOVZ W0, #1 0x97ffdca6 BL 0xffffffffffff7298
__TEXT_EXEC: 0xfffffe00093ae620: 0xaa0003f1 MOVr X17, X0 0x979f4a06 BL 0xfffffffffe7d2818
__TEXT_EXEC: 0xfffffe00093ae624: 0x937d7e88 SBFIZ X8, X20, #3, #-29 0x937d7e88 SBFIZ X8, X20, #3, #-29
__TEXT_EXEC: 0xfffffe00093ae6d8: 0x179c4c9b B 0xfffffffffe71326c 0x179f46e7 B 0xfffffffffe7d1b9c
__TEXT_EXEC: 0xfffffe00093ae6dc: 0xd65f03c0 RET 0xd65f03c0 RET
__TEXT_EXEC: 0xfffffe00093be600: 0x979c1e7b BL 0xfffffffffe7079ec 0x979c1e7b BL 0xfffffffffe7079ec
__TEXT_EXEC: 0xfffffe00093be604: 0xd2800000 MOVZ X0, #0 0xd503237f PACIBSP
__TEXT_EXEC: 0xfffffe00093be608: 0xd65f03c0 RET 0x6db923e9 STP D9, D8, [X31, #-112]!
__TEXT_EXEC: 0xfffffe00093be60c: 0xa9016ffc STP X28, X27, [X31, #16] 0xa9016ffc STP X28, X27, [X31, #16]
__TEXT_EXEC: 0xfffffe00093c38f8: 0xd65f03c0 RET 0xd65f03c0 RET
__TEXT_EXEC: 0xfffffe00093c38fc: 0xd2800000 MOVZ X0, #0 0xd503237f PACIBSP
__TEXT_EXEC: 0xfffffe00093c3900: 0xd65f03c0 RET 0xa9bc6ffc STP X28, X27, [X31, #-64]!
__TEXT_EXEC: 0xfffffe00093c3904: 0xa90157f6 STP X22, X21, [X31, #16] 0xa90157f6 STP X22, X21, [X31, #16]
__TEXT_EXEC: 0xfffffe00093c3a90: 0xd2800000 MOVZ X0, #0 0xd503237f PACIBSP
__TEXT_EXEC: 0xfffffe00093c3a94: 0xd65f03c0 RET 0xa9bc6ffc STP X28, X27, [X31, #-64]!
__TEXT_EXEC: 0xfffffe00093c3c48: 0xd2800000 MOVZ X0, #0 0xd503237f PACIBSP
__TEXT_EXEC: 0xfffffe00093c3c4c: 0xd65f03c0 RET 0xa9bd6ffc STP X28, X27, [X31, #-48]!
__TEXT_EXEC: 0xfffffe00093c5618: 0xd2800000 MOVZ X0, #0 0xd503237f PACIBSP
__TEXT_EXEC: 0xfffffe00093c561c: 0xd65f03c0 RET 0xa9bd6ffc STP X28, X27, [X31, #-48]!
__TEXT_EXEC: 0xfffffe00093e8f60: 0x97a3b14a BL 0xfffffffffe8ec528 0x97a3b14a BL 0xfffffffffe8ec528
__TEXT_EXEC: 0xfffffe00093e8f64: 0xd503201f NOP 0x37700160 TBNZ W0, #14 0x2c
__TEXT_EXEC: 0xfffffe0009439298: 0xb94053e5 LDRi W5, [X31, #80] 0xb94053e5 LDRi W5, [X31, #80]
__TEXT_EXEC: 0xfffffe000943929c: 0x52800000 MOVZ W0, #0 0x9401349a BL 0x4d268
__TEXT_EXEC: 0xfffffe000948e1b0: 0xeb00001f CMPsr X0, X0 0xeb08001f CMPsr X0, X8
__TEXT_EXEC: 0xfffffe000948e1b4: 0x540019c0 B.EQ 0x338 0x540019c0 B.EQ 0x338
__TEXT_EXEC: 0xfffffe000948fad0: 0xd503201f NOP 0x37281048 TBNZ W8, #5 0x208
__TEXT_EXEC: 0xfffffe000948fad4: 0x36000a7b TBZ W27, #0 0x14c 0x36000a7b TBZ W27, #0 0x14c
__TEXT_EXEC: 0xfffffe000948fd68: 0x97a115c8 BL 0xfffffffffe845720 0x97a115c8 BL 0xfffffffffe845720
__TEXT_EXEC: 0xfffffe000948fd6c: 0x52800000 MOVZ W0, #0 0x37700060 TBNZ W0, #14 0xc
__TEXT_EXEC: 0xfffffe00094a3cb8: 0x97a0cc08 BL 0xfffffffffe833020 0x97a0cc08 BL 0xfffffffffe833020
__TEXT_EXEC: 0xfffffe00094a3cbc: 0xd503201f NOP 0xb4000440 CBZ X0, 0x88
__TEXT_EXEC: 0xfffffe00094a3cd0: 0xd503201f NOP 0x340003a0 CBZ W0, 0x74
__TEXT_EXEC: 0xfffffe00094a3cd4: 0xf804d3ff STUR XZR, [X31, #77] 0xf804d3ff STUR XZR, [X31, #77]
__TEXT_EXEC: 0xfffffe00094a3d90: 0xd503201f NOP 0x34000c40 CBZ W0, 0x188
__TEXT_EXEC: 0xfffffe00094a3d94: 0x52800002 MOVZ W2, #0 0x52800002 MOVZ W2, #0
__TEXT_EXEC: 0xfffffe00094a5968: 0xaa1703e0 MOVr X0, X23 0xaa1703e0 MOVr X0, X23
__TEXT_EXEC: 0xfffffe00094a596c: 0x52800000 MOVZ W0, #0 0x97fe28fa BL 0xfffffffffff8a3e8
Compared 44089344 bytes
Another annoyance is that the kernelcache booted by vphone is in the form of an IMG4, containing a BVX (LZFSE) compressed binary. This adds to the patching workflow steps of unpacking the kernel, and then repacking it.*
The disarm(j) utility has long been able to work directly on IMG4, and use lzfse_decode_buffer to perform in-memory decompression. It also has the -P switch to apply patches anywhere, but until recently would only save its output uncompressed. We had Jonathan update the utility so now, if a BVVX compressed binary is detected, the -P switch will recompress the patched image, and recreate its IMG4 header (since the payload size might change) and its footer.
* - A better approach would be to patch iBoot so as to not apply LZFSE if bvx compression is not detected, though this might be possible already - not verified by us yet
Adding custom patches
In our research we make extensive use of Xn00p, a tool originally developed by Jonathan Levin, now offered through DataFlow Forensics for public use. A limiting factor for making the tool publicly available has always been its reliance on a kernel memory read primitive - which in iOS necessitated a jailbreak. But no more. vPhone can provide direct access to kernel memory and can be made instantly compatible with Xn00p - in two simple steps:
- Patch the kernel so it reveals its slide:
- Provide the classic "TFP0" primitive: