Дарвин - использовать расширение ядра в качестве UserClient для другого расширения ядра.

Мне было интересно, можно ли написать расширение ядра, которое будет действовать как UserClient для другого расширения ядра. Обычно мы используем IOConnect на стороне пользователя для доступа к IOUserClient методам расширения ядра. Но такой метод недоступен в Kernel.framework (я полностью понимаю тот факт, что он предназначен для использования именно таким образом). Но мне просто интересно, возможно ли вышесказанное.


person Muntashir Akon    schedule 14.02.2019    source источник


Ответы (1)


Во-первых, когда вы вызываете IOServiceOpen() в пользовательском пространстве, это вызывает IOService::newUserClient() службу, дескриптор которой вы передали. Объект, класс которого создается в результате, зависит от того, переопределяет ли служба этот метод и каким образом.

Есть две основные возможности, которые, в свою очередь, определяют, как вы можете изменить поведение по умолчанию.

  1. Если служба не переопределяет newUserClient или если в некоторых случаях она вызывает реализацию по умолчанию IOService::newUserClient() (например, если она не знает переданный type), определяется класс клиента пользователя. свойством IOUserClient на сервисе.
  2. Если служба действительно переопределяет newUserClient(), класс пользовательского клиента (ов) обычно жестко запрограммирован, в противном случае будет соблюдаться некоторая логика, специфичная для kext.

Чтобы переопределить пользовательский клиентский класс при использовании свойства IOUserClient (1):

  • Создайте kext, содержащий реализацию вашего пользовательского клиентского класса, и убедитесь, что он загружается и т. Д.
  • In the Info.plist, create a copy of the original kext's IOKitPersonality.
    • Increase the IOProbeScore (or add a nonzero IOProbeScore if none was present) in your version of it, so your personality takes precedence over the original kext's.
    • Задайте свойство IOUserClient для пользовательского клиентского класса, который вы хотите использовать.
    • Я не уверен в этом на 100%, но я думаю, что вам нужно изменить CFBundleIdentifier личности на ваш kext, а другой kext указать в OSBundleLibraries. Если это не сработает, попробуйте использовать исходный идентификатор пакета.
    • Если в исходном файле kext Info.plist есть значение для ключа OSBundleReqired, убедитесь, что вы скопировали его и в свой, с тем же значением.

Это все равно может не работать, если служба специально содержит код для предотвращения пользовательских клиентов, о которых она не знает.

Примечание: включение исходного kext в OSBundleLibraries будет работать только в том случае, если исходный файл kext Info.plist содержит значение OSBundleCompatibleVersion. Если этого не произойдет, вы не сможете добавить его в свой OSBundleLibraries, но вы все равно сможете заставить его работать - например, если вы вызываете только virtual функции-члены в старом кексте.

Примечание 2: это, конечно, полностью переопределит старый пользовательский клиентский класс. Любой процесс, создающий клиентское соединение пользователя, получит вашего клиента, а не исходный. Это может мешать работе приложений в песочнице.

Примечание 3: вам может потребоваться добавить фиктивную службу с привязкой к IOResources, чтобы ваш kext оставался загруженным, пока нет пользовательских клиентов, поскольку обычно kexts выгружаются, если нет активных экземпляров любого из их классов.

Чтобы переопределить класс клиента пользователя путем переопределения функции newUserClient() (2):

Это работает аналогично описанному выше, но вы фактически подклассифицируете исходный класс обслуживания и напрямую переопределяете newUserClient. Это позволяет вам добавлять клиентов пользователей (например, для другого значения type), а не заменять единственный существующий. Вам снова нужно будет заменить исходный IOKitPersonality на реализацию с более высокой оценкой, но на этот раз вы также измените IOClass на свой класс.

Некоторые дополнительные ограничения в этом:

  • Вам понадобятся (стабильные) заголовки для класса, который вы переопределяете. Если ABI не гарантирует, что класс не изменит размер в будущем, вам нужно действовать очень, очень осторожно.
  • Исходный kext должен иметь OSBundleCompatibleVersion установленный, иначе вы не сможете установить с ним ссылку - это необходимо для вызова его конструктора, заполнения vtable вашего подкласса и т. Д.

Мне, вероятно, не нужно указывать на это, но: как правило, будьте особенно осторожны при этом, особенно при переопределении системных ключей, вы можете вызвать сбой в работе ОС, если сделаете это неправильно. Я бы только сделайте что-то подобное в крайнем случае, если то, что я в конечном итоге пытаюсь сделать, невозможно по-другому.

person pmdj    schedule 14.02.2019