crypto-base65536(INS‘hAck 2018)

严宇
2023-12-01

题目源码:
https://github.com/InsecurityAsso/inshack-2018/tree/master/crypto/base65536

主要逻辑server.py

#!/usr/bin/python3

import random
from flask import Flask,request

app = Flask(__name__)

FLAG = "INSA{655e6_is_T0_Much}"


def is_ascii(s):
    return len(s) == len(s.encode())


def encrypt_string(st,dest_char_list):
    binlist = ['{0:08b}'.format(ord(x), 'b') for x in st]
    return ''.join([chr(dest_char_list[int(i+j,2)]) for i,j in zip(binlist[::2], binlist[1::2])])


def isprintable(s, codec='utf8'):
    try: s.encode(codec)
    except UnicodeEncodeError: return False
    else: return True


list_decodable=[ i for i in range(100,100000) if isprintable(chr(i))]


@app.route('/',methods=['POST'])
def handle():
    if request.method == 'POST':
        sample = request.form.get('sample')
        if sample:
            if is_ascii(sample):
                for _ in range(random.randint(0, 9)):
                    random.shuffle(list_decodable)
                encrypted_input = encrypt_string(sample,list_decodable)
                encrypted_flag = encrypt_string(FLAG,list_decodable)
                return("Your encrypted sample is %s and the flag is %s !\n" % (encrypted_input,encrypted_flag))
            else :
                return("Only Ascii characters are allowed\n")
        else :
            return ("Param 'sample' is expected\n")
    else:
        return ("FAIL: HTTP method not allowed (%s)\n") % (request.method)


if __name__ == '__main__':
    app.run(host='0.0.0.0')
    

本质上就是将输入的sample和flag同时进行一次encrypt_string操作。
encrypt_string中首先将明文每个字符格式化为二进制字节形式binlist:

binlist = ['{0:08b}'.format(ord(x), 'b') for x in 'deadbeaf']
'''
['01100100',
 '01100101',
 '01100001',
 '01100100',
 '01100010',
 '01100101',
 '01100001',
 '01100110']
'''

然后将明文binlist奇数项和偶数位项成若干二元组 ( b 2 i , b 2 i + 1 ) (b_{2i},b_{2i+1}) (b2i,b2i+1)

zz=zip(binlist[::2],binlist[1::2])                                        
list(zz) 
'''
[('01100100', '01100101'),
 ('01100001', '01100100'),
 ('01100010', '01100101'),
 ('01100001', '01100110')]
'''   

再将每个二元组中两个二进制值相连,转为数字

[int(i+j,2) for i,j in zip(binlist[::2], binlist[1::2])]
#[25701, 24932, 25189, 24934]

最后在dest_char_list中找到对应需要的字符输出。
看到这里解题思路就比较清晰了,将flag字符串INSA{655e6_is_T0_Much}中的字符两两分组,可以分为11组。sample可以一次发送或多次发送进行分组枚举,只要sample中的两两分组能覆盖flag中的分组,就可以通过sample密文和flag密文对照完成最终解密。

 类似资料: