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

Дата публикации 25 дек 2017 | Редактировалось 4 янв 2018
В этой части, мы будем решать упражнение, которое мы оставили для решения в предыдущей части. Оно называется IDA_STRUCT.7Z. Если Вы не решили это упражнение или у Вас его нет, загрузите его отсюда.

http://ricardo.crver.net/WEB/INTRODUCCION AL REVERSING CON IDA PRO DESDE CERO/EJERCICIOS/IDA_STRUCT_RESOLVER DESPUES DE LA PARTE 26.7z

Исполняемый файл называется CONSOLEAPPLICATION4.EXE и в том же каталоге находятся символы CONSOLEAPPLICATION4.PDB.

Когда IDA загрузит файл, то сообщит Вам, что она пытается найти символы. Вы можете указать на этот файл и загрузить символы, с которыми программу станет немного яснее понимать. Но для нашего примера, я буду удалять или переименовывать файл PDB, чтобы загрузить программу без символов, что соответствует тому, с чем мы обычно имеем дело. Хотя это и выглядит сложнее, зато приближено к реальности.

1.png

Очевидно, что без символов, функция не будет определяться как MAIN. Мы можем добраться до неё, так как это консольное приложение, которое ищет аргументы ARGV или ARGC, а если их нет, то её, обычно, можно найти через поиск строк.

Если мы запустим программу, то увидим, что первое, что она сделает - это попросит нас ввести число. Здесь Вы видите строки, которые могут быть хорошим и плохим сообщением.

2.png

Щелкните на строке PLEASE ENTER YOUR NUMBER OF CHOICE:

3.png

Мы видим, что строка имеет ссылки. Помещая курсор над стрелкой или нажимая клавишу X на адресе, мы видим, что строка имеет ссылку.

4.png

5.png

Давайте перейдём по этому адресу.

6.png

Видим, что мы находимся внутри функции. Далее видно вывод строки и вызов функции для печати этой строки. Поскольку у нас нет символом, IDA не говорит нам, что функция по адресу 0x401220 - это функция PRINTF. Если мы посмотрим во внутрь этой функции.

7.png

Вы можете посмотреть во внутрь этой функции и увидеть, что внутри есть ещё несколько функций.

8.png

9.png

В PROXIMITY VIEW, в который можно войти нажав клавишу - и выйти, нажав +, мы видим, что функция 0x401220 вызывает те же самые три функции, но две функции 0x401000 и ACRT_IOB_FUNC - это функции, которые что-то делают и возвращаются назад. Они не идут к другим дочерним функциям.

10.png

Здесь, где есть стрелки, которые я добавил, видно, что блоки не идут к другим функциям. Только одна функция, которая вызывает другие функции - это функция по адресу 0x4010F0, которая вызывает две функции и первая из вызываемых, это функция VFPRINTF. Функция после своего выполнения возвращается обратно и ниже уже нет никаких других функций.

Это также можно увидеть в дизассемблерном списке. Если я посмотрю во внутрь каждой функции, я увижу то же самое.

Видно, что функция 0x401000 никуда не ведёт. Функция просто исполняет ерунду и возвращает выполнение.

11.png

12.png

И _ACRT_IOB_FUNC - это API функция. Поэтому функция не будет продолжаться??? Функция будет только инициализировать поток STDOUT, чтобы затем быть готовой печатать текст.

13.png

Другими словам, передача аргумента 1, как в нашем случае, будет инициализировать поток STDOUT.

14.png

И третья функция, которая будет вызываться, это функция по адресу 4010F0.

15.png

Функция заканчивается вызовом VFPRINTF, т.е. мы пришли к тому же, что видно и в PROXIMITY VIEW, но это занимает больше времени.

16.png

Так что давайте переименуем функцию по адресу 0x401220 в PRINTF.

17.png

Те блоки, которые заканчиваются вызовом API, как в этом случае PRINTF, я буду закрашивать в небесный цвет. Каждый будет делать это по своему вкусу.

18.png

Следующая функция по адресу 0x40109D – это конечно же функция SCANF. Если мы перейдём в неё и посмотрим в PROXIMITY VIEW, то увидим:

19.png

Здесь я нажимаю на +, чтобы увидеть спрятанные блоки.

20.png

Мы видим, что это функция SCANF.

21.png

И в этом случае, функция _ACRT_IOB_FUNC с аргументом 0 инициализирует поток STDIN.

22.png

Поэтому, мы переименовываем эту функцию в SCANF.

23.png

24.png

Мы видим что-то похожее на структуру, потому что когда Вы передаёте адрес как аргумент и затем извлекаете его и прибавляете к нему смещение для доступа к полям в каждом месте, в котором они используются, возможно это является адресом структуры.

Давайте посмотрим на ссылки для следующую функции.

25.png

Мы видим, что есть две ссылки. Если я зайду в первую.

26.png

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

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

Мы видим, что максимальное смещение, которое я нахожу до настоящего времени равно 0x14. Поэтому я буду создавать структуру этой длины. Если структура станет больше, я буду увеличивать её размер.

27.png

Для этого, я иду во вкладку STRUCTURES. Это один из способов её создания. Другой способ - это перейти в LOCAL TYPES и создать её как код в стиле C. Давайте так и сделаем.

Это немного раздражает и это не очень интуитивно. Но хорошо когда мы находимся в месте где определена структура. Здесь мы можем сделать CREATE STRUCT FROM SELECTION. Обычно мы будем создавать структуру в некоторой функции где она не определена, ничего не зная о ней.

Я знаю, что если проанализировать представление стека функции MAIN, я мог бы здесь использовать опцию CREATE STRUCT FROM SELECTION и это облегчило бы мне жизнь, но давайте возьмём наихудший случай. Представим, что мы находимся в функции очень большой программы и что мы далеко от того места, где она была определена, так что мы должны исправить их как только можем.

28.png

Здесь мы видим, что для создания структуры Вы должны нажать клавишу INS. Сделаем же это.

29.png

Я могу назначить имя, какое захочу. Назовём нашу структуру MYSTRUCT.

30.png

Здесь она была создана мной с размером 0. Сейчас я буду делать трюк. Когда я всё ещё не знаю полей или чего-то ещё и я хочу дать полю размер, сначала я нажимаю D на слове ENDS, чтобы добавить одно поле.

31.png

Здесь я добавляю поле длиной 1 байт DB. Если бы я снова нажал D, я бы переключился на слово DW и затем на DD.

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

32.png

Так как я видел поле со смещением 0x14.

33.png

Таким образом, чтобы заполнить это поле с помощью DWORD, структуре нужно ещё 4 байта, поэтому я буду создавать структуру из 0x18 байт. Я буду добавлять ещё 0x17 байт к байту, который был у структуры.

34.png

35.png

Я вижу, что размер стал равен 0x18. Теперь мы оставим структуру такой.

Поскольку эта функция вызывается дважды, первый раз с адресом первой структуры типа MYSTRUCT, которую мы будем произвольно называть PEPE и второй раз с адресом второй структуры того же типа MYSTRUCT, которую мы будем называть JUAN. Внутри функции, мы будем давать общее имя, которое будет обслуживать оба случая.

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

36.png

37.png


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

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

38.png

Я вижу, что определение переменной является простым типом INT, а не как в исходном коде как адрес структуры. Я могу это исправить так.

39.png

Это позволяет выбрать адрес структуры, в котором она находится, и здесь мы будем выбирать тип MYSTRUCT.

40.png

Очевидно, что BUF - это PEPE и здесь он получает свой адрес и передаёт его как аргумент. Давайте посмотрим BUF в представлении стека.

Поэтому структура необязательна, чтобы создать её, потому что она уже существует. Я просто должен сказать Вам, что BUF – это переменная типа MYSTRUCT. Для этого нажмите сочетание ALT + Q на переменной BUF.

41.png

и IDA назначит переменной BUF тип MYSTRUCT. Если мы поместим размер ниже, некоторые поля будут опущены, но затем можно будет увеличить структуру MYSTRUCT и она будет исправлена только здесь.(Если она не сломается конечно)

42.png

Мы переименовываем BUF в PEPE.

Мы видим здесь, что адрес PEPE передан и во втором вызове передаётся адрес VAR_44, которая также будет переменной JUAN типа MYSTRUCT, поэтому мы пойдём в представление стека и на переменной VAR_44 мы также нажмём ALT + Q.

43.png

У нас уже есть две структуры типа MYSTRUCT.

Я возвращаюсь в функцию.

44.png

45.png

Мы видим, что поле 0x10 является DWORD где оно передаётся функции SCANF, поэтому мы переходим в MYSTRUCT и в поле 0x10 мы нажимаем D до тех пор пока оно не будет иметь тип DD.

46.png

47.png

Я переименую это поле в NUMERO.

48.png

Другая запись - это поле по смещению 0x14, которое используется в цикле для удаления символа 0xA. Я назову его C.

49.png

Давайте пойдём в поле по смещению 0x14 структуры MYSTRUCT и будем нажимать D до тех пор пока не появится DWORD и давайте назовём это поле именем C.

50.png

51.png

[​IMG]

1 8.216
yashechka

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

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