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

Дата публикации 3 ноя 2018 | Редактировалось 3 ноя 2018
Хорошо. Мы будем пытаться эксплуатировать переполнение стека из скрипта PYTHON. Обычно эксплуатация ядра происходит локально. Другими словами, скрипт уже эксплуатирует некоторую программу, которая не имеет привилегий системы и хочет повысить привилегии и быть с правами SYSTEM, что устраняет ограничения, которые имеет эксплуатируемый процесс, который имеет только ограниченные привилегии обычного пользователя на машине.

Поэтому, за исключением очень редких исключений, эксплойты ядра - это эксплоиты для повышения привилегий или PRIVILEDGE ESCALATION.

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

В любом случае, как код в C, так и код на PYTHON основаны на вызовах одних и тех же WINDOWS API, таких, как CREATEFILE, DEVICEIOCONTROL и т.д. Поэтому, то, что делается на одном языке, легко переносится на другой.

Давайте напомним нашу модель PYTHON предыдущего примера.

1.png

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

Напомним, что имя генерируется здесь

2.png

3.png

Здесь драйвер возвращает SYMBOLICNAME, который приходит из строки, которая находится в DEVICENAME.

4.png

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

5.png

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

Этот драйвер запущен, и я запускаю скрипт.

6.png

Поскольку SYMBOLICLINK идет отсюда, имеет смысл использовать это имя.

7.png

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

8.png

Мы видим, что всё работает.

9.png

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

10.png

На данный момент, мы удаляем WHILE и все остальное, что нас не интересует. Следующая вещь заключается в том, чтобы увидеть, какой именно IOCTL переносит нас в блок переполнение стека, чтобы отправить его.

Вопрос состоит в том, как добраться туда.

11.png

Мы видим, что драйвер идёт отсюда.

12.png

Регистр EDX имеет код IOCTL, который получается отсюда.

13.png

Программа сделает вычитание из регистра значения 0x222003, и если результатом будет нуль, мы перейдем к той части, которая нам нужна.

Давайте посмотрим, достигнет ли программа блока, где мы хотим присоединить IDA и устанавливаем BP.

14.png

Я запускаю драйвер на целевой машине и попадаю в BP.

15.png

Мы видим, что в регистр EDX драйвер считывает IOCTL код, который он передает.

16.png

17.png

Программа помещает результат в регистр EAX, вычитает из него значение 0x222003 и поскольку результатом будет нуль, драйвер переходит в уязвимый блок.

18.png

19.png

Программа читает длину, которая является нулем, так как я не передал ей аргументы за исключением IOCTL.

20.png

Поскольку аргумент равен нулю, программа пропускает функцию, в которой происходит переполнение стека.

21.png

Поскольку API функция, вызывается из WIN32FILE в PYTHON, она имеет меньше аргументов, чем исходная функция, которая имеет больше.

22.png

23.png

Здесь находится определение WIN32FILE PYTHON.

24.png

Мы увидим, что если мы достигли этого места, нам нужно сделать буфер, чтобы передать его на вход, так как поскольку нам нужен указатель на него, мы можем сделать это с помощью функции ALLOCATEREADBUFFER, которая выделяет нам в куче количество памяти, которое нам нужно передать входному буферу. (Другая опция WIN32FILE не дает нам).

25.png

Поскольку библиотека WIN32FILE не имеет доступа ко всем API, она не позволяет копировать непосредственно в буфер как функция MEMCPY или что-то вроде этого, поэтому мы можем копировать его только с помощью функции READFILE, поэтому мы делаем файл PEPE.BIN, заполняя его 0x1000 буквами A. Мы передаем файл в функцию CREATEFILE, чтобы она открывала его и вернула нам дескриптор, и мы передали его в функцию READFILE с аргументом BUF буфера, который мы выделяем и копировать содержимое файла туда.

Очевидно, что если мы сделаем это на C, C++ или языке, в котором мы можем использовать функцию VIRTUALALLOC и легко копировать с помощью функции MEMCPY или той которую мы хотим. Но здесь у нас есть определенные ограничения, и мы должны приспосабливаться к этому.

