SCTF warmup

这个比赛前的质量是真的高,师傅们太强了
我其实没看啥但是一眼就注意到了那个密码学的

from Crypto.Cipher import AES
from Crypto.Util.strxor import strxor
from Crypto.Random import get_random_bytes
flag = "fuck"

class MAC:
    def __init__(self):
        self.key = get_random_bytes(16)
        self.iv = get_random_bytes(16)

    def pad(self, msg):
        pad_length = 16 - len(msg) % 16
        return msg + chr(pad_length) * pad_length

    def unpad(self, msg):
        return msg[:-ord(msg[-1])]

    def code(self, msg):
        res = chr(0)*16
        # 最终目的 res 相等 24054d4c1a0f19444e0f4016080f1805
        for i in range(len(msg)/16):
            res = strxor(msg[i*16:(i+1)*16], res)
        aes = AES.new(self.key, AES.MODE_CBC, self.iv)
        print(res.encode('hex'))
        return aes.encrypt(res).encode('hex')

    def identity(self, msg, code):
        if self.code(msg) == code:
            msg = self.unpad(msg)
            if msg == 'please send me your flag':
                print 'remote: ok, here is your flag:%s' % flag
            else:
                print 'remote: I got it'
        else:
            print 'remote: hacker!'


if __name__ == '__main__':
    mac = MAC()
    message = 'see you at three o\'clock tomorrow'
    print 'you seem to have intercepted something:{%s:%s}' %(mac.pad(message).encode('hex'), mac.code(mac.pad(message)))
    print 'so send your message:'
    msg = 'please send me your flag'
    print(msg)

    msg_o = msg + chr(63 - len(msg)) * (63 - len(msg))
    res = chr(0)*16
    for i in range(len(msg_o)/16 - 1):
        res = strxor(msg_o[i*16:(i+1)*16], res)

    msg_o = msg_o[:32] + strxor("24054d4c1a0f19444e0f4016080f1805".decode('hex'), res) + msg_o[48:]
    print(msg_o.encode('hex'))

    print 'and your code:'
    code = raw_input()
    mac.identity(msg.decode('hex'), code)
    exit()

这里逻辑很简单就是你输入信息然后服务器加密成code与你输入的code相等,如果信息是’please send me your flag’就会给你flag

这题我一开始就是想怎么爆随机数然后算出私钥,最后还是没结果,最后大佬的wp告诉了我…
原来这里是让我们传上去的明文摘要之后和前一组明文一致,那么就可以用前一组的密文来通过验证了。(应该早点想到的,不可能是爆破啊时间太短了…)

def code(self, msg):
        res = chr(0)*16
        for i in range(len(msg)/16):
            res = strxor(msg[i*16:(i+1)*16], res)
        aes = AES.new(self.key, AES.MODE_CBC, self.iv)
        return aes.encrypt(res).encode('hex')

重点是这个函数这个是先异或然后在用作密钥加密的

对明文进行异或摘要到 16 位之后,才进行加密的
也就是说我们先打印第一组的明文段(已知),然后打印第二组的明文段,然后再将其加上一段16进制异或与第一段相等就能用已知的code绕过了
大佬的poc

#!/usr/bin/python
# -*- coding: utf-8 -*-

from Crypto.Cipher import AES
from Crypto.Util.strxor import strxor
from Crypto.Random import get_random_bytes
flag = "fuck"

class MAC:
    def __init__(self):
        self.key = get_random_bytes(16)
        self.iv = get_random_bytes(16)

    def pad(self, msg):
        pad_length = 16 - len(msg) % 16
        return msg + chr(pad_length) * pad_length

    def unpad(self, msg):
        return msg[:-ord(msg[-1])]

    def code(self, msg):
        res = chr(0)*16
        # 最终目的 res 相等 24054d4c1a0f19444e0f4016080f1805
        for i in range(len(msg)/16):
            res = strxor(msg[i*16:(i+1)*16], res)
        aes = AES.new(self.key, AES.MODE_CBC, self.iv)
        print(res.encode('hex'))
        return aes.encrypt(res).encode('hex')

    def identity(self, msg, code):
        if self.code(msg) == code:
            msg = self.unpad(msg)
            if msg == 'please send me your flag':
                print 'remote: ok, here is your flag:%s' % flag
            else:
                print 'remote: I got it'
        else:
            print 'remote: hacker!'


if __name__ == '__main__':
    mac = MAC()
    message = 'see you at three o\'clock tomorrow'
    print 'you seem to have intercepted something:{%s:%s}' %(mac.pad(message).encode('hex'), mac.code(mac.pad(message)))
    print 'so send your message:'
    msg = 'please send me your flag'
    print(msg)

    msg_o = msg + chr(63 - len(msg)) * (63 - len(msg))
    res = chr(0)*16
    for i in range(len(msg_o)/16 - 1):
        res = strxor(msg_o[i*16:(i+1)*16], res)

    msg_o = msg_o[:32] + strxor("24054d4c1a0f19444e0f4016080f1805".decode('hex'), res) + msg_o[48:]
    print(msg_o.encode('hex'))

    print 'and your code:'
    code = raw_input()
    mac.identity(msg.decode('hex'), code)
    exit()

大佬的解释可以看到 code 那里我加了个 print ,输出第一组明文的十六位摘要和第二组明文的十六位摘要。
而后对第二组明文进行二次摘要,对其加上一段十六位文本,让其异或之后与第一段明文的十六位摘要相等。再加上 1~15 个 pad,最后处理时利用 pad 保留下我们需要的文本 ‘please send me your flag’。

【前 32 位不用动】【32~48 位 拿来和前面异或,使得和前面已知密文的明文摘要一致】【48(4963) 位 拿来 padding,不是 64 位就是为了让这一段不参与前面的摘要计算,保证最后一位可控】
输出的明文就是我们要发的消息,然后code用服务器发过来的
嗯嗯就会爆flag
膜拜大佬

你可能感兴趣的:(题目)