Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
super-tart-vphone-writeup — Guía para construir un iPhone virtual usando componentes VPHONE600AP del firmware PCC de Apple, con parcheo de firmware, modificación de cadena de arranque y depuración del kernel para investigación de seguridad en iOS. | Kitploit
Herramientas/GitHubGitHub/wh1te4ever/super-tart-vphone-writeup
Seguridad iOSAnálisis de VulnerabilidadesExplotaciónIngeniería InversaDepuradoresPruebas de PenetraciónSeguridad MóvilSeguridad de Hardware e IoTAnálisis de Firmware

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Explotación de Binarios
GitHubwh1te4ever/super-tart-vphone-writeup

super-tart-vphone-writeup

Guía para construir un iPhone virtual usando componentes VPHONE600AP del firmware PCC de Apple, con parcheo de firmware, modificación de cadena de arranque y depuración del kernel para investigación de seguridad en iOS.

Ver Repositorio
1.2k168hace 5 mesesRevisado por Kitploit

Construyendo un iPhone virtual utilizando el componente VPHONE600AP del firmware PCC lanzado recientemente

Agradecimientos especiales / Reconocimientos

  • dlevi309 (Proporcionó ideas para la interacción táctil en el iPhone virtual)
  • khanhduytran0, 34306, asdfugil, verygenericname (Proporcionaron otras ideas para construir el iPhone virtual, incluyendo Cryptex, Activación del dispositivo, arranque con Ramdisk, etc.)
  • ma4the, Mard, SwallowS (Probando si funciona bien en otros entornos)

Motivación

A finales de 2024, Apple comenzó a presentar Private Cloud Compute, afirmando abrir un nuevo horizonte para la privacidad de la IA basada en la nube. Luego, alrededor de finales de 2025, aparecieron noticias interesantes: Apple había añadido recientemente componentes relacionados con vphone600ap al firmware PCC, comenzando con cloudOS 26.

Fuente: https://x.com/matteyeux/status/2006339694783848660/photo/1

Fuente: https://x.com/matteyeux/status/2006339694783848660/photo/1

"¿Máquina virtual del entorno de investigación del iPhone?"

¿Es este un movimiento planificado por Apple para construir y distribuir un entorno de iPhone virtual para otros investigadores de seguridad en el futuro, o fue simplemente un error? Dado que el kernel de compilación DEVELOPMENT/KASAN fue descubierto una vez en las OTA de iOS 15.0 beta a 15.1 beta3 en 2021, la posibilidad de un descuido no puede descartarse. En ese momento, el kernel permaneció incluido durante aproximadamente 4 meses, de junio a octubre de 2021.

Luego, alrededor de enero de este año, se publicó un tuit mostrando un iPhone virtual arrancando utilizando estos componentes relacionados con vphone600ap.

Fuente: https://x.com/_inside/status/2008951845725548783

Fuente: https://x.com/_inside/status/2008951845725548783

Screenshot 2026-02-24 at 7.39.03 PM.png

Por lo que vi, casi todo funcionaba de manera realmente elegante. En comparación con el proyecto QEMUAppleSilicon(Inferno) que había visto anteriormente, se ejecuta mucho más rápido y fluido. Además, incluso parecía soportar aceleración Metal. Finalmente, completamente cautivado por ello, me sumergí y comencé a construir mi propio iPhone virtual el 31 de enero.

Screenshot 2026-02-24 at 7.46.41 PM.png

Modificando super-tart para arrancar el iPhone virtual

El proyecto de referencia es security-pcc. Corresponde al código fuente del binario /System/Library/SecurityResearch/usr/bin/vrevm. Un punto interesante es que utiliza métodos privados proporcionados por Virtualization.framework. En la máquina virtual utilizada para la investigación de PCC, se puede ver que el ISA y PlatformVersion se especifican explícitamente durante el proceso de inicialización del modelo de hardware.

Screenshot 2026-02-24 at 8.27.01 PM.png

Para el bootrom, se utiliza AVPBooter.vresearch1.bin (/System/Library/Frameworks/Virtualization.framework/Resources/AVPBooter.vresearch1.bin)

Screenshot 2026-02-24 at 8.32.08 PM.png

y para el SEPROM (avpsepbooter), se utiliza AVPSEPBooter.vresearch1.bin, que carga por separado un archivo SEPStorage que funciona de manera similar a AuxiliaryStorage. (/System/Library/Frameworks/Virtualization.framework/Versions/A/Resources/AVPSEPBooter.vresearch1.bin)

Otro punto interesante es que si observas el código para establecer la resolución, se configura a 1290x2796, que corresponde a los dispositivos iPhone 14 Pro Max, 15 Plus, 15 Pro Max y 16 Plus.

Screenshot 2026-02-24 at 8.34.11 PM.png

