• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Сравнение патчей с помощью Гидры

yashechka

Генератор контента.Фанат Ильфака и Рикардо Нарвахи
Эксперт
Регистрация
24.11.2012
Сообщения
2 344
Реакции
3 563
Введение

Этот пост предназначен для людей, которые заинтересованы в патчах безопасности для реверс инжиниринга, но не имеют доступа к дорогостоящим инструментам, таким как IDA Pro, для выполнения таких задач. Прежде всего, мы создадим программу, которая представляет общий класс ошибок, такой как переполнение буфера, а затем пропатчим указанную ошибку. После этого мы будем использовать патч BinExport для Ghidra для экспорта обеих версий программы, а затем будем использовать программу BinDiff для анализа патча. К концу этого поста в блоге вам будет довольно удобно исследовать патчи с помощью BinDiff.

Инструменты

Мы будем использовать следующие инструменты:

- Microsoft Visual Studio Community 2019 version 16.5.1.
- Kali Linux установленный на виртуальной машине.
- Ghidra version 9.1.2 программное обеспечение для реверсинга файлов
- BinExport один из компонентов BinDiff.
- BinDiff version 6 это инструмент сравнения бинарных файлов, который помогает исследователям и инженерам по уязвимостям быстро находить различия и сходства в дизассемблированном коде.

Уязвимая программа

Ниже приведена программа на C, которая уязвима для переполнения буфера из-за использования небезопасной функции gets. Я предполагаю, что читатель уже знаком с программированием на C и переполнением буфера, если нет, то Google - ваш верный помощник.


C:
#include <stdio.h>
#include <string.h>

int main(void)
{
    char buf[14];

    printf("Enter password: ");
    gets(buf);

    if (strcmp(buf, "falafelislife"))
    {
        printf("Wrong password!\n");
    }
    else
    {
        printf("You're good.\n");
    }

    return 0;
}

Программист здесь делает предположение, что пользователь уже знает, что пароль должен быть не длиннее 13 символов, и как таковой массив с нулевым символом в конце char buf [14] используется для хранения пароля. Давайте подтвердим работу программы, как и ожидалось.

1.PNG


Как мы видим выше, программа работает, и мы смогли повредить стек, введя 14-символьный пароль.

Патч

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

C:
#include <stdio.h>
#include <string.h>

int main(void)
{
    char buf[14];

    printf("Enter password: ");
    //gets(buf);
    fgets(buf, 14, stdin);

    if (strcmp(buf, "falafelislife"))
    {
        printf("Wrong password!\n");
    }
    else
    {
        printf("You're good.\n");
    }

    return 0;
}

После применения исправления мы больше не получаем сообщение об ошибке отладки при вводе паролей длиной более 13 символов.

2.PNG


Setup

На этом этапе мы будем следовать инструкциям, изложенным здесь, чтобы настроить BinExport для Ghidra внутри нашей виртуальной машины Kali Linux. Прежде всего, мы должны убедиться, что у нас установлены все необходимые зависимости, а затем мы собираем BinExport, используя программу gradle.

3.PNG


Если все идет хорошо, вы должны увидеть .zip файл в папке dist.

4.PNG


Затем мы устанавливаем расширение BinExport, загружая zip-файл в Ghidra в File-> Install Extensions ..., а затем проверяем установку.

5.PNG


Теперь у нас должно быть все необходимое для экспорта в BinDiff.

Анализ патча

Давайте загрузим как уязвимые, так и исправленные программы в Ghidra и обязательно запустим их через первоначальный анализ. Я следовал инструкции, упомянутой здесь, и включил опцию агрессивного поиска команд, чтобы получить лучшее покрытие при экспорте. Теперь мы экспортируем программы, используя расширение BinExport.

6.PNG


А затем загружаем их в BinDiff, создав новое рабочее пространство.

7.PNG



Мы получаем хороший обзор обеих программ, которые показывают такие вещи, как хеши, архитектуру и так далее.

8.PNG


Затем мы щелкаем правой кнопкой мыши на Overflow v1.1.exe vs Overflow v1.0.exe и затем нажимаем Open Diff, чтобы создать несколько вкладок.

9.PNG

Я кратко опишу каждую вкладку, но не стесняйтесь смотреть на руководство BinDiff здесь для более подробной информации:

- Граф вызовов: после создания начальных совпадений для двух исполняемых файлов, графы вызовов (графики, которые содержат информацию об отношениях вызовов между функциями) используются для генерации большего количества совпадений.
- Совпадающие функции: Есть несколько алгоритмов сопоставления, используемых для определения того, является ли данная функция сходной, например алгоритмы, основанные на хэше и сопоставлении графов. В этом представлении вы можете быстро определить, какие функции были изменены, основываясь на значениях сходства и достоверности среди других факторов.
- Первичные несовпадающие функции отображает функции, которые содержатся в текущей открытой базе данных и не были связаны с какой-либо функцией базы данных сравнения.
- Вторичные несовпадающие функции: содержит функции, которые находятся в базе данных diffed, но не были связаны с какими-либо функциями в первой.

Перейдя на вкладку Matched Functions, я заметил довольно много изменений, учитывая, насколько маленьким был патч, однако FUN_140011840 быстро привлек мое внимание из-за количества базовых блоков по сравнению с другими функциями, которые были изменены. Обратите внимание, что линии окрашены в соответствии с тем, насколько похожи совпадающие функции, где зеленые цвета указывают на высокое сходство, тогда как красные тона указывают на слабые совпадения.

10.PNG


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

- Сходство: значение от нуля до единицы, указывающее, насколько похожи две совпадающие функции. Значение ровно один означает, что две функции идентичны (в отношении их инструкций, а не их адресов памяти). Значения меньше единицы означают, что функция имеет измененные части.

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

Давайте дважды щёлкнем по функции FUN_140011840 и посмотрим, где был применен патч.

11.PNG


Из рисунка выше видно, что это основная функция. Ниже приведены все возможные цвета в этом представлении и то, что представляет каждый цвет:

- Красный: указывает основные блоки, где BinDiff не смог найти эквиваленты.
- Желтый: указывает узлы, для которых алгоритмы смогли находить эквивалентные функции, но в которых были изменены некоторые инструкции между версиями.
- Зеленый: Обозначает основные блоки, которые имеют одинаковую мнемонику команд в обоих исполняемых файлах.

Теперь, прежде чем мы перейдем к изменениям, вот как выглядит функция fgets и где должны быть размещены аргументы в соответствии с соглашением о вызовах __fastcall:

C:
char *fgets(char *str, int n, FILE *stream)
RCX = This is the pointer to an array of chars where the string read is stored.
RDX = This is the maximum number of characters to be read (including the final null-character). Usually, the length of the array passed as str is used.
R8  = This is the pointer to a FILE object that identifies the stream where characters are read from.

- XOR ECX, ECX - убедитесь, что регистр ECX равен нулю.

- CALL qword ptr [PTR__acrt_iob_func_140020310] - __acrt_iob_func - это внутренняя функция CRT, ссылающаяся на стандартный поток ввода, которая используется по умолчанию в Visual Studio. Возвращаемое значение будет сохранено в регистр RAX.


12.png


- MOV R8, RAX - помещает указатель файлового объекта из регистра RAX в R8.
- MOV EDX, 0xe - помещает значение 14 в регистр EDX.

В завершение я должен упомянуть указатель на буфер, в котором будут храниться данные, которые затем сохраняются в регистр RCX через инструкцию LEA RCX, [RBP, 0x8], и, в конечном счете, выполняется вызов функции fgets, который соответствует патчу. В этот момент вы можете спросить себя, что насчет вызова функции fgets? Почему он не помечен как изменение по сравнению с непропатченной версией? Причина, по которой инструкция CALL qword ptr [PTR_fgets_140020308] не была выделена, и, пожалуйста, исправьте меня, если я ошибаюсь, заключается в отсутствии изменений в самой мнемонике, а скорее в операнде, который, насколько я знаю, BinDiff не учитывает.

Вывод

Надеемся, что это сообщение в блоге пролило некоторый свет на тему сравнения патчей, и я настоятельно рекомендую прочитать руководство BinDiff, чтобы полностью понять, что происходит на самом деле для получения окончательных изменений. Наконец, огромное спасибо @AdmVonSchneider за то, что сделали доступными BinDiff и BinExport, и @h0mbre_ за рецензирование.

Источник: https://ihack4falafel.github.io/Patch-Diffing-with-Ghidra/
Автор перевода: yashechka
Переведено специально для портала xss.pro (c)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
не все понял, но годное есть, особенно word чекать как новый патч выходит
дифить ядерные компоненты проще всего, в зависимости от баги, по биндиффу становится понятно в чем суть баги от нескольких минут (к примеру простейшие integer overflow) до нескольких дней (к примеру баги в win32k.sys где надо понять взаимосвязь обьектов).
в usermode примерно также единственное исключение браузеры, adobe reader, ms office, adobe flash, foxit reader - биндиффить такое это хардкор из-за размеров особенно ms office из-за отсутствия отладочных символов
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх