# [11] Chicken Dance (1/2)

## Идея задачи

Методом реверс-инжиниринга разобрать мини-игру, написанную при помощи библиотеки SDL2, 
и выяснить секретную комбинацию движений курицы, которая расшифрует нам флаг.

## Решение

### Обзор данных файлов

Нам дан архив [chicken-game-dev.zip](../public/chicken-game-dev.zip).

Распаковываем и видим:
- Скрипт run.sh
- Директория build с каким-то исполняемым файлом
- Директория resources с какими-то картинками
- Директория Docs с документацией и исходниками библиотеки SDL2.

В run.sh видим запуск файла `./build/main-dev`. Пробуем запустить его, видим какую-то игру с курицей из minecraft.

![alt text](img/1773349232791_image.png)

При нажатии клавиш курица двигается, а в левой части экрана записывается последние 6 движений курицы. Сверху видим какой-то счётчик очков.

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

### Погружаемся в исполняемый файл.

Загружаем файл в гидру, ждём пока проанализируется.

Поверхностно смотрим функции и строки.

Из функций мы понимаем, что:

- Программа написана на плюсах
- Тут явно используется криптография (функции EVP_* и прочие)
- Используется библиотека SDL2 для отрисовки графики (для этого и приложена библиотека с документацией в /docs)
  
![alt text](img/1773359457702_image.png)


Из строк становится ясно, что

- Автор решил оставить символы, что должно помочь в реверсе. Всё же на решение всех задач даётся всего 5 часов.
- Среди Строк можно заметить какие-то комбо

![alt text](img/1773359429467_image.png)


Смотрим по перекрёстным ссылкам (xref) что за комбо и где они используются. Видим, что какой-то массив `(int*) key_pressed` сравнивается с массивами значений, которые начинаются с `combo_`. 

![alt text](img/1773359657218_image.png)

![alt text](img/1773359710665_image.png)

Если посмотреть по xref что за `(int*) key_pressed` и как с ним взаимодействует программа, то увидим выше, что на основании значений этого массива что-то рендерится:

![alt text](img/1773359835704_image.png)

А ещё выше в этот массив записываются значения. Не забудьте поменять тип данных для `key_pressed` чтобы декомпилятор корректно отображал взаимодействие с этим массивом.

![alt text](img/1773359944703_image.png)


Чуть выше мы видим функцию `SDL_PollEvent`, на основании которой в переменную `local_c8` сохраняется следующее событие в очереди событий и оно обрабатывается. Если посмотреть документацию, которая приложена в `/docs`, то станет понятно - `local_c8[0x0] == 0x300` это проверка на событие нажатия клавиши, а значит в следующем блоке происходит проверка нажатых кодов клавиш.

После нужно найти в исходниках\документации соответствующие коды клавиш. Либо можно поступить проще - просто импортировать все типы данных из библиотеки в гидру.

![alt text](img/1773360443599_image.png)

> Правда надо будет немного помочь гидре распарсить базовые типы данных SDL2 - их нужно добавить в базу данных чтобы не было ошибок.
> ![alt text](img/1773360689477_image.png)

> Нам нужен файл SDL_Scancode.h. Там нам нужен только один тип данных, собственно SDL_Scancode - его можно положить в отдельный файл с расширением .h и его импортировать, чтобы не править 100500 ошибок парсинга макросов C.

После этого выясняется, что проверяются нажатия клавиш стрелок на клавиатуре. И действительно, если мы попробуем их нажать, то курица будет двигаться, а нажатые клавиши сохранятся в массив из 6 слотов. 

> Число выглядит странным потому что это на самом деле SDLK_SCANCODE_MASK | <нужный код клавиши>
> ![alt text](img/1773361828581_image.png)

Подождите, но ведь `key_pressed` это тоже массив на 6 интов! И в него сохраняются нажатые клавиши в каком-то своём формате enum-а.

Восстанавливаем enum на основании проверки нажатых клавиш через SDL, получаем что

- Код 01 - Стрелка влево
- Код 02 - Стрелка вправо
- Код 03 - Стрелка вверх
- Код 04 - Стрелка вниз

Получается, что массивы `combo*` - это просто нужные стрелки, которые нужно нажать чтобы засчиталось комбо.

![alt text](img/1773362121088_image.png)

При этом можно заметить, что одно из комбо помимо очков ещё и расшифровывает нам флаг.

![alt text](img/1773361991877_image.png)

Нужная комбинация для получения флага - Вверх, Вверх, Вверх, Влево, Вправо, Вниз.

![alt text](img/1773362051422_image.png)

### Флаг

`vsosh{chicken_secret_move}`

# [11] Chicken Dance (2/2)

## Идея задачи

Методом реверс-инжиниринга разобрать мини-игру, написанную при помощи библиотеки SDL2, 
и набрать 13371337 очков, при достижении которых расшифруется флаг.

## Решение

### Способы решения задачи

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

а) В статике патчим проверку на какое-то маленькое число по типу 100. Быстро набираем случайную комбинацию, получаем флаг.
б) В динамике поправить кусочек памяти, который содержит количество набранных очков.

Посмотрим на статический способ решения задачи через Ghidra.

### Как запатчить инструкцию в Ghidra

Нам нужно запатчить проверку, расположенную по адресу `00108066`

![alt text](img/1773362267187_image.png)

![alt text](img/1773362281332_image.png)

Для этого в гидре есть специальный инструмент, который можно выбрать через контекстное меню (ПКМ по инструкции)

![alt text](img/1773362342159_image.png)

Патчим на какое-то маленькое значение, например 0x10, и сохраняем файл через экспорт в `File > Export`.

![alt text](img/1773362628059_image.png)

Делаем `chmod`, запускаем файл из правильной директории чтобы загрузились ресурсы, набиваем небольшое количество очков делая случайные 6 движений, получаем флаг.

![alt text](img/1773362752430_image.png)

### Флаг

`vsosh{winner_winner_chicken_dinner}`

# Альтернативный способ решения задач для криптографов

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

Сначала из пароля `reverse-from-greg0r0-with-love` при помощи PBKDF2 вырабатывался ключ для AES-256-CBC, а затем при помощи AES расшифровывался флаг.

Чтобы этот вариант решения был валидным, то для обоих флагов использовались одинаковые параметры PBKDF2 и AES. 

Когда вы достанете параметры, то можно вызвать соответствующие функции в CLI версии OpenSSL:

1) Генерируем ключ на основании пароля:
```
openssl kdf \
-kdfopt digest:SHA256 \
-kdfopt pass:reverse-from-greg0r0-with-love \
-kdfopt salt:1234567890abcdef \
-kdfopt iter:100000 \
-keylen 32 PBKDF2 | tr -d ':\n'
```

Но... Почему-то при одинаковых параметрах дерайв ключа в библиотеке OpenSSL и CLI OpenSSL отличается. Поэтому лучше было в динамике снять ключ из памяти программы.

2) Расшифровываем секрет, предварительно положив хексы из бинаря в файл `data.hex` :

```
tr -d ' \n' < daa.hex | xxd -r -p | \
openssl enc -aes-256-cbc -d \
-K "Ключ из бинаря" \
-iv 101112131415161718191a1b1c1d1e1f -nosalt
```

Подставляя в data.hex  шифротексты получим флаги.