Con solo esta información, debería ser más que suficiente para modificar super-tart y arrancar el iPhone virtual. Realicé las modificaciones como se muestra a continuación.

  • /Sources/tart/VM.swift```swift ... class VM: NSObject, VZVirtualMachineDelegate, ObservableObject { ... // vzHardwareModel derives the VZMacHardwareModel config specific to the "platform type" // of the VM (currently only vresearch101 supported) static private func vzHardwareModel_VRESEARCH101() throws -> VZMacHardwareModel { var hw_model: VZMacHardwareModel

    guard let hw_descriptor = _VZMacHardwareModelDescriptor() else { fatalError("Failed to create hardware descriptor") } hw_descriptor.setPlatformVersion(3) // .appleInternal4 = 3 hw_descriptor.setBoardID(0x90) hw_descriptor.setISA(2) hw_model = VZMacHardwareModel._hardwareModel(withDescriptor: hw_descriptor)

    guard hw_model.isSupported else { fatalError("VM hardware config not supported (model.isSupported = false)") }

    return hw_model }

    static func craftConfiguration( diskURL: URL, nvramURL: URL, romURL: URL, sepromURL: URL? = nil, vmConfig: VMConfig, network: Network = NetworkShared(), additionalStorageDevices: [VZStorageDeviceConfiguration], directorySharingDevices: [VZDirectorySharingDeviceConfiguration], serialPorts: [VZSerialPortConfiguration], suspendable: Bool = false, nested: Bool = false, audio: Bool = true, clipboard: Bool = true, sync: VZDiskImageSynchronizationMode = .full, caching: VZDiskImageCachingMode? = nil ) throws -> VZVirtualMachineConfiguration { let configuration: VZVirtualMachineConfiguration = .init()

    // Boot loader let bootloader = try vmConfig.platform.bootLoader(nvramURL: nvramURL) Dynamic(bootloader)._setROMURL(romURL) configuration.bootLoader = bootloader

    // SEP ROM let homeURL = FileManager.default.homeDirectoryForCurrentUser var sepstoragePath = homeURL.appendingPathComponent(".tart/vms/vphone/SEPStorage").path let sepstorageURL = URL(fileURLWithPath: sepstoragePath) let sep_config = Dynamic._VZSEPCoprocessorConfiguration(storageURL: sepstorageURL) if let sepromURL { // default AVPSEPBooter.vresearch1.bin from VZ framework sep_config.romBinaryURL = sepromURL } sep_config.debugStub = Dynamic._VZGDBDebugStubConfiguration(port: 8001) configuration._setCoprocessors([sep_config.asObject])

    // Some vresearch101 config let pconf = VZMacPlatformConfiguration() pconf.hardwareModel = try vzHardwareModel_VRESEARCH101()

    let serial = Dynamic._VZMacSerialNumber.initWithString("AAAAAA1337") let identifier = Dynamic.VZMacMachineIdentifier._machineIdentifierWithECID(0x1111111111111111, serialNumber: serial.asObject) pconf.machineIdentifier = identifier.asObject as! VZMacMachineIdentifier

    pconf._setProductionModeEnabled(true) var auxiliaryStoragePath = homeURL.appendingPathComponent(".tart/vms/vphone/nvram.bin").path let auxiliaryStorageURL = URL(fileURLWithPath: auxiliaryStoragePath) pconf.auxiliaryStorage = VZMacAuxiliaryStorage(url: auxiliaryStorageURL)

    if #available(macOS 14, *) { let keyboard = VZUSBKeyboardConfiguration() configuration.keyboards = [keyboard] }

    if #available(macOS 14, *) { let touch = _VZUSBTouchScreenConfiguration() configuration._setMultiTouchDevices([touch]) } ... configuration.platform = pconf

root@kitploit:~
# Modificando el Firmware

El proyecto referenciado es [vma2pwn](https://github.com/nick-botticelli/vma2pwn). Específicamente para la versión 12.0.1, arranca una máquina virtual Mac con casi toda la cadena de arranque modificada.

Primero veamos el script [prepare.sh](https://github.com/nick-botticelli/vma2pwn/blob/main/prepare.sh). Extrae componentes del firmware, como el gestor de arranque y el kernel comprimido en formato IM4P, a formato RAW y parchea instrucciones/datos en direcciones hardcodeadas específicas. RestoreRamdisk es el sistema de archivos raíz utilizado al restaurar el firmware, y AVPBooter es el BootROM utilizado en la máquina virtual.

En resumen, extrae los archivos individuales incluidos en el firmware y parchea las comprobaciones de integridad para permitir la restauración de firmware personalizado, o modifica los parámetros boot-args para facilitar la visualización de registros relacionados con el arranque.

Finalmente, [vma2pwn.sh](https://github.com/nick-botticelli/vma2pwn/blob/main/vma2pwn.sh) es el encargado de restaurar el firmware personalizado. Lo hace entrando previamente en modo DFU. Aquí, la máquina virtual utiliza algo llamado super-tart. Esta es una versión de la máquina virtual tart existente con características añadidas como un bootrom personalizado, salida serie, modo DFU y depuración GDB. (Nota: SIP/AMFI debe estar desactivado para que funcione.)

Lo he estado utilizando últimamente de manera muy útil mientras [estudio vulnerabilidades de 1 día del kernel XNU (CVE-2021-30937, CVE-2021-30955)](https://github.com/wh1te4ever/xnu_1day_practice). Es fantástico porque admite depuración del kernel en vivo.

## Construyendo Firmware Personalizado

Mezclé los componentes de cloudOS 26.1 (23B85) e iOS 26.1 (iPhone17,3; 23B85), eh…, pero… no recuerdo los detalles exactos. Para ser preciso, tuve que mezclar adecuadamente los componentes relacionados con iPhone 16 y vphone para crear el firmware personalizado, pero he olvidado exactamente cuáles terminé mezclando. Según recuerdo:

- BuildManifest.plist:
Modifiqué los elementos del diccionario bajo la clave Manifest. Lo configuré para que durante el proceso de restauración, se usaran SystemVolume, SystemVolumeCanonicalMetadata, OS, StaticTrustCache, RestoreTrustCache y RestoreRamDisk del modelo iPhone 16 (iOS 26.1). El resto se configuró para usar archivos relacionados con vphone del firmware PCC.
- Restore.plist:
Creo que añadí propiedades relacionadas con DeviceMap o SupportedProductTypes, o cambié el elemento SystemRestoreImageFileSystems.

Los archivos a continuación son el resultado final de mi mezcla.

[Restore.plist](https://github.com/wh1te4ever/super-tart-vphone-writeup/blob/HEAD/contents/Restore.plist)

[BuildManifest.plist](https://github.com/wh1te4ever/super-tart-vphone-writeup/blob/HEAD/contents/BuildManifest.plist)

- get_fw.py (Parcial)```python
...

# 3. Import things from cloudOS
# kernelcache
os.system("cp 399b664dd623358c3de118ffc114e42dcd51c9309e751d43bc949b98f4e31349_extracted/kernelcache.* iPhone17,3_26.1_23B85_Restore")
# agx, all_flash, ane, dfu, pmp...
os.system("cp 399b664dd623358c3de118ffc114e42dcd51c9309e751d43bc949b98f4e31349_extracted/Firmware/agx/* iPhone17,3_26.1_23B85_Restore/Firmware/agx")
os.system("cp 399b664dd623358c3de118ffc114e42dcd51c9309e751d43bc949b98f4e31349_extracted/Firmware/all_flash/* iPhone17,3_26.1_23B85_Restore/Firmware/all_flash")
os.system("cp 399b664dd623358c3de118ffc114e42dcd51c9309e751d43bc949b98f4e31349_extracted/Firmware/ane/* iPhone17,3_26.1_23B85_Restore/Firmware/ane")
os.system("cp 399b664dd623358c3de118ffc114e42dcd51c9309e751d43bc949b98f4e31349_extracted/Firmware/dfu/* iPhone17,3_26.1_23B85_Restore/Firmware/dfu")
os.system("cp 399b664dd623358c3de118ffc114e42dcd51c9309e751d43bc949b98f4e31349_extracted/Firmware/pmp/* iPhone17,3_26.1_23B85_Restore/Firmware/pmp")
# sptm, txm, etc...
os.system("cp 399b664dd623358c3de118ffc114e42dcd51c9309e751d43bc949b98f4e31349_extracted/Firmware/*.im4p iPhone17,3_26.1_23B85_Restore/Firmware")

# 4. TODO: parse what things needed from BuildManifest.plist, Restore.plist in cloudOS 26.1
# It will be really complicated, so import things from already parse completed
os.system("sudo cp custom_26.1/BuildManifest.plist iPhone17,3_26.1_23B85_Restore")
os.system("sudo cp custom_26.1/Restore.plist iPhone17,3_26.1_23B85_Restore")

os.system("echo 'Done, grabbed all needed components for restoring'")

Parchear AVPBooter.vresearch1.bin

Hice referencia a esa publicación. Debes parchear image4_validate_property_callback para cargar un bootloader personalizado después. Simplemente usa la función "Text-search (slow!)" en IDA Pro para buscar "0x4447", y parchea el epílogo de la función correspondiente para que siempre devuelva 0.

image.png

Modificar y compilar libirecovery

Antes de restaurar el firmware, fueron necesarias algunas modificaciones para admitir el modelo vresearch101ap. Una vez compilado, la restauración del firmware es posible usando la herramienta idevicerestore.

https://github.com/wh1te4ever/libirecovery

Screenshot 2026-02-24 at 9.52.14 PM.png

Parchear componentes del firmware

Similar a AVPBooter, los bootloaders usados para la restauración, iBSS e iBEC, fueron parcheados para omitir la verificación de firmas. También habilité la salida de registro serial para que, si hay algún problema de arranque, se pueda identificar la causa de inmediato.

Como verás más adelante, omitir la verificación SSV (Signed System Volume) es necesario para cargar un Cryptex arbitrario. Esto se realiza en el LLB, que se carga al iniciar en modo normal en lugar de modo DFU, y la verificación también se realiza a veces en el kernel.

Además, parcheé el TXM para que, incluso si un binario/biblioteca no está registrado en Trustcache, sea reconocido como si lo estuviera.

  • patch_fw.py (Contenido parcial, Parte 1)```python

Patch iBSS

patch image4_validate_property_callback

patch(0x9D10, 0xd503201f) #nop patch(0x9D14, 0xd2800000) #mov x0, #0

Patch iBEC

patch image4_validate_property_callback

patch(0x9D10, 0xd503201f) #nop patch(0x9D14, 0xd2800000) #mov x0, #0

patch boot-args with "serial=3 -v debug=0x2014e %s"

patch(0x122d4, 0xd0000082) #adrp x2, #0x12000 patch(0x122d8, 0x9101c042) #add x2, x2, #0x70 patch(0x24070, "serial=3 -v debug=0x2014e %s")

Patch LLB

patch image4_validate_property_callback

patch(0xA0D8, 0xd503201f) #nop patch(0xA0DC, 0xd2800000) #mov x0, #0

patch boot-args with "serial=3 -v debug=0x2014e %s"

patch(0x12888, 0xD0000082) #adrp x2, #0x12000 patch(0x1288C, 0x91264042) #add x2, x2, #0x990 patch(0x24990, "serial=3 -v debug=0x2014e %s")

make possible load edited rootfs (needed to command snaputil -n later)

patch(0x2BFE8, 0x1400000b) patch(0x2bca0, 0xd503201f) patch(0x2C03C, 0x17ffff6a) patch(0x2fcec, 0xd503201f) patch(0x2FEE8, 0x14000009)

some unknown patch, bypass panic

patch(0x1AEE4, 0xd503201f) #nop

6. Grab & Patch TXM

Patch TXM for make running binary which is not registered in trustcache

TXM [Error]: CodeSignature: selector: 24 | 0xA8 | 0x30 | 1

Some trace: FFFFFFF01702B018->sub_FFFFFFF0170306E4->sub_FFFFFFF01703059C->sub_FFFFFFF01703037C->sub_FFFFFFF017030164->sub_FFFFFFF01702EC70 (base: 0xFFFFFFF017004000)

patch(0x2c1f8, 0xd2800000) #FFFFFFF0170301F8 patch(0x2bef4, 0xd2800000) #FFFFFFF01702FEF4 patch(0x2c060, 0xd2800000) #FFFFFFF017030060

7. Grab & patch kernelcache

========= Bypass SSV =========

_apfs_vfsop_mount: Prevent panic "Failed to find the root snapshot. Rooting from the live fs ..."

patch(0x2476964, 0xd503201f) #FFFFFE000947A964

_authapfs_seal_is_broken: Prevent panic "root volume seal is broken ..."

patch(0x23cfde4, 0xd503201f) #FFFFFE00093D3DE4

_bsd_init: Prevent panic "rootvp not authenticated after mounting ..."

patch(0xf6d960, 0xd503201f) #FFFFFE0007F71960 ...

root@kitploit:~
Después de convertir al formato RAW y parchearlo, debes convertirlo de vuelta a IM4P.
En el caso del kernel o TXM, existe una estructura PAYP, por lo que fue necesario preservar esa estructura.
A continuación se muestra el código que convierte IM4P → RAW → IM4P usando las herramientas [pyimg4](https://pypi.org/project/pyimg4/), [img4tool](https://github.com/tihmstar/img4tool), [img4](https://github.com/xerub/img4lib).

- patch_fw.py (Contenido parcial, Parte 2)```python
...

# Patch iBSS
if not os.path.exists("iPhone17,3_26.1_23B85_Restore/Firmware/dfu/iBSS.vresearch101.RELEASE.im4p.bak"):
    os.system("cp iPhone17,3_26.1_23B85_Restore/Firmware/dfu/iBSS.vresearch101.RELEASE.im4p iPhone17,3_26.1_23B85_Restore/Firmware/dfu/iBSS.vresearch101.RELEASE.im4p.bak")
os.system("tools/img4 -i iPhone17,3_26.1_23B85_Restore/Firmware/dfu/iBSS.vresearch101.RELEASE.im4p.bak -o iBSS.vresearch101.RELEASE")
... # patch things from raw
os.system("tools/img4tool -c iPhone17,3_26.1_23B85_Restore/Firmware/dfu/iBSS.vresearch101.RELEASE.im4p -t ibss iBSS.vresearch101.RELEASE")

# Patch iBEC
if not os.path.exists("iPhone17,3_26.1_23B85_Restore/Firmware/dfu/iBEC.vresearch101.RELEASE.im4p.bak"):
    os.system("cp iPhone17,3_26.1_23B85_Restore/Firmware/dfu/iBEC.vresearch101.RELEASE.im4p iPhone17,3_26.1_23B85_Restore/Firmware/dfu/iBEC.vresearch101.RELEASE.im4p.bak")
os.system("tools/img4 -i iPhone17,3_26.1_23B85_Restore/Firmware/dfu/iBEC.vresearch101.RELEASE.im4p.bak -o iBEC.vresearch101.RELEASE")
... # patch things from raw
os.system("tools/img4tool -c iPhone17,3_26.1_23B85_Restore/Firmware/dfu/iBEC.vresearch101.RELEASE.im4p -t ibec iBEC.vresearch101.RELEASE")

# Patch LLB
if not os.path.exists("iPhone17,3_26.1_23B85_Restore/Firmware/all_flash/LLB.vresearch101.RESEARCH_RELEASE.im4p.bak"):
    os.system("cp iPhone17,3_26.1_23B85_Restore/Firmware/all_flash/LLB.vresearch101.RESEARCH_RELEASE.im4p iPhone17,3_26.1_23B85_Restore/Firmware/all_flash/LLB.vresearch101.RESEARCH_RELEASE.im4p.bak")
