Darwin - 将内核扩展用作另一个内核扩展的UserClient

问题描述 投票:1回答:1

我一直想知道是否可以编写内核扩展来充当另一个内核扩展的UserClient。通常,我们在用户端使用IOConnect来访问内核扩展上的IOUserClient方法。但是在Kernel.framework中没有这样的方法(我完全理解它的意图是以这种方式使用)。但我只是想知道上述情况是否可行。

macos iokit kernel-extension darwin
1个回答
2
投票

首先,当您在用户空间中调用IOServiceOpen()时,会在传入其句柄的服务上调用IOService::newUserClient()。作为结果创建类的对象取决于服务是否以及如何覆盖该方法。

主要有两种可能性,它们可以决定如何覆盖默认行为。

  1. 如果服务没有覆盖newUserClient,或者它在某些情况下调用IOService::newUserClient()默认实现(例如,如果它不知道传入的type),则用户客户端类由服务上的IOUserClient属性确定。
  2. 如果服务确实覆盖newUserClient(),则用户客户端类通常是硬编码的,否则将遵循一些特定于kext的逻辑。

要在使用IOUserClient属性(1)时覆盖用户客户端类:

  • 创建一个包含用户客户端类实现的kext,并确保它是可加载的,等等。
  • 在Info.plist中,创建原始kext的IOKitPersonality的副本。 在你的版本中增加IOProbeScore(或添加非零IOProbeScore,如果没有),所以你的个性优先于原来的kext。 将IOUserClient属性设置为要使用的用户客户端类。 我对此并不是100%肯定,但我认为你需要将个性的CFBundleIdentifier更改为你的kext,并在OSBundleLibraries下列出另一个kext。如果这不起作用,请尝试使用原始包标识符。 如果原始kext的Info.plist具有OSBundleReqired键的值,请确保将其复制到您的值,具有相同的值。

如果服务专门包含防止其不知道的用户客户端的代码,则仍然无法工作。

注意:包括OSBundleLibraries中的原始kext仅在原始kext的Info.plist包含OSBundleCompatibleVersion值时才有效。如果没有,你就不能把它添加到你的OSBundleLibraries,但你仍然可以使它工作 - 例如,如果你只是在旧的kext上调用virtual成员函数。

注意2:当然,这将完全覆盖旧的用户客户端类。创建用户客户端连接的任何进程都将获得您的客户端,而不是原始客户端。这可能会干扰沙盒应用。

注意3:您可能需要添加一个虚拟的IOResources绑定服务,以便在没有用户客户端的情况下加载kext,因为如果没有任何类的实例没有活动,通常会卸载kexts。

要通过覆盖newUserClient()函数来覆盖用户客户端类(2):

这与上面的工作方式类似,但实际上您是子类的原始服务类并直接覆盖newUserClient。这允许您添加用户客户端(例如,用于不同的type值),而不是替换唯一的现有客户端。您将再次需要用更高分的实现替换原始的IOKitPersonality,但这次您还将IOClass更改为您的类。

这一个的一些进一步限制:

  • 你需要(稳定的)标题来覆盖你所覆盖的类。如果没有ABI保证该课程将来不会改变大小,你需要非常非常谨慎地行事。
  • 原始kext必须设置OSBundleCompatibleVersion,否则你将无法链接它 - 这需要上传到它的构造函数,填写你的子类的vtable等。

我可能不需要指出这一点但是:在执行此操作时通常要格外小心,特别是在覆盖系统关键字时,如果出错,可能会导致操作系统出现故障。我只会做这样的事情作为最后的手段,如果我最终想要做的事情是不可能的任何其他方式。

© www.soinside.com 2019 - 2024. All rights reserved.