• CryptoCTF easy


    2023

    suction

    题目描述:

    from Crypto.Util.number import *
    from flag import flag
    
    def keygen(nbit, r):
    	while True:
    		p, q = [getPrime(nbit) for _ in '__']
    		e, n = getPrime(16), p * q
    		phi = (p - 1) * (q - 1)
    		if GCD(e, phi) == 1:
    			N = bin(n)[2:-r]
    			E = bin(e)[2:-r]
    			PKEY = N + E
    			pkey = (n, e)
    			return PKEY, pkey
    
    def encrypt(msg, pkey, r):
    	m = bytes_to_long(msg)
    	n, e = pkey
    	c = pow(m, e, n)
    	C = bin(c)[2:-r]
    	return C
    
    r, nbit = 8, 128
    PKEY, pkey = keygen(nbit, r)
    print(f'PKEY = {int(PKEY, 2)}')
    FLAG = flag.lstrip(b'CCTF{').rstrip(b'}')
    enc = encrypt(FLAG, pkey, r)
    print(f'enc = {int(enc, 2)}')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    题目分析:
    给出了n,e,c且每个都是少最后8bit
    n - 256bit,e - 16bit,由于都比较小,可直接爆破出来
    n这里用factor()分解,若最后分解得到的是两个数,并且都是128bit,那么p,q,n都可以确定了
    n出来了那之后再爆e和c,256 * 256,也不大,最后通过得到的flag是否都为可打印字符来判断flag是否正确

    from Crypto.Util.number import *
    from gmpy2 import *
    PKEY = 55208723145458976481271800608918815438075571763947979755496510859604544396672
    ENC = 127194641882350916936065994389482700479720132804140137082316257506737630761 << 8
    n_ = int(bin(PKEY)[2:-8],2) << 8
    e_ = int(bin(PKEY)[-8:],2) << 8
    
    # for i in range(45,256):
    #     print(i)
    #     n = n_ + i
    #     if n % 2 == 0:
    #         continue
    #     a = factor(n)
    #     if len(a) == 2:
    #         print(n,a,i) # 69
    
    n = 55208723145458976481271800608918815438075571763947979755496510859604544396613 
    p = 188473222069998143349386719941755726311
    q = 292926085409388790329114797826820624883
    phi = (p - 1) * (q - 1)
    for i in range(256):
        e = e_ + i
        if not isPrime(e):
            continue
        for j in range(256):
            c = ENC + j
            d = inverse(e,phi)
            m = pow(c,d,n)
            flag = long_to_bytes(int(m))
            if flag.isascii():
                print(flag)
    # CCTF{6oRYGy&Dc$G2ZS}  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    Blue Office

    题目描述:

    import binascii
    from secret import seed, flag
    
    def gen_seed(s):
        i, j, k = 0, len(s), 0
        while i < j:
            k = k + ord(s[i])
            i += 1
        i = 0
        while i < j:
            if (i % 2) != 0:
                k = k - (ord(s[i]) * (j - i + 1))
            else:
                k = k + (ord(s[i]) * (j - i + 1))
    
            k = k % 2147483647
            i += 1
    
        k = (k * j) % 2147483647
        return k
    
    def reseed(s):
        return s * 214013 + 2531011
    
    def encrypt(s, msg):
        assert s <= 2 ** 32
        c, d = 0, s
        enc, l = b'', len(msg)
        while c < l:
            d = reseed(d)
            enc += (msg[c] ^ ((d >> 16) & 0xff)).to_bytes(1, 'big')
            c += 1
        return enc
    
    enc = encrypt(seed, flag)
    print(f'enc = {binascii.hexlify(enc)}')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    题目分析:
    gen_seed()压根没用到呀,感觉是用来耗时间的,有些人喜欢顺着看下来,看完之后才发现这串没用,但时间也过去了。所以还是从加密那里看起吧。
    步入正题
    主要在下面两串
    d = reseed(d)
    enc += (msg[c] ^ ((d >> 16) & 0xff)).to_bytes(1, 'big')
    第一串LCG,第二串flag的其中一个字节和d的第16-24位(1个字节)异或。assert s <= 2 ** 32表明s应该在32位左右,但我们只需用到24位,所以可以把这个运算看成GF(2 ** 24)下的运算,flag的格式固定CCTF{},故通过异或运算可以得到seed的第16-24位,还16位未知,不大直接爆破,之后flag也就出来了

    import binascii
    enc = 'b0cb631639f8a5ab20ff7385926383f89a71bbc4ed2d57142e05f39d434fce'
    enc = binascii.unhexlify(enc)
    flag = b'CCTF{'
    
    def reseed(s):
        return s * 214013 + 2531011
    
    def encrypt(s, msg):
        assert s <= 2 ** 32
        c, d = 0, s
        enc, l = b'', len(msg)
        while c < l:
            d = reseed(d)
            enc += (msg[c] ^ ((d >> 16) & 0xff)).to_bytes(1, 'big')
            c += 1
        return enc
    
    s1 = (enc[0] ^ flag[0]) << 16
    
    for i in range(2 ** 16):
        seed = s1 + i
        flag = encrypt(seed,enc[1:])
        if b'CTF' in flag:
            print(flag)
    # CCTF{__B4ck_0r!F1c3__C1pHeR_!!}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2022

    Baphomet

    题目描述:

    from base64 import b64encode
    from flag import flag
    
    def encrypt(msg):
    	ba = b64encode(msg.encode('utf-8'))
    	baph, key = '', ''
    
    	for b in ba.decode('utf-8'):
    		if b.islower():
    			baph += b.upper()
    			key += '0'
    		else:
    			baph += b.lower()
    			key += '1'
    
    	baph = baph.encode('utf-8')
    	key = int(key, 2).to_bytes(len(key) // 8, 'big')
    
    	enc = b''
    	for i in range(len(baph)):
    		enc += (baph[i] ^ key[i % len(key)]).to_bytes(1, 'big')
    
    	return enc
    
    enc = encrypt(flag)
    f = open('flag.enc', 'wb')
    f.write(enc)
    f.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    题目分析:
    密文长度为48,说明key长度为6(字节)
    CCTF{40bit,大于6 * 6base64以6字节分组加密)
    故可知baph前6位q0nurN,与密文前6位异或得到key
    key和密文都知道,异或便可得到完整flag

    未完待续…

  • 相关阅读:
    Markdown使用教程
    【代码随想录算法训练营】第50天 | 第九章 动态规划(十一)+ 复习第20天 第六章 二叉树(六)
    Go语言入门心法(二): 结构体
    saas化调研
    【AI视野·今日NLP 自然语言处理论文速览 第四十七期】Wed, 4 Oct 2023
    Git系列之撤销
    剑指 Offer 48. 最长不含重复字符的子字符串
    将Java程序打包为为.exe文件
    Pyecharts | 历年全国各地民政局登记数据分析+可视化
    516. 最长回文子序列
  • 原文地址:https://blog.csdn.net/XiongSiqi_blog/article/details/133147036