
kfd, short for kernel file descriptor, is a project to read and write kernel memory on Apple devices.
Краткое предупреждение: я не собираюсь добавлять офсеты для других устройств и версий iOS.
kfd (сокращение от kernel file descriptor) — это проект для чтения и записи памяти ядра на устройствах Apple. Он использует различные уязвимости, которые можно эксплуатировать для получения висячих PTE — далее это называется примитивом PUAF (сокращение от «physical use-after-free»). Затем он повторно размещает определённые объекты ядра внутри этих физических страниц и управляет ими напрямую из пользовательского пространства через висячие PTE, чтобы получить примитив KRKW (сокращение от «kernel read/write»). Эксплойт-код полностью содержится в библиотеке libkfd, но проект также содержит простые исполняемые обёртки для iOS и macOS. Публичный API библиотеки libkfd довольно мал и интуитивно понятен:
enum puaf_method {
puaf_physpuppet,
puaf_smith,
puaf_landa,
};
enum kread_method {
kread_kqueue_workloop_ctl,
kread_sem_open,
};
enum kwrite_method {
kwrite_dup,
kwrite_sem_open,
};
u64 kopen(u64 puaf_pages, u64 puaf_method, u64 kread_method, u64 kwrite_method);
void kread(u64 kfd, u64 kaddr, void* uaddr, u64 size);
void kwrite(u64 kfd, void* uaddr, u64 kaddr, u64 size);
void kclose(u64 kfd);
Функция kopen() концептуально открывает «файловый дескриптор ядра» и принимает следующие 4 аргумента:
puaf_pages: целевое количество физических страниц с висячими PTE.puaf_method: метод, используемый для получения примитива PUAF, со следующими вариантами:
puaf_physpuppet:
puaf_smith:
puaf_landa:
kread_method: метод, используемый для получения начального примитива kread().kwrite_method: метод, используемый для получения начального примитива .В случае успешного эксплойта kopen() возвращает 64-битный непрозрачный файловый дескриптор. На
практике это просто указатель пользовательского пространства на структуру, необходимую libkfd. Однако,
поскольку к этой структуре не следует обращаться за пределами библиотеки, она возвращается как
непрозрачное целое число. Если эксплойт неуспешен, библиотека выведет сообщение об ошибке,
приостановится на 30 секунд, а затем завершится с кодом состояния 1. Она приостанавливается на 30
секунд, потому что при выходе ядро может уйти в панику для некоторых методов PUAF, требующих очистки
после KRKW (например, puaf_smith).
kread() и kwrite() являются пользовательскими аналогами copyout() и copyin() соответственно.
Обратите внимание, что варианты для kread_method и kwrite_method описаны в отдельном
разборе. Кроме того, начальные примитивы, предоставляемые этими
методами, можно использовать для построения более совершенного примитива KRKW. Наконец, kclose()
просто закрывает файловый дескриптор ядра. Все они принимают непрозрачное целое число, возвращаемое
kopen(), в качестве первого аргумента.
В Xcode откройте корневую папку проекта и подключите ваше iOS-устройство.
В терминале перейдите в корневую папку проекта.
При желании, чтобы увеличить глобальные и попроцессные лимиты файловых дескрипторов, что повысит
частоту успешных запусков, особенно при нескольких последовательных запусках, выполните команду
make s и введите пароль sudo.
make b.make r.make br.В этом README представлен общий обзор проекта kfd. Как только примитив PUAF получен, остальная часть эксплойта становится универсальной. Поэтому я вынес общую часть эксплойтов в отдельный разбор:
Кроме того, я разделил специфичную для уязвимостей часть эксплойтов, используемых для достижения примитива PUAF, на отдельные разборы, перечисленные ниже в хронологическом порядке обнаружения:
Однако обратите внимание, что эти разборы написаны для аудитории, уже знакомой с системой виртуальной памяти XNU.
kwrite()