Часть 59
Last updated
Was this helpful?
Last updated
Was this helpful?
Давайте рассмотрим ARBITRARY OVERWRITE (записать то, что мы хотим туда куда мы хотим) того же самого уязвимого драйвера. Конечно, я хочу уточнить, что это старый метод, который работает только на WINDOWS XP и WINDOWS 7, и в этом случае только для машин x86. НА МАШИНАХ С WINDOWS 7 64 БИТ ЭТО НЕ БУДЕТ РАБОТАТЬ. По крайней мере если не адаптировать немного эксплоит. Мы должны хорошо проверить некоторые значения которые не равны.
Наша цель - это 32-х битная WINDOWS 7.
Но всё равно это нам понадобиться для того, чтобы свыкнуться с CTYPES, которые являются немного сложными и чтобы продвигаться вперед понемногу.
В диспетчере, который обрабатывает различные IOCTL коды. Мы видим, что есть один, который помечен как ARBITRARY OVERWRITE, поэтому мы отмечаем его. Давайте сначала посмотрим, что значение IOCTL приносит нас сюда.
Мы видим, что программа вычитает из EAX константу 4 дважды и до того, как она вычитает значение 0x222003.
Поэтому с этим IOCTL программа приходит к блоку, который нам нужен из этой уязвимости, потому что:
И если результат равен нулю, программа переходит в этот блок.
Хорошо. Мы здесь. Давайте посмотрим на уязвимость.
Напомним, что в IRP + 0x60 находится указатель на структуру _IO_STACK_LOCATION, это было 0x40 из TAIL в структуре IRP, а внутри TAIL по смещению 0x20 есть указатель на CURENTSTACKLOCATION.
Поэтому, 0x60 является смещением CURENTSTACKLOCATION, которое имеет тип _IO_STACK_LOCATION.
Я нажимаю T. Я вижу поле и оттуда программа читает IOCTL код.
Программа передаёт два аргумента. Указатель на IRP в регистре EDI как первый и указатель на структуру _IO_STACK_LOCATION.
Здесь в регистр ECX помещается указатель на _IO_STACK_LOCATION.
Мы уже видели, что PARAMETERS менялись в зависимости от случая, поскольку, когда вызывается DEVICEIOCONTROL, это
По смещению 0x10 от начала (помните, что вам нужно добавить 0x4 к PARAMETERS) для случая DEVICEIOCONTROL - это поле TYPE3INPUTBUFFER.
Здесь появляются четыре аргумента, которые передаются в функцию DEVICEIOCONTROL.
Поэтому, это наш входной буфер, который мы передали в функцию DEVICEIOCONTROL.
Мы видим, что в регистр ESI помещается адрес нашего буфера, который здесь называется USERWRITEWHATWHERE и печатается его адрес.
Затем мы видим, что программа читает содержимое ESI и из ESI + 4 и печатает свои адреса, что заставляет нас думать, что это структура из двух указателей. Здесь нам говорится, что её размер равен 8.
Поэтому, мы будем создавать структуру из 8 байтов. Мы видим, что есть два поля: WHAT и WHERE, и которые оба являются указателями, поэтому в 32 битных системах они будут по 4 байта каждый.
Поэтому здесь программа печатает значения WHAT и WHERE.
Здесь мы видим уязвимую часть драйвера.
Регистр EDI - это WHAT, поэтому он должен быть указателем, поскольку он ищет содержимое [EDI] и записывает его в содержимое WHERE в [EBX].
Поэтому WHAT должен быть указателем на указатель на наш код и в WHERE, мы должны искать таблицу для записи (возможно, непосредственный CALL, чтобы мы записали указатель на наш код и в конечном итоге перешли на него, чтобы выполнить его.)
Мы будем использовать старый метод таблицы HAL. (Он не работает в системах с защитой INTEL SMEP, поэтому в WINDOWS XP и 7 он по-прежнему работает)
Intel CPU feature: Supervisor Mode Execution Protection (SMEP). This feature is enabled by toggling a bit in the cr4 register, and the result is the CPU will generate a fault whenever ring0 attempts to execute code from a page marked with the user bit.
Другими словами, если вы переходите из ядра, чтобы выполнить страницу, помеченную как принадлежащую режиму USER, это дает исключение. Я избегаю выполнения, как в методе, который мы сейчас увидим.
Также мы можем писать в KERNEL куда захотим. Вы можете отключить удачно навыками и чем-то еще эти защиты. Пока мы сконцентрируемся на старом способе эксплуатации, который работает для WINDOWS XP и WINDOWS 7 для 32х битных систем, и также может работать в процессорах, которые не имеют SMEP в других системах.
http://poppopret.blogspot.com.ar/2011/07/windows-kernel-exploitation-basics-part.html
Этот метод основывается на таблице HAL DISPATCH.
Хорошо. Существует функция, импортированная из NTDLL под названием NTQUERYINTERVALPROFILE. Eсли я открою в другой IDA NTDLL.DLL 32 бита, я увижу функции, которые экспортируются, которые есть здесь.
Эта функция, которая может быть вызвана из пользовательского режима, поступает в ядро.
К функции NT!KEQUERYINTERVALPROFILE
Затем следуйте сюда.
И программа переходит на адрес KERNEL, который находится в таблице HAL DISPATCH + 4.
Метод заключается в том, что, поскольку из режима пользователя мы не можем записать эту таблицу. Уязвимость в ядре позволяет нам писать туда, куда мы хотим, чтобы адрес для записи был содержимым NT!HALDISPATCHTABLE + 0x4, и мы должны сделать это с указателем на буфер с нашим кодом.
После этого мы можем сделать вызов когда хотим, так функция может вызваться от из режима пользователя, поэтому, сделав вызов, как правило, из нашего скрипта, в конце кода, программа придет сюда.
И программа будет переходить на код в отсутствие SMEP, поскольку не проверяется, что страница, на которую переходит программа, не является ядром, а помечена как страница пользовательского режима.
Если SMEP был активирован, генерируется исключение, и программа не будет переходить на наш код.
Я прикрепляю скрипт, для тех, кто хочет его попробовать. Он довольно длинный. Поэтому мы объясним его в следующей части. Помните, что он работает только в 32-битной целевой машине WINDOWS 7.
Автор оригинального текста — Рикардо Нарваха.
Перевод и адаптация на русский язык — Яша Яшечкин.
Перевод специально для форума системного и низкоуровневого программирования - WASM.IN
05.12.2018