【问题标题】:IOMobileFramebufferGetLayerDefaultSurface not working on iOS 9IOMobileFramebufferGetLayerDefaultSurface 在 iOS 9 上不起作用
【发布时间】:2015-08-27 03:00:02
【问题描述】:

我的主要问题是,如何对已经存在但在新版本的 iOS 中修改的私有 API 函数进行反向工程?

我创建了一个 iOS 应用程序来使用 IOSurface 和 IOMobileFramebuffer 记录屏幕内容。帧缓冲区用来打开它的主要函数是IOMobileFramebufferGetMainDisplay(connect)IOMobileFramebufferGetLayerDefaultSurface

这些功能从应用程序的第一个版本开始就已经使用,它们适用于 iOS 7 和 8 的所有版本。但是,在最新的 iOS 9 测试版(即 beta 5)上,IOMobileFramebufferGetLayerDefaultSurface 函数可以不行。该函数不会像成功打开帧缓冲区时那样返回 0。

StackOverflow 上的其他用户似乎也遇到了同样的问题:IOMobileFramebufferGetLayerDefaultSurface function failed on iOS 9。我们有一个名为“_framebufferConnection”的 IOMobileFramebufferConnection 和一个名为“_screenSurface”的 IOSurfaceRef 这是当前代码:

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

如前所述,这些功能在 iOS 7-8 上完美运行,但在 iOS 9 上,第二个函数崩溃了。我还查看了带有两个版本符号的二进制文件并进行了比较。与 iOS 8.4.1 二进制文件相比,LDR 的第二个参数在 iOS 9 中略有不同。那么,回到主要问题,我如何对IOMobileFramebufferGetLayerDefaultSurface 进行逆向工程,或者查看它在 iOS 9 上的实际修改方式?

【问题讨论】:

  • 你用的是什么ios9版本?
  • iOS 9 beta 5。但同样的情况发生在所有 iOS 9 beta/版本上。

标签: ios objective-c iphone


【解决方案1】:

为了回答“它在 iOS 9 上的实际修改方式”这个问题,我对 iOS8 与 iOS9 (GM) 上的 IOMobileFramebufferGetLayerDefaultSurface 进行了一些研究。以下是我发现的结果:

设置:

IOMobileFramebufferRef fb; IOMobileFramebufferGetMainDisplay(&fb);

iOS8 实现:

  • 致电kern_GetLayerDefaultSurface

  • 访问底层 IOConnection

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

  • 通过

    检索 IOSurfaceID

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

  • 返回IOSurfaceLookup(surfaceID)

iOS9 实现:

  • 除返回外与上述步骤相同

  • 然后尝试检索一个马赫端口以通过

    访问表面

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

  • 成功返回IOSurfaceLookupFromMachPort(surfacePort)

IOServiceOpen 在最后一步返回错误0x2c7(不支持的功能)。请注意,在打开帧缓冲服务时,指定连接类型的第三个参数是3,而不是通常的0。几乎可以肯定的是,这种新的连接类型具有权限限制,可以防止除 Apple 之外的任何人检索 mach 端口来访问 IOMFB 表面。

有点有趣的是,对IOConnectCallScalarMethod 的调用仍然可以检索 IOMFB 表面的 ID。但是,不能再使用IOSurfaceLookup 访问它,因为该表面不再是全局的。首先它是全球性的,这有点令人惊讶!

希望这有助于揭开为什么 IOMFB 不能再用于记录屏幕的原因。

来源:我自己使用运行 iOS 8.4 的 iPhone6 和运行 iOS9 GM 的 iPhone6+ 使用 LLDB

【讨论】:

  • 我怀疑 Apple 以某种方式将其锁定...有没有其他方法可以捕获不带 IOMobileFramebuffer 的 IOSurface,或者可以使用其他框架来代替它?
  • @anthonya1999 当你的应用程序在后台时,我无法记录屏幕。如果你想录制你的应用程序,你可以使用公共的drawViewHierarchyInRect: UIView 方法。这种方法也是 App Store 安全的,但我怀疑这对你的情况并不重要。
  • 非常有用的侦探工作。感谢您发布它。 (已投票。)下一个问题是,Apple 是否添加了一项权利(可能是私有的),以便其应用程序仍能使用它?如果不是,那么 AirPlay 使用什么机制来进行屏幕镜像? (请参阅我关于如何在 iOS 9 中执行此操作的问题 Trying to do screen capture with private framework IOSurface no longer seems to work in iOS 9
  • @DuncanC 我认为这很可能是有权利的。我想一旦有人可以访问越狱的 iOS9 设备,我们就会知道。不过,AirPlay 屏幕镜像是另一种动物,似乎使用虚拟显示器。这是通过 AirPlay 进行镜像时系统日志的样子:mediaserverd[23] <Notice>: [AirPlay] Virtual display stream activating with options <<NULL>> mediaserverd[23] <Notice>: [AirPlayEndpointScreen] Screen start backboardd[57] <Notice>: IOMFB setting virtual mode: 0 0
  • 是的。我为当前客户所做的工作几乎停滞不前,直到我们可以访问 iOS 9 越狱,以便我们进行调查。越狱不是最终产品的选项,但私有 API 是一个选项,如果我们能找到授权,我们可以自己解锁。
【解决方案2】:

我相信@nevyn 是正确的。但是,我想详细说明一下。我已经广泛研究了这个确切的问题,IOMobileFramebufferGetLayerDefaultSurface 函数 确实 返回 -536870201,而如果它运行该函数没有任何问题,它应该返回 0。此错误在 Internet 上,但仅在用户遇到 QuickTime 的一般问题时才会出现。可能是 Apple 确实完全锁定了框架,并且需要 Apple 独有的权利来访问帧缓冲区。我们无法添加这些权利,因为它也必须在配置文件中。我目前正在尝试阅读和解释反汇编并对 IOMobileFramebuffer 二进制文件进行一些逆向工程工作,以查看自上一个 iOS 版本以来是否有任何参数发生了变化。如果我发现任何东西,我一定会更新这个答案。但如果是这种情况,我建议尝试另一种方法来尝试捕获/记录屏幕内容。

-更新-

似乎有证据表明会出现这种情况,如果您阅读this,它会显示完全相同的错误代码,这意味着该函数“不受支持”,并返回一个 IOKit 错误。至少我们现在知道这意味着什么。但是,我仍然不确定如何修复它或使该功能正常工作。我会继续研究这个。

更新 2

我实际上在 iOS 9 中发现了一个全新的类,“FigScreenCaptureController”,它是 MediaToolbox 框架的一部分!奇怪的是,为什么 Apple 只会在 iOS 9 中包含这个功能?所以,也许会有一种方法可以通过this 记录显示...我很快就会更深入地研究这个课程。

【讨论】:

  • 嘿@anthonya1999,使用 FigScreenCaptureController 捕获屏幕有什么运气吗?
  • @ShirishKamath 我知道这是一个迟到的回复,但我在课堂上看了一会儿,你可以调用 start/stop capture 就好了,但我不知道如何设置它向上。 (即视频路径、帧率等)我会继续看看我能用这个做什么......
【解决方案3】:

不完全正确 - 这只是一个权利问题,如果您转储 kext,您会看到:

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

如果您使用 this 自行签名 (jtool --sign --ent),一切正常。

这确实意味着您无法在非 JB 设备上使用它。但随着越狱,巨大的力量再次掌握在你的手中。

【讨论】:

  • 谢谢,我怎样才能为越狱调整签名?
【解决方案4】:

IOMobileFramebuffer 在 iOS 9 上完全锁定,不能再从非 Apple 应用程序中使用。 AFAICT,这将关闭最后一个私有 API 以有效捕获屏幕。 ReplayKit 是唯一的替代品,但不允许以编程方式访问实际视频数据。

【讨论】:

    猜你喜欢
    • 2015-11-15
    • 1970-01-01
    • 2018-11-03
    • 2015-12-14
    • 1970-01-01
    • 2016-02-21
    • 2017-12-26
    • 2016-06-15
    • 1970-01-01
    相关资源
    最近更新 更多