Когда я посещаю конференции по безопасности, мне нравится говорить с людьми о том, как они усиливают свои собственные усилия по обратному проектированию. Всегда полезно узнать, как другие автоматизируют утомительные задачи. Одна вещь, которая часто удивляет меня, - то, что многие люди, использующие 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.
Рисунок один - KiServiceLimit
Исходя из этого, мы можем видеть, что существует 401 (0x191) системных вызовов.
Рисунок два - KiServiceTable
Если мы посмотрим на таблицу на рисунке 2, мы можем вручную сопоставить функции с их идентификаторами. Исходя из того, что мы видим выше, NtMapUserPhysicalPagesScatterимеет идентификатор 0x0000, NtWaitForSingleObject0x0001, NtCallbackReturn0x0002 и т. Д.
Есть два особых случая, с которыми нам нужно разобраться. Если мы посмотрим win32k.sys, идентификатор будет индексом функции в таблице плюс 0x1000. Кроме того, в 64-разрядных сборках для Windows 10 начиная с сборки Windows 1607 необходимо работать по-разному. В этих сборках таблица системных вызовов содержит смещения функций в виде четырехбайтовых значений, а не восьмибайтовых значений.
Это из ntoskrnl.exeверсии 10.0.17134.48:
Рисунок три - 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:
Рисунок четвертый - GetInputFile
Затем мы можем определить, какие имена символов нам нужно использовать. Далее нам нужно проверить, нужно ли нам использовать варианты подчеркивания:
Рисунок 5 - LocByFile
LocByNameвернется, BADADDRесли имя не существует, поэтому мы можем использовать его, чтобы проверить, существует ли имя символа с подчеркиванием или без него.
Теперь, когда у нас есть правильные имена символов, давайте возьмем фактический размер таблицы:
Рисунок 6 - Предел
Сначала мы получаем адрес с LocByName, затем мы получаем значение по адресу с Dword.
Последний угловой случай для обработки, 64-разрядный случай Windows 10:
Рисунок 7 - DataRefsFrom
DataRefsFromбудет перебирать ссылки на данные в основании таблицы. Должен быть один, если только мы не рассмотрим одну из более новых версий Windows 10. При рассмотрении этих более новых сборок Windows 10 нам просто нужно убедиться, что мы добавили базовый адрес образа, который мы будем получить с get_imagebase.
На данный момент все, что нам нужно сделать, это прочитать последовательные значения, начиная с базы таблицы. Мы можем использовать Qwordдля 64-битных версий (за исключением более новых сборок Windows 10) и Dwordдля 32-битных версий.
Вот пример того, что это может распечатать:
Рисунок 8 - Результаты
Вы можете увидеть полную копию этого кода на нашей странице Github
Вывод
Время от времени программное обеспечение для обратного проектирования может быть утомительным, но автоматизация задач может убрать часть этой утомительной работы. Надеюсь, вам понравился этот пост в блоге, обратите внимание на будущие посты в блогах по IDA и Python. А до тех пор вы можете найти меня в Twitter по адресу
В качестве введения в 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.
Рисунок один - KiServiceLimit
Исходя из этого, мы можем видеть, что существует 401 (0x191) системных вызовов.
Рисунок два - KiServiceTable
Если мы посмотрим на таблицу на рисунке 2, мы можем вручную сопоставить функции с их идентификаторами. Исходя из того, что мы видим выше, NtMapUserPhysicalPagesScatterимеет идентификатор 0x0000, NtWaitForSingleObject0x0001, NtCallbackReturn0x0002 и т. Д.
Есть два особых случая, с которыми нам нужно разобраться. Если мы посмотрим win32k.sys, идентификатор будет индексом функции в таблице плюс 0x1000. Кроме того, в 64-разрядных сборках для Windows 10 начиная с сборки Windows 1607 необходимо работать по-разному. В этих сборках таблица системных вызовов содержит смещения функций в виде четырехбайтовых значений, а не восьмибайтовых значений.
Это из ntoskrnl.exeверсии 10.0.17134.48:
Рисунок три - 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:
Рисунок четвертый - GetInputFile
Затем мы можем определить, какие имена символов нам нужно использовать. Далее нам нужно проверить, нужно ли нам использовать варианты подчеркивания:
Рисунок 5 - LocByFile
LocByNameвернется, BADADDRесли имя не существует, поэтому мы можем использовать его, чтобы проверить, существует ли имя символа с подчеркиванием или без него.
Теперь, когда у нас есть правильные имена символов, давайте возьмем фактический размер таблицы:
Рисунок 6 - Предел
Сначала мы получаем адрес с LocByName, затем мы получаем значение по адресу с Dword.
Последний угловой случай для обработки, 64-разрядный случай Windows 10:
Рисунок 7 - DataRefsFrom
DataRefsFromбудет перебирать ссылки на данные в основании таблицы. Должен быть один, если только мы не рассмотрим одну из более новых версий Windows 10. При рассмотрении этих более новых сборок Windows 10 нам просто нужно убедиться, что мы добавили базовый адрес образа, который мы будем получить с get_imagebase.
На данный момент все, что нам нужно сделать, это прочитать последовательные значения, начиная с базы таблицы. Мы можем использовать Qwordдля 64-битных версий (за исключением более новых сборок Windows 10) и Dwordдля 32-битных версий.
Вот пример того, что это может распечатать:
Рисунок 8 - Результаты
Вы можете увидеть полную копию этого кода на нашей странице Github
Ссылка скрыта от гостей
.Вывод
Время от времени программное обеспечение для обратного проектирования может быть утомительным, но автоматизация задач может убрать часть этой утомительной работы. Надеюсь, вам понравился этот пост в блоге, обратите внимание на будущие посты в блогах по IDA и Python. А до тех пор вы можете найти меня в Twitter по адресу
Ссылка скрыта от гостей
и следить за
Ссылка скрыта от гостей
за новейшими техниками эксплойтов и исправлениями безопасности.