Завершилась третья неделя нашего марафона, позади — первый серьёзный таск. Поздравляем всех, кому он оказался по зубам, но советуем не прятать Иду далеко — через некоторое время она вам ещё пригодится.
На данный момент скорборд таков:
herrlestrate 600
R3seh 600
W0lFreaK 600
roflanLUL 300
Kotoline 300
alex12321xela 300
tvoikoteika 300
fixed_e 300
Root_bash 300
elly_zing 300
enriqvalch 300
Kathrin17 300
None 300
mlsDmitry 300
Slonser 300
revker 300
pigadoor 200
None 200
zxexTB 200
awawa0_0 200
None 200
nikolaenkovalerii 200
Fr0stt 200
artmayer 200
Alexstar_46 100
ilya_kurbet 100
ciplenok57 100
AsformeMynameisAyat 100
meyakovenkoj 100
maximadrian 100
None 100
finkrer 100
kekov 100
konseytov 100
shokking 100
aquaearth 100
s4lat 100
ol_euua 100
keltecc 100
None 100
- JekRid 100
Как можно заметить, в турнирной таблице уже появились лидеры с весомым отрывом. И к счастью и к сожалению, пока это ничего не значит — на десерт у нас припасены самые сложные таски, решив которые можно полностью перевернуть игру. Даже если пока у вас 0 баллов. Но о новом задании мы поговорим чуть ниже, а сейчас — райтап на реверс предыдущей недели:
Смотрим строки, видим, что файл запакован UPX-ом.
Пытаемся распаковать.
UPX пишет, что бинарный файл им не запакован. Открываем файл в IDA, смотрим таблицу импорта. Видим, что она пустая, значит, бинарь действительно запакован (нормальные упаковщики шифруют таблицу импорта и получают нужные функции динамически).
Нам нужно распаковать бинарь, сделать это можно разными способами:
Можно попытаться восстановить метаданные (они испорчены, поэтому распаковать нельзя), а затем распаковать с помощью самого UPX-а.
- Поставить брейкпойнт на переход на OEP (Original Entry Point — оригинальная точка входа, это точка входа запакованного файла, на неё выполняется переход после распаковки).
После распаковки мы должны найти main, это сделать очень просто: достаточно найти возле точки входа инструкцию вида mov rdi, (какой-то адрес), после которой следует вызов __libc_start_main.
Дважды нажимаем на "offset sub_4014ee", и IDA открывает main, нажимаем tab, чтобы увидеть вывод декомпилятора.
Судя по всему, sub_400470 — это strncmp, и здесь пользовательский ввод сравнивается со строкой "CTF{3z_r3v3rs3_nggyu}" (nggyu — это Never Gonna Give You Up). Если мы попытаемся запустить бинарный файл и передать ему на вход флаг, то он напишет, что флаг неправильный, но, если мы запустим в отладчике, то увидим, что флаг правильный.
Делаем вывод, что в программе есть антиотладка и, в случае, если она детектирует отладчик, срабатывает этот код. Смотрим функцию loc_401493 — на первый взгляд она просто выводит флаг, но, если посмотреть внимательнее, то можно увидеть странные инструкции в конце.
Здесь использована техника jump in the middle — это когда байты добавляются к нужным инструкциям в начале, чтобы дизассемблер распознал инструкции неправильно, а потом добавляют куда-то инструкцию jmp, которая прыгает не на саму инструкцию, а, например, на адрес инструкции + 1, таким образом можно скрывать инструкции. Наводим курсор на инструкцию "or eax, 4011C168h", нажимаем U, а затем на Ok, после чего ставим курсор на адрес 4014E0 и нажимаем C.
Видим последовательность инструкций push, ret. Push кладёт на стек значение, а ret — снимает его со стека и прыгает по нему. Т.е эти две инструкции — аналог jmp 0x4011c1. Переходим по этому адресу и сразу видим код, который осуществляет переход на фейковый код для проверки флага, если системный вызов ptrace (аргументы PTRACE_TRACEME, NULL, NULL, NULL) возвращает -1. Нажимаем tab, анализируем код.
В начале идёт вызов функции sub_400f84, она принимает 2 аргумента: указатель на строку и её длину, а затем берёт в цикле XOR каждый байт строки с 0xff и передаёт на вход какой-то функции.
Если мы применим XOR к строке с 0xff , то получим "Enter the key:". На основании этого можно понять, что эта функция — putchar. После этого следует вызов fgets (можно догадаться по аргументам или посмотреть, что она делает в дебаггере). Затем из строки убирается "/n" (sub_4004C8 — это strchr), после этого проверяется, соответствует ли введённая пользователем строка формату флага, и после этого начинается самая важная часть.
В цикле программа берёт 4 байта из строки, применяет функцию XOR с переменной (она иницаилизирована значением 0x7B465443 — "{FTC"), подаёт их на вход одной функции. Эта функция возвращает указатель на строку. Указатель вместе с длинной это строки и указателем на 16-байтный буфер мы передаём второй функции, после чего содержимое буфера сравнивается с 16-байтной строкой и массивом.
Нам осталось лишь понять, что эти две функции делают.
Первая функция разделяет строку на куски по 3 байта, их в свою очередь разделяет на 4 куска по 6 бит и каждый из этих кусочков — это индекс в алфавите с выравниванием в конце с помощью символа "=", в целом — это base64, только с другим алфавитом. Вторую функцию можно не анализировать, а просто глядя на константы понять, что это md5. Брутим 5 хэшей и получаем флаг.
CTF{fl4gus_l4gus_p1lagus}
Что касается нового задания: это всего лишь web. Web за 400 поинтов. Разработчиком которого стал Владимир Черепанов.
Если глядя на эту картинку вы ничего не поняли, то наша пояснительная бригада с радостью поделится некоторыми фактами из биографии Владимира. Участник многочисленных CTF-команд (VoidHack, C4T BuT S4D, HoS, Corrupted Pwnis, pwnthanasia — и это далеко не весь список!), куратор олимпиады RuCTF, тимлид таскового этапа Кубка CTF России 2019, автор нескольких A/D сервисов, а также разработчик десятков заданий на криптографию, в том числе — на постквантовые алгоритмы (а ещё — те самые таски, которые никто не решил).
По заверениям Владимира, таск решается очень просто. Но если у вас возникнут трудности — ждём вопросы в нашем чате.
Бот: @letoctfbot
Задание: EasyWeb
Я добавил несколько проверок в код, чтобы усилить безопасность сайта. Надеюсь, что теперь мой сайт полностью безопасен. Если вы обойдёте защиту, сможете получить флаг в директории /tmp/. Не думаю, что у вас получится.
Категория: web
Стоимость: 400
Мы в соцсетях