Нам нужно дополнительно знать, какую длину мы должны отправить. Давайте посмотрим на буфер назначения в IDA.

26.png

Мы замечаем, что с начала буфера до адреса возврата получается 520 десятичных байт * 4 размер элемента.

Поэтому

hex(520*4) = '0x820'

Поэтому мы должны отправить 0x820 + RET.

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

27.png

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

28.png

29.png

Здесь cуществует адрес, который мы можем передать с помощью STRUCT.PACK после 0x820 A. Досадно, что мы должны записать их в файл, который читается.

Следовательно, как только у меня есть адрес буфер.

30.png

Я пишу в файл ФРУКТЫ, которые хочу отправить.

31.png

Перед функцией READFILE скопируем их в буфер.

Давайте посмотрим, заработает ли это. В этом случае нет необходимости иметь файл, потому что он будет создан и заполнен, поэтому мы удалили предыдущий.

32.png

Для этого мы изменили аргумент на CREATE ALWAYS.

33.png

Хорошо. Предположительно здесь - наш буфер с буквами A. IDA остановлена. Давайте посмотрим, что я передаю.

34.png

Мы видим, что входной буфер, который передается в регистр EDX, показывает нам то же самое значение. Давайте посмотрим, есть ли там A.
=======================================================================
35.png
=======================================================================
36.png
=======================================================================
Он не заполнился буквами A. Давайте пропустим эксплуатацию и давайте исправим скрипт.

37.png

Я меняю EIP здесь с помощью правой кнопки и SET IP и нажимаю RUN.

Я думаю, что проблема в том, что размер буфера должен соответствовать размеру файла.

38.png

Давайте сделаем так.

Ах, уже упал.

39.png

Скрипту не хватало установки указателя файла в начале файла. Он читал файл с конца, где я оставил WRITEFILE, поэтому я не читал A. Теперь всё работает.

40.png

Я трассирую до MEMCPY.

41.png

Я добираюсь до RET.

42.png

Я продолжаю с помощью F7.

43.png

Я вижу, что я попал в буфер. Проблема состоит в том, что, поскольку я не выделил его с помощью VIRTUALALLOC, а выделяю его с помощью API ALLOCATEREADBUFFER, WIN32FILE у него нет прав на выполнение. Поэтому мне придется найти способ выделить исполняемый код другим способом.

44.png

Я добавил библиотеку CTYPES, и у неё есть функция VIRTUALPROTECT, поэтому я дал ей права на выполнение, и теперь у нас нет проблем.

45.png

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

Версия c CTYPES – это так

46.png

Библиотека использует напрямую функции CREATEFILE, VIRTUALALLOC, RTLMOVENEMORY и DEVICEIOCONTROL. Вам просто нужно быть осторожным с одним из типов, но она работает хорошо.

47.png

Здесь всё работает. Вопрос сейчас состоит в том, что мы выполняем код. Нам осталось бы делать шеллкод, потому что так у нас будет только красивый синий экран.

Мы проанализируем шеллкод и создадим его в следующей части.

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

5 767
yashechka

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

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

Комментарии


      1. yashechka 7 ноя 2018
        Спасибо.
      2. Jupiter 5 ноя 2018
        Поломались комментарии? Не работают теги и редактирование!
        yashechka нравится это.
      3. Jupiter 5 ноя 2018
        Так для новичков есть № 1, и начинать надо именно с него, а не с № 57.
        yashechka нравится это.
      4. hryu$h4 3 ноя 2018
        Объем проделанной работы поражает воображение, ты просто молоток! Но я думаю что материал подобного уровня сложности из новичков мало кто сможет оценить по достоинству, поэтому с донатом пока что так туго. Я нуб и для меня эти курсы просто океан, я захлёбываюсь информацией. Я обязательно закину деньжат тебе как только будет возможность. Всё будет ОК :-)
        yashechka нравится это.
      5. yashechka 3 ноя 2018
        Поэтому это всё бессмысленно. Нет ни одного лайка, что говорить, про донаты. Для кого перевожу - не знаю.