Гостевая статья MINDSHARE: variant hunting c IDA python

Variant hunting - полезный навык, и также может быть полезно найти способы увеличения поисков. У меня были некоторые очень грубые заметки о чем-то, что я попробовал, когда искал вариант уязвимости Mobile Pwn2Own, и понял, что это было бы идеальным введением в поиск вариантов с IDA Python, так как он очень минимален. Первоначальная уязвимость была представлена как командой 360 Security Team, так и Tencent Keen Security Lab и идентифицирована и . Оба идентифицированы CVE-2017-7171, потому что Apple после конкурса определила, что они имеют одну и ту же основную причину.
\
Суть этой уязвимости заключается в использовании службы которой одна из функций ожидает от отправителя сложных данных, но не проверяет, установлен ли во входном сообщении MACH_MSGH_BITS_COMPLEXбит (0x80000000) в msgh_bitsполе. Правильный поиск вариантов этой уязвимости будет включать отслеживание входных аргументов, которые следуют за mach_msgаргументом, поиск разыменования, эквивалентного смещению msgh_bitsполя, и, наконец, проверку его сравнения с 0x80000000. Это выполнимо, но давайте посмотрим, есть ли более простой способ.

Вот пример правильно обработанной функции:

1 (2).png


Вот еще одна правильно обработанная функция:

2 (2).png



Это двоичный файл ARM, но мы можем сосредоточиться только на последней инструкции в каждом изображении: TBZ - это тестовый бит и ветвь, если ноль, а TBNZ - тестовый бит и ветвь, если не ноль. Первый аргумент - это значение для тестирования, второй - битовая позиция, а третий аргумент - цель перехода. Так 0x1fкак 31, эти два кода операции - то, как этот двоичный код проверяет, установлен ли MACH_MSGH_BITS_COMPLEXбит в msgh_bitsполе.

Быстрый, но простой способ найти это - найти любой код операции TBZ / TBNZ 0x1fв качестве второго операнда. Есть много потенциальных проблем с этим подходом, но как наивный старт, он будет работать. Мы могли бы ограничить наше пространство поиска одним из первых нескольких основных блоков в функции, но это усложняется, и в нескольких тестах я пропустил кое-что из того, что мне было нужно, поэтому я пропустил это. Я обычно пытаюсь начать с более быстрого, хотя и более слабого подхода, прежде чем перейти к чему-то более тяжелому.

План игры

Наш первоначальный подход будет состоять в том, чтобы просмотреть все обработчики функций Маха для этой конкретной службы и проверить код операции TBZ / TBNZ, где 0x1fнаходится второй операнд, а затем мы вручную проверим совпадения.

Во-первых, давайте разберем все функции, которые нам понадобятся:

- filter

Это встроенный Python, и он принимает два аргумента: функцию и итерацию. Он вернет итерируемое, содержащее только элементы, для которых функция возвращает истинное значение.

Использование этой функции эквивалентно выполнению:

3 (3).png


- idc.GetMnem

Этот IDA API берет адрес (ea_t) и возвращает мнемонику кода операции для этого адреса. Использовать его считается плохой практикой, так как DecodeInstructionв большинстве случаев он более устойчивый. Мы используем его исключительно потому, что мы можем проверить две разные инструкции одновременно.

- idc.GetOperandValue

Этот IDA API принимает адрес (ea_t) и индекс на основе 0 и возвращает значение соответствующего операнда. Это также считается плохой практикой, поскольку значение здесь будет варьироваться в зависимости от типа операнда.

- idc.Name

Этот IDA API берет адрес (ea_t) и возвращает имя, если оно есть, связанное с ним. Теперь он возвращает, ''если имя отсутствует, однако в более старых версиях IDA он возвращался None. Поэтому я часто делаю что-то вроде того, (idc.Name(x) or '')чтобы убедиться, что имею дело со строкой.

- idautils.Functions

Этот IDA API перечисляет все известные функции в IDB.

- idc.NextHead

Этот IDA API возвращает следующий определенный элемент после указанного адреса. Мы не будем использовать его напрямую, но от этого зависит один из моих вспомогательных методов.

- idautils.Chunks

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

- glitch_helpers._get_function_instr_iter

Это личный вспомогательный метод, который принимает один аргумент: адрес функции. Он вернет итерацию, которая даст все адреса для конкретной функции. Зависит от того, idautils.Chunksчтобы получить основные блоки функции и idc.NextHeadвыполнять итерации по инструкциям в каждом базовом блоке.

- glitch_helpers.set_result_iterator

Это личный вспомогательный метод, который принимает два аргумента: функцию и итерацию. Вы выполняете итерацию вперед и назад с помощью Ctrl-Shift-N и Ctrl-Shift-P соответственно. Каждый раз, когда вы выполняете итерацию, функция вызывается для всех возвращаемых итераций.

- pgo

Это персональный вспомогательный метод, который принимает один аргумент: адрес для перехода к нему будет напечатан.

Собирая все вместе, вот одна строчка, которую я использовал:

4 (1).png


Это определенно немного чудовищно, поэтому давайте рассмотрим его по одному. Начнем с того, что переписать его, чтобы он не был однострочным:

5 (1).png



instr_checks_COMPLEX Функция принимает адрес и сначала проверяет , чтобы увидеть , если опкод по адресу является либо TBNZили , TBZа затем проверяет , является ли второй операнд 0x1f. Это скажет нам, если конкретная инструкция отвечает за выполнение сравнения 0x80000000.

func_checks_COMPLEX Функция принимает адрес, считающийся начало функции, и перебирает каждую команду в этой функции. Если какая-либо из инструкций выполняет проверку, функция возвращает результат, Falseуказывая, что мы не заинтересованы в этой функции.

searchspace Фильтр заполняются с использованием быстрого и грязным способом найти все функции , которые я переименован (с другим IDA Python) , чтобы быть интересными для данного конкретного случая. Мы просматриваем каждую функцию, о которой знает IDA, и проверяем, начинается ли имя функции mach__0x, после чего мы включаем его в список.

Я, наверное, должен сказать, что моя попытка была неудачной. Я искал варианты в пропатченном двоичном файле и не увидел ничего полезного. Я подозреваю, что, если бы были какие-либо другие уязвимые методы, Apple пошла вперед и заранее исправила их. Несмотря на это, это показалось приличным примером того, что вы можете сделать относительно быстро с IDA Python API, если у вас есть несколько вспомогательных методов.

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

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

Источник:
 
Мы в соцсетях:

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