judgement writeup

Сейчас попробуем с вами решить pwn таск под названием judgement c прошедших MMA CTF 2016!

Что же нам дано:

Нам дан файл judgement.zip [3,92 Kb] (cкачиваний: 13) и ссылка на сервис:

Host : pwn1.chal.ctf.westerns.tokyo
Port : 31729


Начнем решать!

Тип файла сразу не определи. Посмотрим, что выдаст нам команда file на данный бинарный файл:

judgement writeup

Значит перед нами 32-битный бинарный исполняемый ELF файл для Linux'a. Значит пришло время включать виртуалку и IDAPro!


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

$chmod +x judgement


Далее запустим наш бинарник:

judgement writeup

Видим, что без файла flag.txt он не запустится. Создаем в той же директории файл flag.txt с содержимым FLAGFLAGFLAG.

Заного запускаем программу:

judgement writeup

Программа требует от нас какого то ввода. Введем строку abcdef:

judgement writeup

Вот мы уже догадываемся, что программа требует на ввод флаг, который вписан в файл flag.txt. Проверим нашу догадку:

judgement writeup

Мы оказались правы!

Обобщим то, что мы пока узнали о программе:

1. Программа берет флаг из файла flag.txt
2. Принимает с нашего ввода строку.
3. Выводит эту строку.
4. Сравнивает флаг из файла и нашу строку.
5. Выводит результат сравнения.


Посмотрим внимательнее на второй и третий пункт. Ничего не напоминает?

Одной из наиболее распространенной уязвимостью является "фича" форматирования строки в С/С++, позволяющая получать значения из стека.

Подробнее об уязвимости

Форматирование строки обычно используют в функции printf и др. Наглядный пример:

#include <stdio.h>

int main(void)
{
  printf("%d", 1234);
  return 0;
}


Данный код выведет 1234 тк %d означает замену на десятичное число, которое было передано как второй аргумент.

Но если мы уберем второй аргумент из функции printf и заменим %d на %08x, то мы получим верхнее значение стека (08 означает преобразование значения в 4 байта тк в hex при переводе строки в стандартную каждый байт=символ занимает две char ячейки , например символ 'U' в hex -> str будет занимать две ячейки '55'.)

#include <stdio.h>

int main(void)
{
  printf("%x %x %x");
  return 0;
}


выведет нам первые три значения стека. Пример:

judgement writeup

Но это только ссылки на ячейки памяти, а нам нужны их значения. Для этого есть конструкция %N$s, которая выводит строковое значение. Но об этом чуть позже.


Вернемся к задаче.


Протестируем уязвимость форматирования строки, введя несколько %x:

judgement writeup

Замечания по решению:

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

• Последующее решение таска может быть заменено на обыкновенный перебор значений стека путем написания %1$s %2$s %3$s и тд. Но мы с вами проанализируем программу и по-умному найдем, какой номер в стеке нам нужен.



Меньше слов, больше дела!

Открываем наш исполняемый файл в IDAPro, переходим в главную (main) функцию и видим следующую картину:

judgement writeup

Выделенная красная строка - брейкпоинт(пауза) на выводе сообщения об ожидании ввода флага.

Первое условие проверяет наш ввод на читабельные символы, и в обратном случае выводит следующее сообщение и завершается:

judgement writeup

Нас это не сильно касается, так что переходим ко второму условию (в случае если наша строка имеет только читабельные символы):

judgement writeup


В начале первого окна замечаем вывод строки, используя уже знакомую нам функцию printf().

call    _printf


Далее у нас идет сравнение строки ввода и флага:

call    _strcmp



Ну и соответственно в зависимости от этого два перехода на "Wrong flag" и "Correct flag".


Как мы ранее убедились нам интересен момент вывода нашей форматированной строки. Ставим breakpoint на _printf, перезапускаем программу но уже в отладчике IDAPro и вводим случайные значения.

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

Вот мы достигли брейкпоинта _printf и видим следующее (некоторые окна свернуты для удобства):

judgement writeup

В правом окне Stack view мы можем наблюдать нашу текущую позицию в стеке и последующие (которые ниже). Полистаем вниз и поищем "подозрительные" записи, содержащие в себе флаг. Вот нашли!

judgement writeup

Проверим, два раза тыкнув на адрес ячейки (зеленый цвет - в данном случае 0804A0A0) и переведя взгляд на окно Hex-View-1 заметим ЭТО:

judgement writeup

Значит мы опять все верно сделали и эта ячейка хранит в себе флаг!

Теперь вернемся к форматированию строки. Помните я сказал, что %N$s выведет строковую запись под номером N из стека? Так вот чтобы вывести флаг, нам потребуется посчитать, какой по счету в стеке является эта запись (отсчет идет от нашей текущей позиции). Эта позиция будет под номером 28. И чтобы программа вывела содержимое флага нужно ввести %28$s.

Cказано - сделано:) Тестируем:

judgement writeup

Ура работает! Подключаемся к сервису, который был дан задании (для тех, кто не в курсе: на нем крутится такой же бинарник, но с флагом) и пробуем проэксплуатировать:

judgement writeup

Успех, флаг получен:)

TWCTF{R3:l1f3_1n_4_pwn_w0rld_fr0m_z3r0}



P.S. Райтап в данной категории пишу впервые, так что рад услышать ваши замечания по нему в комментариях.скачать dle 10.5фильмы бесплатно

  • Автор: drakylar
  • Комментарии: 2
  • Просмотры: 2829

Добавить комментарий

Вы не авторизованы и вам запрещено писать комментарии. Для расширенных возможностей зарегистрируйтесь!
    • Написал: swani
    • Комментарии: 6
    • 21 октября 2016 10:49
      • Нравится
      • 1
    'Эта позиция будет под номером 28.'
    Почему?)
    • Написал: AseN
    • Комментарии: 4
    • 21 октября 2016 20:20
      • Нравится
      • 1
    Цитата: swani
    'Эта позиция будет под номером 28.'
    Почему?)

    Бруут, нацальника. Обычно нужные данные лежат "где-то рядом"