Гостевая статья MINDSHARE: прогулка по ядру WINDOWS с помощью IDA PYTHON

Когда я посещаю конференции по безопасности, мне нравится говорить с людьми о том, как они усиливают свои собственные усилия по обратному проектированию. Всегда полезно узнать, как другие автоматизируют утомительные задачи. Одна вещь, которая часто удивляет меня, - то, что многие люди, использующие IDA, не используют включенные API, чтобы увеличить их усилия. Чтобы попытаться изменить это, я собираюсь начать делиться некоторыми кодами и продемонстрировать некоторые вещи, которые вы можете выполнить с помощью IDA и Python.

В качестве введения в IDA Python я собираюсь показать, как вы можете перечислять таблицы системных вызовов Windows.

Для тех, кто не знает, все системные вызовы в Windows имеют идентификатор. Этот идентификатор является уникальным значением, которое используется для указания функции, которую вы хотели бы вызвать при выполнении системного вызова. Эти идентификаторы могут сильно различаться в разных версиях Windows, особенно в разных пакетах обновления. Начиная с Windows 10, они могут различаться в зависимости от версии выпуска. Для обычных приложений это не имеет большого значения, так как библиотеки пользовательских полей всегда будут использовать соответствующий идентификатор для вашей системы.

Если вы анализируете эксплойт или пытаетесь сделать системные вызовы самостоятельно, это может быть не так. Как следствие, удобно знать, какие идентификаторы соответствуют каким функциям для данной версии ОС. В течение долгого времени ссылаться на одну из таблиц, которые Mateusz Jurczyk размещает на своем было самым простым способом, но если вы хотите, чтобы версия отсутствовала там, вам нужно знать, как это сделать самостоятельно.
Я быстро объясню, как перечислять таблицы вручную, а затем перейдем к автоматической обработке с помощью Python.

Перечисление таблиц системных вызовов Windows вручную


Существует три важных символа для анализа таблиц системных вызовов: основание таблицы, размер таблицы и количество байтов, которые аргументы принимают в стеке. Для ntoskrnl.exeимен этих символов KiServiceTable, KiServiceLimitи KiArgumentTableсоответственно. Для win32k.sysимен этих символов W32pServiceTable, W32pServiceLimitи W32pArgumentTable. В 32-битных сборках к этим именам символов добавляется знак подчеркивания.

В качестве примера давайте рассмотрим 64-разрядную версию Windows 7. Это из ntoskrnl.exeверсии 6.1.7601.24117.

01-Win7x64-KiServiceLimit.png

Рисунок один - KiServiceLimit

Исходя из этого, мы можем видеть, что существует 401 (0x191) системных вызовов.

image-asset.png

Рисунок два - KiServiceTable

Если мы посмотрим на таблицу на рисунке 2, мы можем вручную сопоставить функции с их идентификаторами. Исходя из того, что мы видим выше, NtMapUserPhysicalPagesScatterимеет идентификатор 0x0000, NtWaitForSingleObject0x0001, NtCallbackReturn0x0002 и т. Д.

Есть два особых случая, с которыми нам нужно разобраться. Если мы посмотрим win32k.sys, идентификатор будет индексом функции в таблице плюс 0x1000. Кроме того, в 64-разрядных сборках для Windows 10 начиная с сборки Windows 1607 необходимо работать по-разному. В этих сборках таблица системных вызовов содержит смещения функций в виде четырехбайтовых значений, а не восьмибайтовых значений.

Это из ntoskrnl.exeверсии 10.0.17134.48:

03-Win10x64-KiServiceTable.png

Рисунок три - KiServiceTable

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

Автоматизация картирования в IDA

Давайте сначала рассмотрим функции IDA, которые нам нужно будет вызвать:
- idaapi.get_imagebase- Эта функция вернет базовый адрес в модуле, на который мы смотрим.
- idc.GetInputFile- Эта функция возвращает имя файла, для которого был загружен IDB.
- idc.BADADDR- Это постоянное значение, которое отображается в -1 как целое число без знака (его также можно использовать для проверки того, находимся ли мы в 32-битном режиме или в 64-битном режиме)
- idc.Name- Эта функция будет возвращать имя заданного адрес.
- idc.LocByName- Обратное значение idc.Name, эта функция будет возвращать адрес данного имени.
- idc.Dword- Эта функция вернет четырехбайтовое значение по заданному адресу.
- idc.Qword- Эта функция вернет восьмибайтовое значение по заданному адресу.
-idautils.DataRefsFrom - Эта функция будет перечислять любые ссылки на данные с данного адреса.

Мы начнем с обеспечением мы рассматриваем как ntoskrnl.exeили win32k.sys:

04-GetInputFile.png

Рисунок четвертый - GetInputFile

Затем мы можем определить, какие имена символов нам нужно использовать. Далее нам нужно проверить, нужно ли нам использовать варианты подчеркивания:

05-LocByName.png

Рисунок 5 - LocByFile

LocByNameвернется, BADADDRесли имя не существует, поэтому мы можем использовать его, чтобы проверить, существует ли имя символа с подчеркиванием или без него.

Теперь, когда у нас есть правильные имена символов, давайте возьмем фактический размер таблицы:

06-Limit.png

Рисунок 6 - Предел

Сначала мы получаем адрес с LocByName, затем мы получаем значение по адресу с Dword.

Последний угловой случай для обработки, 64-разрядный случай Windows 10:

07-DataRefsFrom.png

Рисунок 7 - DataRefsFrom

DataRefsFromбудет перебирать ссылки на данные в основании таблицы. Должен быть один, если только мы не рассмотрим одну из более новых версий Windows 10. При рассмотрении этих более новых сборок Windows 10 нам просто нужно убедиться, что мы добавили базовый адрес образа, который мы будем получить с get_imagebase.
На данный момент все, что нам нужно сделать, это прочитать последовательные значения, начиная с базы таблицы. Мы можем использовать Qwordдля 64-битных версий (за исключением более новых сборок Windows 10) и Dwordдля 32-битных версий.

Вот пример того, что это может распечатать:

08-Results.png

Рисунок 8 - Результаты

Вы можете увидеть полную копию этого кода на нашей странице Github .

Вывод

Время от времени программное обеспечение для обратного проектирования может быть утомительным, но автоматизация задач может убрать часть этой утомительной работы. Надеюсь, вам понравился этот пост в блоге, обратите внимание на будущие посты в блогах по IDA и Python. А до тех пор вы можете найти меня в Twitter по адресу и следить за за новейшими техниками эксплойтов и исправлениями безопасности.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!