Darwin - использовать расширение ядра в качестве UserClient для другого расширения ядра - PullRequest
0 голосов
/ 14 февраля 2019

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

1 Ответ

0 голосов
/ 14 февраля 2019

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

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

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

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

  • Создать kext, содержащий реализацию пользовательского клиентского класса, иубедитесь, что это лоаdable и т. д.
  • В Info.plist создайте копию оригинального kext's IOKitPersonality.
    • Увеличьте IOProbeScore (или добавьте ненулевой IOProbeScore, если его не было) в вашей версии, так что ваша личность будет иметь приоритет над исходным kext.
    • Установите IOUserClient свойство пользовательского клиентского класса, который вы хотите использовать.
    • Я не уверен на 100% в этом, но я думаю, что вам нужно изменить CFBundleIdentifier личности на ваш kext и перечислите другой kext в OSBundleLibraries.Если это не сработает, попробуйте использовать исходный идентификатор пакета.
    • Если в исходном kext-файле Info.plist есть значение для ключа OSBundleReqired, убедитесь, что вы скопировали его и себе, сто же значение .

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

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

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

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

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

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

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

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

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

...