强网杯-crypto modestudy

1、modestudy
这道题nc过后发现该题分为六个部分
(1)challenge1
[$] challenge 1
[+] cookie:session=6b1f33a78c5b9c17;admin=0;checksum=552ebbeb9276a8cd9f741b7d29f8c9e1eb455757207ac420659e7eab56ddee25
[+] checksum=aes128cbc.encrypt(session=6b1f33a78c5b9c17;admin=0)
[+] only admin can see flag
[-] cookie:(待输入)

![cbc
](https://img-blog.csdnimg.cn/20200831203215331.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L29zaWVyMTIzNDU=,size_16,c
根据CBC的加密模式,我们为了得到明文首先应该将密文解密,再与前一组密文进行模加才会得到明文,根据题意,我们需要得到明文为admin=1的该组的输入值才能破解该关卡。所以根据加密模式我们将校验和代入先与0异或再与1异或即可得到输入值,破解challenge1。
主要再与对CBC加密模式的理解,主要是加密过后的密文会作为密钥再对下一步进行加密,这也是破解CBC密码的关键。异或之后可以得到输入值:
session=0037f692a72e8507;admin=0;checksum=994456fcdcabb9f7f1f0c2c950f
e6e4aa311c4397734780e96a7d2396a125c43

(2)challenge2
[$] challenge 2
[+] sha256(iv)=11f595abc9d7b986d24fce986d1f9ddfb0d83f2f978db20b862ea730e570bff0
[+] 1. server’s job: print aes_cbc_dec(key,iv,your_input_c).encode(‘hex’)
[+] 2. your job: guess iv
[-] your choice:(待输入)
看了大佬的wp之后看出来了这是CBC的选择密文攻击(菜鸡表示对CBC似乎没多大了解,上次魔改aes的时候只接触过一次CBC)
还是根据CBC加密的特点,由于输入的密文作为下一轮加密的密钥,所以我们假设第一轮输入的密文是C0,第二轮是C1,第一轮输出的明文是M0,第二轮是M1,那么dec(c0) = m0 ^ iv,dec(c1) = m1 ^ c0,如果我们令两次输入的密文相同,那么iv = m0 ^ m1 ^ c0,所以只要输入两段相同的16字符内容,在分别对这两段内容进行加密,将三个部分进行异或,就可以得到iv
解得iv=ee42fad0d874a822f3d462302c4ef1e6

(3)challenge3
[$] challenge 3
[+] cookie=session:0884ce7c;timedl=1;admin=0;guess_cookie_ma=1;guess_mp_ab=1;guess_cookie_mb=0;hell_pad=233
[+] 128bit_ecb_encrypt(cookie):0632b3e7adb2f6d5ae4a92f553f2f4a4c9f95b099cfd8e3408137d134eb51d147045f278246a831fabdbdccde099b4b694b07e699ffae6a82c6cfbc4454816b1c78e5d1be8b67e235fbbfd2a75e73f32bac806808bc2e102db8f2c159b250415
[+] only admin can see the flag
[-] input your encrypted cookie(encode hex):(待输入)
该题使用了ECB加密模式,与1相同,依然是当admin=1的时候可以通过,那么根据分组加密的长度进行分组:

第 1 分组 session:f8e9b447
第 2 分组 ;timedl=1;admin=
第 3 分组 0;guess_cookie_m
第 4 分组 a=1;guess_mp_ab=
第 5 分组 1;guess_cookie_m
第 6 分组 b=0;hell_pad=233
看大佬wp发现了神奇的事情,第三组和第五组只相差一个字符,将第三组的密文和第五组的密文交换,就可以使得admin=1,输入新的密文,即可进入下一环节
强力补课了一波ECB,主要是对ECB模式的攻击方法,ECB的显著弱点是不破解密文也可以操纵明文,详细可见https://blog.csdn.net/chengqiuming/article/details/82262417,该题的破解方法就是利用ECB加密的弱点,在不破解密文的情况下对明文直接进行操作,最终可以得到本轮的输入值6e0b333f565abac1949c208b4b98313399f460d5aeabb631e24895fa017a9012656db
f3ce6b036f949a3b2bf9feb6acca32a7460f01c4fad467ee054979c8b05656dbf3ce6
b036f949a3b2bf9feb6acce7b2e3a521ca2d3c5b21e5ef7c2d51c3

(4)challenge4
[$] challenge 4
[+] sha256(secret)=d014cbddd2cbb0fa2404c519c166bc85c03ee3445d643f451a5f5d6244e7e34d
[+] assert len(secret)==16
[+] 1. server’s job: print aes_ecb(key,input+secret+’\x00’*((16-(len(input+secret) % 16)) % 16))
[+] 2. your job: guess secret
[-] your choice:(待输入)
根据观察可知又是ECB的加密模式,根据wp的提示按位爆破(主要是由于ECB加密的每个模块之间并不相关),最后一位可以任意尝试,然后与sha值进行比较用来确定secret的最后一位,然后再进行第二位的爆破,重复上述步骤,直到所有都被爆破出来。
我只尝试爆破了前6位,真的太考验耐心了,也可能是我没找到其中有什么规律(但我个人认为哈希函数应该也没有什么规律,毕竟他是不可逆的),所以就失去耐心直接参考wp给出的secret值:
3567935aebe5e517caf233dbc7cb9959
代码如下:

def solve_step_4(level, known):
    print "Level %s" % str(level)
    if(level == 16):
        return known
    records = []
    for i in range(256):
        p.recvuntil("[-] your choice:")
        p.sendline("1")
        p.recvuntil("[-] input(encode hex):")
        tmpstr = ('a'*(15-level) + known + chr(i)).encode('hex')
        p.sendline(tmpstr)
        text = p.recvuntil("[+] 2. your job: guess secret")
        s = text.split("[+] ")[2].strip()
        s = s[15:47]
        print "Process: %s/256 %s %s" % (str(i), tmpstr, s)
        records.append(s)
    p.recvuntil("[-] your choice:")
    p.sendline("1")
    p.recvuntil("[-] input(encode hex):")
    tmpstr = ('a'*(15-level)).encode('hex')
    p.sendline(tmpstr)
    text = p.recvuntil("[+] 2. your job: guess secret")
    s = text.split("[+] ")[2].strip()
    s = s[15:47]
    newknown = known + chr(records.index(s))
    print "==========================="
    print newknown.encode('hex')
    print "==========================="
    return solve_step_4(level+1, newknown)

def pad4(text):
    return '0'*(4-len(text))+text

代码主要还是在字母和数字里一位一位检索进行了ECB
加密后再利用hash函数加密后与题目中所给逐个对比,亲测这位巨佬的代码是可以用的,里面有一些函数我之前见过但是是头一次在编译器中投入使用以及感觉这应该是一个很有用的脚本
(5)challenge5
[$] challenge 5
[+] sha256(secret)=4c766c8749526dd1a14fdf37619d2fbebbbc2478e25e27e63e591ae0aafb305d
[+] assert len(secret)==16
[+] myblockencrypt_ecb(secret).encode(“hex”)=4c21cc2bc7941b224ed45bd02ee11b60
[+] In this challenge, you need to try something.
[+] 1. server’s job: print myblockencrypt_ecb(your_input)
[+] 2. your job: guess secret
[-] your choice:(待输入)
感觉自己到5这就彻底傻了,因为其实题目的条件越来越少,以及无法得知myblockencrypt的函数是干啥的
按照wp的指引用函数随意加密了一串,发现这种加密方式相互之间确实是互不影响并且紧跟wp的指引认为这是个固定的映射(其实换我自己想我可能也得想好久才敢这么判断,因为估计要进行很多次的尝试)
然后就和解决4的方式相同,利用脚本进行爆破,代码如下:

def solve_step_5(cipher):
    f = open("step5.txt",'w+')
    for i in range(0, 65536, 8):
        print "Processing: %s/65536" % str(i)
        tmpstr = ""
        for j in range(8):
            tmpstr += pad4(long_to_bytes(i+j).encode('hex'))
        p.recvuntil("[-] your choice:")
        p.sendline("1")
        p.recvuntil("[-] input(encode hex):")
        p.sendline(tmpstr)
        text = p.recvuntil("[+] 2. your job: guess secret")
        cipher = text.split("[+] ")[1]
        cipher = cipher[45:]
        for j in range(8):
            f.write("'"+tmpstr[4*j:4*j+4]+"' ")
        f.write("=== ")
        for j in range(8):
            f.write("\""+cipher[4*j:4*j+4]+"\" ")
        f.write("\r\n")
    return ""

Python把六万多个结果跑完需要的时间太长,于是按照wp说的进行了人工比对,虽然工作量也比较大,但是基本还是能出来结果,输入值如下:
157112520917d275b9d9dc9539c340bb
(6)challenge6
[$] challenge 6
[+] padding(m):m+chr(16-(len(m)%16))*(16-(len(m)%16))
[+] unpadding(m):m[:-ord(m[-1])]
[+] len(secret):16
[+] iv+aes128_cbc(key,iv,padding(secret)):31313131313131313131313131313131891f3925b171f363bfc1ab0f4c03c9172cdfbd56dbd225d2accaf2b6fcbd0780
[+] 1. server’s job: decrypt and unpadding
[+] 2. your job: guess secret
[-] your choice:(待输入)
CBC填充模式(wp告诉我的),当输入实际密文并且iv随便给的时候,会得到正确的结果根据代码可知填充方式为标准填充,也可判断出分组的第二组是对填充的加密结果。根据 cbc 模式的特点,第一组加密的输入为明文与 IV 的模加和,若修改 IV 的值使得解密后第一分组的最后一个值为 01,则系统会判断它为填充值大小,返回解填充正确的信息,根据修改值与原 IV 的差值可以求出第一分组实际输入的最后 1 字节,依次类推,同理求出第一分组所有输入

def solve_step_6(c0, level, known):
    tmpknown = strxor(known, chr(level))
    newknown = ""
    if(level>=17):
        return known
    for i in range(256):
        print "Process: %s/256" % str(i)
        tmpcipher = '1'*16+'\x00'*(16-level)+chr(i)+tmpknown+c0
        p.recvuntil("[-] your choice:")
        p.sendline("1")
        p.recvuntil("[-] input your iv+c (encode hex):")
        p.sendline(tmpcipher.encode('hex'))
        text = p.recvuntil("[+] 2. your job: guess secret")
        if text.find("[+] unpadding success") >= 0:
            newknown = chr(i^level) + known
            print "==============================="
            print newknown.encode('hex')
            print "==============================="
            break
    return solve_step_6(c0, level+1, newknown)

可以得到输入值:
fb1a5485aaf6af850a369b76c888f35d2ac042a05bd0c7619e458935cec795b0
完成六个部分,得到
flag{ 6f0fc66aa7cc0d373f22bb86d37a5e2a}

其中第六个部分还希望有识之士多帮我补课,网上关于CBC填充模式的介绍甚少,只能按照wp将代跑出来,但是缺少真正的理解与认知
这道题属于AES体系加密,基本使用CBC和ECB加密方式来进行加密,其中第四五六的部分基本靠爆破来实现,属于大量交互
通过这道题,我对CBC和ECB加密模式有了一些了解,其中他们还有各自的几种模式我目前还不是非常清楚,特别是最后的标准填充模式我还属于云里雾里,给代码能跑,不给就玩完的阶段,以及我认为以后这种模式出现在赛题中,我估计自己还是不能准确的把握到,以后多多努力~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值