
фреймворк для перехвата функций ядра iOS на устройствах, поддерживающих checkra1n

Вывод из журнала ядра после компиляции и запуска example/open1_hook.c
xnuspy — это модуль pongoOS, который устанавливает новый системный вызов xnuspy_ctl, позволяющий перехватывать функции ядра из пользовательского пространства. Поддерживаются iOS 13.x, iOS 14.x и iOS 15.x на checkra1n 0.12.2 и выше. Устройства с 4K не поддерживаются.
Этот модуль полностью нейтрализует KTRR/KPP и позволяет создавать RWX-память внутри EL1. Не используйте это на вашем основном устройстве.
Требуется libusb: brew install libusb
Выполните make в корневом каталоге. Будут собраны загрузчик и модуль.
Добавьте их перед make.
XNUSPY_DEBUG=1
kprintf).XNUSPY_SERIAL=1
IOLog.XNUSPY_LEAKED_PAGE_LIMIT=n
64. Дополнительную информацию можно найти в разделе Отладка паник ядра.XNUSPY_TRAMP_PAGES=n
XNUSPY_DEBUG и XNUSPY_SERIAL не зависят друг от друга.
После сборки всего, заставьте checkra1n загрузить ваше устройство в оболочку pongo: /Applications/checkra1n.app/Contents/MacOS/checkra1n -p
В том же каталоге, где вы собрали загрузчик и модуль, выполните loader/loader module/xnuspy. После этого xnuspy выполнит свою работу, и через несколько секунд ваше устройство загрузится. loader подождет еще несколько секунд после выдачи xnuspy-getkernelv на случай, если необходимо эксплуатировать SEPROM.
Иногда несколько моих телефонов зависали на этапе "Загрузка" после выполнения KPF от checkra1n. Я еще не выяснил причину, но если это произойдет, попробуйте снова. Также, если устройство зависает после bootx, попробуйте снова. Наконец, пометка скомпилированного кода xnuspy_ctl как исполняемого на моем iPhone X под iOS 13.3.1 работает с перебоями, но на других телефонах удается в 100% случаев. Если при выполнении вашей программы перехвата возникает паника с ошибкой выборки инструкции ядра, попробуйте снова.
xnuspy изменяет системный вызов enosys, чтобы он указывал на xnuspy_ctl_tramp. Это небольшой трамплин, который помечает скомпилированный код xnuspy_ctl как исполняемый и переходит к нему. Реализацию xnuspy_ctl можно найти в module/el1/xnuspy_ctl/xnuspy_ctl.c, а примеры — в каталоге example.
Внутри include/xnuspy/ находится xnuspy_ctl.h — заголовочный файл, определяющий константы для xnuspy_ctl. Он предназначен для включения во все программы, которые перехватывают функции ядра.
Вы можете использовать sysctlbyname, чтобы узнать, какой системный вызов был изменен:```
size_t oldlen = sizeof(long);
long SYS_xnuspy_ctl = 0;
sysctlbyname("kern.xnuspy_ctl_callnum", &SYS_xnuspy_ctl, &oldlen, NULL, 0);
Этот системный вызов принимает четыре аргумента: `flavor`, `arg1`, `arg2` и `arg3`.
Тип операции может быть `XNUSPY_CHECK_IF_PATCHED`, `XNUSPY_INSTALL_HOOK`,
`XNUSPY_REGISTER_DEATH_CALLBACK`, `XNUSPY_CALL_HOOKME`, `XNUSPY_CACHE_READ`,
`XNUSPY_KREAD`, `XNUSPY_KWRITE` или `XNUSPY_GET_CURRENT_THREAD`.
Значение следующих трёх аргументов зависит от типа операции.
## `XNUSPY_CHECK_IF_PATCHED`
Этот тип существует, чтобы вы могли проверить, присутствует ли `xnuspy_ctl`. Вызов с этим
типом заставит его вернуть `999`. Значения остальных аргументов
игнорируются.
## `XNUSPY_INSTALL_HOOK`
Я спроектировал этот тип, чтобы он соответствовал API [`MSHookFunction`](http://www.cydiasubstrate.com/api/c/MSHookFunction/).
`arg1` — это *НЕСМЕЩЁННЫЙ* адрес функции ядра, которую вы хотите перехватить. Если вы
укажете смещённый адрес, скорее всего произойдёт паника. `arg2` — это указатель на вашу
ABI-совместимую функцию-замену. `arg3` — это указатель для `xnuspy_ctl`,
чтобы `copyout` (скопировать наружу) адрес трамплина, представляющего исходную функцию
ядра. Он может быть `NULL`, если вы не собираетесь вызывать исходную.
## `XNUSPY_REGISTER_DEATH_CALLBACK`
Этот тип позволяет зарегистрировать опциональный «callback смерти» — функцию, которую xnuspy
вызовет при завершении вашей программы-перехватчика. Он даёт вам возможность очистить всё,
что вы создали в своих перехватчиках ядра. Если вы создавали какие-либо потоки ядра,
вы должны сообщить им о завершении в этой функции.
Ваш callback не вызывается асинхронно, поэтому если вы заблокируете выполнение, вы помешаете
потоку сборки мусора xnuspy выполниться.
`arg1` — это указатель на вашу callback-функцию. Значения остальных аргументов
игнорируются.
## `XNUSPY_CALL_HOOKME`
`hookme` — это небольшая заглушка на ассемблере, которую xnuspy экспортирует через кеш xnuspy
для вашего перехвата. Вызов `xnuspy_ctl` с этим типом приведёт к вызову `hookme`,
предоставляя вам простой способ получить выполнение кода ядра без необходимости
перехватывать реальную функцию ядра.
`arg1` — это аргумент, который будет передан `hookme` при его вызове.
Он может быть `NULL`.
## `XNUSPY_CACHE_READ`
Этот тип даёт вам возможность читать из кеша xnuspy. Он содержит много полезных
вещей, таких как `kprintf`, `current_proc`, `kernel_thread_start`, некоторые функции libc,
и сдвиг ядра, чтобы вам не пришлось искать их самостоятельно. Полный список
идентификаторов кеша смотрите в `example/xnuspy_ctl.h`.
`arg1` — это один из идентификаторов кеша, определённых в `xnuspy_ctl.h`, а `arg2` — это
указатель для `xnuspy_ctl`, чтобы `copyout` (скопировать наружу) адрес или значение того, что вы запросили.
Значения остальных аргументов игнорируются.
## `XNUSPY_KREAD`
Этот тип даёт вам простой способ читать память ядра из пользовательского пространства без
tfp0.
`arg1` — это виртуальный адрес ядра, `arg2` — адрес буфера пользовательского пространства,
а `arg3` — размер этого буфера пользовательского пространства. `arg3` байтов будет записано
из `arg1` в `arg2`.
## `XNUSPY_KWRITE`
Этот тип даёт вам простой способ записывать в память ядра из пользовательского пространства без
tfp0.
`arg1` — это виртуальный адрес ядра, `arg2` — адрес буфера пользовательского пространства,
а `arg3` — размер этого буфера пользовательского пространства. `arg3` байтов будет записано
из `arg2` в `arg1`.
## `XNUSPY_GET_CURRENT_THREAD`
Этот тип предоставляет пользовательскому пространству адрес ядра вызывающего потока.
`arg1` — это указатель для `xnuspy_ctl`, чтобы `copyout` (скопировать наружу) возвращаемое значение
`current_thread`. Значения остальных аргументов игнорируются.
### Ошибки
Для всех типов, кроме `XNUSPY_CHECK_IF_PATCHED`, в случае успеха возвращается `0`.
При ошибке возвращается `-1` и устанавливается `errno`. `XNUSPY_CHECK_IF_PATCHED`
не возвращает никаких ошибок. Для преобразования `kern_return_t` в соответствующий `errno`
используется `mach_to_bsd_errno` из XNU.