💎 Кристально ясное задание [клик]
На вход дан ELF-файл crystal_clear, на быстрый взгляд видно, что он чем-то запакован, похоже на UPX. Качаем последний UPX и пробуем распаковать:
$ ./upx -d cc
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2026
UPX 5.1.0 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 7th 2026
File size Ratio Format Name
-------------------- ------ ----------- -----------
upx: cc: CantUnpackException: l_info corrupted
Unpacked 1 file: 0 ok, 1 error.
К сожалению получаем ошибку, проверим на обычные трюки по коррапту UPX'a (аналогично можно просто дампнуть бинарь в рантайме, что проще и не требует ничего восстанавливать, но так менее красиво смотреть на решение). Видим что upx magic value в хедере неверный, он не "UPX!", а "BOBA". Пробуем восстановить его заменив на UPX!, затем распаковать снова:
./upx -d cc
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2026
UPX 5.1.0 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 7th 2026
File size Ratio Format Name
-------------------- ------ ----------- -----------
589112 <- 192360 32.65% linux/amd64 cc
Unpacked 1 file
Нам повезло, всё распаковалось только поменяв magic value в хедере (ещё бы, таск ведь easy). Теперь смотрим на сам таск, оно просит нас инпут и затем выводит nope если инпут неверный. Найдём строку nope в IDA, и посмотрим референс на неё.
Как мы видим, XREF'ов на саму строку нет, но сверху, на полях информации (предполагается что библиотека/язык используют её как служебную инфу) есть xref, идём по нему и попадаем в main, на что-то типа проверки, отлично.
Как видим здесь v190 проверяется с v189, v190 берётся из unk_63ED0, а v189 - это наш инпут как-то преобразованный. Это единственный бренч в котором программа говорит nope. Что интересно, позже содержание v189 зачем-то используется, и после этого функция для вывода вызывается повторно. Что должно натолкнуть на мысль что то, что мы вводим не совсем флаг, да и длина сравниваемого всегда 32 байта, когда длина инпута неограничено, что значит функция преобразований - что-то в духе хэша или KDF, что вряд ли даст нам изначальную строку восстановить, так что попробуем пропатчить и понадеется на лучшее. Для этого поставим бряк перед IF'ом, и затем пропатчим v189 на содержание из v190. v189 находится как указатель в r12 на момент перед IF'ом, и сравнивается оно затем с:
d0a7cd04c00a420d2f24a82f6ab8e16a5944334c6b69b53ebbf6771cc65b993aПо коду в проверке явно видим сравнение с числом 32, да и сам v189 похож на буффер в 32 байта судя по коду, значит вероятно эта строка - это шестнадцатеричное представление байт, а значит писать будем их в r12 как bytes.fromhex, для этого сделаем следующее, используя IDAPython (аналогично можно сделать в gdb):
idc.write_dbg_memory(idc.get_reg_value('r12'), bytes.fromhex('d0a7cd04c00a420d2f24a82f6ab8e16a5944334c6b69b53ebbf6771cc65b993a'))После этого запустим программу дальше и посмотрим что произошло.

