1 puntos por GN⁺ 2023-10-03 | 1 comentarios | Compartir por WhatsApp
  • gala es un proyecto que implementa directamente un jailbreak de iOS 4 para iPhone 4, y esta parte 1 se centra en obtener ejecución inicial de código aprovechando una vulnerabilidad de SecureROM en dispositivos antiguos
  • El arranque de iOS sigue una cadena de confianza en la que SecureROM verifica LLB o iBSS, y cada etapa posterior verifica la siguiente; SecureROM no puede reemplazarse con actualizaciones después de la fabricación
  • limera1n ataca la SecureROM del SoC A4 cuando el dispositivo en modo DFU espera la transferencia de iBSS, y el fallo hallado mediante fuzzing de mensajes de control USB parece derivar en un desbordamiento de heap y ejecución de shellcode
  • Tomando como referencia el dumper de SecureROM de pod2g, se reaprovecha la región de comunicación 0x84000000 y la solicitud de lectura USB 0xA1:2, reimplementando el flujo para traer al host un volcado de SecureROM y valores de depuración
  • Se creó una tubería para extraer y ejecutar shellcode escrito en Rust desde __TEXT,__text de un Mach-O, pero al ubicarse cadenas estáticas en __const fue necesario usar direccionamiento relativo al puntero de instrucción y ubicar datos con ensamblador

Punto de partida del proyecto de jailbreak del iPhone 4

  • gala es un proyecto para crear un jailbreak de iOS 4 para iPhone 4, y este documento corresponde a su parte 1, “Gaining Entry”
  • La experiencia previa desarrollando tweaks para iOS llevó a distribuir por Cydia, modificar funciones de SpringBoard, usar directamente el runtime de Objective-C y hacer ingeniería inversa de binarios de código cerrado
  • El objetivo de escribir un jailbreak propio es entender cómo funciona realmente el proceso de jailbreak
  • Este trabajo depende en gran medida del conocimiento compartido como código abierto por p0sixninja y axi0mX

Elección de iPhones antiguos y una vulnerabilidad de Boot ROM

  • El primer paso fue comprar un iPhone 4 y un iPhone 3GS en eBay
  • Como las versiones actuales de Xcode no permiten apuntar a versiones antiguas de iOS, pronto se cerró la vía de compilar e instalar apps al estilo de la década de 2010
    • También se evaluó instalar versiones antiguas de Mac OS X y Xcode en una VM, pero se descartó
    • Tampoco estaba claro si Apple seguiría firmando binarios para targets heredados de iOS
  • La alternativa fue apuntar directamente a una vulnerabilidad de Boot ROM
    • Se puede intentar solo con código que interactúe con el dispositivo por USB desde la máquina host, sin toolchains viejos ni VMs
    • En la sección Vulnerabilities and Exploits de iPhone Wiki se revisó el código del exploit limera1n

SecureROM y la cadena de confianza del arranque de iOS

  • En la terminología de Apple, SecureROM es la primera etapa del proceso de arranque de iOS y la que inicia la siguiente etapa
  • SecureROM puede cargar dos componentes
    • En un arranque normal, inicia Low Level Bootloader, es decir, LLB, desde una partición de disco en la NOR
    • Si está conectado por USB a una computadora en modo DFU, durante el proceso de Restore iPhone puede recibir el cargador iBoot Single Stage, es decir, iBSS
  • SecureROM verifica que LLB o iBSS sea una imagen confiable firmada por Apple
  • Después, LLB e iBSS también verifican la siguiente etapa que cargan, formando una cadena de confianza
  • Como SecureROM es la primera etapa, no está verificada por una etapa anterior y queda grabada en memoria de solo lectura durante la fabricación
    • Las demás etapas sí pueden reemplazarse mediante actualizaciones de iOS
    • Una vulnerabilidad en una versión específica de SecureROM permanece de forma permanente en los dispositivos fabricados con esa versión

Obtener ejecución de código en un dispositivo DFU con limera1n

  • limera1n es un exploit de SecureROM publicado por geohot en 2010 y empaquetado en una herramienta de jailbreak con el mismo nombre
  • limera1n puede usarse cuando un dispositivo en modo DFU está esperando recibir iBSS desde el host por USB
  • Como la SecureROM incluida en el SoC A4 es vulnerable, el iPhone 4 resulta un objetivo adecuado
  • El mecanismo exacto de limera1n no está completamente documentado en público
    • geohot dijo que no sabía por qué funcionaba
    • p0sixninja planteó una teoría
    • El fallo se descubrió con fuzzing de mensajes de control USB y parece una race condition que deriva en un desbordamiento de heap, permitiendo inyectar y ejecutar shellcode

Lectura de memoria en un dispositivo en modo DFU

  • El dumper de SecureROM de pod2g sirve como implementación de referencia que muestra una implementación de limera1n, un payload de ejemplo y una forma de leer memoria por USB
  • El dumper de SecureROM copia la memoria 0x0, donde está mapeada SecureROM, al área de recepción USB, y luego el host lee los datos mediante mensajes de control USB
  • El flujo entendido es el siguiente
    • La MMU del A4 mapea el inicio de la SRAM en 0x84000000
    • El host puede enviar la imagen iBSS en fragmentos mediante paquetes de control USB con request type 0x21 y request ID 1
    • Estos datos se copian en la SRAM a partir de 0x84000000, y SecureROM mantiene un contador interno para seguir la siguiente posición de copia de paquetes
    • El dispositivo también responde a paquetes de control con request type 0xA1 y request ID 2, enviando al host el contenido de memoria de 0x84000000
  • Esta función de lectura es especialmente útil cuando ya se puede ejecutar código en el dispositivo
    • El payload copia los datos deseados a 0x84000000
    • El host puede recuperarlos con la solicitud de lectura A1:2
  • Las diapositivas de la charla de p0sixninja en Hack In the Box Malaysia 2013 indican que el dumper de SecureROM de pod2g está basado en SHAtter, pero la utilidad real usa una implementación de limera1n
  • Se logró obtener un volcado de SecureROM con una implementación propia de limera1n

Depuración del payload usando 0x84000000

  • Después de obtener ejecución de código, hizo falta confirmar dónde se ejecuta el shellcode, dónde está la pila y qué memoria sobreescribe
  • Se reutilizó el flujo de lectura del dumper de SecureROM como salida de depuración
    • El payload copia a 0x84000000 los valores del puntero de instrucción (instruction pointer) y del puntero de pila (stack pointer)
    • El código del lado del host vuelve a leer esos valores del mismo modo
    • Este método funciona como un print() improvisado mediante volcados de memoria
  • Un script automatizado vuelca las primeras palabras de 0x84000000 después de ejecutar el exploit y las muestra en la ventana de salida
  • Los valores observados mostraron la ubicación de ejecución del shellcode y de la pila
    • El puntero de instrucción estaba cerca de 0x8402b048
    • El puntero de pila estaba en 0x8403bfa0
    • El puntero de pila estaba dentro del área de pila general configurada por SecureROM, y el puntero de instrucción dentro del área de imagen recibida

Payload en Rust y extracción de shellcode desde Mach-O

  • En lugar de escribir el payload solo en ensamblador, se armó un sistema de build para compilar un payload en Rust y convertirlo en shellcode
  • Rust dejó de soportar el target armv7-apple-ios a inicios de 2020, pero rustup permite cambiar a toolchains antiguos que sí lo soportan
  • Al compilar en un lenguaje de alto nivel se genera un binario que incluye no solo código máquina puro, sino también metadatos, información de configuración del espacio de direcciones virtuales, tablas de símbolos e información del linker
  • Para el exploit solo hacen falta los bytes que se inyectarán en memoria y a los que luego se saltará, por lo que no se necesita todo el Mach-O, sino solo la sección __text del segmento __TEXT
  • strongarm es una biblioteca de análisis de Mach-O, y se usa en el sistema de build para parsear el Mach-O y extraer a un archivo la sección __TEXT,__text
  • Los bytes del archivo extraído se convierten en el shellcode que limera1n ejecutará en el dispositivo

Problemas con el linker y los datos estáticos

  • Los binarios normales usan la infraestructura del sistema operativo y convenciones de símbolos de entrada como start o _main, pero para este uso como shellcode esos símbolos no hacen falta
  • El linker, por defecto, da error si no existen _main o start
  • Con una combinación de opciones -U _main, -U start y -static fue posible crear un archivo Mach-O que no usa dyld
  • Al principio, strongarm no podía procesar binarios sin el comando de carga LC_DYLD_INFO y lanzaba una excepción
    • Ese binario no tiene LC_DYLD_INFO porque no usa dyld
    • Se agregó un parche a strongarm para manejarlo
  • Al agregar cadenas estáticas al código Rust, el payload dejaba de funcionar
    • Las cadenas estáticas compiladas se colocan en __const
    • El proceso de extracción de shellcode conserva solo __TEXT,__text, así que los datos de __const no se cargan en memoria
    • Como resultado, el código intenta leer cadenas desde direcciones no mapeadas y falla
  • La solución fue incluir los datos estáticos dentro de __TEXT,__text y usar direccionamiento relativo al puntero de instrucción para no asumir una dirección de carga estable
  • El método actual define las cadenas en ensamblador y pasa su dirección al punto de entrada del payload en Rust

La tubería de ejecución completada en la parte 1

  • La tubería final funciona en este orden
    • Se modifica el payload en Rust
    • Se presiona un botón para compilar el payload
    • Se extrae el shellcode del binario
    • Un runner ejecuta el payload con limera1n en un iPhone en modo DFU conectado
    • El runner lee automáticamente datos desde 0x84000000, que usa como espacio de comunicación, y los muestra como hexdump
  • En este punto ya se puede ejecutar código arbitrario en el dispositivo
  • La ejecución arbitraria de código permite hacer muchas cosas en teoría, pero lograr que el dispositivo haga algo realmente interesante sigue siendo una etapa aparte
  • El siguiente paso continúa en Part 2: Bypassing the Bootchain

1 comentarios

 
GN⁺ 2023-10-03
Opiniones en Hacker News
  • Después de años de solo leer, finalmente me hice una cuenta en Hacker News para dejar este comentario. Gracias por explicar así algo que durante mucho tiempo fue una caja negra misteriosa para mucha gente.
    Recuerdo con claridad lo nervioso que estaba cuando le hacía jailbreak a mi iPod 4G con iOS 4, viendo pasar líneas y líneas de mensajes en la terminal. Después, durante la hora del almuerzo en la escuela, también se lo hacía a los dispositivos de mis amigos, preocupado de que por error arruinara un teléfono y lo convirtiera en un ladrillo de cientos de dólares.
    Mirando hacia atrás, varios años después, esa “magia” de atravesar los muros de Apple y ejecutar código de usuario fue lo que me hizo engancharme con la programación, y estoy profundamente agradecido con todos los involucrados.

    • Cuando trabajas en la industria tecnológica, hay muchos días en los que terminas odiándola por cosas que te propones y no entiendes o no logras hacer. Aun así, leer textos como este de vez en cuando me hace sentir que no debería rendirme con el open source ni con la comunidad tecnológica en general.
    • Me gusta el iPhone, pero extraño instalar CyanogenMod en varios dispositivos Android de antes. Se sentía realmente genial.
    • Tuve una experiencia parecida. Terminé empezando a crear mis propios tweaks de jailbreak, y eso fue lo que me metió de lleno en la programación.
  • Muchas gracias por el artículo. Hace falta una comprensión profunda para explicar conceptos tan complejos de forma sencilla. Mientras leía, me vinieron buenos recuerdos de cuando me quedaba hasta tarde hackeando proyectos de jailbreak.

  • Disfruté muchísimo leerlo, especialmente porque todavía no soy muy hábil en ingeniería inversa de código nativo.
    Esto parece un jailbreak tethered, ya que usa el mecanismo de recuperación del sistema para romper la cadena de confianza y arrancar un iOS modificado. Entonces me pregunto cómo funciona un jailbreak untethered. ¿Es correcto que explota un proceso privilegiado o no privilegiado del sistema en ejecución, y luego realiza una elevación de privilegios aparte, dejando intacta la cadena de arranque seguro y sin saltársela por completo? También me pregunto cómo se logra la persistencia y cómo se parchean las verificaciones de firma del kernel sin tocar las verificaciones de firma del bootloader y del propio kernel.

    • Por lo general se configuraba algo para volver a explotar el kernel desde espacio de usuario durante el proceso de arranque o justo después. Técnicas que recuerdo incluyen agregar un nuevo launch daemon, firmar una app con un certificado de desarrollador y colocar binarios que abusaban de comportamientos peculiares del enlazador dinámico para eludir la verificación de firmas.
  • Un artículo realmente excelente. Me alegra ver que sigues activo en la comunidad.

  • Gracias por crear esto. Tengo un iPhone 4s con muchas fotos especiales, pero por alguna razón olvidé el PIN y lleva años en un estado en el que tendría que seguir esperando.
    Si no fuera por las fotos, simplemente lo habría restaurado, pero me pregunto si con esto podría restablecer el PIN y copiar las fotos.

    • Probablemente sea difícil. Según [0], la contraseña se usa para proteger la clave de cifrado del sistema de archivos, así que sin la contraseña no se pueden descifrar los archivos. No sé si las fotos se almacenan cifradas, pero supongo que sí.
      Edición: puede que esté equivocado. [0] también dice que durante un tiempo solo el almacenamiento de Mail estaba cifrado y que el valor predeterminado cambió en iOS 7. Así que si el iPhone tiene iOS <= 6, tal vez este método permita acceder al dispositivo y copiar las fotos. La herramienta de [1] podría ayudar.
      [1] https://code.google.com/archive/p/iphone-dataprotection/
      [0] https://darthnull.org/ios-encryption/
  • Fue un artículo muy bueno. Aunque la parte en la que la antigua interfaz de iOS muestra toda la gloria del diseño esqueuomórfico me revolvió el estómago. Me hizo recordar cuánto detesto a John Ive.

    • ¿Te refieres a la época en que los botones parecían botones que se podían hacer clic? A diferencia de ahora, con un diseño plano tan pobre que al final tuvieron que agregar funciones de accesibilidad para rodear sus defectos.
      Tal vez Jony debería haberse limitado a seguir diseñando reposamuñecas de aluminio afilados como navajas, en vez de encargarse del software.
    • Creo que el iPhone alcanzó su punto máximo con el iPhone 4 e iOS 4. Después hubo mejoras graduales, pero ese fue el último momento en que sentí que un nuevo iPhone era una actualización realmente grande. Dejando de lado el antennagate, tanto el hardware como el software simplemente encajaban muy bien.
  • Leí con mucho gusto las primeras partes. Es genial seguir el tema desde esta perspectiva. Yo también leo muchísimo código fuente para descubrir cómo implementan otras personas cosas como exploits, así que me alegra saber que otros también lo hacen.

  • Todavía no lo leí, pero me entusiasma. Usé todos los tweaks enumerados al principio y quería decir gracias por haberlos creado. Los jailbreaks de los primeros iOS eran realmente divertidos.

  • Muy bueno. Intenté ejecutarlo, pero por desgracia mi dispositivo viejo ni siquiera arrancaba desde el principio.
    Yo también hacía tweaks en esa época y el jailbreak me parecía magia negra. Después de leer este artículo, todavía me lo parece en cierta medida.

  • Muchísimas gracias por poner todo esto en orden. Me interesa mucho aprender sobre estos temas. En particular, quiero aprender cosas como “liberar” cámaras de seguridad Wi-Fi baratas, al estilo de dafang-hacks, con mi propio firmware personalizado, o crear nuevos exploits para rootear tablets Kindle Fire.
    Pero sorprende lo difícil que es encontrar artículos que expliquen ese proceso en detalle.