crypto-Xor很心疼你(xctf)

文章提供了一道关于Python加密的题目,明文包含flag信息,加密过程涉及随机数生成和异或操作。解题策略是通过爆破随机数种子来找到正确的加密密钥,然后使用相同算法进行解密。最终通过示例代码展示了如何解密已知密文以获取原始flag。
摘要由CSDN通过智能技术生成

新出密码题,记录一下。
源码:

# Python3
from secret import flag
import random
import base64

pool = 'qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM'
r = random.randint(2, 250)
assert flag.startswith('hsctf{')


def generate(length):
    return ''.join(random.choices(pool, k=length))


def f(x):
    random.seed(x)
    return random.getrandbits(8)


def encrypt(plaintext, key):
    plaintext = list(map(ord, plaintext))
    for _ in range(20):
        key = f(key)
        assert key != 0
    for i in range(len(plaintext)):
        key = f(key)
        tmp = (key * r) % 251
        assert tmp != 0 and key != 0
        plaintext[i] = plaintext[i] ^ tmp
    plaintext = bytes(plaintext)
    return base64.b64encode(plaintext)


m = generate(random.randint(200, 300)) + flag + generate(random.randint(200, 300))
c = encrypt(m, random.getrandbits(128))
print(c)
# b'8OcTbAfL6/kOMQnC9v8SNmmSzvQMeGTT8vANM1T+7vIce2fo0fc2RnScrNxTSmeSyuMjMF//w8BWaXX91dsGcnvmreg0NQTw96ceVVXj3sQ3Znn51OU1S0bOyaMtNHTj36AcWFqewN4zRUXD6agGbAPE+tQtd3XG0doAa1Ll9fhcQ1zk0McTM1bv8PIQOAnn3vQ3UgLD3PsONXLs4KkXMnjTyMEQOFn/0uYVUwOY1PsleEHCyNopRVDr+Kc0e2PH9v0XNXfprfIPU3nw7KYTNX/G7twLSkHoyaUlQHXi3v02UHmdy/4iNgme3Pc8bgPp+tYWV1+YzPkXYkXM4ulUc27DrM4SNUPT2fQlckj1qP4Fal+YoPYJMlyZ8qhXfF3Y0tUDdUXl3vg0dFTi++VVOFfH/dgMS1ru9N8WU0HF9cUCTgPe+qVdSn/u7Mkda0GTw/QDcWPZ9KYGN2jSzfk0OVrMzt0yRHD64KMrUgPF2sFWcmP56KZSTAD61PUGeXrd49MgU1bL8OsVNWj91vIsalXwqf0qaWbwzv0lWETA4eElS3L99cYmU1nv9dRQTWbDyclScQTN6NIhV2j//+ZWbH7Z68kwM3Dy4dcUc1PQy8kRTl/4zcU9WGWfoakOMXuf69MXZQTEz+kJT1Dar8UN'

大概分析一下题目逻辑,首先明文 mflag 前后各加200多个字符padding生成的字符串。
加密得到密文的函数 encrypt 逻辑包括:

  • 首先把明文转为数组,数组元素即明文字符的ASCII值
  • 然后调用20次 key = f(key) 取随机字节,上一次的返回值作为下一次的随机数种子
  • 然后遍历每个明文字符,每次调用 key = f(key) 取一个随机字节,然后计算 tmp = (key * r) % 251 其中 2<r<250,最后将当前明文字符与 tmp 进行一次异或加密

随机数题目还是要先解决种子未知的问题,好在这个题目 key,r 都只有8位,直接爆破,寻找 hsctf{ 正确加密后的密文,然后就是个简单的异或解密了。

最终exp:

# Python3
#from secret import flag
import random
import base64

cc=b'8OcTbAfL6/kOMQnC9v8SNmmSzvQMeGTT8vANM1T+7vIce2fo0fc2RnScrNxTSmeSyuMjMF//w8BWaXX91dsGcnvmreg0NQTw96ceVVXj3sQ3Znn51OU1S0bOyaMtNHTj36AcWFqewN4zRUXD6agGbAPE+tQtd3XG0doAa1Ll9fhcQ1zk0McTM1bv8PIQOAnn3vQ3UgLD3PsONXLs4KkXMnjTyMEQOFn/0uYVUwOY1PsleEHCyNopRVDr+Kc0e2PH9v0XNXfprfIPU3nw7KYTNX/G7twLSkHoyaUlQHXi3v02UHmdy/4iNgme3Pc8bgPp+tYWV1+YzPkXYkXM4ulUc27DrM4SNUPT2fQlckj1qP4Fal+YoPYJMlyZ8qhXfF3Y0tUDdUXl3vg0dFTi++VVOFfH/dgMS1ru9N8WU0HF9cUCTgPe+qVdSn/u7Mkda0GTw/QDcWPZ9KYGN2jSzfk0OVrMzt0yRHD64KMrUgPF2sFWcmP56KZSTAD61PUGeXrd49MgU1bL8OsVNWj91vIsalXwqf0qaWbwzv0lWETA4eElS3L99cYmU1nv9dRQTWbDyclScQTN6NIhV2j//+ZWbH7Z68kwM3Dy4dcUc1PQy8kRTl/4zcU9WGWfoakOMXuf69MXZQTEz+kJT1Dar8UN'
cc=base64.b64decode(cc)
flag = 'hsctf{'
pool = 'qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM'
#r = random.randint(2, 250)
assert flag.startswith('hsctf{')


def generate(length):
    return ''.join(random.choices(pool, k=length))


def f(x):
    random.seed(x)
    return random.getrandbits(8)


def encrypt(plaintext, key):
    plaintext = list(map(ord, plaintext))
    for i in range(len(plaintext)):
        key = f(key)
        tmp = (key * r) % 251
        #assert tmp != 0 and key != 0
        plaintext[i] = plaintext[i] ^ tmp
    plaintext = bytes(plaintext)
    return plaintext

def decrypt(ciphertext, key):
    ciphertext=list(ciphertext)
    for i in range(len(ciphertext)):
        key = f(key)
        tmp = (key * r) % 251
        #assert tmp != 0 and key != 0
        ciphertext[i] = ciphertext[i] ^ tmp
    ciphertext = bytes(ciphertext)
    return ciphertext

for r in range(2,251):
    for key in range(1,256):
        m = flag
        c = encrypt(m, key)
        if(c in cc):
            print(r)
            print(key)
            print(c)
            print(cc.index(c))

r=187
key=34
pos=247
mm=decrypt(cc[247:],key)
print(mm)
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值