os.system("tools/img4 -i iPhone17,3_26.1_23B85_Restore/Firmware/all_flash/LLB.vresearch101.RESEARCH_RELEASE.im4p.bak -o LLB.vresearch101.RESEARCH_RELEASE")
... # patch things from raw
os.system("tools/img4tool -c iPhone17,3_26.1_23B85_Restore/Firmware/all_flash/LLB.vresearch101.RESEARCH_RELEASE.im4p -t illb LLB.vresearch101.RESEARCH_RELEASE")

# 6. Grab & Patch TXM
if not os.path.exists("iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p.bak"):
    os.system("cp iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p.bak")
os.system("pyimg4 im4p extract -i iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p.bak -o txm.raw")
... # patch things from raw
#create im4p
os.system("pyimg4 im4p create -i txm.raw -o txm.im4p -f trxm --lzfse")
# preserve payp structure
txm_im4p_data = Path('iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p.bak').read_bytes()
payp_offset = txm_im4p_data.rfind(b'PAYP')
if payp_offset == -1:
    print("Couldn't find payp structure !!!")
    sys.exit()

with open('txm.im4p', 'ab') as f:
    f.write(txm_im4p_data[(payp_offset-10):])

payp_sz = len(txm_im4p_data[(payp_offset-10):])
print(f"payp sz: {payp_sz}")

txm_im4p_data = bytearray(open('txm.im4p', 'rb').read())
txm_im4p_data[2:5] = (int.from_bytes(txm_im4p_data[2:5], 'big') + payp_sz).to_bytes(3, 'big')
open('txm.im4p', 'wb').write(txm_im4p_data)
os.system("mv txm.im4p iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.research.im4p")

# 7. Grab & patch kernelcache
if not os.path.exists("iPhone17,3_26.1_23B85_Restore/kernelcache.research.vphone600.bak"):
    os.system("cp iPhone17,3_26.1_23B85_Restore/kernelcache.research.vphone600 iPhone17,3_26.1_23B85_Restore/kernelcache.research.vphone600.bak")
os.system("pyimg4 im4p extract -i iPhone17,3_26.1_23B85_Restore/kernelcache.research.vphone600.bak -o kcache.raw")
... # patch things from raw
#create im4p
os.system("pyimg4 im4p create -i kcache.raw -o krnl.im4p -f krnl --lzfse")

# preserve payp structure
kernel_im4p_data = Path('iPhone17,3_26.1_23B85_Restore/kernelcache.research.vphone600.bak').read_bytes()
payp_offset = kernel_im4p_data.rfind(b'PAYP')
if payp_offset == -1:
    print("Couldn't find payp structure !!!")
    sys.exit()

with open('krnl.im4p', 'ab') as f:
    f.write(kernel_im4p_data[(payp_offset-10):])

payp_sz = len(kernel_im4p_data[(payp_offset-10):])
print(f"payp sz: {payp_sz}")

kernel_im4p_data = bytearray(open('krnl.im4p', 'rb').read())
kernel_im4p_data[2:5] = (int.from_bytes(kernel_im4p_data[2:5], 'big') + payp_sz).to_bytes(3, 'big')
open('krnl.im4p', 'wb').write(kernel_im4p_data)

os.system("mv krnl.im4p iPhone17,3_26.1_23B85_Restore/kernelcache.research.vphone600")
...

Restauración del Firmware

Una vez que todo esté listo, pongamos la máquina virtual en modo DFU e intentemos restaurarla.

A continuación se muestra una captura de pantalla del pánico que ocurre si el SEP no está configurado correctamente. Si lo configuras correctamente, debería pasar este punto sin problemas.

image.png

Después de que la restauración se complete, se reinicia automáticamente. Sin embargo, ocurre un pánico en el proceso launchd porque falta la biblioteca /usr/lib/libSystem.B.dylib. Esta biblioteca se encuentra dentro de dyld_shared_cache en la partición Cryptex, y por alguna razón, la partición Cryptex no pudo restaurarse. Como solución temporal, debes crear un SSH Ramdisk para modificar el sistema de archivos raíz e inyectar los archivos necesarios. Esa es exactamente la razón por la que se necesitaba el parche relacionado con la verificación SSV.

Screenshot 2026-02-24 at 10.24.33 PM.png

image.png

Solución del problema de arranque iniciando con SSH Ramdisk

Voy a intentar solucionar el problema de fallo de arranque utilizando el ramdisk usado en https://github.com/verygenericname/SSHRD_Script.

Para cargar componentes como el bootloader o el kernel usando la herramienta irecovery en modo DFU, se necesita una imagen IMG4, la cual requiere un archivo IM4M. Por lo tanto, primero obtuve el archivo shsh usando la herramienta idevicerestore, y luego lo convertí en un archivo IM4M.```bash idevicerestore -e -y ./iPhone17,3_26.1_23B85_Restore -t

mv shsh/[ECID]-iPhone99,11-26.1.shsh shsh/[ECID]-iPhone99,11-26.1.shsh.gz

gunzip shsh/[ECID]-iPhone99,11-26.1.shsh.gz

...

pyimg4 im4m extract -i shsh/[ECID]-iPhone99,11-26.1.shsh -o vphone.im4m

root@kitploit:~
Luego, usando ese archivo IM4M, generé varios archivos IMG4 para cada uno de los componentes de firmware utilizados, como iBSS, iBEC y el devicetree.```python
# 1. Grab & Patch iBSS 
if not os.path.exists("iPhone17\\,3_26.1_23B85_Restore/Firmware/dfu/iBSS.vresearch101.RELEASE.im4p.bak"):
    os.system("cp iPhone17\\,3_26.1_23B85_Restore/Firmware/dfu/iBSS.vresearch101.RELEASE.im4p iPhone17\\,3_26.1_23B85_Restore/Firmware/dfu/iBSS.vresearch101.RELEASE.im4p.bak")
os.system("tools/img4 -i iPhone17\\,3_26.1_23B85_Restore/Firmware/dfu/iBSS.vresearch101.RELEASE.im4p.bak -o iBSS.vresearch101.RELEASE")
... # patch things from raw
os.system("tools/img4tool -c iBSS.vresearch101.RELEASE.im4p -t ibss iBSS.vresearch101.RELEASE")
os.system("tools/img4 -i iBSS.vresearch101.RELEASE.im4p -o ./Ramdisk/iBSS.vresearch101.RELEASE.img4 -M ./vphone.im4m")

# 2. Grab & Patch iBEC
if not os.path.exists("iPhone17\\,3_26.1_23B85_Restore/Firmware/dfu/iBEC.vresearch101.RELEASE.im4p.bak"):
    os.system("cp iPhone17\\,3_26.1_23B85_Restore/Firmware/dfu/iBEC.vresearch101.RELEASE.im4p iPhone17\\,3_26.1_23B85_Restore/Firmware/dfu/iBEC.vresearch101.RELEASE.im4p.bak")
os.system("tools/img4 -i iPhone17\\,3_26.1_23B85_Restore/Firmware/dfu/iBEC.vresearch101.RELEASE.im4p -o iBEC.vresearch101.RELEASE")
... # patch things from raw
os.system("tools/img4tool -c iBEC.vresearch101.RELEASE.im4p -t ibec iBEC.vresearch101.RELEASE")
os.system("tools/img4 -i iBEC.vresearch101.RELEASE.im4p -o Ramdisk/iBEC.vresearch101.RELEASE.img4 -M vphone.im4m")

# 3. Grab SPTM
os.system("tools/img4 -i iPhone17\\,3_26.1_23B85_Restore/Firmware/sptm.vresearch1.release.im4p -o Ramdisk/sptm.vresearch1.release.img4 -M vphone.im4m -T sptm")

# 4. Grab devicetree
os.system("tools/img4 -i iPhone17\\,3_26.1_23B85_Restore/Firmware/all_flash/DeviceTree.vphone600ap.im4p -o Ramdisk/DeviceTree.vphone600ap.img4 -M vphone.im4m -T rdtr")

# 5. Grab sep
os.system("tools/img4 -i iPhone17\\,3_26.1_23B85_Restore/Firmware/all_flash/sep-firmware.vresearch101.RELEASE.im4p -o Ramdisk/sep-firmware.vresearch101.RELEASE.img4 -M vphone.im4m -T rsep")

# 6. Grab & Patch TXM
if not os.path.exists("iPhone17\\,3_26.1_23B85_Restore/Firmware/txm.iphoneos.release.im4p.bak"):
    os.system("cp iPhone17\\,3_26.1_23B85_Restore/Firmware/txm.iphoneos.release.im4p iPhone17\\,3_26.1_23B85_Restore/Firmware/txm.iphoneos.release.im4p.bak")
os.system("pyimg4 im4p extract -i iPhone17\\,3_26.1_23B85_Restore/Firmware/txm.iphoneos.release.im4p.bak -o txm.raw")
... # patch things from raw
#create im4p
os.system("pyimg4 im4p create -i txm.raw -o txm.im4p -f trxm --lzfse")
# preserve payp structure
txm_im4p_data = Path('iPhone17,3_26.1_23B85_Restore/Firmware/txm.iphoneos.release.im4p.bak').read_bytes()
payp_offset = txm_im4p_data.rfind(b'PAYP')
if payp_offset == -1:
    print("Couldn't find payp structure !!!")
    sys.exit()

with open('txm.im4p', 'ab') as f:
    f.write(txm_im4p_data[(payp_offset-10):])

payp_sz = len(txm_im4p_data[(payp_offset-10):])
print(f"payp sz: {payp_sz}")

txm_im4p_data = bytearray(open('txm.im4p', 'rb').read())
txm_im4p_data[2:5] = (int.from_bytes(txm_im4p_data[2:5], 'big') + payp_sz).to_bytes(3, 'big')
open('txm.im4p', 'wb').write(txm_im4p_data)

# sign
os.system("pyimg4 img4 create -p txm.im4p -o Ramdisk/txm.img4 -m vphone.im4m")

# 7. Grab & patch kernelcache
if not os.path.exists("iPhone17\\,3_26.1_23B85_Restore/kernelcache.research.vphone600.bak"):
    os.system("cp iPhone17\\,3_26.1_23B85_Restore/kernelcache.research.vphone600 iPhone17\\,3_26.1_23B85_Restore/kernelcache.research.vphone600.bak")
os.system("pyimg4 im4p extract -i iPhone17\\,3_26.1_23B85_Restore/kernelcache.research.vphone600.bak -o kcache.raw")
... # patch things from raw

#create im4p
os.system("pyimg4 im4p create -i kcache.raw -o krnl.im4p -f rkrn --lzfse")

# preserve payp structure
kernel_im4p_data = Path('iPhone17,3_26.1_23B85_Restore/kernelcache.research.vphone600.bak').read_bytes()
payp_offset = kernel_im4p_data.rfind(b'PAYP')
if payp_offset == -1:
    print("Couldn't find payp structure !!!")
    sys.exit()

with open('krnl.im4p', 'ab') as f:
    f.write(kernel_im4p_data[(payp_offset-10):])

payp_sz = len(kernel_im4p_data[(payp_offset-10):])
print(f"payp sz: {payp_sz}")

kernel_im4p_data = bytearray(open('krnl.im4p', 'rb').read())
kernel_im4p_data[2:5] = (int.from_bytes(kernel_im4p_data[2:5], 'big') + payp_sz).to_bytes(3, 'big')
open('krnl.im4p', 'wb').write(kernel_im4p_data)

# sign
os.system("pyimg4 img4 create -p krnl.im4p -o Ramdisk/krnl.img4 -m vphone.im4m")

# 8. Grab ramdisk & build custom ramdisk
os.system("pyimg4 im4p extract -i iPhone17,3_26.1_23B85_Restore/043-53775-129.dmg -o ramdisk.dmg")
os.system("mkdir SSHRD")
os.system("sudo hdiutil attach -mountpoint SSHRD ramdisk.dmg -owners off")
os.system("sudo hdiutil create -size 254m -imagekey diskimage-class=CRawDiskImage -format UDZO -fs APFS -layout NONE -srcfolder SSHRD -copyuid root ramdisk1.dmg")
os.system("sudo hdiutil detach -force SSHRD")
os.system("sudo hdiutil attach -mountpoint SSHRD ramdisk1.dmg -owners off")

... #remove unneccessary files for expand space

#resign all things preserving ents
target_path= [
    "SSHRD/usr/local/bin/*", "SSHRD/usr/local/lib/*",
    "SSHRD/usr/bin/*", "SSHRD/bin/*",
    "SSHRD/usr/lib/*", "SSHRD/sbin/*", "SSHRD/usr/sbin/*", "SSHRD/usr/libexec/*"
]
for pattern in target_path:
    for path in glob.glob(pattern):
        if os.path.isfile(path) and not os.path.islink(path):
            if "Mach-O" in subprocess.getoutput(f"file \"{path}\""):
                os.system(f"tools/ldid_macosx_arm64 -S -M -Cadhoc \"{path}\"")

#8-2. Grab & build custom ramdisk's trustcache while building custom ramdisk
os.system("pyimg4 im4p extract -i iPhone17,3_26.1_23B85_Restore/Firmware/043-53775-129.dmg.trustcache -o trustcache.raw")
os.system("tools/trustcache_macos_arm64 create sshrd.tc SSHRD")
os.system("pyimg4 im4p create -i sshrd.tc -o trustcache.im4p -f rtsc")
# sign
os.system("pyimg4 img4 create -p trustcache.im4p -o Ramdisk/trustcache.img4 -m vphone.im4m")
#8-2. end

