Знайдіть код підтвердження
Роздатковий матеріал являє собою виконуваний файл розміром 15 КБ. Він запитує прапорець, потім виводить "Correct! або "Incorrect!. Почніть з простого запиту до свого агента.
Використовуйте REA для аналізу ms_flag_checker та пошуку прапора. Поясніть, як працюють перевірки, а потім перевірте відповідь за допомогою оригінальної програми.
Приклад запиту із завантаженим завданням, доступним локально, та підключеним постачальником програм для аналізу машинного коду.
-
Дотримуйтесь інструкцій щодо введення, щоб перейти до його функції
Агент → REAopen_binary {"path": "ms_flag_checker"} search_strings {"pattern": "flag|correct|wrong|input", "mode": "regex", "case_sensitive": false} xrefs {"address": "0x102004"} resolve_containing_procedure {"address": "0x10126d"}REA → агент * вибрані результати0x102004 "What is the flag? " 0x10201c "Incorrect!" 0x102027 "Correct!" Prompt referenced at: 0x10126d Containing function: 0x10124dПосилання дає агенту можливість провести розслідування, навіть незважаючи на те, що оригінальні імена функцій виконуваного файлу були видалені.
-
Ознайомтеся з програмою перевірки і двома її помічниками
Агент → REAanalyze_function {"procedure": "0x10124d"} analyze_function {"procedure": "0x101189"} analyze_function {"procedure": "0x101217"}REA → агент * вибрані інструкції0x1012c1: CMP EDI, 0x24 0x1012c6: LEA RBX, [0x1040e0] 0x1012cd: LEA RBP, [0x104060] 0x1012d4: LEA R13, [RBX + 0x270] 0x1012e1: CALL 0x00101189 0x1012ec: CALL 0x00101217 0x1012f1: CMP dword ptr [RBP], EAX 0x1012f4: JNZ 0x00101335 0x1012f6: ADD RBX, 0x18Перший цикл копіює коди з 36 символів. Цикл перевірки розшифровує маску, підсумовує вибрані коди та порівнює результат із збереженим числом. Його кроки розміром
0x18байт по0x270байт дають 26 масок.
Це вибрані результати нового аналізу REA. Шлях до локального цільового об'єкта скорочено для відображення; адреси стосуються імпортованого зображення REA.
Одна перевірка виявляє один символ
Програма перевірки впорядковує вхідні дані у вигляді сітки розміром 6×6. Маска визначає, які клітини беруть участь у сумі. Компактне кодування використовує негативні числа для пропуску комірок і позитивні числа для їх вибору.
Порахуйте маску та її ціль із двійкового файлу
{"address": "0x1040e0", "length": 624}
{"address": "0x104060", "length": 144}
Mask at 0x104170:
eb 01 f2 00 → -21, +1, -14, stop
Target at 0x104078:
37 00 00 00 → 55
Команда MOVSX зчитує байти маски як значення зі знаком. Ось чому eb означає -21. Метою є ціле число в порядку убування. Разом ці байти повідомляють агенту, що code[21] = 55, так що цей символ дорівнює 7.
Від інструкцій до читабельного чеку
Виберіть крок для підключення допоміжного засобу підсумовування та об'єкта, що його викликає, до того самого правила в C.
0x10121c: MOV ECX, 0x0
0x10122c: CMP dword ptr [RSI + RAX*0x1], 0x0
0x101230: JZ 0x00101223
0x101232: ADD ECX, dword ptr [RDI + RAX*0x1]
0x101223: ADD RAX, 0x4
0x1012f1: CMP dword ptr [RBP], EAX
0x1012f4: JNZ 0x00101335
int check_one_mask(const int codes[36],
const int mask[36],
int target) {
int total = 0;
for (int i = 0; i < 36; ++i) {
if (mask[i]) {
total += codes[i];
}
}
return total == target;
}
01 * почніть з нуля. ECX містить поточну суму.
02 * перевірте клітинку маски. Нульове значення пропускає символ; ненульове значення включає його.
03 * додайте символьний код. До суми додається ціле число, отримане при введенні з тим же зміщенням.
04 * перехід до наступної комірки. Початковий цикл просувається по чотири байти на ціле число і відвідує шість рядків по шість комірок.
05 * порівняти зі збереженим цільовим значенням. Абонент отримує суму в EAX. Невідповідність стає Incorrect!.
Інструкції надходять від помічника по підсумовуванню і викликає його пристрою. C - це пояснювальна записка з описовими назвами та згладженим циклом із 36 клітинок.
Розв'яжіть 26 рівнянь
У більшості масок вибирається кілька осередків. Наприклад, при першій перевірці додається 16 кодів символів, і потрібно в цілому 1441. Перекриваються вибірки дають рівняння, які може вирішити невеликий скрипт Python.
from z3 import Int, Or, Solver, Sum, sat
codes = [Int(f"code_{i}") for i in range(36)]
solver = Solver()
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_{}"
for code in codes:
solver.add(Or(*[code == ord(c) for c in alphabet]))
for code, char in zip(codes, "DUCTF{"):
solver.add(code == ord(char))
solver.add(codes[-1] == ord("}"))
for selected, target in checks:
solver.add(Sum([codes[i] for i in selected]) == target)
assert solver.check() == sat
model = solver.model()
print("".join(chr(model.eval(code).as_long()) for code in codes))
Z3-це програма-вирішувач, яка знаходить значення, що задовольняють цим рівнянням. Цей фрагмент використовує витягнуті перевірки та використовує DUCTF{…} з буквами, цифрами, символами підкреслення і фігурними дужками. Повне завантаження включає всі 26 масок і цільових об'єктів.
Перевірте відповідь за допомогою оригінальної програми
Програма захоплення процесу REA записує оригінальний виконуваний файл, який приймає прапор solved. Зміна одного вибраного символу з z на y призводить до отримання першої суми 1440 замість 1441, і програма відхиляє її.
| Уведення | Спостережуваний результат | Код виходу |
|---|---|---|
| Прапор вирішувача | Correct! |
0 |
| Один персонаж змінено | Incorrect! |
255 |
Відобразити відновлений прапор і захоплені вихідні дані
What is the flag? DUCTF{ezzzpzzz_07bcda7bfe81faf43caa}
Correct!
Відновлене значення також відповідає прапору в опублікованих організаторами метаданих задачі, який був перевірений після вирішення двійкової задачі.
Ідентифікація джерела, цілі та деталі аналізу
Новий аналіз та два записи процесів, опубліковані 8 жовтня 2026 року, використовуючи REA 4.1.0 та Ghidra 12.1.4 на Linux x64. Двійковий файл являє собою урізаний x86-64 ELF, об'ємом 15 248 байт.
dcd3bec4f608e11f3a12ce461100aaf5f621851ee63a1f870d7c90d4e3dd51ae
Посилання на рядки, функції та константи були перевірені перед читанням вихідного коду або рішення організаторів. На основі цих результатів REA було створено вирішувач Python та діаграму.
Порівняйте з джерелом, наданим організаторами · Метадані та прапор конкурсу · Примітки до доказів REA
Спробуйте самі
Завантажте оригінальне завдання та рішення в одну папку. Скористайтеся наведеною вище інструкцією, щоб провести розслідування за допомогою свого агента, або запустіть доданий сценарій.
python3 -m venv .venv
.venv/bin/python -m pip install z3-solver
.venv/bin/python solve.py
chmod +x ms_flag_checker
./ms_flag_checker
Сценарій виводить прапор кандидата; вставте його в командний рядок програми. Для вирішення потрібен Python і z3-solver. Для запуску оригінального виконуваного файлу потрібен Linux x86-64.