-
Notifications
You must be signed in to change notification settings - Fork 4
Старый друг
- Категория: Reverse
- Стоимость: 450
- Автор: Михаил Гнедашев
- Репозиторий
Только что увиделись с моим давним другом. Он не богат, да и не красавец. Но говорит, что всегда носит с собой автомат. Как ни странно, оружия я у него не увидел. Удивился, переспросил. Он лишь усмехнулся и дал мне флешку с этим файлом.
- бинарник
Попытаемся разревёрсить бинарник в IDA, но не получим адекватный код, так как таск писался на nasm
. Попытаемся разобраться с ассемблером.
Рассмотрим функцию _start
, с которой и начинается исполнение программы.
Всё, что происходит до iter
- проверка аргументов. Действительно, запустив бинарник, он попросит передать ему вторым аргументом флаг.
Так же перед iter
есть инструкция mov r8 [rsp+10h]
, т.е мы кладём в регистр r8
ссылку на первый символ флага.
Внутри iter
сначала выполняем слкдующие инструкции:
mov al, [r8]
test al, al
jz short final
Здесь мы каждый раз кладём в регистр al
символ, находящийся по адресу, лежащему в r8
. Если в al
лежит 0, то прыгаем на функцию final
. (проверяем, не закончилась ли строка)
Далее кусок кода:
mov rbx, offset alpha
xlat
интерпретируем как al = alpha[al]
. Т.е. в al
после этого будет лежать элемент массива alpha
, находящийся по индексу введённого символа.
mov bx, 0Fh
mul bx
add al, state
mov rbx, offset dfa
xlat
Интерпретируется как al = dfa[al*0x0f + state]
После этого кладём в state
значение al
и переходим к следующему символу, инкрементируя r8
.
Т.е. iter
двигается по введённому аргументу и меняет state
по описанным выше правилам.
Стартовое значение state
и массивы dfa
и alpha
можно найти в сегменте data
(идущем после сегмента кода)
В функции final
следующий код:
Он проверяет, что текущее значение state
должно быть равно 4. Это будет означать, что мы всё сделали верно.
Т.е весь код можно переписать следующим образом:
state = 0x0d
dfa = [...]
alpha = [...]
for x in FLAG:
x = alpha[x]
x = dfa[x*0x0f + state]
state = x
if state == 4:
print('Right!')
else:
print('Wrong!')
Т.е. весь код представляет из себя проверку флага по ДКА (Детерминированному конечному автомату).
Для решения можно либо нарисовать этот автомат на бумаге и прочитать флаг (так как он получается довольно маленький и простой), либо отлаживая (например, в gdb
) ввод, подбирать используемые символы из alpha
(это все индексы, которые не дают 0), которые будут менять текущее состояние в нужном направлении.
Останется лишь обернуть полученный флаг в QCTF{flag}
и сдать.