os.system("sudo hdiutil detach -force SSHRD")
os.system("sudo hdiutil resize -sectors min ramdisk1.dmg")
# sign
os.system("pyimg4 im4p create -i ramdisk1.dmg -o ramdisk1.dmg.im4p -f rdsk")
os.system("pyimg4 img4 create -p ramdisk1.dmg.im4p -o Ramdisk/ramdisk.img4 -m vphone.im4m")

Una vez que todas las imágenes IMG4 estén creadas, carguémoslas una por una e iniciemos con el Ramdisk.

  • boot_rd.sh```bash #!/bin/zsh irecovery -f Ramdisk/iBSS.vresearch101.RELEASE.img4 irecovery -f Ramdisk/iBEC.vresearch101.RELEASE.img4 irecovery -c go

sleep 1; irecovery -f Ramdisk/sptm.vresearch1.release.img4 irecovery -c firmware

irecovery -f Ramdisk/txm.img4 irecovery -c firmware

irecovery -f Ramdisk/trustcache.img4 irecovery -c firmware irecovery -f Ramdisk/ramdisk.img4 irecovery -c ramdisk irecovery -f Ramdisk/DeviceTree.vphone600ap.img4 irecovery -c devicetree irecovery -f Ramdisk/sep-firmware.vresearch101.RELEASE.img4 irecovery -c firmware irecovery -f Ramdisk/krnl.img4 irecovery -c bootx

root@kitploit:~
Luego, verás la cara del Creeper de Minecraft en la tercera ventana de la izquierda, como se muestra a continuación.
Si revisas el menú USB en la aplicación Información del Sistema y ves "iPhone Research...",
ahora puedes acceder al shell del iPhone virtual usando la herramienta [iproxy](https://github.com/libimobiledevice/libusbmuxd/blob/master/tools/iproxy.c). (`iproxy 2222 22 &`)

![image.png](https://assets.kitploit.com/production/public/readmes/12192/85efc44a2cadf64fa0ee4858541766fd9c9b2b46977b4e9c415d0812e6965d10.png)

Para modificar el sistema de archivos raíz, renombra la instantánea.```python
ssh [email protected] -p2222
#pw: alpine

mount_apfs -o rw /dev/disk1s1 /mnt1

snaputil -l /mnt1
# (then will output will be printed with hash, result may be differ)
com.apple.os.update-8AAB8DBA5C8F1F756928411675F4A892087B04559CFB084B9E400E661ABAD119

snaputil -n <com.apple.os.update-hash> orig-fs /mnt1

umount /mnt1

exit

Descifra el archivo AEA usando la herramienta ipsw para crear un archivo dmg, móntalo y luego transfiere los archivos desde la partición Cryptex a la máquina virtual. Junto con la transferencia de archivos, se requirieron parches específicos. Para mayor comodidad, agregué tres procesos específicos para que se inicien al arrancar: bash, dropbear y trollvnc.

