Разбор категории ревёрс с Зимней школы ИТМО. Таски spbctf от groke и mrvos
@ Rakovsky Stanislav | Thursday, Feb 13, 2020 | 4 minutes read | Update at Thursday, Feb 13, 2020

Ыж на фоне ритуального торта.

Во время Зимней школы, spbctf подготовили для нас соревнование в формате jeopardy.

Таски на реверс за авторством @groke (Egor Zaytsev)

reverse, 150 баллов > Hand Cracker

Помогите мне решить эту крякмиху!

nc 109.233.56.90 15451

reverse, 300 баллов > Robots Taking Reversers' Jobs

Говорят, скоро всех заменят роботы. А те, кто делает роботов, будут править миром.

Начинайте править уже сейчас: решите 10 таких же крякмих, как на первом уровне.

nc 109.233.56.90 15451

Как видите, оба таска имеют одну цель, поэтому проще начать решать сразу вторую задачу, чтобы покрыть сразу два таска.

Постучавшить по нэткату, получаем такое вот приветствие.

Оно статично из раза в раз и его решение покрывает первую часть нашего задания. Второй и следующий текст генерируются рандомно.

Если упростить объяснения, получается такой механизм:

  1. Программа состоит из двух типов структур: состояний state и переходов transition.
  2. Переход характеризуется буквой перехода и ссылкой на какую-либо структуру state.
  3. Состояние характеризуется значением состояния и набором переходов (0+) к следующему состоянию. У состояний есть также индекс.
  4. Назначаются начальное (с индексом 0) и конечное (со значением состояния 0xCADE7) состояния.
  5. От пользователя требуется передать ключ, представляющий собой строку.
  6. Программа пытается пройтись от начального состояния до других, используя переходы между состояниями.

Пример схемы переходов

Таким образом, если состояние с индексом 0 будет обладать значением 1337, то ключом, который введет пользователь, должен быть RK.

Поделим программу на несколько частей:

  1. Получение кода.
  2. Парсинг кода.
  3. Нахождение пути до нужного состояния.
  4. Отправка решения.

Внизу представлен код из тетради Юпитера как есть, без красоты и дополнительных комментариев

import nclib
from time import sleep


nc = nclib.Netcat(('109.233.56.90', 15451), verbose=False)
sleep(1)
target_value = 0xCADE7
while 1:
    ans = getcode()
    blocks = gen_block(ans)
    tos = wave(blocks)
    nc.send(tos.encode())
Основной блок

Получения кода

Когда-нибудь я перейду на использование pwntools

def getcode():
    ans = ""
    while "answer:" not in ans:
        #sleep(0.3)
        ans+= nc.read().decode()
    return ans

Так как я получаю строки блоками по 4096 символов, я просто жду появления стоп-фразы.

С задержкой была проблема: когда ты прорешивал все 10 задач, то сервер отправлял тебе флаг и закрывал соединение, поэтому мы просто не могли получить флаг. Функция nc.recv_all, которая может в таймауты, почему-то не возвращала содержимое сообщения, поэтому такой вот костыль.

Парсинг кода

#blocks = {} # индекс:          {символ_перехода: значение_блока, 
#                               символ_перехода: значение_блока,
#                               value: val                          }

def gen_block(ans):
    blocks = {}
    lines = ans.split("\n")

    i=0
    while i!= len(lines):
        line = lines[i]
        print(line)
        if "struct state **a = malloc(sizeof(struct state *) * " in line:
            print("### Init struct state a")
            str_len = int(line.split()[-1].replace(");", ""))
    
        while " " == line[0]:
            line = line[1:]
        if line.startswith("b = ") or line.startswith("int b = "):
            print("### Block init")
            b = int(line.split()[-1].replace(";", ""))
            i+=1
            #print("## pl", lines[i])
            print("## BA", b, lines[i])
            ___ = lines[i].replace(" ", "").replace("b+=", "").replace(";", "")
            #exec(lines[i])
            b+= int(___)
            print("## BB", b)
            i+=1
            a_value = int(lines[i].split()[-1].replace(";", ""))
            print("## a_val", a_value)
            blocks.update({b:{"value": a_value}})
            i+=3
            while "create_trans" in lines[i]:
                tt = lines[i].replace("create_trans(tptr, ", "").replace("]);++tptr;", "").split()
                t_sym = tt[0][1]
                t_b_offs = b+ int(tt[-1])
                print("Create trans",t_sym, t_b_offs)
                blocks[b].update({t_sym: t_b_offs})
                i+=1
        i+=1
    return blocks

Непростая схема парсинга кода на сях, костыльно-велосипедная методология функционального программирования. Если ты, @user, знаешь, как это можно упростить, при этом затратив на это полчаса, как и в этом варианте - стучись.

Нахождение пути до нужного состояния.

# распространение
# string: cur_index
def wave(blocks):
    strs = {"":blocks[0]}

    while 1:
        strs_temp = {}
        for strr, dictt in strs.items():
            #print(strr, dictt)
            if dictt["value"] == target_value:
                print("OK", strr)
                return strr
            for symbol, index in dictt.items():
                if symbol == "value":
                    continue
            
                if len(strr)>3 and symbol == strr[-1] == strr[-2]:
                    continue
                strs_temp.update({strr+symbol: blocks[index]})
        strs = strs_temp

Вот такой обход в глубину. Строка с прекращением ветки, если последние три символа одинаковы, нужна для теоретического случая, когда один из переходов состояния ссылается на то же самое состояние.

Если ты знаешь модуль, который сделает этот волновой обход гораздо более лаконичным, то отзовись)

Итог таска

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

Таски на реверс за авторством @mrvos (Vlad Roskov)

reverse, 150 баллов > Scratch

Решил обучать свою шестимесячную дочку ревёрсу:

https://scratch.mit.edu/projects/366017349/

Докажите, что вы круче неё

Проект на языке программирования с помощью блоков Scratch.

Нас встречает вот такая медузка, спрашивающая флаг.

Дальнейший разбор находится здесь. Да, попробуйте поковырять его самостоятельно, он в действительности приносит много опыта а разборе алгоритмов.

Cats!

Under construction

Wow! Flipable!

Hello from another side of the Moon!

Looking for a flag? Okay, take this:
LFXXKIDBOJSSA43XMVSXIIC6LYQCAIA=

About me

Under construction. You can try to contact me and fill this field… haha… ha…