User1 Mon, Jun 28, 2021 5:07 AM
Самый секьюрный канал на бешаном востоке @ch4nnel1
Original write-up: https://hackmd.io/@osogi/Secure-Database
Сам таск (https://ctf.bi.zone/challenges/8)
Сначала, постучимся на сервер с помощью приведенной команды nc securedb.2021.ctfz.one 7777
, он попросит у нас id дадим ему id, который столь любезно дали нам админы 229386e9-d6b0-4006-babc-5a15f7acee72
Просто блекбокся сервер, мы мало чего получим, так что стоит взглянуть на файл из таска. В нем как нестрано дан бинарник.
Так как время поджимало (до конца ctf'а осталось около часа), то я сразу подключил читы воспользовался идой.
Там в списке функций сразу приметилась одна start_routine
, рутина все такое.
Открыв ее сразу замечаем строчку "To retrieve your medical report..."
, что говорит о том, что мы нашли функцию с которой стоит начать курить бинарь.
Дальше нас интересует функция sub_4013C8
, в которую передается сокет (20 строчка).
Тут нас будет интересовать получение данных и что потом с ними происходит. Для начала это строчки 31 и 36, по строчке 31 все понятно в переменную s
записываются 2 первых байта, и после если все хорошо в 36 строчке s
передается в функцию sub_401847
.
Чуть изучив эту функцию легко понять, что она конвертит хексовое представление байта в инт (int(s[:2], 16)
- псевдокод в студию).
Окей, вернемся к анализу sub_4013C8. Этот инт как раз записывается по адресу a2
, из дальнейшего кода модно понять, что в a2
хранится длина данных, которые будут при приняты дальше (после первых 2 символов), записаны в ptr
и возвращены в start_routine. В результате в start_routine
ptr
хранит переданные данные (без первых двух байт), а v1
- размер этих данных, и все это вместе с сокетом передается в sub_4018E5
.
Одно из самых интересных мест для нас это строчки 30-36 в них создается строчка s="SELECT * FROM PatientList WHERE HashID = '{src}'"
, где src
занимает 8 байт и получается посредством передачи в sub_401B1B
значений ptr
и v1
из sub_4018E5
. После как нестрано s
используется как sql запрос, форматированный результат которого и выдается нам по сокету назад.
Дальше я пытался понять каким HashID обладает нужный мне пациент, но решил подумать об этом позже, когда научусь генерить нужные s
. Так что я пошел изучать sub_401B1B
.
Увидев эту страшную крипто-функцию, я сразу же пошел гуглить константу C6A4A7935BD1E995
, первой же ссылкой получил https://github.com/vitkyrka/kninja/blob/master/mmh2.py, чуть изучив этот код я пришел к выводу, что он очень схож с функцией sub_401B1B
. Подав им на входы одинаковые данные (sub_401B1B
и коду), я получил одинаковый результат, что лучше всего доказывает, что sub_401B1B
есть MurmurHash2 (такое название было в ссылке выше).
Загуглив MurmurHash2 reverse
, натыкаемся на любимый сайт, stackoverflow. Хоть конкретно в этом вопросе и спрашивают про mmh3, а не про mmh2 во втором ответе есть полезная ссылочка с инверсией разных алгоритмов. Воспользовавшись все тойже константой C6A4A7935BD1E995
, найдем нужную функцию инверсии murmur_hash_64_inverse
.
Чуть поигравшись, понастраивая и помучавшись с ендингами, получил такой сишный скрипт, который получает в аргументах желаемую 8 битную строчку, и выдает 8 байт необходимых для генерации такой строчки. Потестил, работает, теперь пришло время вспомнить про s="SELECT * FROM PatientList WHERE HashID = '{src}'"
, и тут я приисполнился в сознании, осознал (вспомнил), что sql это максимально дырявая технология. Но так как из меня вебер (ну или кто обычно эксплуатирует sql), как из рыбы топор (лучшей аналогии в 4 часа ночи я не придумал), то я попросил помощи у пошлых одуванчиков моей команды
Они мне предожили использовать 'or not'
, запихнем это в уже скомпилированный код, что был разработан раньше
С первого раза не получилось, но потом я исправился. Теперь все что осталось это, отослать эти байтики на сервер, не забыв про 'хедер', который будет равен 08
(так как байтов после него 8 штук). И так же стоит не забыть про греп, чтобы потом не искать флаг в куче мусора.
Ееее флаг!
src
"SELECT * FROM PatientList WHERE HashID = '{src}'"
sub_401B1B
== MurmurHash2src
для эксплуатации "SELECT * FROM PatientList WHERE HashID = '{src}'"
(один из вариантов src
=='or not'
)src
(пример скрипта)Он будет коротким, иметь умных сокомандников - круто! А вообще, вот такие смешаные таски они и вправду прикольные, понимаешь надобность команды.
А может и неочень коротким, вот написал я уже второй райтап на русском для ctf'а, где вроде участвует немало другого народа, незнающих русский язык. Тип вот будет им интересно решение таска, а у меня мало того, что используется свободный стиль (пытаюсь не писать сухо, оставлять коментарии), так и в русском языке есть ошибки.
In short, exuse me if you read my writeups by translater.
Using russian text on photo for apology, genius!