Головоломка «My Test Patience» від Check Point Security Academy

 «Check Point Security Academy»: суть її в тому, що фірма Check Point влітку оголосила конкурс у форматі «Capture the Flag», де не важливий минулий досвід учасника, а важливі лише його здатності до розплутування кібер-головоломок. За результатами цього конкурсу фірма набрала двадцять учасників на тримісячний професійний курс з кібер-безпеки, і всі учасники з самого початку курсу отримують повну зарплату фахівця з КБ, під зобов’язання відпрацювати у фірмі два роки після закінчення курсу.


У змаганні CTF прапор може бути навіть картинкою, наприклад такий.

Відбір учасників завершився в серпні, але сайт конкурсу продовжить діяти до наступного літа, і я запрошую бажаючих зареєструватися і спробувати свої сили заради спортивного інтересу. Конкурс складається з 12 головоломок різної складності, оцінених від 10 до 150 очок.
Тут я хочу розібрати головоломку «My Test Patience» з категорії «Surprise». Вона середньої складності (50 очок), і ось її повний текст:
Hi there,
We found This executable on the local watchmaker’s computer.
It is rumored that somehow the watchmaker was the only person who succeeded to crack it.
Think you’re as good as the watchmaker?
Note: This file is not malicious in any wayЗа посиланням — 32-бітний бінарники для Windows, який лаються деякі антивіруси, але якщо його все ж запустити, то виглядає він так:

Всередині бінарники зашифрований; запускатися під відладчиком він відмовляється; якщо до нього до запущеного спробувати підключити відладчик — він моментально завершується. Ймовірно, фахівці з Check Point обернули свою головоломку в крипто-пакер, запозичений у якийсь малварі.
Як же будемо вгадувати числа, загадане годинникарем?

Є два способи. Перший можна умовно назвати «сила є, розуму не треба»: якщо програму не можна налагоджувати наживо — значить, будемо налагоджувати мертву!
Запускаємо 32-бітний «Диспетчер завдань» (WindowsSysWOW64taskmgr.exe), клікаєм по загадковому процесу правою кнопкою миші, і вибираємо Create dump file. (64-бітний «Диспетчер завдань» для 32-бітних процесів створює дамп емулятора wow64cpu, з яким працювати складніше.)
Заглядаємо в дамп і бачимо, що як мінімум, рядки в ній вже розшифровано:

Читайте також  Управління станом в додатках на Flutter

Але рядків ні із загаданою числом, ні з прапором поки не видно.
Переходимо до гармати головного калібру WinDbg (X86) -> Open Crash Dump…

Де в пам’яті той рядок, яку ми хочемо побачити надрукованій — «Good job my friend!»?
Команда lm дозволяє визначити, що бінарники завантажений від 01140000 до 015b2000; потім s-a 01140000 015b2000 "Good job my friend!" знаходить шукану рядок за адресою 0115a0d0:

Давайте тепер знайдемо, де ця рядок друкується: може, в якій-небудь команді містяться байти d0 a0 15 01, відповідні адресою шуканого рядка? (s-b 01140000 015b2000 d0 a0 15 01)
Удача! — така команда знайшлася:

Що за код навколо цієї команди? (ub 011412f7; u 011412f7)

Бачимо, що в залежності від результату функції 01141180 друкується або шукане повідомлення, або «Wrong one…»
Код функції 01141180 займає три екрана; досить легко зрозуміти, що це реалізація strcmp(), всередину якої доданий виклик Sleep(700). Поки незрозуміло, навіщо там Sleep(); але на результат функції це все одно не впливає, так що краще розберемося, що за рядки порівнюються:

Передаються два покажчика, рівні ebp-14h і ebp-24h; другий з них перед цим передавався аргументом у функцію 011410b0.
Чи Не та ця функція, яка запитує загадане число? Перевіримо по стеку викликів (k):

Так, це саме вона!
Загальна схема головоломки тепер зрозуміла: здогадка користувача зберігається за адресою ebp-24h, загадане число — за адресою ebp-14h, потім вони порівнюються і друкується або «Good job my friend!», або «Wrong one…»
Все, що залишилося — витягнути загадане число з стекового фрейму. Його ebp нам вже відомий з стека викликів:

Ну-ка, ну-ка…

Успіх! Можна відкорковувати що-небудь смачне.

Читайте також  Як збільшити оперативну пам'ять на ноутбуці

Але залишилися без пояснення три загадкові речі:

  1. Навіщо всередині тутешньої strcmp() виклик Sleep(700)?
  2. Чому, коли ми ввели загадане число, програма підвисла на десяток секунд, перш ніж надрукувала «Good job my friend!»?
  3. Який стосунок до цієї головоломці має годинникар?

Так ось, виявляється, що є другий — більш інтелектуальний — спосіб відгадати загадане число. Якщо просто пробувати навмання цифри 0-9, то легко помітити, що на дев’ятці програма трошки «підвисає». Якщо пробувати числа 90-99, то можна помітити, що на 98 програма «підвисає» вдвічі надовше. (Расковыряв її тельбухи, ми вже розуміємо, в чому справа: успішне порівняння кожної пари символів викликає затримку на 0.7 с.) Щоб вирішити головоломку, навіть не запускаючи відладчик, достатньо було підбирати кожну наступну цифру так, щоб затримка до відповіді збільшувалася або вручну з точним секундоміром, або нескладним скриптом. Таким чином укладачі натякали на давній спосіб атаки на криптографічні алгоритми, коли заміряються і аналізується час до повідомлення про помилку.

Але навчитися розколупувати програми, обгорнені невідомими крипто-пакерами — на мій погляд, і цікавіше, і цінніше 🙂
Зауважте, що нам не потрібно розбиратися ні яким чином бінарники зашифрований, ні яким чином в стеку з’являється рядок із загаданою числом (ми бачили в дампі, що серед строкових констант її немає) — і те, і інше ми зуміли отримати готовим, причому на все про все вистачило дюжини команд WinDbg.

Степан Лютий

Обожнюю технології в сучасному світі. Хоча частенько і замислююся над тим, як далеко вони нас заведуть. Не те, щоб я прям і знаюся на ядрах, пікселях, коллайдерах і інших парсеках. Просто приходжу в захват від того, що може в творчому пориві вигадати людський розум.

Вам також сподобається...

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *