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

Дата публикации 19 мар 2018 | Редактировалось 24 мар 2018
Хорошо. Давайте начнем работать с версией программы, которая имеет защиту DEP. Мы знаем, что программа похожа на предыдущую, но что произойдёт, если мы запустим скрипт для версии где защита DEP отсутствует.

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

1.png

Я запускаю скрипт и присоединяюсь к процессу помощью IDA, которая уже имеет анализ файла DEP.EXE.

2.png

Я установлю BP сразу после функции GETS, чтобы увидеть, что происходит в функции SALUDA, так как процесс ожидает здесь внутри API функции, когда мы присоединяемся к нему.

3.png

Программа остановилась здесь. Я буду трассировать её до инструкции RET c помощью клавиши F8.

4.png

Здесь мы видим перезапись стека. Программа будет переходить на гаджет PUSH ESP - RET, который находится по адресу 0x7800F7C1. Здесь не должно быть никаких проблем, потому что это инструкция кодовой секции модуля и эти секции всегда имеют разрешение на выполнение. Мы нажимаем клавишу F7.

5.png

Трассируем программу далее с помощью клавиши F7.

6.png

Программа помещает в стек значение регистра ESP, а затем переходит к исполнению инструкции RET. Здесь программа будет переходить на адрес 0x78FBC8, чтобы выполнить его, как если бы это был обратный адрес для выполнения и здесь это мой шеллкод в стек. В файле NO DEP программа переходила и выполняла этот шеллкод, который я засылал. Но что происходит здесь ? Я нажимаю клавишу F7.

0078FBC4 0078FBC8 STACK[00005608]:0078FBC8

7.png

Код в стеке, который программа выполняла без проблем для файла NO DEP, не может быть здесь выполнен, потому что защита DEP удаляет разрешение на выполнение в стеке (в куче и т.д.) и оставляет только права на чтение и запись.

Что мы можем сделать здесь ?

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

Например, если я хочу поместить значение в регистр EAX, то вместо перехода на гаджет PUSH ESP - RET я буду переходить на гаджет POP EAX - RET. Я буду искать гаджет POP EAX - RET среди гаджетов IDASPLOITER в моей библиотеке MYPEPE, которая не имеет защиту ASLR.

8.png

9.png

Здесь такой гаджет расположен по адресу 0x78003D08.

10.png

Здесь, мы заменили переход на гаджет PUSH ESP - RET нашим ROP, который начинается с инструкции POP EAX, которая помещает значение 0x41424344. Это значение находится ниже в регистре EAX и затем когда программа переходит к инструкции RET (помните, что все или почти все гаджеты заканчиваются на инструкции RET) она переходит к следующему гаджету по адресу 0xCCCCCCCC. Позже я посмотрю, что это такое, но сейчас давайте выполним этот код, чтобы посмотреть, что произойдёт. Давайте снова присоединимся к процессу и потрассируем его немного, как и раньше.

11.png

Когда я дохожу до инструкции RET, я вижу как гаджет POP EAX - RET переходит в мой ROP. Значение 0x41424344, которое в конечном итоге поместится в регистр EAX и значение 0xCCCCCCCC где вы должны добавить указатель на следующий гаджет. Давайте потрассируем этот гаджет с помощью клавиши F7.

12.png

Мы переходим к моему первому гаджету. Это гаджет POP EAX - RET. Мы знаем, что инструкция POP берет значение с вершины стека и помещает его, в нашем случае, в регистр EAX. Если я выполю код с помощью клавиши F7.

13.png

Здесь это значение было помещено в регистр EAX, и поскольку программа достигла инструкции RET, теперь она будет переходить на следующий гаджет, в этом случае на адрес 0xCCCCCCCC. У Вас его ещё нет, но мы должны добавить его сюда.

И всё это называется ROP. Объединяя разные гаджеты вместе, программа будет делать то, что пожелаю. Гаджет будет выполняться один за другим. Вот почему всё это называется ROP (RETURN ORIENTED PROGRAMMING). Потому что мы исполняем код без сборки наших собственных инструкций. Мы только помещает список адресов, которые указывают на кусочки кода. Они служат нам для достижения цели и приводят к захвату системы.

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

Общий метод состоит в том, чтобы разместить определенные значения в регистрах и затем перейти к гаджету PUSHAD - RET. Мы увидим, что программа будет перестраивать всё. Хотя есть тысячи способов собрать ROP. Это самый распространенный метод.

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

Мы знаем, что сейчас есть две вкладки с модулями. Это IDASPLOLITER и сама IDA. Последняя находится в меню DEBUGGER→ DEBUGGER WINDOWS → MODULE LIST. Здесь мы сделаем щелчок правой кнопкой по библиотеке MYPEPE и будем анализировать его. Затем заставьте IDA загрузить его символы, если они конечно, есть.

14.png

Поскольку у нас нет символов для библиотеки MYPEPE, это выглядит хорошо(???), но IDA не добавляет никакой информации про импортированные функции, которые видно в списке функцией. Там есть только для библиотеки MYPEPE(???).

Но хорошо, давайте будем искать строку OFF_.

15.png

Мне не нужны все вхождения. Только одно.

16.png

Инструкция CALL является типичным переходом к импортированной функции IAT, так как префикс OFF_(не путать с OFFSET, который указывает адресом) в этом случае означает, что это содержимое адреса, куда программа будет переходить. Он также является указателем, как в случае IAT. Давайте перейдём по этому адресу.

17.png

Хорошо. Смотря между функциями IAT мы видим функцию VIRTUALALLOC. Поэтому мы будем подготавливать для неё ROP (мы уже знаем, что 0x7802E0B0 это начало IAT VA. С этого момента я будет называть VIRTUALALLOC –> VA)

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

18.png

Мы видим, что нам нужно поместить значение 0x90909090 в регистр EAX. Для это есть гаджет PUSH EAX - RET мы уже добавили его. Теперь нам нужно изменить регистр POPEA на регистр EAX в 0x90909090, но регистр EAX всегда соглашается установить его последним, потому что он может быть необходим для установки других значений. Рекомендуется добавлять сначала самые сложные. В регистре ESI должен быть адрес функции VIRTUALALLOC, но у нас есть только расположение IAT и адрес API будет меняться, записи IAT не будет. Поэтому основываясь на местоположении, мы будем искать адрес и ROP будет работать всегда.

Для этого, мы должны искать самые простые гаджеты. Если есть такой гаджет MOV ESI, [РЕГИСТР] - RET. Давайте искать эту последовательность среди гаджетов.

Такого гаджета нет, но зато есть такой.

19.png

Всё хорошо. Мы помещаем в регистр EAX адрес IAT + 4 и с помощью этой инструкции мы помещаем адрес API в регистр EAX. Нам придется переместить значение из регистра EAX в регистр ESI с помощью другого гаджета. Но давайте упорядочим всё это и попробуем всё это в деле.

Расположение записи IAT было по адресу 0x7802E0B0. Мы добавим к ней значение 4 и поместим значение в регистр EAX с помощью гаджета POP EAX - RET, который у нас уже есть.

20.png

При этом у нас будет местоположение IAT + 4 в регистре EAX. Следующий гаджет будет тем, который мы уже нашли.

780022DE MOV EAX, [EAX - 4] # RETN

21.png

Здесь мы объединяем оба гаджета. Давайте протестируем их, чтобы убедиться, что они делают то, что мы задумали и адрес VIRTUALALLOC остаётся в EAX.

Одно из неудобств, которое мы увидим, заключается в том, что IDASPLOITER работает только в режиме отладки. Поэтому если нам нужно отлаживать, он будет закрываться при перезагрузке, но мы можем открыть другой экземпляр IDA с процессом c остановленным процессом отладки, для того чтобы найти его в IDA SPLOITER и отлаживать его в другом окне.

22.png

Мы будем трассировать ROP, который мы сделали, до этого места с помощью клавиши F7.

23.png

Теперь программа будет помещать адрес записи IAT из VA + 4 в регистр EAX.

24.png

Сейчас, программа будет переходить на второй гаджет. Я продолжаю с помощью клавиши F7.

25.png

Я исполняю гаджет с помощью клавиши F7.

26.png

Мы видим, что мы достигли нашей цели. Адрес API находится в регистр EAX и мы вытащили его из IAT. Поэтому он будет работать на любой машине. Следующий гаджет должен поместить VA адрес из регистра EAX в регистр ESI, чтобы он оставался в регистр ESI, где это соответствует следующему.

27.png

Здесь нет инструкции MOV ESI, EAX или что-то в этом роде. Поэтому мы должны использовать наше воображение. Несмотря на то, что гаджеты обычно заканчивает на инструкции RET, любой код, даже если он не заканчивается на RET, позволяет мне продолжать и удерживать контроль. Он также будет считаться гаджетом, хотя он и менее традиционный, но он всё равно будет работать.

28.png

Если я помещу значение регистра EAX в стек используя гаджет PUSH EAX - CALL ESI и подготовлю регистр ESI для гаджета POP ESI - RET, я мог бы поместить содержимое регистра EAX в ESI используя стек. Давайте посмотрим на этот случай.

29.png

Поэтому я буду добавлять гаджет POP ESI – RET в ESI раньше.

30.png

31.png

Мы видим, что инструкция POP ESI, помещает в регистр ESI тот же самый указатель на гаджет POP ESI – RET, чтобы после следующего гаджета восстановить управление.

32.png

Этот гаджет будет помещать в стек адрес VA и снова переходит с помощью инструкции CALL ESI обратно к гаджету POP ESI - RET так как мы сохранили адрес гаджета POP ESI - RET в регистр ESI.

33.png

Мы видим, что гаджет не сработал, потому что он помещает адрес возврата, который он сохранил в регистр ESI и чуть ниже это адрес VA. Поэтому вместо гаджета POP ESI - RET последним должен быть гаджет POP XXX, POP ESI - RET что перенести первое значение из стека в другое место и затем вытолкнуть в регистр ESI адрес VA.

34.png

Вот нужный нам гаджет. Поэтому я меняю именно его, который я помещаю в регистр ESI. Другой гаджет должен оставаться таким же.

35.png

Давайте попробуем сейчас.

36.png

Я вхожу в гаджет с помощью клавиши F7.

37.png

Готово. Первая цель уже достигнута. В регистре ESI находится адрес VA и программа будет переходить по адресу 0xCCCCCCCC, который является адресом следующего гаджета. Поэтому я снова взял контроль над выполнением.

38.png

Следующий гаджет будет легче. В регистр EBP мы должны поместить адрес гаджета JMP ESP, CALL ESP или PUSH ESP - RET. У нас уже был гаджет PUSH ESP - RET. Мы только должны найти гаджет POP EBP - RET чтобы поместить его в регистр EBP.

39.png

40.png

41.png

Это настройка для регистра EBP. При этом, он будет установлен с указателем на гаджет PUSH ESP - RET. Давайте продолжим.

42.png

EDI = ROP NOP означает, что регистр должен указывать на RET, который является NOP в программировании ROP. Поэтому давайте найдем гаджет POP EDI - RET для установки регистра EDI.

43.png

44.png

Мы устанавливаем любой указатель библиотеки MYPEPE на RET. Он переместит его в регистр EDI. Давайте продолжим.

45.png

Нам нужно установить 4 константы: значение 90909090 в регистр EAX, значение 40 в регистр ECX, значение 1000 в регистр EDX и значение 1 в EBX. Мы будем искать соответствующие POP и добавлять константы.

46.png

47.png

48.png

49.png

Давайте добавим их в нашу цепочку ROP.

50.png

Готово. Теперь нам нужен только последний гаджет, который завершит всю цепочку. Им будет PUSHAD - RET.

51.png

Вот он. Инструкция ADD AL, XX ничего не делает, потому что до этого была инструкция PUSHAD. Поэтому он будет сохранять 90909090 в стеке. Давайте добавим его.

52.png

Цепочка уже должна заработать с этими гаджетами. Давайте трассировать её полностью до тех пор пока не доберемся до функции VIRTUALALLOC.

Мы пришли к инструкции PUSHAD.

53.png

Всё выглядит хорошо. Мы нажимаем клавишу F7.

54.png

Мы добрались до функции VIRTUALALLOC. Мы видим аргументы в стеке. Первым будет место, где программа вернётся после возвращения из API. Если я посмотрю, это будет гаджет PUSH ESP - RET. Затем приходят аргументы для API. Давайте проверим.

55.png

Адрес для снятия защиты LPADDRESS принадлежит стеку и показывает, где находится мой шеллкод.

56.png

Затем идёт параметр SIZE 1, который будет снимать защиту блока длиной равной 0x1000, потому что это минимальный блок для снятия защиты. Независимо от того, что вы введете. Затем идёт значение 0x1000, которое является константой для указания типа распределения и значение 0x40, которое является другой константой FLPROTECT. Если я выполню код API до инструкции RET, то нажимая CTRL + F7, я увижу, что программа возвращается к гаджету PUSH ESP - RET.

57.png

Если в регистре EAX программа вернет адрес, то гаджет правильный и стек теперь не защищен. Сейчас я могу выполнить мой код в стеке. Я продолжаю трассировать с помощью клавиши F7.

58.png

Мы видим, что программа прибывает в мой шеллкод без проблем и он исполняется.(Аллилуйя)

59.png

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

МЫ ПОБЕДИЛИ.
=======================================================

Screenshot_5.png


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

7 634
yashechka

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

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

Комментарии


      1. yashechka 7 апр 2018
        А где написано, что я реверсер?
        И где написано, что я публицист?
      2. yashechka 7 апр 2018
        Мммммммм........., что я не так сделал?
      3. sn0w 7 апр 2018
        ты форумы перепутал, яша. одно дело быть реверсером - а другое - публицистом
      4. yashechka 24 мар 2018
        [​IMG]
      5. yashechka 24 мар 2018
        [​IMG]