2019-De1CTF-xorz

作者: 简言之_ | 来源:发表于2019-08-07 13:42 被阅读5次

    题目给了一个异或脚本:

    from itertools import *
    from data import flag,plain
    
    key=flag.strip("de1ctf{").strip("}")
    assert(len(key<38))
    salt="WeAreDe1taTeam"
    ki=cycle(key)
    si=cycle(salt)
    cipher = ''.join([hex(ord(p) ^ ord(next(ki)) ^ ord(next(si)))[2:].zfill(2) for p in plain])
    print cipher
    
    cipher = ''.join([hex(ord(p) ^ ord(next(ki)) ^ ord(next(si)))[2:].zfill(2) for p in plain])
    

    三者进行异或,未知部分有两个,flag和plain,最后输出的结果是16进制的密文
    salt和key都是循环使用
    salt是已知的因此先把salt层异或去掉

    from itertools import *
    salt="WeAreDe1taTeam"
    si=cycle(salt)
    c = '49380d773440222d1b421b3060380c3f403c3844791b202651306721135b6229294a3c3222357e766b2f15561b35305e3c3b670e49382c295c6c170553577d3a2b791470406318315d753f03637f2b614a4f2e1c4f21027e227a4122757b446037786a7b0e37635024246d60136f7802543e4d36265c3e035a725c6322700d626b345d1d6464283a016f35714d434124281b607d315f66212d671428026a4f4f79657e34153f3467097e4e135f187a21767f02125b375563517a3742597b6c394e78742c4a725069606576777c314429264f6e330d7530453f22537f5e3034560d22146831456b1b72725f30676d0d5c71617d48753e26667e2f7a334c731c22630a242c7140457a42324629064441036c7e646208630e745531436b7c51743a36674c4f352a5575407b767a5c747176016c0676386e403a2b42356a727a04662b4446375f36265f3f124b724c6e346544706277641025063420016629225b43432428036f29341a2338627c47650b264c477c653a67043e6766152a485c7f33617264780656537e5468143f305f4537722352303c3d4379043d69797e6f3922527b24536e310d653d4c33696c635474637d0326516f745e610d773340306621105a7361654e3e392970687c2e335f3015677d4b3a724a4659767c2f5b7c16055a126820306c14315d6b59224a27311f747f336f4d5974321a22507b22705a226c6d446a37375761423a2b5c29247163046d7e47032244377508300751727126326f117f7a38670c2b23203d4f27046a5c5e1532601126292f577776606f0c6d0126474b2a73737a41316362146e581d7c1228717664091c'.decode('hex')
    no_salt = ''.join([chr(ord(p) ^ ord(next(si))) for p in c])
    print no_salt.encode('hex')
    
    no_salt =1e5d4c055104471c6f234f5501555b5a014e5d001c2a54470555064c443e235b4c0e590356542a130a4242335a47551a590a136f1d5d4d440b0956773613180b5f184015210e4f541c075a47064e5f001e2a4f711844430c473e2413011a100556153d1e4f45061441151901470a196f035b0c4443185b322e130806431d5a072a46385901555c5b550a541c1a2600564d5f054c453e32444c0a434d43182a0b1c540a55415a550a5e1b0f613a5c1f10021e56773a5a0206100852063c4a18581a1d15411d17111b052113460850104c472239564c0755015a13271e0a55553b5a47551a54010e2a06130b5506005a393013180c100f52072a4a1b5e1b165d50064e411d0521111f235f114c47362447094f10035c066f19025402191915110b4206182a544702100109133e394505175509671b6f0b01484e06505b061b50034a2911521e44431b5a233f13180b5508131523050154403740415503484f0c2602564d470a18407b775d031110004a54290319544e06505b060b424f092e1a770443101952333213030d554d551b2006064206555d50141c454f0c3d1b5e4d43061e453e39544c17580856581802001102105443101d111a043c03521455074c473f3213000a5b085d113c194f5e08555415180f5f433e270d131d420c1957773f560d11440d40543c060e470b55545b114e470e193c155f4d47110947343f13180c100f565a000403484e184c15050250081f2a54470545104c5536251325435302461a3b4a02484e12545c1b4265070b3b5440055543185b36231301025b084054220f4f42071b1554020f430b196f19564d4002055d79
    

    去掉salt层,就剩下plain和key了,key就是我们要求的flag,这里注意到key位数小于38,所以是用key来循环异或加密的,对于利用重复密钥异或的情况有现成的脚本,原理为汉明距离hamming_distance

    hamming_distance:在信息论中表示两个等长字符串在对应位置上不同字符的数目 以d(x, y)表示字符串x和y之间的汉明距离 简单来说 汉明距离度量了通过替换字符的方式将字符串x变成y所需要的最小的替换次数

    # coding:utf-8
    
    # python3
    
    no_salt =bytes.fromhex('1e5d4c055104471c6f234f5501555b5a014e5d001c2a54470555064c443e235b4c0e590356542a130a4242335a47551a590a136f1d5d4d440b0956773613180b5f184015210e4f541c075a47064e5f001e2a4f711844430c473e2413011a100556153d1e4f45061441151901470a196f035b0c4443185b322e130806431d5a072a46385901555c5b550a541c1a2600564d5f054c453e32444c0a434d43182a0b1c540a55415a550a5e1b0f613a5c1f10021e56773a5a0206100852063c4a18581a1d15411d17111b052113460850104c472239564c0755015a13271e0a55553b5a47551a54010e2a06130b5506005a393013180c100f52072a4a1b5e1b165d50064e411d0521111f235f114c47362447094f10035c066f19025402191915110b4206182a544702100109133e394505175509671b6f0b01484e06505b061b50034a2911521e44431b5a233f13180b5508131523050154403740415503484f0c2602564d470a18407b775d031110004a54290319544e06505b060b424f092e1a770443101952333213030d554d551b2006064206555d50141c454f0c3d1b5e4d43061e453e39544c17580856581802001102105443101d111a043c03521455074c473f3213000a5b085d113c194f5e08555415180f5f433e270d131d420c1957773f560d11440d40543c060e470b55545b114e470e193c155f4d47110947343f13180c100f565a000403484e184c15050250081f2a54470545104c5536251325435302461a3b4a02484e12545c1b4265070b3b5440055543185b36231301025b084054220f4f42071b1554020f430b196f19564d4002055d79')
    import base64
    import string
    
    def bxor(a, b):# xor two byte strings of different lengths
       if len(a) > len(b):
            return bytes([x ^ y for x, y in zip(a[:len(b)], b)])
       else:
          return bytes([x ^ y for x, y in zip(a, b[:len(a)])])
    def hamming_distance(b1, b2):
        differing_bits =0
    
        for byte in bxor(b1, b2):
            differing_bits += bin(byte).count("1")
        return differing_bits
    
    def score(s):
       freq = {}
       freq[' '] = 700000000
       freq['e'] = 390395169
       freq['t'] = 282039486
       freq['a'] = 248362256
       freq['o'] = 235661502
       freq['i'] = 214822972
       freq['n'] = 214319386
       freq['s'] = 196844692
       freq['h'] = 193607737
       freq['r'] = 184990759
       freq['d'] = 134044565
       freq['l'] = 125951672
       freq['u'] = 88219598
       freq['c'] = 79962026
       freq['m'] = 79502870
       freq['f'] = 72967175
       freq['w'] = 69069021
       freq['g'] = 61549736
       freq['y'] = 59010696
       freq['p'] = 55746578
       freq['b'] = 47673928
       freq['v'] = 30476191
       freq['k'] = 22969448
       freq['x'] = 5574077
       freq['j'] = 4507165
       freq['q'] = 3649838
       freq['z'] = 2456495
    
       score = 0
       string=bytes.decode(s)
       for c in string.lower():
           if c in freq:
                score += freq[c]
       return score
    
    def break_single_key_xor(b1):
        max_score = 0
        english_plaintext = 0
        key = 0
    
        for i in range(0,256):
            b2 = [i]* len(b1)
            try:
                plaintext = bxor(b1, b2)
                pscore = score(plaintext)
            except Exception:
                continue
            if pscore > max_score or not max_score:
               max_score = pscore
               english_plaintext = plaintext
               key = chr(i)
        return key
    
    b = no_salt
    
    normalized_distances = []
    
    for KEYSIZE in range(2, 40):
    
       # 我们取其中前6段计算平局汉明距离
    
       b1 = b[: KEYSIZE]
       b2 = b[KEYSIZE: KEYSIZE * 2]
       b3 = b[KEYSIZE * 2: KEYSIZE * 3]
       b4 = b[KEYSIZE * 3: KEYSIZE * 4]
       b5 = b[KEYSIZE * 4: KEYSIZE * 5]
       b6 = b[KEYSIZE * 5: KEYSIZE * 6]
       b7 = b[KEYSIZE * 6: KEYSIZE * 7]
    
       normalized_distance = float(
          hamming_distance(b1, b2) +
          hamming_distance(b2, b3) +
          hamming_distance(b3, b4) +
          hamming_distance(b4, b5) +
          hamming_distance(b5, b6) 
       ) / (KEYSIZE * 5)
       normalized_distances.append(
          (KEYSIZE, normalized_distance)
       )
    
    normalized_distances = sorted(normalized_distances, key=lambda x: x[1])
    
    
    for KEYSIZE, _ in normalized_distances[:5]:
       block_bytes = [[] for _ in range(KEYSIZE)]
       for i, byte in enumerate(b):
            block_bytes[i % KEYSIZE].append(byte)
       keys = ''
    
       for bbytes in block_bytes:
            keys += break_single_key_xor(bbytes)
       key = bytearray(keys * len(b), "utf-8")
       plaintext = bxor(b, key)
       print("keysize:", KEYSIZE)
       print("key is:", keys, "n")
       s = bytes.decode(plaintext)
       print(s)
    
    图片.png

    最后发现plain就是莎士比亚的十四行诗。。。


    图片.png

    flag{W3lc0m3tOjo1nu55un1ojOt3m0cl3W}

    参考:
    小记一类ctf密码题解题思路
    https://xz.aliyun.com/t/3256#toc-22
    https://cypher.codes/writing/cryptopals-challenge-set-1
    https://cryptopals.com/sets/1/challenges/6
    https://mp.weixin.qq.com/s?__biz=MzU3ODc2NTg1OA==&mid=2247484089&idx=1&sn=3f41f1d65595f47dc72918b22cffc128&chksm=fd7117f4ca069ee292d6bbabe37d5aa9445747d0c13dd8b2d2f1d274f7afa32f910fe28ff07e&mpshare=1&scene=23&srcid=&sharer_sharetime=1565101436270&sharer_shareid=0a12e40935fbeb4e04dfab7ff42aca93#rd

    相关文章

      网友评论

        本文标题:2019-De1CTF-xorz

        本文链接:https://www.haomeiwen.com/subject/zolodctx.html