seputil tenía un problema por el cual no podía encontrar correctamente el archivo gigalocker, así que lo parcheé para que siempre busque AA.gl. Además, parcheé launchd_cache_loader para asegurar que el archivo modificado /System/Library/xpc/launchd.plist se cargue correctamente.```python ... ========= INSTALL CRYPTEX(SystemOS, AppOS) =========

Grab and Decrypt Cryptex(SystemOS) AEA

key = subprocess.check_output("ipsw fw aea --key iPhone17,3_26.1_23B85_Restore/043-54303-126.dmg.aea", shell=True, text=True).strip() print(f"key: {key}") os.system(f"aea decrypt -i iPhone17,3_26.1_23B85_Restore/043-54303-126.dmg.aea -o CryptexSystemOS.dmg -key-value '{key}'")

Grab Cryptex(AppOS)

os.system(f"cp iPhone17,3_26.1_23B85_Restore/043-54062-129.dmg CryptexAppOS.dmg")

Mount CryptexSystemOS

os.system("mkdir CryptexSystemOS") os.system("sudo hdiutil attach -mountpoint CryptexSystemOS CryptexSystemOS.dmg -owners off")

Mount CryptexAppOS

os.system("mkdir CryptexAppOS") os.system("sudo hdiutil attach -mountpoint CryptexAppOS CryptexAppOS.dmg -owners off")

Prepare

remote_cmd("/sbin/mount_apfs -o rw /dev/disk1s1 /mnt1")

remote_cmd("/bin/rm -rf /mnt1/System/Cryptexes/App") remote_cmd("/bin/rm -rf /mnt1/System/Cryptexes/OS")

remote_cmd("/bin/mkdir -p /mnt1/System/Cryptexes/App") remote_cmd("/bin/chmod 0755 /mnt1/System/Cryptexes/App") remote_cmd("/bin/mkdir -p /mnt1/System/Cryptexes/OS") remote_cmd("/bin/chmod 0755 /mnt1/System/Cryptexes/OS")

send Cryptex files to device

print("Copying cryptexs to vphone! Will take about 3 mintues...") os.system("tools/sshpass -p 'alpine' scp -q -r -ostricthostkeychecking=false -ouserknownhostsfile=/dev/null -o StrictHostKeyChecking=no -P 2222 CryptexSystemOS/. '[email protected]:/mnt1/System/Cryptexes/OS'") os.system("tools/sshpass -p 'alpine' scp -q -r -ostricthostkeychecking=false -ouserknownhostsfile=/dev/null -o StrictHostKeyChecking=no -P 2222 CryptexAppOS/. '[email protected]:/mnt1/System/Cryptexes/App'")

Thanks nathan for idea

/System/Library/Caches/com.apple.dyld -> /System/Cryptexes/OS/System/Library/Caches/com.apple.dyld/

remote_cmd("/bin/ln -sf ../../../System/Cryptexes/OS/System/Library/Caches/com.apple.dyld /mnt1/System/Library/Caches/com.apple.dyld")

/System/DriverKit/System/Library/dyld -> /System/Cryptexes/OS/System/DriverKit/System/Library/dyld

remote_cmd("/bin/ln -sf ../../../../System/Cryptexes/OS/System/DriverKit/System/Library/dyld /mnt1/System/DriverKit/System/Library/dyld")

========= PATCH SEPUTIL =========

remove if already exist

os.system("rm custom_26.1/seputil 2>/dev/null") os.system("rm custom_26.1/seputil.bak 2>/dev/null")

backup seputil before patch

file_path = "/mnt1/usr/libexec/seputil.bak" if not check_remote_file_exists(file_path): print(f"Created backup {file_path}") remote_cmd("/bin/cp /mnt1/usr/libexec/seputil /mnt1/usr/libexec/seputil.bak")

grab seputil

os.system("tools/sshpass -p 'alpine' scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P 2222 [email protected]:/mnt1/usr/libexec/seputil.bak ./custom_26.1") os.system("mv custom_26.1/seputil.bak custom_26.1/seputil")

patch seputil; prevent error "seputil: Gigalocker file (/mnt7/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.gl) doesn't exist: No such file or directory"

fp = open("custom_26.1/seputil", "r+b") patch(0x1B3F1, "AA") fp.close()

sign

os.system("tools/ldid_macosx_arm64 -S -M -Ksigncert.p12 -Icom.apple.seputil custom_26.1/seputil")

send to apply

os.system("tools/sshpass -p 'alpine' scp -q -r -ostricthostkeychecking=false -ouserknownhostsfile=/dev/null -o StrictHostKeyChecking=no -P 2222 custom_26.1/seputil '[email protected]:/mnt1/usr/libexec/seputil'") remote_cmd("/bin/chmod 0755 /mnt1/usr/libexec/seputil")

clean

os.system("rm custom_26.1/seputil 2>/dev/null")

Change gigalocker filename to AA.gl

remote_cmd("/sbin/mount_apfs -o rw /dev/disk1s3 /mnt3") remote_cmd("/bin/mv /mnt3/*.gl /mnt3/AA.gl")

... # ========= INSTALL AppleParavirtGPUMetalIOGPUFamily =========

========= INSTALL iosbinpack64 =========

Send to rootfs

os.system("tools/sshpass -p 'alpine' scp -q -r -ostricthostkeychecking=false -ouserknownhostsfile=/dev/null -o StrictHostKeyChecking=no -P 2222 jb/iosbinpack64.tar '[email protected]:/mnt1'")

Unpack

remote_cmd("/usr/bin/tar --preserve-permissions --no-overwrite-dir -xvf /mnt1/iosbinpack64.tar -C /mnt1") remote_cmd("/bin/rm /mnt1/iosbinpack64.tar")

Setup initial dropbear after normal boot

''' /iosbinpack64/bin/mkdir -p /var/dropbear /iosbinpack64/bin/cp /iosbinpack64/etc/profile /var/profile /iosbinpack64/bin/cp /iosbinpack64/etc/motd /var/motd '''

========= PATCH launchd_cache_loader (patch required if modifying /System/Library/xpc/launchd.plist) =========

remove if already exist

os.system("rm custom_26.1/launchd_cache_loader 2>/dev/null") os.system("rm custom_26.1/launchd_cache_loader.bak 2>/dev/null")

backup launchd_cache_loader before patch

file_path = "/mnt1/usr/libexec/launchd_cache_loader.bak" if not check_remote_file_exists(file_path): print(f"Created backup {file_path}") remote_cmd("/bin/cp /mnt1/usr/libexec/launchd_cache_loader /mnt1/usr/libexec/launchd_cache_loader.bak")

grab launchd_cache_loader

os.system("tools/sshpass -p 'alpine' scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P 2222 [email protected]:/mnt1/usr/libexec/launchd_cache_loader.bak ./custom_26.1") os.system("mv custom_26.1/launchd_cache_loader.bak custom_26.1/launchd_cache_loader")

patch to apply launchd_unsecure_cache=1

fp = open("custom_26.1/launchd_cache_loader", "r+b") patch(0xB58, 0xd503201f) fp.close()

sign

os.system("tools/ldid_macosx_arm64 -S -M -Ksigncert.p12 -Icom.apple.launchd_cache_loader custom_26.1/launchd_cache_loader")

send to apply

os.system("tools/sshpass -p 'alpine' scp -q -r -ostricthostkeychecking=false -ouserknownhostsfile=/dev/null -o StrictHostKeyChecking=no -P 2222 custom_26.1/launchd_cache_loader '[email protected]:/mnt1/usr/libexec/launchd_cache_loader'") remote_cmd("/bin/chmod 0755 /mnt1/usr/libexec/launchd_cache_loader")

clean

os.system("rm custom_26.1/launchd_cache_loader 2>/dev/null")

========= MAKE RUN bash, dropbear, trollvnc automatically when boot =========

Send plist to /System/Library/LaunchDaemons

os.system("tools/sshpass -p 'alpine' scp -q -r -ostricthostkeychecking=false -ouserknownhostsfile=/dev/null -o StrictHostKeyChecking=no -P 2222 jb/LaunchDaemons/bash.plist '[email protected]:/mnt1/System/Library/LaunchDaemons'") os.system("tools/sshpass -p 'alpine' scp -q -r -ostricthostkeychecking=false -ouserknownhostsfile=/dev/null -o StrictHostKeyChecking=no -P 2222 jb/LaunchDaemons/dropbear.plist '[email protected]:/mnt1/System/Library/LaunchDaemons'") os.system("tools/sshpass -p 'alpine' scp -q -r -ostricthostkeychecking=false -ouserknownhostsfile=/dev/null -o StrictHostKeyChecking=no -P 2222 jb/LaunchDaemons/trollvnc.plist '[email protected]:/mnt1/System/Library/LaunchDaemons'") remote_cmd("/bin/chmod 0644 /mnt1/System/Library/LaunchDaemons/bash.plist") remote_cmd("/bin/chmod 0644 /mnt1/System/Library/LaunchDaemons/dropbear.plist") remote_cmd("/bin/chmod 0644 /mnt1/System/Library/LaunchDaemons/trollvnc.plist")

Edit /System/Library/xpc/launchd.plist

remove if already exist

os.system("rm custom_26.1/launchd.plist 2>/dev/null") os.system("rm custom_26.1/launchd.plist.bak 2>/dev/null")

backup launchd.plist before patch

file_path = "/mnt1/System/Library/xpc/launchd.plist.bak" if not check_remote_file_exists(file_path): print(f"Created backup {file_path}") remote_cmd("/bin/cp /mnt1/System/Library/xpc/launchd.plist /mnt1/System/Library/xpc/launchd.plist.bak")

grab launchd.plist

os.system("tools/sshpass -p 'alpine' scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P 2222 [email protected]:/mnt1/System/Library/xpc/launchd.plist.bak ./custom_26.1") os.system("mv custom_26.1/launchd.plist.bak custom_26.1/launchd.plist")

Inject bash, dropbear, trollvnc to launchd.plist

os.system("plutil -convert xml1 custom_26.1/launchd.plist")

1. bash

target_file = 'custom_26.1/launchd.plist' source_file = 'jb/LaunchDaemons/bash.plist' insert_key = '/System/Library/LaunchDaemons/bash.plist'

with open(target_file, 'rb') as ft, open(source_file, 'rb') as fs: target_data = plistlib.load(ft) source_data = plistlib.load(fs)

target_data.setdefault('LaunchDaemons', {})[insert_key] = source_data

with open(target_file, 'wb') as f: plistlib.dump(target_data, f, sort_keys=False)

2. dropbear

source_file = 'jb/LaunchDaemons/dropbear.plist' insert_key = '/System/Library/LaunchDaemons/dropbear.plist'

with open(target_file, 'rb') as ft, open(source_file, 'rb') as fs: target_data = plistlib.load(ft) source_data = plistlib.load(fs)

target_data.setdefault('LaunchDaemons', {})[insert_key] = source_data

with open(target_file, 'wb') as f: plistlib.dump(target_data, f, sort_keys=False)

3. trollvnc

source_file = 'jb/LaunchDaemons/trollvnc.plist' insert_key = '/System/Library/LaunchDaemons/trollvnc.plist'

with open(target_file, 'rb') as ft, open(source_file, 'rb') as fs: target_data = plistlib.load(ft) source_data = plistlib.load(fs)

target_data.setdefault('LaunchDaemons', {})[insert_key] = source_data

with open(target_file, 'wb') as f: plistlib.dump(target_data, f, sort_keys=False)

send to apply

os.system("tools/sshpass -p 'alpine' scp -q -r -ostricthostkeychecking=false -ouserknownhostsfile=/dev/null -o StrictHostKeyChecking=no -P 2222 custom_26.1/launchd.plist '[email protected]:/mnt1/System/Library/xpc'") remote_cmd("/bin/chmod 0644 /mnt1/System/Library/xpc/launchd.plist")

clean

os.system("rm custom_26.1/launchd.plist 2>/dev/null")

========= End of MAKE RUN bash, dropbear, trollvnc automatically when boot =========

... remote_cmd("/sbin/halt") ...

root@kitploit:~
# Primer intento de arranque

El proceso de arranque debería funcionar bien ahora, pero cuando intentas continuar más allá de la pantalla de configuración negra, hace respring y no avanza más.

![image.png](https://assets.kitploit.com/production/public/readmes/12192/0c83d9ac19f4310482d591218a5a501e3e632cf7e1bb166fad6b29915c043490.png)

![image.png](https://assets.kitploit.com/production/public/readmes/12192/81098ce1af2d8558b868db3073e644e43a3f09580fb64010a03fdb7d0f63f9b9.png)

# Implementando Metal

Al verificar con un programa personalizado llamado MetalTest, se muestra que Metal no es compatible.```python
#import <stdio.h>
#import <Metal/Metal.h>
#import <Foundation/Foundation.h>

int main(int argc, char *argv[], char *envp[]) {
    id<MTLDevice> device = MTLCreateSystemDefaultDevice();
    NSLog(@"device: %@", device);

    if (device) {
        NSLog(@"Metal Device Create Success: %@", [device name]);
    } else {
        NSLog(@"Metal Not Supported!");
    }

    return 0;
}
  • Resultado de ejecución```python -bash-4.4# ./MetalTest 2026-02-08 22:49:02.293 MetalTest[633:9434] device: (null) 2026-02-08 22:49:02.294 MetalTest[633:9434] Metal Not Supported! -bash-4.4# sysctl kern.version kern.version: Darwin Kernel Version 25.1.0: Thu Oct 23 11:11:48 PDT 2025; root:xnu-12377.42.6~55/RELEASE_ARM64_VRESEARCH1
root@kitploit:~
Normalmente, el resultado debería haber sido similar al que se muestra a continuación.```python
seo@seos-Virtual-Machine Desktop % sysctl kern.version
kern.version: Darwin Kernel Version 25.0.0: Mon Aug 25 21:17:21 PDT 2025; root:xnu-12377.1.9~3/RELEASE_ARM64_VMAPPLE
seo@seos-Virtual-Machine Desktop % ./MetalTest        
2026-02-08 23:16:56.846 MetalTest[682:5810] device: <AppleParavirtDevice: 0x102c48fe0>
    name = Apple Paravirtual device
2026-02-08 23:16:56.847 MetalTest[682:5810] Metal Device Create Success: Apple Paravirtual device
seo@seos-Virtual-Machine Desktop % 

Al verificar con ioreg -l, como puedes ver, el kernel estaba reconociendo AppleParavirtGPU.

image.png

Al verificar en un iPad de 7ª generación con iOS 16.6.1, llamar a la función MTLCreateSystemDefaultDevice accede internamente al controlador IOGPU a través de una biblioteca específica llamada AGXMetalA10. Esta biblioteca AGXMetalA10 se encuentra en /System/Library/Extensions.

De repente se me ocurrió una idea: ¿no habría también bibliotecas relacionadas con GPU/Metal utilizadas para el iPhone virtual?

image.png

Al verificar esa misma ruta en la máquina virtual PCC, se revela que existen 7 archivos allí.

Tomé el /System/Library/Extensions/AppleParavirtGPUMetalIOGPUFamily.bundle usado en PCC y lo coloqué directamente en el iPhone virtual. (Usé el Ramdisk SSH para esto.)

image.png

Al verificar MetalTest nuevamente, la función MTLCreateSystemDefaultDevice ahora funciona correctamente.

image.png

Sin embargo, debido a que un archivo dylib específico no existe en la dsc (caché compartida dyld) del modelo iPhone 16, necesité realizar ingeniería inversa por separado e implementarlo desde la dsc en el PCC.

  • /System/Library/Extensions/AppleParavirtGPUMetalIOGPUFamily.bundle/libAppleParavirtCompilerPluginIOGPUFamily.dylib

Screenshot 2026-02-25 at 1.19.40 PM.png

image.png

Segundo Intento de Arranque

Una vez implementado, ahora te recibe la pantalla de configuración con un fondo. Como no pude implementar correctamente el botón de inicio, resolví esto usando una solución temporal controlando a través de iproxy/VNC.

image.png

Compatibilidad

Solo es compatible con Macs Apple Silicon, y los dispositivos/versiones confirmados que funcionan son los siguientes:

  • Apple M3, 16GB RAM, Sequoia 15.7.4
  • Apple M1 Pro, 32GB RAM, Tahoe 26.3

Espero que probablemente funcione en cualquier objetivo que soporte pccvre.

Fuente: https://security.apple.com/documentation/private-cloud-compute/vresetup

Fuente: https://security.apple.com/documentation/private-cloud-compute/vresetup

Habilitar la Interacción Táctil en Sequoia

A diferencia de la versión Tahoe 26, no es posible la interacción táctil usando solo el objeto VZVirtualMachineView, por lo que fue necesario sobrescribir las funciones de eventos del ratón.

ScreenSharingVNC.swift

Código Fuente del Proyecto

  • https://github.com/wh1te4ever/super-tart-vphone
Descargar herramienta

// Display let graphics_config = VZMacGraphicsDeviceConfiguration() let displays_config = VZMacGraphicsDisplayConfiguration( widthInPixels: 1179, heightInPixels: 2556, pixelsPerInch: 460 ) graphics_config.displays.append(displays_config) configuration.graphicsDevices = [graphics_config] ...