Forwarded from Michael Andersen
Лига новичков, задача Человек-Жук.
На сайте каждый note можно получить по его индексу, но некоторые репортажи зашифрованы в архивы. Посмотрел первые 20 записей по id, среди которых был пользователь petya.parkin, который публиковал незашифрованные репортажи про человека-жука. Но один из его репортажей все же был зашифрован (под индексом 10, https://t-bugman-18kk0hkv.spbctf.net/note/10). Я скачал этот архив и сегодня ночью ставил его на перебор. 6 часов, не перебрал.
Потом решил исходник разобрать, посмотрел как работает сайт скопировал себе генератор паролей для архивов. Он оказался уязвимым, я создал 100 млн паролей по такому же алгоритму и у них у всех первая буква была одна из 5 конкетных, вторая из 8, третья из 20, четвертая из 16 ну и дальше примерно по смыслу. А сам пароль всего из 8 символов. Благодаря этому количество перебора сократилось до 168 млн комбинаций, я сделал следующую маску для john-the-ripper и он уже перебрал все пароли. В архиве лежал адрес на веб-страницу с флагом.
Маска для джона:
На сайте каждый note можно получить по его индексу, но некоторые репортажи зашифрованы в архивы. Посмотрел первые 20 записей по id, среди которых был пользователь petya.parkin, который публиковал незашифрованные репортажи про человека-жука. Но один из его репортажей все же был зашифрован (под индексом 10, https://t-bugman-18kk0hkv.spbctf.net/note/10). Я скачал этот архив и сегодня ночью ставил его на перебор. 6 часов, не перебрал.
Потом решил исходник разобрать, посмотрел как работает сайт скопировал себе генератор паролей для архивов. Он оказался уязвимым, я создал 100 млн паролей по такому же алгоритму и у них у всех первая буква была одна из 5 конкетных, вторая из 8, третья из 20, четвертая из 16 ну и дальше примерно по смыслу. А сам пароль всего из 8 символов. Благодаря этому количество перебора сократилось до 168 млн комбинаций, я сделал следующую маску для john-the-ripper и он уже перебрал все пароли. В архиве лежал адрес на веб-страницу с флагом.
Маска для джона:
-mask='[M, N, O, Y, Z][2, D, G, T, W, j, m, z][A, B, E, F, I, J, M, N, Q, R, U, V, Y, Z, c, d, g, h, k, l][0, 1, 2, 3, 4, 5, h, i, j, k, l, m, w, x, y, z][M, N, O, Y, Z][2, D, G, T, W, j, m, z][A, B, E, F, I, J, M, N, Q, R, U, V, Y, Z, c, d, g, h, k, l][0, 1, 2, 3, 4, 5, h, i, j, k, l, m, w, x, y, z]'👍6👏1
Forwarded from S
Задача про землекопов лига опытных.
Открываем в режиме разработчика бразуер. Смотрим сеть.
Видим там запрос, раскрываем его и через курл тыкаем
curl -X PUT https://site.ctfapi/cloner/{id} -H "Content-Type: application/json" -d '{"config": {"count": 1000000}}'
Оно не срабатывает, подбираем количество каунтов опционально.
Как то так, вроде ничего не перепутал, но смысл точно тот.
Не записывал к сожалению решение(
Открываем в режиме разработчика бразуер. Смотрим сеть.
Видим там запрос, раскрываем его и через курл тыкаем
curl -X PUT https://site.ctfapi/cloner/{id} -H "Content-Type: application/json" -d '{"config": {"count": 1000000}}'
Оно не срабатывает, подбираем количество каунтов опционально.
Как то так, вроде ничего не перепутал, но смысл точно тот.
Не записывал к сожалению решение(
Forwarded from VRN
Гипнолуч
Скачиваем исходники на go и видим что с именем dr.cosmodinamikov не удастся зарегистрироваться. Пробуем им войти и использую это имя и как пароль. Внутри читаем прикольные комменты тех, кто побывал тут до тебя 😁👍
Скачиваем исходники на go и видим что с именем dr.cosmodinamikov не удастся зарегистрироваться. Пробуем им войти и использую это имя и как пароль. Внутри читаем прикольные комменты тех, кто побывал тут до тебя 😁👍
😱5👎3😁1
Forwarded from thxStuck
к доменному имени через / добавляем docs
https://t-bugman-18kk0hkv.spbctf.net/docs
мы переходим на FastApi
Тут у нас есть все Get и Post запросы сайта
😱5👍1
Forwarded from thxStuck
Видим /bugman-photos-stash-20240328
Нажимаем на него и тыкаем Try it out -> Execute
Forwarded from thxStuck
Получаем html code. Отсюда уже можно взять флаг, но мы обязаны увидеть картинку))
Forwarded from thxStuck
Forwarded from Vladimir Markov
Привет. По задаче "Элементарно, Ватсон!" в канале какое-то очень сложное решение предложено. Есть в разы проще в одну строчку кода)
В задаче сказано что используется "Усовершенствованный классический метод шифрования" (имеется в виду классический шифр древней спарты). Просто вместо одной палочки там две. Однако на процедуре взлома это никак не сказывается, принцип остается точно таким же: нам нужно подобрать такой
На строчках 11 и 12 замечаем две части нашего ключа:
В задаче сказано что используется "Усовершенствованный классический метод шифрования" (имеется в виду классический шифр древней спарты). Просто вместо одной палочки там две. Однако на процедуре взлома это никак не сказывается, принцип остается точно таким же: нам нужно подобрать такой
m, чтобы data[::m] представлял собой осмысленный текст. При m = 32 мы получаем "HOLMES_CASE_DB||Case_1:_The". Далее выводим все остальные строчки (соединять их в один текст не будем - слишком сложно):data = "H_S_|_e_gI..."
print("\n".join(data[i::32] for i in range(32)))
На строчках 11 и 12 замечаем две части нашего ключа:
m3_th0Ugh7_r3WarD_bRoU6ht} и tctf{Cr1. Остается только их правильно соединить.❤5👍1👏1🤯1
Forwarded from Vladimir Markov
Еще там нет решения задачи "Доктор Хаос":
Ключевые элементы, которые нужно было заметить:
1. Используется симметричное шифрование без перестановок с помощью надежного алгоритма RC4 (взломать его возможно)
2. Строка до шифрования представляет из себя результат сериализации protobuf структуры (первые 3 байта служебные, потом zip от введенного текста, служебные байты, zip от флага и еще служебные байты)
3. Для генерации ключа используется
Так как алгоритм RC4 взломать невозможно, а алгоритм генерации ключа явно очень слабый, стоит атаковать его. Все что нужно сделать это написать C++ программку, которая будет подавать на вход EncryptBirthmaRC4 один и тот же текст (главное не забыть про служебные байты от protobuff) и сверять что первые N байт (например 4) зашифрованного текста совпадают с теми что лежат в patient-chart.bin (или наоборот можно подавать зашифрованный текст на вход - без разницы, шифрование делается с помощью xor). Так как initial_seed локально и на сервере равен 1, а количество запросов на сервер скорее всего не превысило 100к, правильный seed (а с ним и key) мы найдем меньше чем за секунду. После чего используем найденный ключ для расшифровки текста.
По сути вся задача решалась в 6 строчек:
Ключевые элементы, которые нужно было заметить:
1. Используется симметричное шифрование без перестановок с помощью надежного алгоритма RC4 (взломать его возможно)
2. Строка до шифрования представляет из себя результат сериализации protobuf структуры (первые 3 байта служебные, потом zip от введенного текста, служебные байты, zip от флага и еще служебные байты)
3. Для генерации ключа используется
default_random_engine, который представляет из себя самый простой псевдослучайный генератор. Более того, каждый раз при запуске программы seed будет одним и тем же (initial_seed=1), никакой инициализации от текущего времени.Так как алгоритм RC4 взломать невозможно, а алгоритм генерации ключа явно очень слабый, стоит атаковать его. Все что нужно сделать это написать C++ программку, которая будет подавать на вход EncryptBirthmaRC4 один и тот же текст (главное не забыть про служебные байты от protobuff) и сверять что первые N байт (например 4) зашифрованного текста совпадают с теми что лежат в patient-chart.bin (или наоборот можно подавать зашифрованный текст на вход - без разницы, шифрование делается с помощью xor). Так как initial_seed локально и на сервере равен 1, а количество запросов на сервер скорее всего не превысило 100к, правильный seed (а с ним и key) мы найдем меньше чем за секунду. После чего используем найденный ключ для расшифровки текста.
По сути вся задача решалась в 6 строчек:
int main(int argc, char* argv[]) {
// Содержимое patient-chart.bin
std::string ciphertext = {5, 110, -102, 115, ...};
for (int i = 0; i < 100000; i++) {
std::string plaintext = EncryptBirthmaRC4(ciphertext);
// Проверяем удалось ли расшифровать
if (plaintext[0] == -48 && plaintext[1] == -111 &&
plaintext[2] == 60 && plaintext[3] == -32) {
printf("Message decoded on #%d! See plaintext\n", i);
}
}
}
❤1