Введение в реверсинг с нуля используя IDA PRO. Часть 9

Дата публикации 21 июл 2017 | Редактировалось 24 июл 2017
Мы разбираемся понемногу как нужно работать с ЗАГРУЗЧИКОМ, мы оставили некоторые вещи на потом, чтобы наблюдать за ними позже в ОТЛАДЧИКЕ, например, как меняются флаги в зависимости от используемых инструкций.

Мы будем практиковаться на очень простых примерах, в нашем случае это очень простые крэкми, которые скомпилированы в VISUAL STUDIO 2015 для нашей практики. Очевидно, для того, чтобы крэкми заработал, у Вас должны быть установлены последние версия библиотек VISUAL STUDIO 2015 C++.

https://www.microsoft.com/es-ar/download/details.aspx?id=48145

Пакеты Visual C++ Redistributable устанавливают компоненты среды выполнения, которые необходимы для запуска приложений написанных на языке C++ и скомпилированные в Visual Studio 2015.

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

Присоединенный файл - это исполняемый файл, который называется HOLA_REVERSER.EXE и который запускается под WINDOWS 7.

1.png

При вводе номера крэкми будет говорить, насколько я хороший или плохой реверсер.

2.png

Мы видим, что это очень простой крэкми, если я открою его в IDA и только в ЗАГРУЗЧИКЕ без отладчика, увидим следующее.

В моём случае (не в Вашем) функция MAIN появляется среди других функций, поэтому я могу найти её с помощью комбинации CTRL + F здесь на этой вкладке или там, где у меня открыта вкладка с функциями, но это происходит, потому что я скомпилировал программу с помощью VISUAL STUDIO и создал PDB файл с символами, который обнаруживает IDA и загружает оттуда имена функций и имена переменных, мы видим, что в моём листинге равно как и в моём исходном коде, появляется функция MAIN, а ниже функция PRINTF, мы будем смотреть, что будет происходить в Вашем случае.

3.png

В Вашем случае, IDA не скажет, что это за функция, потому что у IDA'Ы нет символов.

Вероятно, это потому, что никто не распространяет программу с символами.

4.png

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

Мы видим, что здесь у нас нет символов.

5.png

Мы имеем очень мало информации, но хорошо то, что мы можем видеть строки.

6.png

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

Мы можем сделать двойной щелчок на строке “Pone un numerito\n”.

7.png

Здесь мы видим, что 0x402108 это адрес строки, а рядом с адресом мы видим ТЭГ, который помещен рядом и всегда начинается с буквы “a” если это строка ASCII, а оставшиеся символы принадлежат к той же строки, поэтому её очень легко распознать, в нашем случае тэг называется aPoneUnNumerito, а затем идут символы DB, потому что строка - это последовательность байт.

Строку можно рассыпать на байты с помощью клавиши D, теперь мы видим те же самые символы только по вертикали и по одному.

8.png

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

9.png

Поместив курсор мыши на ссылку в виде маленькой стрелки, мы видим откуда вызывается эта строка, но будет лучше, если мы нажмем клавишу X, чтобы увидеть список ссылок и перейдём туда.

10.png

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

11.png

Предполагается, что мы не знаем исходный код программы, но я Вам его покажу.

12.png

Я понимаю, что переменные, которые Вы создаете, становятся оптимизированными, например такие как COOKIE и MAX, которые заменены константами и остаётся только мой буфер, который в моём коде составлял 120 байт в десятичной системе.

Буфер - это пространство памяти зарезервированное, чтобы хранить данные, в нашем случае резервируется 120 байтов.

Как мы можем узнать в IDA размер буфера в стеке, если у нас нет исходного кода?

13.png

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

14.png

Здесь мы видим буфер BUF, но он определен как последовательность байт DB (IDA если нет символов не может обнаружить буфер). Чтобы собрать его в массив символов или пустой массив, щелкните правой кнопкой мыши на слове BUF и выберите параметр ARRAY.

-= Примечание от Яши — Можно также нажать символ * на цифровой клавиатуре=-

15.png

Здесь мы видим, что до следующей переменной или того, что находится ниже в стеке, IDA обнаружила 120 десятичных DB, а элемент массива равен длине каждого поля, так как размер поля равен 1 байту, то это массив символов или байтов и его сумма рассчитывается так 120*1 байт или просто 120 байт.

Если согласимся с этим, то получится так.

16.png

Я вижу, что буфер состоит из 120 байт, что соответствует моему исходному коду, хотя компилятор может сделать его больше, пока он минимум равен 120 байт, то всё хорошо, в этом случае они равны. DUP - означает дубликат (на самом деле он должен быть умножен) 120 раз на символ “?”, потому что значение ещё не определено и это соответствует пустому статическому буферу.

17.png

Я буду прояснять представление статического стека позже, но ниже BUF есть переменная DWORD (DW) называемая VAR_4

S
и R - это сохраненный EBP родительской функции, которая вызвала эту функцию и АДРЕС ВОЗВРАТА, как мы видели при входе в первую функцию - сначала кладутся аргументы с помощью PUSH, а затем делается CALL, чтобы войти в функцию, которая сохранит АДРЕС ВОЗВРАТА в стек, и локальные переменные будут выше S.

ПЕРЕМЕННЫЕ


S (Сохраненный EBP - как правило, происходит от PUSH EBP, которая является первой инструкцией функции)
R (Адрес возврата)
АРГУМЕНТЫ

Поскольку аргументы помещаются в стек перед CALL, который помещает адрес возврата в стек, они будут ниже него, затем будет идти адрес возврата, а выше него СОХРАНЕННЙ EBP порожденный инструкцией PUSH EBP, которая как правило первая инструкция в функции, а затем выше идет пространство локальных переменных, мы увидим их более подробно позже.

Если я нажму X, чтобы увидеть откуда вызывается эта функция, то увижу:

18.png

19.png

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

20.png

IDA обнаружила, что никогда не используются такие аргументы как ARGC, ARGV и ENVP, они присутствуют по умолчанию в функции MAIN, но так как там не было никаких ссылок на них или их использование в функции, IDA избавилась от них.

21.png

Кроме того, в моём коде даже не передаются переменные как аргументы к функции MAIN, так что все хорошо - функция без аргументов.

Когда мы хотим увидеть из какого место получается доступ к переменной, мы отмечаем её и нажимаем X.

22.png

Мы видим, что VAR_4 используется в двух местах, для тех кто не знает, это переменная COOKIE, которую я не программировал, это защита от переполнения стека, программа сохраняет их в начале при запуске функции, проверяет их на целостность при выходе из функции, теперь мы можем переименовать их в COOKIE_DE_SEGURIDAD или CANARY.

23.png

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

24.png

Мы видим, что в версии с символами IDA обнаружила её непосредственно как функцию PRINTF.

25.png

Но только если мы посмотрим внутрь CALL то узнаем, что аргументы, это строки, которые печатаются в консоли и мы делаем вывод, что это функция PRINTF.

26.png

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

27.png

У нас остаётся только буфер из 120 байт, давайте посмотрим, что будет с ним происходить.

Мы видим, что буфер идет как аргумент к функции GETS_S - эта функция, которая получает то, что мы вводим в консоли.

28.png

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

29.png

Ранее мы сказали, что LEA вычисляет адрес переменной, в этом случае LEA является указателем на буфер BUF, который передаётся с помощью инструкции PUSH EAX, а затем идёт PUSH 0x14, который указывает максимальное количество символов, которое можно ввести в консоли.

30.png

В моём исходном, мы видим тот же самый вызов GET_S с двумя аргументами - БУФЕР и его максимальное значение, который я обозвал как переменную MAX из 20 элементов, но компилятор, чтобы сохранить пространство поместил именно 20 в десятичной или 0x14 в HEX в этот аргумент, так как не нужно использовать больше.

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

Позже, тот же указатель на буфер помещается как аргумент к функции ATOI.

31.png

Она делает то же самое.

32.png

Эта функция конвертирует строку в целое число и если она не может это сделать, потому что происходит переполнение (выход за максимально возможное значение), нам будет показываться ошибка и вернётся ноль, тоже самое происходит и с отрицательным числом, но идея состоит в том, что всё что я буду вводить будет конвертироваться в число, если я введу значение 41424344 оно будет конвертироваться в десятичное значение 41424344, а так как в ассемблере мы работаем с HEX значениями, оно будет возвращено в HEX через регистр EAX.

Каждая функция возвращает генерируемое значение INT, она интерпретирует входные символы как число. Функция возвращает значение 0 для ATOI и _WTOI, если ввод не может быть преобразован в значение этого типа.

34.png

Мы видим, что значение возращенное из EAX переносится в ESI и после печати первоначальной строки, которая была введена, сравнивает ESI с числом 0x124578.

Так что, то, что набрано интерпретируется как строка в десятичном формате, которая возвращается в HEX виде и это число сравнивается с этой константой, передавая десятичное значение этой константы.

35.png

Мы видим, что если сравнение не равно (JNZ) оно переносит меня к BAD REVERSER, а если равно, то переносит к GOOD REVERSER, давайте попробуем в консоли PYTHON увидеть десятичное значение числа 0x124578.

36.png

Мы вводим это значение в наш CRACKME.

37.png

38.png

Хорошо, это простой пример статического реверсинга, далее также продолжим работу с ЗАГРУЗЧИКОМ

До встрече в 10-той части.

Рикардо Нарваха.

23 16.474
yashechka

yashechka
Ростовский фанат Нарвахи

Регистрация:
2 янв 2012
Публикаций:
90

Комментарии


      1. Spec122 17 янв 2021
        yashechka Большое спасибо за перевод.
        Однако почему то не прикрепляешь нужные файлы, ссылка в комментарии уже к сожалению мертвая.
        Знаю, что курсы все еще читает большое количество людей, поэтому оставлю тут эту ссылочку
        https://github.com/hdbreaker/RicardoNarvaja_ExploitingWithIDAPRO_Desde0
        Это репозиторий Нарвахи, где можно выкачать нужные файлы.
        Файл для этого урока находится здесь -> https://github.com/hdbreaker/Ricard...N AL REVERSING CON IDA PRO DESDE CERO PARTE 9
      2. yashechka 3 авг 2018
        renessans нравится это.
      3. renessans 3 авг 2018
        не нашел ссылку на hola_reverser
      4. yashechka 1 мар 2018
        :preved::preved::preved:
      5. yashechka 27 окт 2017
        Спасибо =)
      6. neutrino596 20 авг 2017
        спасибо, совсем туплю
        yashechka нравится это.
      7. yashechka 20 авг 2017
        neutrino596 нравится это.
      8. yashechka 20 авг 2017
        Так в архиве же, Вы чито.
      9. neutrino596 20 авг 2017
        Не подскажете, где искать HOLA_REVERSER? Нигде не могу найти его
        yashechka нравится это.
      10. yashechka 4 авг 2017
        Виртухе спасибо за лайки.
        virtuha нравится это.
      11. yashechka 4 авг 2017
        >Когда будет 10 часть ? )))
        Сегодня наверное, а что Вы хотели?
      12. alex-rudenkiy 4 авг 2017
        Когда будет 10 часть ? )))
      13. yashechka 29 июл 2017
        Какой краусаувчик))
      14. jkmjkmjkm 29 июл 2017
        Вот собрал публикации в .chm. Может пригодится кому
        Глава 1-9
        Ronin_ и yashechka нравится это.
      15. yashechka 29 июл 2017
        Пока только перевожу. У меня даже нет ПК такого, точнее у меня есть ПК, где я писал про Олли, но он не тянет Вин7, а по урокам Нарвахи, нужна вообще Вин10. Как только закончу перевод, начну снимать новый курс интересный, который потянет старый комп. Хочу тем временем создать краудфандинг, для донатов. Я вот думаю, если мопсу донятят 50т за пол часа, и всяким каринам с дотой, что наше сообщество не поможет собрать на хороший ПК для годных курсов? -- Не верю. Сам я сейчас без работы. Я вот только создал кошели как биржа ушла в оффлайн. >:/ Ну............... Ну вот Вы все кто читает посмотрите здесб - https://hex-rays.com/products/ida/training/index.shtml сколько стоит курсы от Ильфака. Да на пол цены можно купить хороший ПК, а остальное за мной, я готов трудится, у меня в блокноте 10 курсов расписано, и сис. администрирование и даже juniper Короче буду смотреть на общественность - захотят - сделаю, нет - значит нет. Под новый год выложу на рутрекер видео про Олли в оригинальном качестве. Сейчас учу испанский, первожу с инглиша на русский, а потом с испанского на русский, составляю словарь, учу глаголы и слова. Никуда не спешу!!!
      16. rudolfninja 29 июл 2017
        Спасибо за старания. Вот с pdf - вообще отличная идея.
        Впорос может показаться глупым, но я все же задам его: а ты только переводишь или проделываешь все эти же шаги, что бы убедиться, что на парктике так же как и в статье?
      17. yashechka 28 июл 2017
        Не вижу ни лайков, ни коммов.
      18. yashechka 26 июл 2017
        BTCE сдох
      19. yashechka 23 июл 2017
        Со следующей части буду делать и красивые PDF сразу.
        rudolfninja нравится это.
      20. yashechka 23 июл 2017
        Готово.