CTF解题——[ACTF新生赛2020]crypto-aes(保姆级图解+讲解)

[ACTF新生赛2020]crypto-aes

文章涉及代码均使用python3环境

——————————开始做题————————————

  • 首先拿到附件后,有两个文件,一个py,一个txt
    在这里插入图片描述

  • 看到AES,刚接触的小伙伴可能还是有点不太熟悉,我们先了解下AES加密。

  • AES(非对称加密(加解密使用同一种密钥))如何加密的(python3.11环境实现)

  • AES在python中的加密限制:

    • ​ 1、在Python中进行AES加密解密时,所传入的密文、明文、秘钥、iv偏移量、都需要是bytes(字节型)数据。python 在构建aes对象时也只能接受bytes类型数据

    • ​ 2、当秘钥,iv偏移量,待加密的明文,字节长度不够16字节或者16字节倍数的时候需要进行补全。

    • ​ 3、CBC模式需要重新生成AES对象,为了防止这类错误,我写代码无论是什么模式都重新生成AES对象。

      • python中bytes类型数据与中文的转换。Tips:utf8一个中文三个字节,gbk一个中文两个字节。

      • key = "中文数据"   #中文数据
        key_b = key.encode()  #转换成字节型数据
        print(key_b)
        print(key_b.decode()) #字节型数据转换成中文数据
        

        在这里插入图片描述

  • 现在我们读一下aes.py的代码

  • from Cryptodome.Cipher import AES
    import os
    import gmpy2
    from flag import FLAG
    from Cryptodome.Util.number import *
    
    def main():
        key = os.urandom(2) * 16  # 生成一个随机的密钥,长度为32字节(256位)
        iv = os.urandom(16)  # 生成一个随机的初始化向量,长度为16字节(128位)
        print(bytes_to_long(key) ^ bytes_to_long(iv))  # 将密钥和初始化向量转换为长整数,并执行异或操作,然后打印结果
        aes = AES.new(key, AES.MODE_CBC, iv)  # 使用密钥、模式(CBC)和初始化向量创建一个新的AES加密对象
        enc_flag = aes.encrypt(FLAG)  # 使用AES加密对象对FLAG进行加密,并将加密后的结果存储在enc_flag变量中
        print(enc_flag)  # 打印加密后的FLAG
    
    if __name__ == "__main__":
        main()  # 如果当前模块是主模块,则调用main函数
    
  • 最后他输出了两个值,一个key和iv(偏移量)xor的结果,一个enc_flag也就是key和iv利用aes的cbc模式加密后的结果。(推荐大家反复阅读,配合注释食用更佳。大佬扫一眼即OK)

  • 这边可以观察到的是,他的key是随机生成了16字节的值,然后*2,变成32字节的。其实也就是说key的高位128位和低位128位是相同的。

  • iv是16字节的,也就是128位的,那么去计算key和iv的异或时,其实key仅有低位参与了异或运算,高位相当于没变。这里也就引出了解题的思路,我们现在先拿异或运算过渡一下,大佬可跳过直接看解题的脚本。

这个是aes.py输出的结果(output.txt)

91144196586662942563895769614300232343026691029427747065707381728622849079757
b'\x8c-\xcd\xde\xa7\xe9\x7f.b\x8aKs\xf1\xba\xc75\xc4d\x13\x07\xac\xa4&\xd6\x91\xfe\xf3\x14\x10|\xf8p'
  • 异或运算图解(逐个bit位进行运算,相同为0,不同为1)

  • 异或运算(XOR)[通俗易懂]

  • 仅异或了低16位。(手画的,不太好看,大家谅解。为了简单理解,这边用了32位,并没有还原到256位和128位。)
    在这里插入图片描述
    在这里插入图片描述

  • 在原题的加密文件aes.py中key和iv仅异或了低16字节,key的高16字节是不变的,所有由aes.py中key是生成来看解题思路,获取了key的高16字节,便获取了key的256位。(因为aes.py中是*2)

  • 然后通过key的低位与xor的低位进行异或得到的结果就是aes.py中的iv

具体的解题代码(附注释)

from Cryptodome.Cipher import AES
import os
from gmpy2 import*
from Cryptodome.Util.number import*

xor = 91144196586662942563895769614300232343026691029427747065707381728622849079757
enc_flag = b'\x8c-\xcd\xde\xa7\xe9\x7f.b\x8aKs\xf1\xba\xc75\xc4d\x13\x07\xac\xa4&\xd6\x91\xfe\xf3\x14\x10|\xf8p'
out = long_to_bytes(xor)      #将异或的数值转换为字节型数据
key = out[:16]*2              #取了之前加密key和iv的异或的前16字节,相当于取了高位的128位。
iv = bytes_to_long(key[16:])^bytes_to_long(out[16:])    #此时取了key的后16位与xor的后16位进行xor来还原iv
iv = long_to_bytes(iv)
aes = AES.new(key,AES.MODE_CBC,iv)
flag = aes.decrypt(enc_flag)
print(flag)

—————————————————————————————————————————
至此,解题结束。我总结了一下,该题还是考察队AES加密的了解程度。所以,大家多多研究底层原理配合代码实践还是没问题的。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花园小宝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值