hctf-2018-Crypto-xorgame

题目

#这是一首英文诗,但它是加密的。找到标志,并恢复它
from Crypto.Util.strxor import strxor
import base64
import random


def enc(data, key):
    key = (key * (len(data) / len(key) + 1))[:len(data)]
    return strxor(data, key)


poem = open('poem.txt', 'r').read()
flag = "hctf{xxxxxxxxxxx}"

with open('cipher.txt', 'w') as f:
    f.write(base64.b64encode(enc(poem, flag[5:-1])))
    f.close()


附件:

ciMbOQxffx0GHQtSBB0QSQIORihXVQAUOUkHNgQLVAQcAVMAAAMCASFEGQYcVS8BNh8BGAoHFlMAABwCTSVQC2UdMQx5FkkGEQQAAVMAAQtHRCNLF0NSORscMkkaHABSExIYBQseUmBCFgtSKwEWfwELFRcGbzwEDABHVS8DDAcXfwUcMQwCDUUBCgYYSQEBATNKGwQeOkkbPhsYERYGDB0TYzwCUSVCDE8dKh0BNg4GAAkLSVMWHBpHQCxQF08AOhkWPh1OAA0XRQQRBQJKQyVKFghSMA95Gh8LGhEHBB8YEE4UViFaEQEVfwAdfx0GEUUWAAARGxpHTiFQERx4FkkROgUHERMXRTpUCANtYy9RFk8TLEkHNwxOFhcbAhsASR0STC1GCk8UMwYEOhsdfiEdRR0bHU4QSDRLHR0XO0kGMQ0LEgATERYQSQgORDJaWAsXMgYdfxsbGAB4LRYVGxpHUyFXHU8TMQ1TPRsLFREaDB0TSRoIASJGGR1SKwEWfwUBFQFSChVUHQYCASNWFQ0XLRocMgxkNgoAABd+PRkIKwkDEAoTLQ1TKwELVAgHFhoXRU4BUy9OWBsaOkkeMAYAVAQcAVMXCBwEQDNQci4HJwAfNggcDUUXHQcGDAMCASFGCxsaOh0aPAAdGUUQBBoASRoIASNCCBsHLQxTMgAdABx4IxoYBQcJRmBXEApSNgcHOgcdEUUeDBURRU4FVDQDGQMBMEkVNgUCHQsVRQccDE4XVDJGcjsaOhsWfwgcEUUTCQQVEB1HTCVOFx0bOhpTKwEcGxAVDRwBHU4TSSUDHQ4AKwF5FkkMEQkbAAURSSdHQC0pPAYXO0kSLEkaHABSFAYdDBpHQyVCDRsLfwYVfwgbABAfC1MYDA8RRDMpKwcXMQ5TNhpOGgoGRRAcCAEUDWBQFQAZOkkUOhoaARcXbzYCDABHVilPDE8TMxocfxsLAAQbCxYQSQwITyUDCB0dKg0fJkk/HQsVRTURBwlHTDVQGwMXVSYQPBwCAG8mDQERDGQuAShGGR1SMwYFOkVOPUUQAB8dDBgCASlNWAMdKQx5EwYYEUUbFlMVSR4ITiwDFwlSLB0BKg4JGAwcAlMWBRsCDCdRHQocfwgfOAgLfiQBRRcRGgELQDRGWAIbPBsccgsbBhYGRRwSSRkOTyQpOgMXOg0aMQ5OAA0ACgYTAU4KWGBVHQYcLGMqOggcB0UBERIAAAEJRCQDEQFSKwEWfwsLGAwXA3kyBhsVKwkDGgoeNgwFOkkaHAQGRRIYBU4EQC4DEAoTLWM2KQwAVAQcERoXAB4GVSUDHAYBPBsWKwxCVCxSCBYASRoPRGBMDAcXLUkHNwwHBkUdEh1+OgEKRGBAGQFSMQYHfw4cFRYCRQccDE4KTi1GFht4EwwVK0kaG0UGDRZULA8UVWBXF08VMEkkOhoaWEUGDRZUDQsGRWBODRwGfwccK0kcEREHFx1UHQFHTy9UEAoAOmMgOgxCVCxSEhYVG049QC4DPgMdKAwBLEkBGkUfHFMcDA8DDWBKFk8UKgUffwsCGwofRRIYBgAAATRLHU8FPhBTPgUCVBEaAFMDCBdtZzJGCRoXMR0fJkkDHRYBABdUGgEKRGwDGhoGfwgfLAZOEAAXFR8NSQMIVyVHWA0Lfx4aMQ1CVAMACgAARU4UTy9UWAAAfxsSNgdkMgwEAHkkGw8NTyEDKA4APgQaKwhCVBYdCh1UCB1HUi9MFk8TLGMfNg8LVAcXRRERCBsTSCZWFE8eNgIWfxobGQgXF1MSBQEQRDJQWA4cO0kXOggaHEUeDBgRSQ8SVTVOFk8eOggFOhpkNQkBClMXCBwCASFBFxoGfx4bPh1OHAQB

分析

题目中比较重要的就是enc函数,其传参有需要加密的data和密钥key

key = (key * (len(data) / len(key) + 1))[:len(data)]

将key扩展为可加密data的长度,并将长于(多余)data的部分丢弃。([:len(data)])。扩展方式为重复key,类似维吉尼亚密码。

如:明文长度为11,密钥为ok,则密钥扩展为:okokokokoko

而此题中的密钥即为我们所要求的flag

附件中保存的密文是英文诗填充flag 异或后再base64之后的结果

因为明文是英文诗, 则明文空间为:[a-z]+[A-Z]+[0-9]+常用英文标点符号

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.!? :;"’@&()+=%’\n0123456789

所以我们第一时间会想到密文 ^明文=flag,但flag的位数不定。

假设,如果我们知道了flag的位数,或者我们可以试出flag的位数,那么就可以把整个密文或明文分成很多组,每一组的长度就为flag的长度。然后每一组中对应的位置的flag字符应相同,若用我们的明文空间对密文进行异或,每一组的异或值都将出现对应的位置的flag字符。那么该怎么验证这个位数是正确的呢?

明文空间是小于ascii码表示字符的,则一位密文与明文空间异或得到的一个数组明显是小于ascii码所表示的字符的。若假设的位数分组后,每一组对应的位次与明文空间异或后有着交集(交集可能不唯一),但flag是会存在在交集中且将所有的集合并起来的话,flag位数的概率应会是最大的。

则如果对应位次异或值相同,我们就认为,位次假设可能正确

def get_key(i,j):
    list = []
    for a in dictionary:
        for b in dictionary:
            if ord(a) ^ cipher[i] == ord(b) ^ cipher[j]:
                list.append(chr(ord(a) ^ cipher[i]))
    return list

根据上面这一分析,我们就采用分组然后使用明文空间爆破的形式。

先用xortools给我们提供一个位数可能方向

image-20220316212827572

然后排除一下长度为1的情况,我们大致定为range(2,28)

然后选择出现频率最大的作为flag的字符,然后再去看一看输出的结果即可找出正确的flag与位数

collections

常用类型有:

计数器(Counter)

双向队列(deque)

默认字典(defaultdict)

有序字典(OrderedDict)

可命名元组(namedtuple)

这里我们主要用了Counter类型:

s = 'abccbaccba'
获取各元素的个数,返回字典
print(Counter(s))   # Counter({'c': 4, 'b': 3, 'a': 3})

most_common
most_common(d) 按照元素出现的次数进行从高到低的排序,返回前d个元素的字典
本题中就用该方法可以选出概率最大的那个元素
from Crypto.Util.strxor import strxor
import base64
import string
import collections
with open(r"D:\\Mango\\xorgame\\cipher.txt",'r') as f:
    s=f.read()
cipher=list(base64.b64decode(s))
with open(r"D:\\Mango\\xorgame\\analyze.txt",'w') as p:
    p.write("".join(list(map(chr,base64.b64decode(s)))))
#print(cipher)
dictionary=string.ascii_letters+ "-,.!? :;\"@&()+=%'\n"+string.digits
#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.!? :;\"'@&()+=%'\n0123456789
def get_key(i,j):
    list = []
    for a in dictionary:
        for b in dictionary:
            if ord(a) ^ cipher[i] == ord(b) ^ cipher[j]:
                list.append(chr(ord(a) ^ cipher[i]))
    return list
for length in range(2,28):
    key=""
    group_nums=len(cipher)//length-1 #分组长度,若取len(cipher)//length,有可能会超出下面的运算范围。这里再减一即可,因为概率很大。
    for i in range(length):
        keylist=[]
        for j in range(group_nums):
            keylist=keylist+(get_key(j*length+i,(j+1)*length+i))
        key+=''.join(collections.Counter(keylist).most_common(1)[0][0])
        #采用collections.Counter().most_commom取出出现次数最多即概率最大的字符为flag
    print(key)

可以把key和密文再次放入enc函数中求出poem来验算

#xor_is_interesting!@#
flag="xor_is_interesting!@#"
def enc(data, key):
    key = (key * (len(data) // len(key) + 1))[:len(data)]
    return strxor(data, key)
with open(r"D:\Mango\\xorgame\\reverse.txt",'w')as r:
    r.write(str(enc("".join(list(map(chr,base64.b64decode(s)))).encode(),flag.encode())))
    r.close()
    f.close()

reverse.txt

b’\nLife, thin and light-off time and time again\nFrivolous tireless\none\nI heard the echo, from the valleys and the heart\nOpen to the lonely soul of sickle harvesting\nRepeat outrightly, but also repeat the well-being of\nEventually swaying in the desert oasis\nI believe I am\nBorn as the bright summer flowers\nDo not withered undefeated fiery demon rule\nHeart rate and breathing to bear the load of the cumbersome\nBored\nTwo\nI heard the music, from the moon and carcass\nAuxiliary extreme aestheticism bait to capture misty\nFilling the intense life, but also filling the pure\nThere are always memories throughout the earth\nI believe I am\nDied as the quiet beauty of autumn leaves\nSheng is not chaos, smoke gesture\nEven wilt also retained bone proudly Qing Feng muscle\nOccult\nThree\nI hear love, I believe in love\nLove is a pool of struggling blue-green algae\nAs desolate micro-burst of wind\nBleeding through my veins\nYears stationed in the belief\nFour\nI believe that all can hear\nEven anticipate discrete, I met the other their own\nSome can not grasp the moment\nLeft to the East to go West, the dead must not return to nowhere\nSee, I wear Zan Flowers on my head, in full bloom along the way all the way\nFrequently missed some, but also deeply moved by wind, frost, snow or rain\nFive\nPrajna Paramita, soon as soon as\nlife be beautiful like summer flowers and death like autumn leaves\nAlso care about what has’

参考文章:

https://blog.youkuaiyun.com/qq_51999772/article/details/123472212

https://igml.top/2018/11/13/2018-HCTF/

https://blog.youkuaiyun.com/qwe1257/article/details/83272340

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值