- Открываем
msg.py
и видим что-то наподобии меча, а так же импортserpent
модуля. - Гуглим
serpent python github
: link - Открываем код проекта и смотрим, как создаётся меч и что он значит.
- Копируем часть кода:
alphabet = [
"PY", "PT", "PH", "PO", "PN", "YP", "YT", "YH", "YO", "YN", "TP", "TY", "TH", "TO", "TN",
"HP", "HY", "HT", "HO", "HN", "OP", "OY", "OT", "OH", "ON", "NP", "NY", "NT", "NH", "NO", "PP", "YY"
]
def _serpent_sword_alphabet_to_hex(sentence):
"Convert the serpent alphabet string back to python bytecode"
return [alphabet.index(symbol[0:-1]) + int(symbol[-1]) * 32 for symbol in sentence]
def _lex_hex(infile):
"Extract the serpent string from the ss file"
with open(infile, 'r') as source:
regex = re.compile(r'[PYTHON][PYTHON][0-9]')
tokens = []
for line in source:
pos = 0
while(pos < len(line)):
match = regex.match(line, pos)
if match:
tokens.append(match.group(0))
pos += 1
return tokens
def convert_to_pyc(fname):
pyc = _serpent_sword_alphabet_to_hex(_lex_hex(fname))
pycout = ".".join(fname.split(".")[0:-1]) + ".pyc"
with open(pycout, "wb") as f:
for val in pyc:
f.write(chr(val))
f.close()
return pycout
- Конвертируем файл с помощью:
fname = sys.argv[1]
pycout = convert_to_pyc(fname)
f = open(pycout, "rb").read()
- Далее смотрим код через:
for x in range(len(f)):
try:
code = marshal.loads(f[x:])
for item in code.co_consts:
print('\t\t%s: %r' % (type(item), item))
if str(type(item)) == "<type 'code'>":
uncompyle6.main.decompile(2.7, item, sys.stdout)
и вытаскиваем оттуда переменные mod_fix
, KEY
, функции get_next_key
и decrypt
, а так же длинный массив байт:
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]
- Скрипт по дешифровке флага будет выглядеть так:
import struct
mod_fix = 0xFFFFFFFF
KEY = "SAFE"
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]
def get_next_key(current_key, current_byte):
a = current_byte + current_key
a = ((a << 12) + a + 0x7ED55D16) & mod_fix
a = ((a >> 19) ^ a ^ 0xC761C23C)
a = ((a << 5) + a + 0x165667B1) & mod_fix
a = ((a << 9) ^ (a - 0x2C5D9B94))
a = ((a << 3) + a - 0x28FB93B) & mod_fix
a = ((a >> 16) ^ a ^ 0xB55A4F09)
return a
def decrypt(data, bytes_key):
key = struct.unpack('=L', bytes_key)[0]
data = bytearray(data)
for i in range(len(data)):
old_byte = data[i]
data[i] ^= key & 255
key = get_next_key(key, old_byte)
return bytes(data)
if __name__ == "__main__":
print(decrypt(flag, KEY.encode("utf-8")))
- Запускаем и получаем флаг:
mctf{pyc_d3c0mp1l4710n!!}
не знаю, как ты это сделал, но это не работает