Райтап на задачу «Тихий страж»

Fderious

Автор:

Fderious

7 ноября 2026

9

07.11.2026
Тихий страж
Категория:

Rev

Задача «Тихий страж»

xof

Автор:

xof

Первая кровь:
Testerovich
Сложность:
easy
Дата публикации:
31.08.2025
Решений:
158
Рейтинг:
4.77/5
Ссылка:
Решать

Начнём наше решение с того, что разберёмся, с чем мы работаем:

file silent_guardian

OUTPUT:

silent_guardian: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, BuildID[sha1]=033c4c2ac786080dd136f80a4683e5fa550af064, stripped

Итак, перед нами ELF-бинарь, сбилженный под библиотеку /lib/ld-musl-x86_64.so.1. В зависимости от вашей системы у вас может запуститься этот бинарь, а может и не запуститься, как у меня:

chmod +x silent_guardian
bash silent_guardian

OUTPUT:

silent_guardian: silent_guardian: не удалось запустить двоичный файл

Тем не менее на решение это особо не повлияет, задачу можно решить полностью статическим анализом.

Открываем Ghidra, закидываем наш бинарник и не забываем прожать Analyse. Идём в Symbol Tree→Functions. Функций у нас не так много, поэтому ищем ту, где присутствует много кода:

Тихий страж: Список функций бинарного файла в Ghidra

Зайдём в функцию FUN_001010e0, там мы видим выводы; вероятнее всего, перед нами функция main.

Тихий страж: Декомпилированная функция обработки команд в Ghidra

Разберёмся с логикой:

  1. pipe(&local_8c) и dup2(local_8c, 0x45)pipe создаёт неименованный канал. local_8c — это массив из двух дескрипторов (для чтения и записи). dup2(local_8c, 0x45) берёт дескриптор чтения из трубы (local_8c) и дублирует его на файловый дескриптор с номером 0x45 (это 69 в десятичной системе). Теперь всё, что будет записано в трубу, можно прочитать через fd 69.
  2. Цикл while(1)read(0x45, local_84, 99) — читает до 99 байт из fd 69 в буфер local_84. Возвращает количество прочитанных байт (sVar2). if (sVar2 < 1) break; — если read вернул 0 (конец файла) или -1 (ошибка), цикл прерывается. Поскольку записывающий конец трубы был закрыт (или никогда не был открыт), read сразу вернёт 0, и программа завершится.
  3. Обработка вводаlocal_84[sVar2] = '\0'; — завершает строку нулём. if (local_84[sVar2 - 1] == '\n') local_84[sVar2 - 1] = '\0'; — удаляет символ новой строки, если он есть. if (strcmp(local_84, "/flag") == 0) — сравнивает введённую строку с "/flag".
  4. Выдача флагаЕсли строка совпала, вызывается FUN_00101345(&DAT_00102030, 0x1a, "YnJ1aA==", 8). Затем putchar выводит каждый байт результата на экран.

Для нас тут самой важной является строка FUN_00101345(&DAT_00102030, 0x1a, "YnJ1aA==", 8). Из неё, по сути, можно получить флаг, потому что логику FUN_00101345 и значение DAT_00102030 мы можем получить, а константы нам известны. Обратимся к FUN_00101345:

Тихий страж: Функция XOR в декомпиляторе Ghidra

Если разобраться и присмотреться, то перед нами просто функция XOR одной строки на другую. В функцию подаются данные для шифрования, их размер, ключ и размер ключа.

Теперь перед написанием кода для дешифровки остаётся вытащить данные из DAT_00102030. Сделать это можно так:

  1. Жмём на DAT_00102030 в дизассемблированном коде, и нас кидает на место этих данных в памяти.
  2. Выделяем все данные.
  3. Жмём правую кнопку мыши Copy special→Python list — данные скопированы.

Теперь остаётся написать простейший Python-скрипт для нахождения флага:

enc = [0x1b, 0x1b, 0x2d, 0x72, 0x35, 0x07, 0x46, 0x7b, 0x1d, 0x31, 0x7c, 0x08, 0x3e, 0x08, 0x6e, 0x62, 0x0d, 0x26, 0x0f, 0x6e, 0x2a, 0x04, 0x64, 0x40, 0x53, 0x6e]
key = b"YnJ1aA=="

flag = bytes([enc[i] ^ key[i % len(key)] for i in range(26)])
print(flag.decode())

Флаг получен и таска решена!

Если вы нашли опечатку или ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter

Также по теме:

Райтап на задачу «Стружка-код»

/Разборы задач

Райтап на задачу «Стружка-код»

Разбираем обфусцированный Python-код: раскрываем chr() через AST, анализируем проверки и по шагам восстанавливаем флаг.
Прочитать

17

Райтап на задачу «Зона риска»

/Разборы задач

Райтап на задачу «Зона риска»

Разбираем генератор ключа и обращаем шифрование в исполняемом файле, чтобы восстановить флаг.
Прочитать

21