Уязвимости в программах. IDA Pro «с нуля» ч.20

Обсудить статью на форуме


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

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

Что же такое уязвимость ?

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

Уязвимости - это результат ошибок или просчётов в дизайне системы. Хотя, в более широком смысле, они также могут быть результатом самих технологических ограничений, потому что, в принципе, не существует 100% безопасной системы. Таким образом, существуют теоретические и настоящие уязвимости.

То же самое правило применяется и к программам. Уязвимая программа - это такая программа, которая имеет ошибки или изъяны в программном коде и в зависимости от типа ошибок, эти ошибки могут быть эксплуатированы. Из-за этих ошибок может быть запущен вредоносный код в вышеупомянутой программе, но также и аутентификация может завершиться ошибкой и позволит совершать действия, которые не позволены пользователю, провоцировать сбои, поднимать привилегии, и т.д.

Конечно, на уровне ошибок повреждения памяти самые простые - это переполняющиеся буфера.

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

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

В исходном коде простой программы на C, буфер может быть представлен так:

char buf[xxx];

Где XXX - это размер буфера. В нашем случае, это буфер в стеке длиной 0x300 байт.

IDA Pro взлом и реверсинг программ

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

Она приложена к этому туториалу, как файл COMPILADO_1.EXE.

IDA Pro взлом и реверсинг программ

Уже знаем, что нам нужно искать ссылки на аргументы ARGC или ARGV. Так мы можем попасть в функцию MAIN в консольной программе.

Делая двойной щелчок на них, я прибываю сюда:

IDA Pro взлом и реверсинг программ

Теперь поищем перекрёстные ссылки с помощью клавиши X.

IDA Pro взлом и реверсинг программ

Ища перекрёстные ссылки, попадаем в известный блок, который вызывает функцию MAIN. В нашем случае, давайте дадим ему другое имя. Может быть такое, потому что блок ничего не делает.

IDA Pro взлом и реверсинг программ

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

IDA Pro взлом и реверсинг программ

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

IDA Pro взлом и реверсинг программ

Сейчас, мы используем функцию GETS_S, для того, чтобы пользователь ввёл что-нибудь в консоли и этот ввод сохранился в буфер, чтобы это значение можно было бы использовать позже в программе.

IDA Pro взлом и реверсинг программ

Видим, что вышеупомянутая функция имеет два аргумента - буфер и максимальный размер того, что Вы можете ввести, для того, чтобы буфер не переполнился. Очевидно, в примере нет переполнения, потому что размер, который копируется, не превышает размера созданного буфера в 0x300 байт.

IDA Pro взлом и реверсинг программ

Видно, что не существует возможности переполнить буфер, так как то, что я буду вводить будет меньше или равно 0x300 байт.

Давайте посмотрим на эту программу в IDA. Файл приложен к данному туториалу с именем COMPILADO_2.EXE.

IDA Pro взлом и реверсинг программ

Я компилировал файл с символами, и IDA также нашла символы на моей машине.

Так выглядит намного лучше. Уже появилась функция MAIN c её аргументами и переменными.

Давайте немного проанализируем этот код в IDA.

IDA Pro взлом и реверсинг программ

Я делаю двойной щелчок на любой переменной или аргументе и попадаю в статическое представление стека.

Здесь у нас есть три аргумента - ENVP, ARGV и ARGC, которые программа не использует внутри функции MAIN.

Они помещаются в стек перед вызовом MAIN.

IDA Pro взлом и реверсинг программ

Программа помещает три аргумента в стек перед тем как сделать ВЫЗОВ функции MAIN.

Программа сохраняет АДРЕС ВОЗВРАТА, который является адресом, который знает куда нужно вернуться программе после выхода из CALL. В нашем случае, адрес возврата имеет значение 0x401200, если не будет рандомизации.

IDA Pro взлом и реверсинг программ

Программа будет возвращаться сюда, после выполнения функции MAIN. Поэтому она должна сохранить значение 0x401200 в стеке чуть выше 3-х аргументов.

IDA Pro взлом и реверсинг программ

Затем программа начинает выполнять функцию MAIN. Первое, что делает программа — это исполняет инструкцию PUSH EBP.

IDA Pro взлом и реверсинг программ

Эта инструкция сохраняет в стеке значение EBP, которое использовалось функцией, которая вызвала функцию MAIN, чуть выше АДРЕСА ВОЗВРАТА 0x401200. Мы не знаем, какое значение оно может иметь, потому что оно меняется при каждом запуске программы, но сохраненный EBP или STORED EBP - это отец этой функции.

IDA Pro взлом и реверсинг программ

Здесь, EBP будет сохраняться в стек, выше адреса возврата.

Следующая инструкция, которая исполняется - такая.

IDA Pro взлом и реверсинг программ

Она устанавливает EBP как базу в этой функции и выравнивает его с ESP. Это одинокая инструкция MOV. Она меняет значение EBP, а не стек.

Затем, следующая инструкция SUB ESP, 0x304 передвигает указатель ESP вверх памяти, резервируя место для локальных переменных и буферов в стеке, которые расположены выше STORED EBP и ESP будет работать в функции основанной на EBP. Чуть выше резервируется место.

IDA Pro взлом и реверсинг программ

Здесь, мы видим зарезервированное пространство для переменных и буферов. Чуть ниже находится S (STORED EBP).

Первая переменная, которая почти всегда находится сразу после S - это CANARY, которая нужна для защиты стека. В нашем случае переменная называется VAR_4.

IDA Pro взлом и реверсинг программ

Здесь видим, что программа читает значение __SECURITY_COOKIE, которое является случайным значением, которое создаётся каждый раз, когда запускается программа. Это значение XORится с помощью EBP и сохраняется в переменную VAR_4 как мы уже видели ранее. Переименовываем её в CANARY.

IDA Pro взлом и реверсинг программ

Выше CANARY находится буфер BUF. Давайте посмотрим его в статическом представлении стека.

IDA Pro взлом и реверсинг программ

Когда я вижу пустое пространство в статическом представлении стека, я предполагаю, что это может быть буфер. Поэтому мы делаем правый щелчок на этих байтах BUF и выбираем ARRAY.

IDA Pro взлом и реверсинг программ

Видно, что его размер равен 768 * 1 байт, т.к. это длина каждого элемента. Следовательно, размер буфера равен 768, который в HEX представлении равен 0x300.

IDA Pro взлом и реверсинг программ

Поэтому, мы соглашаемся с IDA и получается буфер BUF, который уже определен как буфер из 0x300 байт в HEX или 768 в десятичном виде.

Здесь, есть вызов функции GETS_S и два её аргумента: максимальный размер 0x300 и другой её аргумент - адрес буфера, который получается через инструкцию LEA.

IDA Pro взлом и реверсинг программ

Поэтому, мы проверяем, что размер буфера BUF равен 0x300 байт и он вмещает максимум 0x300 байт, который мы вводим через функцию GETS_S.

Очевидно, что если бы мы могли переполнить буфер, копируя больше чем 0x300 байт, мы переписали бы переменные CANARY, STORED EBP и АДРЕС ВОЗВРАТА, которые находятся чуть ниже БУФЕРА.

IDA Pro взлом и реверсинг программ

Но это не тот случай. Это пример хорошего буфера, который записывается правильно.

IDA Pro взлом и реверсинг программ

Очевидно, часто пользователь не знает размер данных, которые будут скопированы. Если это так, размер должен быть хорошо проверен, что этот SIZE не будет больше, чем размер буфера.

IDA Pro взлом и реверсинг программ

Здесь видим буфер из 0x10 байт или 16 байт в десятичном виде и пользователь имеет возможность ввести размер буфера через функцию GETS_S. Очевидно, не существует никакой проверки этого максимального значения, поэтому, если я компилирую и запускаю этот файл (COMPILADO_3.EXE).

IDA Pro взлом и реверсинг программ

Видно, что теперь в программе есть БАГ и она стала уязвима. Если откроем её в IDA, даже если мы не имеем исходного кода, то увидим.

IDA Pro взлом и реверсинг программ

Как и раньше это переменная CANARY. Чуть выше есть буфер BUF. Давайте посмотри его длину в статическом представление стека.

IDA Pro взлом и реверсинг программ

Размер буфера равен 16 байт * 1, так как это размер одного элемента. Поэтому размер буфера в HEX равен 0x10.

IDA Pro взлом и реверсинг программ

Другими словами, если бы мы смогли скопировать более 16 байтов в буфер, произошло бы переполнение и перезапись переменных CANARY, STORED EBP и АДРЕС ВОЗВРАТА.

Посмотрим размер переменной.

IDA Pro взлом и реверсинг программ

Видно, что после вывода с помощью функции PRINTF сообщения PLEASE ENTER YOUR NUMBER, вызывается функция SCANF_S для ввода значений с клавиатуры, которые сохраняется в переменной, размер которой равен DWORD и передает размер переменной с помощью инструкции LEA в регистр EAX.

Давайте посмотрим описание функции SCANF_S.

IDA Pro взлом и реверсинг программ

Функция scanf_s читает данные из стандартного потока stdin, и пишет данные по адресу, который указан в аргументе. Каждый аргумент должен быть указателем на переменную типа, который соответствует спецификатору типа в формате. Если копирование происходит между строками, которые перекрываются, поведение не определено.

Другими словами, это как противоположность функции PRINTF. Только вместо печати с форматом, формат вводится с консоли с форматом в буфер. В нашем случае, формат %d интерпретирует данные как десятичное число.

Таким образом, когда Вы вызываете функцию GETS_S использую этот размер, который я напечатал, программа будет копировать заданное количество байт и если размер больше чем 0x10, буфер будет переполнен.

IDA Pro взлом и реверсинг программ

Возможным решением этой проблемы будет проверять размер введённых данных перед тем как копировать ввод пользователя в буфер.

IDA Pro взлом и реверсинг программ

Было бы неплохо проанализировать программу, чтобы убедиться, что это решение делает её неуязвимой или оставляет её такой же уязвимой. Эта программа называется VULNERABLE_O_NO.EXE, и мы будем обсуждать её в следующей части.

До встрече в следующей 21-той части друзья.


Автор текста: Рикардо Нарваха - Ricardo Narvaja (@ricnar456)
Перевод на английский: IvinsonCLS (@IvinsonCLS)
Перевод на русский с испанского+английского: Яша_Добрый_Хакер(Ростовский фанат Нарвахи).
28.10.2017
Версия 1.0

Обсуждение статьи: Уязвимости в программах. IDA Pro «с нуля» ч.20 >>>


При перепечатке ссылка на https://exelab.ru обязательна.



Видеокурс ВЗЛОМ