BUUCTF 每日打卡 2022-1-18

本文介绍了一种特殊的加密方式,通过对随机生成的数列进行特定的异或运算和MD5哈希处理,来生成AES加密密钥,并使用该密钥对FLAG进行加密。通过逆向思维,分析并提供了解密算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

[CISCN2018]sm

加密代码如下:

from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long
from Crypto.Cipher import AES
import hashlib
from random import randint
def gen512num():
    order=[]
    while len(order)!=512:
        tmp=randint(1,512)
        if tmp not in order:
            order.append(tmp)
    ps=[]
    for i in range(512):
        p=getPrime(512-order[i]+10)
        pre=bin(p)[2:][0:(512-order[i])]+"1"
        ps.append(int(pre+"0"*(512-len(pre)),2))
    return ps

def run():
    choose=getPrime(512)
    ps=gen512num()
    print "gen over"
    bchoose=bin(choose)[2:]
    r=0
    bchoose = "0"*(512-len(bchoose))+bchoose
    for i in range(512):
        if bchoose[i]=='1':
            r=r^ps[i]
    flag=open("flag","r").read()

    key=long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(),16))
    aes_obj = AES.new(key, AES.MODE_ECB)
    ef=aes_obj.encrypt(flag).encode("base64")

    open("r", "w").write(str(r))
    open("ef","w").write(ef)
    gg=""
    for p in ps:
        gg+=str(p)+"\n"
    open("ps","w").write(gg)

run()

分析代码可知,加密过程是先生成一个随机数choose和一串数ps,然后根据choose的比特位,若为1则与r做异或运算,得到r,然后将choose经过md5加密,作为AES加密的key,再将AES加密得到的密文base64加密得到最终密文
由于base64是方便逆向的,而AES解密所需的key是未知的,所以解密的关键是得到AES的key;而要求出key,就需要先求出choose;要求出choose,就要根据rps求出bchoose
由生成ps的过程可知,ps中的每个数都在末位填充了0,因此ps中的数末位为1当且仅当位数为512位
于是根据这一特性,若r末位为1,就可以判断bchoose对应位置也为1;若不为1,则跳过且在下一循环中排除这个数
同理,若r的倒数第二位为1,则异或的对象末两位只有11和10两种可能,而在上一循环排除了11,那么仅由可能是10的情况
以此类推,即可从后往前还原bchoose,进而完成解密
解密代码如下:

from Crypto.Util.number import long_to_bytes, bytes_to_long
from Crypto.Cipher import AES
import hashlib
import base64
import copy

with open('ps', 'r') as f:
    ps = [int(n.strip()) for n in f.readlines()]
psb = [bin(n)[2:].zfill(512) for n in ps]
with open('r', 'r') as f:
    r = int(f.readlines()[0])

bchoose = ['0'] * 512
psb_ = copy.deepcopy(psb)
for i in range(511, -1, -1):
    rb = bin(r)[2:].zfill(512)
    if rb[i] == '1':
        for sb in psb:
            if sb[i] == '1':
                t = psb_.index(sb)
                bchoose[t] = '1'
                r ^= int(sb, 2)
                psb.remove(sb)
                break
    else:
        for sb in psb:
            if sb[i] == '1':
                psb.remove(sb)
                break
choose = int(''.join(bchoose), 2)
key = long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(), 16))
aes_obj = AES.new(key, AES.MODE_ECB)
with open('ef', 'r') as f:
    ef = f.readlines()[0]
enc = base64.b64decode(ef)
flag = aes_obj.decrypt(enc)
print(flag)

结果为:
在这里插入图片描述

结语

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值