Разбор тасков на реверс с квалификационного этапа M*CTF 2019
@ Rakovsky Stanislav | Thursday, Oct 24, 2019 | 4 minutes read | Update at Thursday, Oct 24, 2019

reverse, medium > Messaging Tool

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

Дан файл, формат .py

Огромная фрейдовская змея обвивает меч

Красиво. При гуглении “serprent PO0” находим либу, которая генерит эту красоту: https://github.com/kharland/Serpent

Закомментируем строку 182, чтобы не удалялся .pyc файл… uncompyle6 не может справиться с его декомпиляцией. По байт-коду можно восстановить самостоятельно часть кода:

import struct
from sys import argv as args
import serpent
mod_fix = 0xffffffff
def get_next_key(...):
    ...
def encrypt(...):
    ...
def decrypt(...):
    ...
encrypted_flag = [25 однобайтовых значений]
KEY = 'SAFE'
if type(encrypted_flag) == list:
    print "Hello, you've received message, but it seems to be encrypted! Use our tool to decrypt it."
else:
    print "".join(list(map( some_lambda(encrypted_flag)))

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

>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
>>> from ddd import *
('scriptType', None)
Hacking scriptType
Hello, you've received message, but it seems to be encrypted! Use our tool to decrypt it.
>>> globals()
{'mod_fix': 4294967295, 'get_next_key': <function get_next_key at 0x7fead2eef230>, 'struct': <module 'struct' from '/usr/lib/python2.7/struct.pyc'>, 'serpent': <module 'serpent' from 'serpent.py'>, '__builtins__': <module '__builtin__' (built-in)>, 'args': [''], 'encrypted_flag': [62, 125, 128, 30, 59, 77, 9, 125, 32, 40, 187, 190, 227, 207, 120, 195, 88, 210, 27, 20, 147, 218, 153, 83, 197], 'decrypt': <function decrypt at 0x7fead2eef320>, '__package__': None, 'sys': <module 'sys' (built-in)>, 'KEY': 'SAFE', '__name__': '__main__', 'encrypt': <function encrypt at 0x7fead2eef2a8>, '__doc__': None}

Нас интересуют названия “decrypt”, “encrypted_flag”. Заглянем в функу “decrypt”:

>>> import dis

>>> decrypt.__code__.co_argcount
2
>>> dis.dis(decrypt)
 33      0 LOAD_GLOBAL       0 (struct)
       3 LOAD_ATTR        1 (unpack)
       6 LOAD_CONST        1 ('=L')     # грустное место
       9 LOAD_FAST        1 (bytes_key)
       12 CALL_FUNCTION      2
       15 LOAD_CONST        2 (0)
       18 BINARY_SUBSCR
       19 STORE_FAST        4 (key)

 34     22 LOAD_GLOBAL       4 (bytearray)
       25 LOAD_FAST        0 (data)
       28 CALL_FUNCTION      1
       31 STORE_FAST        0 (data)

 35     34 SETUP_LOOP       71 (to 108)
       37 LOAD_GLOBAL       6 (range)
       40 LOAD_GLOBAL       7 (len)
       43 LOAD_FAST        0 (data)
       46 CALL_FUNCTION      1
       49 CALL_FUNCTION      1
       52 GET_ITER
    >>  53 FOR_ITER        51 (to 107)
       56 STORE_FAST        8 (i)

 36     59 LOAD_FAST        0 (data)
       62 LOAD_FAST        8 (i)
       65 BINARY_SUBSCR
       66 STORE_FAST        9 (old_byte)

 37     69 LOAD_FAST        0 (data)
       72 LOAD_FAST        8 (i)
       75 DUP_TOPX         2
       78 BINARY_SUBSCR
       79 LOAD_FAST        4 (key)
       82 LOAD_CONST        3 (255)
       85 BINARY_AND
       86 INPLACE_XOR
       87 ROT_THREE
       88 STORE_SUBSCR

 38     89 LOAD_GLOBAL       10 (get_next_key)
       92 LOAD_FAST        4 (key)
       95 LOAD_FAST        9 (old_byte)
       98 CALL_FUNCTION      2
      101 STORE_FAST        4 (key)
      104 JUMP_ABSOLUTE      53
    >> 107 POP_BLOCK

 40   >> 108 LOAD_GLOBAL       11 (bytes)
      111 LOAD_FAST        0 (data)
      114 CALL_FUNCTION      1
      117 RETURN_VALUE
      118 LOAD_CONST        0 (None)
      121 RETURN_VALUE

Сразу отмечаем грустное место в начале. Ключ представлен четырехбайтовым значением, что заставляет нас немного погрустить.

Oh wait, у нас есть переменная KEY длиной в 4 байта. Пробуем запуститься…

>>> decrypt([62, 125, 128, 30, 59, 77, 9, 125, 32, 40, 187, 190, 227, 207, 120, 195, 88, 210, 27, 20, 147, 218, 153, 83,
 197], "SAFE")
'mctf{pyc_d3c0mp1l4710n!!}'

reverse, medium > VM message

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

Файл

64-битный эльф. Заглядываем в main:

Приятно видеть антиотладку.

Берем blob и key, засовываем в cyberchef

К слову, блоб длиной 22 символа.

Вместо того, чтобы его вытаскивать из хекс-представления или выписывать по байтам, можно воспользоваться функцией idapython - GetManyBytes:

Python>t = idc.GetManyBytes(0x202020, 22)
Python>import binascii
Python>binascii.hexlify(t)
f6bc6b117671c6713e7b4ae966022a29433aefc6b673

Но вот таск medium-уровнем назвать язык не поворачивается. Можно было поднять уровень таска, удалив имя функи или переименовав на, к слову, myowncryptofunction, чтобы немножечко поднять сложность.


reverse, easy > СейфSecurity

В этом великом PE-сейфе находится секрет SB о взломе cisco на время.

файл

Нас встречает дельфин от Embarcadero RAD Studio весом в 12 мегабайт *ловит ностальгию по давним временам*

Вот такая гуишка встречает нас

12 секций, 12к функций. По инерции ищем пользовательские функции с конца…

Функция, которая нам нужна, называется _TMain_btn_EnterClick. Там видим веселое (напоминает стековое) заполнение трех строк.

Сила юникода

Особо глазастаые могли заметить, что при запуске с отладчиком после проверки в консоль падает дебаг-строчка

Это одна из трех строк. Так как таск простого уровня, это должно спасти человека от поиска функи.

Добрые разработчики жалеют нервы начинающим реверсерам

Длина строки подсказывает, что это md5. В коде находим подтверждение:

Радужная таблица, дай мне силу!

Флаг: mctf{21031956}


reverse, easy > Старый сидер

Странно, лет десять назад этот файл работал, пожалуй, начну с пролога...

Файл

Прекрасные 9 килобайт не менее прекрасного Mach-O под PowerPC.

Функцию заксорили на первые 12 байт (это три инструкции) её же пролога, их нужно восстановить. Звучит просто, а на деле это просто безумие и я не понимаю, как оценивалась сложность этих тасков.

Будет интересно почитать райтапы тех, кто этот таск решил.

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…