Здесь мы нажимаем T, чтобы освежить информацию.
Наконец, я переименовываю функцию в ENTER.
Мы видим, что три первые функции вызывают ENTER передавая адрес PEPE и три следующие передают адрес JUAN.
Давайте посмотрим на следующую функцию.
Эта функция также использует обе структуры, поэтому Вы можете равно как в предыдущем случае нажать F5.
Здесь на переменной _STRUCT я делаю правый щелчок и выбираю пункт CONVERT TO STRUCT *.
Сейчас, это адрес структуры MYSTRUCT и, как и раньше, мы увидим поля только нажав клавишу T в соответствующем месте.
Здесь мы видим, что программа сравнивает поле NUMERO, которое мы передали, с числом 0x10 и поскольку сравнение знаковое, любое отрицательное число может пройти. Например число 0xFFFFFFFF, которое равно -1 и которое меньше 0x10.
Затем, программа использует NUMERO как размер для функции GETS_S, которое мы передали ей и другой аргумент. Он должен быть буфером, который находится в начале структуры, потому что он использует её начальный адрес.
Я иду в MYSTRUCT и по смещению 0x0 нажимаю D один раз, чтобы создать единственное байтовое поле.
Теперь, здесь, я делаю правый щелчок и выбираю ARRAY.
Размер буфера будет равен 16 байт. Я соглашаюсь с этим значением.
Переименовываю это поле в BUFFER.
Размер поля теперь равен 16 десятичных байт.
Давайте продолжим реверсить.
Проблема состоит в том, что с помощью функции GETS_S буфер может быть переполнен, так как функция CHECK позволяет передавать отрицательные значении при использовании в качестве размера. Они будут восприниматься как беззнаковые значения и будут очень большими.
Если, например, мы передадим 0xFFFFFFFF в сравнение, значение будет равно -1, потому что оно идет как знаковое и будет меньше чем 0x10, но используя его как размер, оно будет большим положительным значением 0xFFFFFFFF, которое позволяет нам передавать количество символом, которое мы хотим через функцию GET_S в буфер и переполнить его.
Таким образом, мы могли бы переименовать функцию в CHECK или GET. Независимо от того, что мы хотим, нужно чтобы имя отражало то, что делает функция. Мы будем проверять это соответствие.
У меня есть третья функция. Аргумент тот же, поэтому я повторяю процедуру, нажимаю F5 и изменяю тип аргумента.
Я продолжаю реверсить.
Мы видим, что есть ещё одно поле, поскольку оно пытается сравнить значение [EAX+0x18], которое мы не определили, так как наше последнее поле структуры MYSTRUCT равно 0x14. Давайте добавим его.
Мы помещаем указатель на слове ENDS и нажимаем D до тех пор пока не создадим новое поле DD.
Я переименовываю это поле в COOKIE.
Я возвращаюсь в нашу функцию и нажимаю T для обновления информации.
Мы видим, что существует ещё другое поле. Это единственный байт.
Поэтому мы возвращаемся назад в структуру MYSTRUCT и на слове ENDS нажимаем D один раз и у нас появляется поле из одного байта.
Я переименовываю это поле во FLAG, чтобы он совпадал с исходным кодом.
Теперь возвращаемся в функцию.
Если переменная COOKIE равна 0x99989796, тогда программа будет устанавливать флаг структуры в 1.
Если для некоторых изменений, которые не распространялись хорошо, переменные функции MAIN сломаются, и мы не сделали снимок, как это случилось со мной, то делаем так.
Я иду в начало поломанной функции и нажимаю U.
Я соглашаюсь на вопрос программы «сломать» функцию.
Затем, там же, в начале функции, я нажимаю C.
И затем я делаю правый щелчок и выбираю пункт CREATE FUNCTION.
Теперь всё хорошо.
Посмотрим в статическое представление стека.
Мы видим, что после каждый структуры остаются три пустых байта, потому что последнее поле было единственным байтом и больше ничего нет.
Только имена структур неправильные, но я буду менять их в соответствии с исходным коде, т. е. я изменяю имена на PEPE и JUAN.
Мы видим, что со структурой JUAN программа будет делать то же самое что и с PEPE. Структуры будут передавать свои адреса функциям ENTER и CHECK. Но программа имеет ещё третью функцию. Давайте посмотрим, что она делает.
Нажимая T в полях, мы видим, что функция похожа на функцию “DESICION”, только константа с которой сравнивается поле COOKIE структуры JUAN отличается. В этом случае константа равна 0x33343536.
Другими словами, поле COOKIE структуры PEPE должно быть равно значению 0x99989796 и поле структуры JUAN должно быть равно 0x33343536. Только так флаги каждой структуры будут равны 1.
Мы видим, что для того, чтобы прийти к хорошему сообщению оба флага должны быть равны 1.
Это упражнение имеет много решений, потому что структура JUAN находится выше в стеке.
Выполняя функции GET_S мы можем перезаписать все флаги так, чтобы они остались равны 1 и таки образом, сделать это одним переполнением. Также это можно сделать индивидуально, перезаписывая в каждой функции GET_S флаг и нет необходимости перезаписывать поле COOKIE правильным значением, потому что мы напрямую перезаписываем флаг, не дожидаясь сравнения поля COOKIE, чтобы изменить его.
Чтобы перезаписать флаг, у меня есть 16 десятичных байт, плюс к этому значению 3 DWORD или это будет 12 байт.
Общая сумма байт будет равна: 16 + 12 = 28 байт.
Поэтому количество фруктов будет равно: FRUTA = 28* “A” + “\x01”
Конечно, для каждой из структур Вы должны передать -1 или отрицательное значение, которое пройдет проверку против числа 0x10, а затем должен следовать фруктовый-шеллкод )).
Если мы немного поотлаживаем, мы увидим значение -1, которое помещается в поле NUMERO структуры PEPE.
Программа проходит проверку и достигает функцию GETS_S. Здесь и читаются переданные фрукты.
Здесь я вижу адрес структуры PEPE на моей машине, после исполнения функции GET_S. Если я пойду в стек.
Здесь я вижу наши ФРУКТЫ, которые я посылаю программе. Если я хочу сконвертировать эти данные в структуру, то я нажимаю ALT + Q.
И выбираю пункт MYSTRUCT.
Я вижу, что поля и флаг уже перезаписан на значение 1 переполнением. Не исследуя подробно другие функции, я продолжаю трассировать.
Мы видим, что программа сравнивает COOKIE со значением 0x99989796 и поскольку это разные значения, программа не изменят флаг. Но флаг уже равен 1, поэтому это не так важно.
Тот же процесс будет повторяться и мы переходим в функцию DECISION2.
Я начинаю трассировать с помощью клавиши F7.
Регистр EAX имеет начало структуры JUAN. Давайте посмотрим на эту структуру в стеке.
Здесь, я также нажимаю сочетание ALT + Q, чтобы из байтов собрать структуру. Снова выбираем нашу структуру MYSTRUCT.
Так же как и раньше флаг будет равен 1. Сравнение с COOKIE не будет равно, но программа продолжит выполняться, потому что с флагом уже всё хорошо.
Поле PEPE.FLAG равно 1 и это хорошо, поэтому продолжаем трассировку.
Поле JUAN.FLAG также правильное, поэтому я достигаю хорошего сообщения.
Готово. Теперь пример решен. Мы победили.
Увидимся в 28 части.
=====================================================
Автор текста: Рикардо Нарваха - Ricardo Narvaja (@ricnar456)
Перевод на английский: IvinsonCLS (@IvinsonCLS)
Перевод на русский с испанского+английского: Яша_Добрый_Хакер(Ростовский фанат Нарвахи).
Перевод специально для форума системного и низкоуровневого программирования — WASM.IN
05.01.2018
Версия 1.0
Введение в реверсинг с нуля, используя IDA PRO. Часть 27-2.
Дата публикации 4 янв 2018
| Редактировалось 5 янв 2018