IOMobileFramebufferGetLayerDefaultSurface no funciona en iOS 9

Mi pregunta principal es: ¿cómo puedo hacer ingeniería inversa de una function de API privada que ya existe, pero se ha modificado en una nueva versión de iOS?

He creado una aplicación de iOS para grabar el contenido de la pantalla usando IOSurface y IOMobileFramebuffer. Las funciones principales que usa el framebuffer para abrirlo son IOMobileFramebufferGetMainDisplay(connect) y IOMobileFramebufferGetLayerDefaultSurface .

Estas funciones se han utilizado desde la primera versión de la aplicación, y han funcionado en todas las versiones de iOS 7 y 8. Sin embargo, en la versión más reciente de iOS 9 beta, que es beta 5, la function IOMobileFramebufferGetLayerDefaultSurface no funciona. La function no devuelve 0, como debería cuando abre correctamente el framebuffer.

Este otro usuario en StackOverflow también está experimentando el mismo problema: la function IOMobileFramebufferGetLayerDefaultSurface falló en iOS 9 . Tenemos una reference a IOMobileFramebufferConnection llamada "_framebufferConnection" y un IOSurfaceRef llamado "_screenSurface" Aquí está el código actual:

IOMobileFramebufferGetMainDisplay(&_framebufferConnection); IOMobileFramebufferGetLayerDefaultSurface(_framebufferConnection, 0, &_screenSurface;

Como se dijo antes, estos funcionan perfectamente en iOS 7-8, pero en iOS 9, la segunda function falla. También miré los binarys con los símbolos para ambas versiones y los comparé. El segundo parámetro del LDR es ligeramente diferente en iOS 9, en comparación con el binary iOS 8.4.1. Entonces, volviendo a la pregunta principal, ¿cómo puedo hacer ingeniería inversa a IOMobileFramebufferGetLayerDefaultSurface , o ver cómo de qué manera se ha modificado realmente en iOS 9?

Creo que @nevyn es correcto. Sin embargo, me gustaría elaborar un poco más. He examinado extensamente este problema exacto y la function IOMobileFramebufferGetLayerDefaultSurface devuelve -536870201, mientras que debería devolver 0 si ejecuta la function sin problemas. Este error está en Internet, pero solo aparece cuando los usuarios encuentran problemas generics con QuickTime. Podría ser que Apple ciertamente haya bloqueado el marco por completo, y necesita un derecho exclusivo de Apple para acceder al framebuffer. No podemos agregar estos derechos, ya que también debe estar en el perfil de aprovisionamiento. Actualmente estoy tratando de leer e interpretar el desassembly y hacer algunos trabajos de ingeniería inversa en el binary IOMobileFramebuffer para ver si alguno de los parameters ha cambiado desde la última versión de iOS. Seguramente actualizaré esta respuesta si descubro algo. Pero si este es el caso, sugeriría tratar de encontrar otro método para tratar de capturar / grabar el contenido de la pantalla.

-ACTUALIZAR-

Parece que hay evidencia de que este sería el caso, si lee esto , muestra exactamente el mismo código de error, y significa que la function es "no compatible", y devuelve un error de IOKit. Al less sabemos lo que significa esto ahora. Sin embargo, todavía no estoy seguro de cómo solucionarlo o de hacer funcionar la function. Seguiré investigando esto.

ACTUALIZACIÓN 2

¡De hecho, he descubierto una nueva class en iOS 9, "FigScreenCaptureController", y forma parte del marco de MediaToolbox! Sin embargo, lo extraño es, ¿por qué Apple includeía esto solo en iOS 9? Entonces, tal vez haya una manera de grabar la pantalla a través de esto … Estaré investigando esta class más en profundidad muy pronto.

Para responder a la pregunta de "cómo de qué manera se modificó realmente en iOS 9", hice un poco de IOMobileFramebufferGetLayerDefaultSurface en IOMobileFramebufferGetLayerDefaultSurface en iOS8 vs iOS9 (GM). Estos son los resultados de lo que encontré:

Preparar:

IOMobileFramebufferRef fb; IOMobileFramebufferGetMainDisplay(&fb);

Implementación iOS8:

  • Llama a kern_GetLayerDefaultSurface

  • ¿Qué acceso a IOConnection subyacente?

    io_connect_t fbConnect = *(io_connect_t *)((char *)fb + 20)

  • Para recuperar el IOSurfaceID vía

    IOSurfaceID surfaceID; uint32_t outCount = 1; IOConnectCallScalarMethod(fbConnect, 3, {0, 0}, 2, &surfaceID, &outCount)

  • Devuelve IOSurfaceLookup(surfaceID)

Implementación de iOS9:

  • Los mismos pasos anteriores, aparte de la devolución

  • Luego intenta recuperar un puerto Mach para acceder a la superficie a través de

    io_service_t fbService = *(io_service_t *)((char *)fb + 16) mach_port_t surfacePort; IOServiceOpen(fbService, mach_task_self(), 3, &surfacePort)

  • En caso de éxito, devuelva IOSurfaceLookupFromMachPort(surfacePort)

Es en el último paso que IOServiceOpen devuelve el error 0x2c7 (function no 0x2c7 ). Observe que el tercer argumento que especifica el tipo de connection es 3 lugar del 0 usual al abrir el service framebuffer. Es casi seguro que este nuevo tipo de connection tiene restricciones de permissions que impiden que cualquier persona, excepto Apple, recupere un puerto Mach para acceder a la superficie del IOMFB.

Lo que es un tanto interesante es que la llamada a IOConnectCallScalarMethod todavía funciona para recuperar el ID de la superficie de IOMFB. Sin embargo, ya no se puede acceder usando IOSurfaceLookup porque la superficie ya no es global. ¡Es un poco sorprendente que fuera global en primer lugar!

Espero que esto ayude a desmitificar por qué el IOMFB ya no puede usarse para grabar la pantalla.

Fuente: Mi propio uso de LLDB con un iPhone6 ​​con iOS 8.4 y un iPhone6 ​​con iOS9 GM

IOMobileFramebuffer está completamente bloqueado en iOS 9 y ya no se puede usar desde aplicaciones que no sean de Apple. AFAICT, esto cierra la última API privada para capturar la pantalla de manera eficiente. ReplayKit es el único reemploop, pero no permite el acceso programático a los datos de video reales.

No es del todo correcto: es solo una cuestión de derecho, como puede ver si descarga el kext:

 $ jtool -d __TEXT.__cstring 97.IOMobileGraphicsFamily.kext | grep com.apple 0xffffff80220c91a2: com.apple.private.allow-explicit-graphics-priority 

Si firma usted mismo (jtool –sign –ent) con esto, todo funciona bien.

Esto significa que en dispositivos que no son JB no puede usarlo. Pero con un jailbreak el inmenso poder está en tus manos una vez más.