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

Дата публикации 25 фев 2018 | Редактировалось 26 фев 2018
Я присоединяюсь к этому процессу.

34.png

Проиграв некоторое время ролик, отладчик остановится на BP.

Я трассирую с помощью клавиши F7 и вижу, что в регистре EDX находится адрес БУФЕРА.

35.png

Я щелкаю на маленькую стрелку рядом с регистром EDX, которая переносит фокус в листинг.

36.png

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

37.png

У меня получается вот так.

38.png

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

39.png

40.png

После нажатия на RUN, отладчик останавливается в библиотеке MSVCRT на инструкции REP MOVSD, копируя данные в буфер.

Через меню DEBUGGER → DEBUGGER WINDOWS → MODULE LIST появляется список модулей и там я ищу библиотеку MSVCRT.DLL.

41.png

42.png

Я делаю правый щелчок и выбираю пункт ANALIZE MODULE, и когда анализ закончится, я выбираю пункт LOAD DEBUG SYMBOLS, и теперь функция выглядит лучше. Мы можем увидеть её в стеке вызовов где мы находимся сейчас.

43.png

Теперь делаем так: DEBUGGER → DEBUGGER WINDOWS → STACK TRACE.

44.png

Теперь мы внутри функции MEMCPY и видим откуда она вызывается.

На самом деле, инструкция REPS MOVS копирует данные из источника, на который указывает регистр ESI в регистр EDI, который является назначением. А в регистре ECX хранится количество копируемых двойных-слов. Давайте посмотрим куда указывает ESI. Для этого делаем щелчок на стрелке, которая находится рядом с ESI, но теперь нужно сфокусироваться на режиме HEX DUMP, чтобы увидеть эти данные там.

45.png

Это то, что функция копирует в БУФЕР. Давайте откроем файл .TY в HEX редакторе и сделаем следующее.

46.png

Давайте выделим эти 32 байта и сделаем EDIT → EXPORT DATA, чтобы скопировать байты, которые отмечены, в желаемый формат.

47.png

Я думаю, что так они будут выглядеть лучше.

48.png

49.png

Итак, мы уже нашли байты, которые программа читает из файла. Мы знаем, что 14-15-16 и 17 байты - это те байты, из которых будет создаваться нужное значение. Программа добавляет к значению 8 и делает деление, а потом приходит к нужному значению. Давайте посмотрим что у нас есть в этом файле.

50.png

Нужные нам байты - 00 00 00 02. Давайте установим BP так, чтобы отладчик остановился, когда происходит возврат из функции STREAM_READ снова в библиотеку LIBTY_PLUGIN.

51.png

Я запускаю отладчик снова, потому что IP был отключен.

52.png

Сейчас буфер будет здесь.

53.png

Я могу скопировать его в HEX DUMP и добавить значение 0x14 в адрес буфера и я увижу, что это значение 00 00 00 02, которое мы и видели в файле.

Давайте будем трассировать, чтобы увидеть, что программа делает с этими данными.

54.png

Мы видим, что все эти вычисления нужны, чтобы создать переменную типа DWORD и переместить её в регистр EDI. Затем к этому регистру прибавляется значение 8.

55.png

Позже программа будет исполнять инструкцию IDIV. Давайте пойдем по этому адресу.

56.png

Здесь, это байт 0x0A, который получился из байта 0x02. Он был прочитан из файла и программа прибавила к нему значение 8. Поэтому результат равен 0xA.

57.png

IDIV - это знаковое деление. Инструкция разделит регистр EDX:EAX на размер, чтобы скопировать, который не будет изменен. Проблема заключается в том, что если я увеличу размер, чтобы скопировать больше, деление будет давать мне результат - нуль и это значение, пойдёт в функцию MALLOC после умножения на 16. Поэтому мы должны хорошо постараться с этим делением, чтобы результат не был равен 0.

Регистр EDX:EAX сейчас равен 00000000:00000148 и это значение делится на 0x0A. Если мы увидим в файле значение 0x148, то оно близко к значению 00000002.

58.png

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

59.png

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

60.png

Здесь программа создаёт число 0x4647 в регистре EDI. Затем прибавляет к нему 8.

61.png

Затем программа исполнит инструкцию IDIV 0000000:AA48, которая поделит это значение на число 0x464F.

62.png

Результат деления будет в регистре EAX и он равен 2.

63.png

Это максимальное значение, которое будет умножено на 16 и будет передано функции MALLOC. Поскольку мы не эксплуатируем переполнение кучи, во время выделения всё будет хорошо.

64.png

Так что программа вызывает функцию MALLOC с аргументом 0x20. Этот размер будет выделяться без проблем.

65.png

Указатель попадёт в блок, где есть уязвимость, со значением переменной SIZE_A_COPIAR равной 0x464F, которая очевидно больше чем 8. В пропатченной версии, программа будет игнорировать такое значение и переполнения не случится.

Я установил BPs на буфер. Регистр ECX указывает на него. Я иду туда и устанавливаю аппаратную BP на чтение и запись для того, чтобы программа остановилась, когда начнёт заполняться буфер.

66.png

67.png

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

68.png

Регистр ECX копирует 1192 DWORDS, так как REP MOVSD это REPEAT MOV DWORDS. Поэтому общая сумма, которая будет записана в 32-х байтовый буфер равна 0x1192 x 4 т.е. 0x4648. Это сумма исходит из округления числа 0x4647. Я поместил это значение в файл.

69.png

70.png

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

Я командую RUN TILL RETURN или CTRL + F7 и возвращаюсь в главную функцию, где расположен буфер, когда программа доходит до RET. Программа должна вызвать крах.

71.png

Я устанавливаю в функции BP на инструкцию RET и выключаю все другие BPs.

72.png

Я вижу, что стек разрушен, потому что я перезаписываю там все данные. Я иду в HEX VIEW и нажимаю маленькую стрелку рядом с регистром ESP.

73.png

И ищу эти байты в файле.

74.png

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

75.png

Сейчас я запускаю VLC c этим измененным файлом.

76.png

Готово. Если сейчас я запущу программу, я возьму под контроль EIP, который является целью нашего POC. Некоторые POC не делают этого. Они просто разрушают программу.

77.png

78.png

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

Нужно заметить, что расширение файла должно быть TY. Если мы его изменим, программа не попадет в уязвимую часть.

До встрече в 32 части.

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

5 757
yashechka

yashechka
Ростовский фанат Нарвахи
Команда форума

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

Комментарии


      1. yashechka 26 фев 2018
        :preved::preved::preved:
      2. LastNoob 26 фев 2018
        Не устаете радовать!)
        Благодарю :good:
      3. yashechka 25 фев 2018
        20
      4. yashechka 25 фев 2018
        Напомню, что донаты стимулируют и ускоряют дальнейший перевод.