macOS XPC
Basic Information
XPC, що означає XNU (ядро, яке використовується в macOS) міжпроцесорна комунікація, є фреймворком для комунікації між процесами на macOS та iOS. XPC надає механізм для виконання безпечних, асинхронних викликів методів між різними процесами в системі. Це частина безпекової парадигми Apple, що дозволяє створювати програми з розділеними привілеями, де кожен компонент працює з тільки тими правами, які йому потрібні для виконання своєї роботи, тим самим обмежуючи потенційні збитки від скомпрометованого процесу.
XPC використовує форму міжпроцесорної комунікації (IPC), яка є набором методів для різних програм, що працюють на одній системі, для обміну даними.
Основні переваги XPC включають:
Безпека: Розділяючи роботу на різні процеси, кожному процесу можуть бути надані тільки ті права, які йому потрібні. Це означає, що навіть якщо процес буде скомпрометований, його можливості завдати шкоди будуть обмежені.
Стабільність: XPC допомагає ізолювати збої до компонента, в якому вони відбуваються. Якщо процес зазнає збою, його можна перезапустити без впливу на решту системи.
Продуктивність: XPC дозволяє легко виконувати кілька завдань одночасно в різних процесах.
Єдиний недолік полягає в тому, що розділення програми на кілька процесів, які спілкуються через XPC, є менш ефективним. Але в сучасних системах це майже не помітно, а переваги переважають.
Application Specific XPC services
XPC компоненти програми знаходяться всередині самої програми. Наприклад, у Safari ви можете знайти їх у /Applications/Safari.app/Contents/XPCServices
. Вони мають розширення .xpc
(як com.apple.Safari.SandboxBroker.xpc
) і також є пакетами з основним бінарним файлом всередині: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/MacOS/com.apple.Safari.SandboxBroker
та Info.plist: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/Info.plist
Як ви, можливо, думаєте, XPC компонент матиме різні права та привілеї в порівнянні з іншими XPC компонентами або основним бінарним файлом програми. ОКРІМ випадку, якщо XPC служба налаштована з JoinExistingSession встановленим на “True” у її Info.plist файлі. У цьому випадку XPC служба буде працювати в тій же безпековій сесії, що й програма, яка її викликала.
XPC служби запускаються за допомогою launchd за потреби і закриваються після завершення всіх завдань, щоб звільнити системні ресурси. Специфічні для програми XPC компоненти можуть використовуватися тільки самою програмою, тим самим зменшуючи ризик, пов'язаний з потенційними вразливостями.
System Wide XPC services
Системні XPC служби доступні всім користувачам. Ці служби, або launchd, або Mach-типу, повинні бути визначені в plist файлах, розташованих у вказаних каталогах, таких як /System/Library/LaunchDaemons
, /Library/LaunchDaemons
, /System/Library/LaunchAgents
, або /Library/LaunchAgents
.
Ці plist файли матимуть ключ під назвою MachServices
з назвою служби та ключ під назвою Program
з шляхом до бінарного файлу:
Ті, що в LaunchDameons
, виконуються від імені root. Тому, якщо неправа процес може спілкуватися з одним з них, це може дозволити ескалацію привілеїв.
XPC Об'єкти
xpc_object_t
Кожне XPC повідомлення є об'єктом словника, який спрощує серіалізацію та десеріалізацію. Більше того, libxpc.dylib
оголошує більшість типів даних, тому можливо перевірити, що отримані дані мають очікуваний тип. У C API кожен об'єкт є xpc_object_t
(і його тип можна перевірити за допомогою xpc_get_type(object)
).
Більше того, функцію xpc_copy_description(object)
можна використовувати для отримання рядкового представлення об'єкта, що може бути корисним для налагодження.
Ці об'єкти також мають деякі методи для виклику, такі як xpc_<object>_copy
, xpc_<object>_equal
, xpc_<object>_hash
, xpc_<object>_serialize
, xpc_<object>_deserialize
...
xpc_object_t
створюються за допомогою виклику функції xpc_<objetType>_create
, яка внутрішньо викликає _xpc_base_create(Class, Size)
, де вказується тип класу об'єкта (один з XPC_TYPE_*
) і його розмір (додаткові 40B будуть додані до розміру для метаданих). Це означає, що дані об'єкта почнуться з офсету 40B.
Отже, xpc_<objectType>_t
є своєрідним підкласом xpc_object_t
, який буде підкласом os_object_t*
.
Зверніть увагу, що саме розробник повинен використовувати xpc_dictionary_[get/set]_<objectType>
, щоб отримати або встановити тип і реальне значення ключа.
xpc_pipe
xpc_pipe
— це FIFO труба, яку процеси можуть використовувати для спілкування (спілкування використовує повідомлення Mach).
Можливо створити XPC сервер, викликавши xpc_pipe_create()
або xpc_pipe_create_from_port()
, щоб створити його, використовуючи конкретний Mach порт. Потім, щоб отримувати повідомлення, можна викликати xpc_pipe_receive
і xpc_pipe_try_receive
.
Зверніть увагу, що об'єкт xpc_pipe
є xpc_object_t
з інформацією в його структурі про два Mach порти, що використовуються, і ім'я (якщо є). Ім'я, наприклад, демон secinitd
у його plist /System/Library/LaunchDaemons/com.apple.secinitd.plist
налаштовує трубу, названу com.apple.secinitd
.
Приклад xpc_pipe
— це bootstrap pipe, створена launchd
, що робить можливим спільне використання Mach портів.
NSXPC*
Це об'єкти високого рівня Objective-C, які дозволяють абстракцію XPC з'єднань. Більше того, їх легше налагоджувати за допомогою DTrace, ніж попередні.
GCD Queues
XPC використовує GCD для передачі повідомлень, більше того, він генерує певні черги диспетчеризації, такі як xpc.transactionq
, xpc.io
, xpc-events.add-listenerq
, xpc.service-instance
...
XPC Сервіси
Це пакети з розширенням .xpc
, розташовані всередині папки XPCServices
інших проектів, і в Info.plist
у них є CFBundlePackageType
, встановлений на XPC!
.
Цей файл має інші ключі конфігурації, такі як ServiceType
, який може бути Application, User, System або _SandboxProfile
, який може визначати пісочницю, або _AllowedClients
, який може вказувати права або ID, необхідні для контакту з сервісом. Ці та інші параметри конфігурації будуть корисні для налаштування сервісу під час запуску.
Запуск Сервісу
Додаток намагається підключитися до XPC сервісу, використовуючи xpc_connection_create_mach_service
, потім launchd знаходить демон і запускає xpcproxy
. xpcproxy
забезпечує виконання налаштованих обмежень і створює сервіс з наданими FDs і Mach портами.
Для покращення швидкості пошуку XPC сервісу використовується кеш.
Можливо відстежувати дії xpcproxy
, використовуючи:
The XPC library використовує kdebug
для логування дій, викликаючи xpc_ktrace_pid0
та xpc_ktrace_pid1
. Коди, які він використовує, не задокументовані, тому їх потрібно додати до /usr/share/misc/trace.codes
. Вони мають префікс 0x29
, і, наприклад, один з них 0x29000004
: XPC_serializer_pack
.
Утиліта xpcproxy
використовує префікс 0x22
, наприклад: 0x2200001c: xpcproxy:will_do_preexec
.
XPC Повідомлення подій
Застосунки можуть підписуватися на різні події повідомлення, що дозволяє їм ініціюватися за запитом, коли такі події відбуваються. Налаштування для цих сервісів виконується в файлах plist launchd, розташованих у тих же каталогах, що й попередні, і містять додатковий ключ LaunchEvent
.
XPC Перевірка процесу підключення
Коли процес намагається викликати метод через XPC-з'єднання, XPC-сервіс повинен перевірити, чи дозволено цьому процесу підключатися. Ось поширені способи перевірки цього та поширені помилки:
XPC Авторизація
Apple також дозволяє додаткам налаштовувати деякі права та способи їх отримання, тому якщо викликаючий процес має їх, йому буде дозволено викликати метод з XPC-сервісу:
XPC Сніфер
Щоб перехоплювати XPC повідомлення, ви можете використовувати xpcspy, який використовує Frida.
Іншим можливим інструментом для використання є XPoCe2.
Приклад коду C для XPC зв'язку
XPC Communication Objective-C Code Example
Клієнт всередині коду Dylb
Remote XPC
Ця функціональність, надана RemoteXPC.framework
(з libxpc
), дозволяє спілкуватися через XPC між різними хостами.
Служби, які підтримують віддалений XPC, матимуть у своєму plist ключ UsesRemoteXPC, як це відбувається у випадку з /System/Library/LaunchDaemons/com.apple.SubmitDiagInfo.plist
. Однак, хоча служба буде зареєстрована з launchd
, саме UserEventAgent
з плагінами com.apple.remoted.plugin
та com.apple.remoteservicediscovery.events.plugin
надає цю функціональність.
Більше того, RemoteServiceDiscovery.framework
дозволяє отримувати інформацію з com.apple.remoted.plugin
, відкриваючи функції, такі як get_device
, get_unique_device
, connect
...
Як тільки використовується connect і збирається сокет fd
служби, можна використовувати клас remote_xpc_connection_*
.
Можна отримати інформацію про віддалені служби, використовуючи інструмент cli /usr/libexec/remotectl
з параметрами, такими як:
Зв'язок між BridgeOS та хостом відбувається через спеціальний інтерфейс IPv6. MultiverseSupport.framework
дозволяє встановлювати сокети, fd
яких буде використовуватися для зв'язку.
Можна знайти ці комунікації, використовуючи netstat
, nettop
або відкриту альтернативу, netbottom
.
Last updated