- Название: Странный PWN?
- Категория: pwn
- Платформа: codeby.games
Конечно, первые 2 пункта выглядят интересно, но что-то подсказывает, что интересней всего будет выбрать пункт 3:
У нас появился какой-то mood, явно не соответствующий реальному, и программа зажилила нам флаг. Так что ковырнём её с помощью IDA:
А тут всё на ладони, под каждую опцию есть своя функция, вызываемая в зависимости от введённого нами символа. И нас, в первую очередь, интересует функция get_flag():
Здесь алгоритм следующий: сначала мы вводим ответ на вопрос "Do you want a flag?", после переменная change_mood сравнивается с единицей, и, если проверка пройдена, то нам дают флаг. Но что интересно: эта переменная нигде не меняется на единицу, а значит - нам самим придётся до неё добраться ручками. Вот её отображение в памяти:
А вот переменная, которая соседничает с ней:
И эта str - та самая переменная, которая используется для хранения ответа на вопрос "Do you want a flag?", она указана в fgets (13-я строка, 2 картинки назад). Между этими метками в секции .bss никаких больше нет, но обратите на адреса этих меток:
0x4AA0C0
для str и 0x4AB0B0
для change_mood. Посчитайте разность, и вы получите число 4080 - именно столько символов нам нужно занести в качестве ответа, чтобы следующий перезаписывал change_mood. Попробуем пронести строку вида "a" * 4080 + "b"
, чтобы увидеть, возымеет ли эффект эта попытка. Подобную строку легко написать на питоне:Дебажить это дело я буду из-под WSL, в IDA соответствующий пункт "Remote Linux Debugger" и небольшая настройка с IP и портом. Копируем получившуюся строку и в процессе дебаггинга вставляем это дело на место str:
А теперь глянем в память:
Сработало! Теперь change_mood хранит в себе символ 'b', или, десятеричным числом, 98. Но нам-то нужно, чтобы там была единица! А если посмотреть в
Ссылка скрыта от гостей
, то chr(1) == CTRL+A
(да-да, такие комбинации - отдельные символы). Заметьте, если попытаться ввести питоновский "\x01", то это лишь будут 4 соответствующих символа. Поэтому воспользуемся методом, который описан
Ссылка скрыта от гостей
- вставим 4080 символов а
, а затем... Просто нажмём CTRL+A
!И снова сработало! Теперь всё, что нам осталось сделать - подключиться через netcat и проделать всё то же самое:
Получилось, таск решён! И, казалось бы, всё круто - но я не указал вам один момент. Внимательного читателя этот райтап смутил одним моментом:
В fgets стоит ограничение на 4000 символов! Тем не менее, нам удалось пробросить аж 4081 символ... Странный, какой-то PWN, не находите?
Когда я увидел это ограничение, я, конечно, огорчился, поняв, что мне не хватает 81 символа, но всё же попробовал, можно сказать - попытал удачу. И каково же было моё удивление, когда сработало!
А оказалось всё интересно: спасибо @yetiraki - он подсказал, что fgets оказался самописной функцией. И действительно - второй аргумент в её псевдокоде мелькает лишь в проверке на неотрицательность, и больше нигде. Полагаю, как такового ограничения по символам эта функция вообще не имеет...
Кстати, после того, как зарешал, придумал, как можно запускать программу, не копируя пейлоад в 4000 символов:
python3 -c "print('3\n' + 'a'*4080 + '\x01')" | ./task.elf
Будет вполне удобно решать у себя на машине!
Штош, надеюсь, этот небольшой райтап помог вам в нашей нелёгкой стезе.
Удачного пывына!
made 4 @rev_with_da_boys
Последнее редактирование: