2020 网鼎杯

admin 2024年8月25日00:42:51评论19 views字数 22765阅读75分53秒阅读模式

青龙组

boom

first:this string md5:46e5efe6165a5afb361217446a2dbd01

在线网站查得:en5oy

This time:Here are have some formulas
3x-y+z=185
2x+3y-z=321
x+y+z=173
input: x =

12
var('x y z')solve([3*x-y+z==185,2*x+3*y-z==321,x+y+z==173],[x,y,z])

Last time: Kill it
x*x+x - 7943722218936282 = 0
input x:

12
var('x')solve([x * x + x - 7943722218936282 == 0],[x])

you raise me up

12345678910111213
#!/usr/bin/env python# -*- coding: utf-8 -*-from Crypto.Util.number import *import randomn = 2 ** 512m = random.randint(2, n-1) | 1c = pow(m, bytes_to_long(flag), n)print 'm = ' + str(m)print 'c = ' + str(c)# m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075# c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499

题中我们的flag在m的指数位置,所以这题是解一个DLP(离散对数问题)

发现题中的n = 2 ** 512, 所以phi(n) = 2 ** 511;即本题模数的欧拉函数具有smooth的性质,即其是由很多小素数乘积而来,所以可用Pohlig Hellman 算法来解决这个DLP,sage的discrete_log用的方法就包括Pohlig Hellman算法,exp:

123456
m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499n = 2 ** 512m = Mod(m,n)c = Mod(c,n)discrete_log(c,m)

easy_ya

题目代码

123456789101112131415161718192021222324252627282930313233343536373839404142
from secret import flag,keyfrom random import randintfrom libnum import n2s,s2nfrom Crypto.Util.number import getPrimelimit = lambda n: n & 0xffffffffpadding="\xe6\xe6\xe7\xe6\xe5\xe6\xe5\xe9\xe5"ek='\xe6\x84\xbf'def encode(key,data):    pad  = randint(0x10000000,0xffffffff)    Key  = [ord(i) for i in key]    Data = [ord(i) for i in data]    a = limit((Key[0] << 24) | (Key[1] << 16) | (Key[2] << 8) | Key[3])    b = limit((Key[4] << 24) | (Key[5] << 16) | (Key[6] << 8) | Key[7])    c = limit((Key[8] << 24) | (Key[9] << 16) | (Key[10] << 8) | Key[11])    d = limit((Key[12] << 24) | (Key[13] << 16) | (Key[14] << 8) | Key[15])    y = limit((Data[0] << 24) | (Data[1] << 16) | (Data[2] << 8) | Data[3])    z = limit((Data[4] << 24) | (Data[5] << 16) | (Data[6] << 8) | Data[7])    pads = 0    for j in range(32):        pads = limit(pads + pad)        y = limit( y + ((z*16 + a) ^ (z + pads) ^ ((z>>5) + b)))        z = limit( z + ((y*16 + c) ^ (y + pads) ^ ((y>>5) + d)))    print hex((y << 52) ^ (pads << 20) ^ z)#pow_check()#token_check()flag=flag.ljust(len(flag)+(-len(flag)&7),'\x00')for i in range(0,len(flag)/8):    encode(key,flag[8*i:8*i+8])for i in range(9):    ek+=padding[i] + key[2*i:2*i+2]p=getPrime(2048)e=0x10001for i in range(2):    q=getPrime(2048)    n=p*q    print n    print pow(s2n(ek),e,n)

显然,我们第一步需要去交互,拿到四个大数,其中两个是有公因子p的大数n,还有两个就是ek的密文。这一步就是凑数的part,没点营养。吐槽,交互的时候什么沙雕PoW,有必要卡这个嘛

破PoW的脚本

123456789101112131415161718192021222324252627282930313233343536373839
from pwn import *import stringimport hashlibcontext.log_level = 'debug'sh = remote("39.96.90.217","17497")sh.recvuntil("x[:20] = ")pa = sh.recv(len('f91a551dfa31e47458df'))sh.recvuntil('openssl_sha')fun = sh.recvuntil(">")[:-1]sh.recvuntil("> ")table = string.printabledef getpow(fun,mess):    for i in table:        for j in table:            for k in table:                for l in table:                    password=i+j+k+l                    if fun == "256":                        if hashlib.sha256(password.encode()).hexdigest()[:20] == mess:                            return i+j+k+l                    elif fun == "384":                        if hashlib.sha384(password.encode()).hexdigest()[:20] == mess:                            return i+j+k+l                    elif fun == "1":                        if hashlib.sha1(password.encode()).hexdigest()[:20] == mess:                            return i+j+k+l                    elif fun == "512":                        if hashlib.sha512(password.encode()).hexdigest()[:20] == mess:                            return i+j+k+l                    elif fun == "224":                        if hashlib.sha224(password.encode()).hexdigest()[:20] == mess:                            return i+j+k+l                    else:                        print(fun)    else:        print("no ans")sh.sendline(getpow(fun,pa))sh.interactive()

然乎我们输入token,拿到自己的data

解得ek

1234567891011121314151617
from Crypto.Util.number import *from gmpy2 import *n1 = n2=p = gcd(n1,n2)q1 = n1//pq2 = n2//passert n1 == p*q1assert n2 == p*q2c1 = e = 65537phi = (p-1)*(q2-1)d = inverse(e,phi)m = pow(c2,d,n2)print(long_to_bytes(m))>>>愿我所爱无忧恙岁长安

python2下会得到这么个ek,有点意思嗷,但你还是沙雕出题人,谁让你用PoW卡我

python3运行得到b'\xe6\x84\xbf\xe6\x88\x91\xe6\x89\x80\xe7\x88\xb1\xe6\x97\xa0\xe5\xbf\xa7\xe6\x81\x99\xe5\xb2\x81\xe9\x95\xbf\xe5\xae\x89'

然后去掉该去的就能得到key了'\x88\x91\x89\x80\x88\xb1\x97\xa0\xbf\xa7\x81\x99\xb2\x81\x95\xbf\xae\x89'

然后就是逆这个encode了。

其中我们交互的时候拿到五组密文,易得,每组密文中,保存了encode中32轮加密后的完整的y,pads和有一部分重合。但是pads加了32次pad后,最后5位已经变成0了。所以z我们可以知道20+5 = 25位,剩下七位未知。

然后我们就去爆pad,我们从密文里头能知道pad的52-32=20位。但这20位其实是中间部分的。最高的5位已经被limit搞没掉了。然后最低的7位我们也是不知道的。所以,,,爆。我们爆了低7位的同时,也能确定一个z,然后反加密看结果咯。

exp:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
from Crypto.Util.number import *limit = lambda n: n & 0xffffffffkey = '\x88\x91\x89\x80\x88\xb1\x97\xa0\xbf\xa7\x81\x99\xb2\x81\x95\xbf\xae\x89'def init(key):    Key  = [ord(i) for i in key]    #Data = [ord(i) for i in data]    a = limit((Key[0] << 24) | (Key[1] << 16) | (Key[2] << 8) | Key[3])    b = limit((Key[4] << 24) | (Key[5] << 16) | (Key[6] << 8) | Key[7])    c = limit((Key[8] << 24) | (Key[9] << 16) | (Key[10] << 8) | Key[11])    d = limit((Key[12] << 24) | (Key[13] << 16) | (Key[14] << 8) | Key[15])    return (a,b,c,d)    #y = limit((Data[0] << 24) | (Data[1] << 16) | (Data[2] << 8) | Data[3])    #z = limit((Data[4] << 24) | (Data[5] << 16) | (Data[6] << 8) | Data[7])(a,b,c,d)=init(key)ans = 0x9d98a72f5c82c26680a65def check(s):    for i in s:        if i not in "flag{0123456789bcde-_}\x00":            return False    return Truefor ans in [0xcf4add0cf5469a49d19c,0xcccd38faa373af5059b5f,0xad0e355d4d8b1cc9771d1,0x703ccca78d36e770d0613,0x54e05275b03e2cdedc053]:    for h in range(2**6):        for l in range(2**8):            y = ans >> 52#取y            mix = ans & (2**52-1)#剩下的为不确定z和pad混合            pads_true = mix >> 32#拿到pad的有效的20位            source_pad = (h<<27)| (pads_true<<7)| l#爆破pad            z = limit(mix ^ (source_pad<<25))#根据猜的pad,然后mix中pad和z的混合部分,确定z            for round in range(32):                pads = limit(source_pad*(32-round))#根据encode来用pads                z = limit( z - ((y*16 + c) ^ (y + pads) ^ ((y>>5) + d)))#加密函数反一下                y = limit( y - ((z*16 + a) ^ (z + pads) ^ ((z>>5) + b)))            flag = (y<<32)+z            #print flag            if check(long_to_bytes(flag)):#根据flag的可能字符来判断咯                print(long_to_bytes(flag))

白虎组

b64

换表base64,将给出对应关系记下来,发现flag密文中[‘E’, ‘G’, ‘I’, ‘s’, ‘X’, ‘z’],这六个字符没有映射关系。

然后有[‘+’, ‘/‘, ‘1’, ‘5’, ‘7’, ‘6’, ‘9’, ‘8’, ‘A’, ‘C’, ‘H’, ‘K’, ‘J’, ‘P’, ‘R’, ‘V’, ‘e’, ‘f’, ‘n’, ‘u’, ‘w’, ‘v’] 这么多位字符也没有被映射。

所以爆破这两个列表中的映射关系

然后根据flag的格式,uuid,来判断结果。

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
# -*- coding: utf-8-*-from base64 import *from string import *def check(s):    for i in s:        if i not in "flag{-1234567890abcdef}":            return False    return Trueflag = 'uLdAuO8duojAFLEKjIgdpfGeZoELjJp9kSieuIsAjJ/LpSXDuCGduouz'a='pTjMwJ9WiQHfvC+eFCFKTBpWQtmgjopgqtmPjfKfjSmdFLpeFf/Aj2ud3tN7u2+enC9+nLN8kgdWo29ZnCrOFCDdFCrOFoF='b='YXNobGtqIUBzajEyMjMlXiYqU2Q0NTY0c2Q4NzlzNWQxMmYyMzFhNDZxd2prZDEySjtESmpsO0xqTDtLSjg3MjkxMjg3MTM='alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789abcdefABCDEF+/'FLAG=''print("fail words")for i in flag:    if i in a:        index = a.index(i)        FLAG+=b[index]    else:        FLAG+='!'        print i,print "\nFLAG cipher"       print FLAG#'ZmxhZ3sxZTNhMm!lN!0xYz!yLT!mNGYtOWIyZ!!hNGFmYW!kZj!xZTZ!'print "alternative words"aw=""for i in alpha:    if i not in b:        aw += iprint aw'@#$%^&'table = 'ACHJKPRVefnuvw156789efAC+/'print("for z")for i in table:    if b64decode("ZTZ"+i)[-1] == '}':        FLAG = FLAG.replace("ZTZ!","ZTZ9")        table = table.replace(i,"")        #print FLAGprint("for G")for i in table:    if check(b64decode("Zj"+i+"x")) and check(b64decode("Yz"+i+"y")):        #print b64decode("Zj"+i+"x")        FLAG = FLAG.replace("Zj!x","Zj"+i+"x").replace("Yz!y","Yz"+i+"y")        table = table.replace(i,"")        #print i        #print FLAGprint("for I and s")for i in table:    for j in table:        if check(b64decode("N"+i+"0x")) and check(b64decode("Z"+i+j+"h")):            #print b64decode("N"+i+"0x"),b64decode("Z"+i+j+"h")            FLAG = FLAG.replace("N!0x","N"+i+"0x").replace("Z!!h","Z"+i+j+"h")            table = table.replace(i,"").replace(j,"")            #print i,j            #print FLAGprint("for X and E")for i in table:    for j in table:        if j == i:            continue        s = b64decode(FLAG.replace("Mm!l","Mm"+i+"l").replace("LT!m","LT"+i+"m").replace("YW!k","YW"+j+'k'))        if check(s):            print s

rand

啊,一道憨憨题,mt19937都快给玩烂了。而且这还是最最简单的预测,直接套上现成的工具就能解key。至于后面的一个只给了加密函数没给解密函数用的feistel的密码,可能是DES吧,没细看。直接把密钥流反过来,用他给的加密函数来解密就好了。

MT19937预测key

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
import randomclass MT19937Recover:    """Reverses the Mersenne Twister based on 624 observed outputs.    The internal state of a Mersenne Twister can be recovered by observing    624 generated outputs of it. However, if those are not directly    observed following a twist, another output is required to restore the    internal index.    See also https://en.wikipedia.org/wiki/Mersenne_Twister#Pseudocode .    """    def unshiftRight(self, x, shift):        res = x        for i in range(32):            res = x ^ res >> shift        return res    def unshiftLeft(self, x, shift, mask):        res = x        for i in range(32):            res = x ^ (res << shift & mask)        return res    def untemper(self, v):        """ Reverses the tempering which is applied to outputs of MT19937 """        v = self.unshiftRight(v, 18)        v = self.unshiftLeft(v, 15, 0xefc60000)        v = self.unshiftLeft(v, 7, 0x9d2c5680)        v = self.unshiftRight(v, 11)        return v    def go(self, outputs, forward=True):        """Reverses the Mersenne Twister based on 624 observed values.        Args:            outputs (List[int]): list of >= 624 observed outputs from the PRNG.                However, >= 625 outputs are required to correctly recover                the internal index.            forward (bool): Forward internal state until all observed outputs                are generated.        Returns:            Returns a random.Random() object.        """        result_state = None        assert len(outputs) >= 624       # need at least 624 values        ivals = []        for i in range(624):            ivals.append(self.untemper(outputs[i]))        if len(outputs) >= 625:            # We have additional outputs and can correctly            # recover the internal index by bruteforce            challenge = outputs[624]            for i in range(1, 626):                state = (3, tuple(ivals+[i]), None)                r = random.Random()                r.setstate(state)                if challenge == r.getrandbits(32):                    result_state = state                    break        else:            # With only 624 outputs we assume they were the first observed 624            # outputs after a twist -->  we set the internal index to 624.            result_state = (3, tuple(ivals+[624]), None)        rand = random.Random()        rand.setstate(result_state)        if forward:            for i in range(624, len(outputs)):                assert rand.getrandbits(32) == outputs[i]        return randdef test_PythonMT19937Recover():    """Just a testcase to ensure correctness"""    mtb = MT19937Recover()    #r1 = random.Random(0x31337)    # just some discarded random numbers to move internal state forward    #[r1.getrandbits(32) for _ in range(1234)]    # the actual leak of 1000 values    #n = [r1.getrandbits(32) for _ in range(1000)]    with open ("random") as f:        nn= f.read().split("\n")        print(nn)        n = [int(_) for _ in nn[:-1]]    r2 = mtb.go(n)    print (r2.getrandbits(32))    #assert r1.getrandbits(32) == r2.getrandbits(32)test_PythonMT19937Recover()

拿到key,改加密函数,解密得到flag。

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
# -*- coding: utf-8 -*-import base64import randomflag = "flag{************************************}"hexadecimalcontrast = {    '0': '0000',    '1': '0001',    '2': '0010',    '3': '0011',    '4': '0100',    '5': '0101',    '6': '0110',    '7': '0111',    '8': '1000',    '9': '1001',    'a': '1010',    'b': '1011',    'c': '1100',    'd': '1101',    'e': '1110',    'f': '1111',}IP = [58, 50, 42, 34, 26, 18, 10, 2,      60, 52, 44, 36, 28, 20, 12, 4,      62, 54, 46, 38, 30, 22, 14, 6,      64, 56, 48, 40, 32, 24, 16, 8,      57, 49, 41, 33, 25, 17, 9, 1,      59, 51, 43, 35, 27, 19, 11, 3,      61, 53, 45, 37, 29, 21, 13, 5,      63, 55, 47, 39, 31, 23, 15, 7]IP_1 = [40, 8, 48, 16, 56, 24, 64, 32,        39, 7, 47, 15, 55, 23, 63, 31,        38, 6, 46, 14, 54, 22, 62, 30,        37, 5, 45, 13, 53, 21, 61, 29,        36, 4, 44, 12, 52, 20, 60, 28,        35, 3, 43, 11, 51, 19, 59, 27,        34, 2, 42, 10, 50, 18, 58, 26,        33, 1, 41, 9, 49, 17, 57, 25]E = [32, 1, 2, 3, 4, 5,     4, 5, 6, 7, 8, 9,     8, 9, 10, 11, 12, 13,     12, 13, 14, 15, 16, 17,     16, 17, 18, 19, 20, 21,     20, 21, 22, 23, 24, 25,     24, 25, 26, 27, 28, 29,     28, 29, 30, 31, 32, 1]S = [[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,      3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,      0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,      13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, ],     [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,      13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,      13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,      1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, ],     [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,      0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,      4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,      15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, ],     [7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,      13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,      10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,      3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, ],     [2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,      14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,      4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,      11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, ],     [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,      10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,      9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,      4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, ],     [4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,      13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,      1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,      6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, ],     [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,      1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,      7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,      2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11, ]]PC_1 = [57, 49, 41, 33, 25, 17, 9, 1,        58, 50, 42, 34, 26, 18, 10, 2,        59, 51, 43, 35, 27, 19, 11, 3,        60, 52, 44, 36, 63, 55, 47, 39,        31, 23, 15, 7, 62, 54, 46, 38,        30, 22, 14, 6, 61, 53, 45, 37,        29, 21, 13, 5, 28, 20, 12, 4, ]PC_2 = [14, 17, 11, 24, 1, 5, 3, 28,        15, 6, 21, 10, 23, 19, 12, 4,        26, 8, 16, 7, 27, 20, 13, 2,        41, 52, 31, 37, 47, 55, 30, 40,        51, 45, 33, 48, 44, 49, 39, 56,        34, 53, 46, 42, 50, 36, 29, 32, ]P = [16, 7, 20, 21,     29, 12, 28, 17,     1, 15, 23, 26,     5, 18, 31, 10,     2, 8, 24, 14,     32, 27, 3, 9,     19, 13, 30, 6,     22, 11, 4, 25, ]movnum = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]def HexToBin(string):    "Convert sixteen to binary"    Binstring = ""    string = string.lower()    for i in string:        try:            Binstring += hexadecimalcontrast[i]        except:            return -1    return Binstringdef BinToStr(strbin):    "Turn the binary string to a ASCII string"    strten = ""    for i in range(len(strbin) // 8):        num = 0        test = strbin[i * 8:i * 8 + 8]        for j in range(8):            num += int(test[j]) * (2**(7 - j))        strten += chr(num)    return strtendef StrToHex(string):    "Converts a string to HEX"    hexStr = ''    for i in string:        tmp = str(hex(ord(i)))        if len(tmp) == 3:            hexStr += tmp.replace('0x', '0')        else:            hexStr += tmp.replace('0x', '')    return hexStrdef Binxor(string1, string2):    "If the length is different, only the short one is returned."    strlen = 0    xorstr = ""    if len(string1) > len(string2):        strlen = len(string2)    else:        strlen = len(string1)    for i in range(strlen):        if string1[i] == string2[i]:            xorstr += '0'        else:            xorstr += '1'    return xorstrdef SubstitutionBox(keyfield, sub):    newkeyfield = ''    for i in range(len(sub)):        newkeyfield += keyfield[sub[i] - 1]    return newkeyfielddef SubkeyGeneration(freq, C, D):    for i in range(movnum[freq]):        C = C[1:] + C[:1]        D = D[1:] + D[:1]    return C, D, SubstitutionBox(C + D, PC_2)def enkey(secretkey):     netss = SubstitutionBox(HexToBin(StrToHex(secretkey)), PC_1)    C, D = netss[:28], netss[28:]    key = []    for i in range(16):         C, D, keyone = SubkeyGeneration(i, C, D)        key.append(keyone)    return keydef Sbox(plaintext, sub):    return HexToBin("%x" % S[sub][int(plaintext[:1] + plaintext[-1:], 2) * 16 + int(plaintext[1:-1], 2)])def Function(plaintext, secretkey):    plaintext = Binxor(SubstitutionBox(plaintext, E),                       secretkey)    sout = ''    for i in range(8):        sout += Sbox(plaintext[i * 6:(i + 1) * 6], i)    sout = SubstitutionBox(sout, P)    return soutdef endecrypt(plaintext, secretkey):    netss = SubstitutionBox(HexToBin(StrToHex(plaintext)), IP)    L, R = netss[:32], netss[32:]    for i in range(16):        L, R = R, Binxor(L, Function(R, secretkey[i]))    return SubstitutionBox(R + L, IP_1)def encryption(plaintext, secretkey):    plaintext = plaintext + (8 - len(plaintext) % 8) * '\0'    keys = enkey(secretkey[:8])    print(keys)    ciphertext = ''    for i in range(len(plaintext) / 8):        ciphertext += endecrypt(plaintext[i * 8:(i + 1) * 8], keys)    return base64.b64encode(BinToStr(ciphertext))def decryption(plaintext, secretkey):    plaintext = "t2GzuEfVDaJsNLBqC8N7C3/2UgIeCoQLC2qLkT1ukFULskzMc1u9QeFizVUfFYfA"    plaintext = base64.b64decode(plaintext)    print plaintext    keys = enkey(secretkey[:8])[::-1]    #print(keys)    ciphertext = ''    for i in range(len(plaintext) / 8):        ciphertext += endecrypt(plaintext[i * 8:(i + 1) * 8], keys)    return (BinToStr(ciphertext))def generate():    fw = open("random", "w")    for i in range(700):        fw.write(str(random.getrandbits(32))+"\n")    fw.close()generate()f = open("flag.txt", "r")key = str(random.getrandbits(32))key = '2990136190'ciphertext = decryption(flag, key)print ciphertext

朱雀组

simple

简单仿射加密,就是123456和26不互素,我们用26的一个素因子13代替26先,得到的答案,可以选择:如果不符合uuid格式,就加个13,不过,后来想想,由于uuid只有abcdef加上 ‘flag’ 的lg,模13其实是足够的。所以其实不需要判断。

由于仿射不加密除字母外的字符,所以直接拼接上来就可以了

确实simple,解密代码就一行:

123
from Crypto.Util.number import inverseflag = ''.join(i if i not in "qwertyuiopasdfghjklzxcvbnm" else chr(((ord(i)-ord('a') - 321564))*inverse(123456,13)%13+ord('a')) for i in 'kgws{m8u8cm65-ue9k-44k5-8361-we225m76eeww}')print(flag)

RUA

rsa低加密指数攻击,直接套先知上的一个脚本,刚开始测e=3,发现失败,于是爆破e

123456789101112131415
import binascii,gmpy2def CRT(mi, ai):    assert(reduce(gmpy2.gcd,mi)==1)    assert (isinstance(mi, list) and isinstance(ai, list))    M = reduce(lambda x, y: x * y, mi)    ai_ti_Mi = [a * (M / m) * gmpy2.invert(M / m, m) for (m, a) in zip(mi, ai)]    return reduce(lambda x, y: x + y, ai_ti_Mi) % Mfor e in range(1,20):    try:        m=gmpy2.iroot(CRT([n1,n2,n3], [c1,c2,c3]), e)[0]        print(binascii.unhexlify(hex(m)[2:].strip("L")))    except:        pass

guess_game

两个考点:LCG和LFSR

LCG攻击原理这里看,NCTF出现过的。

LFSR的攻击手法ctf-wiki上看。

解密流程:

第一步我们通过六个level的值恢复LCG的参数从而预测第七个code,从而达到(500,10)这个level。开局拥有10个coin!

然后我们用9次机会,可以得到72bit的输出,其中前40bit输出逆序可以得到初始的r

但是这里的lfsr其实是39级的,所以至少需要78bit才能恢复

所以我们要爆破6bit的输出

需要说明的是即使有78bit的输出,也有可能因为矩阵没有满秩从而解不出key来。

然后这里我换了个思路,我硬猜,要求前九次猜中一个,这样我就可以多拿两组数据(其实多拿一次就够了)

这样我就能拿到80bit的输出,然后我用下面那个sage脚本,根据wiki所述构造矩阵,解个线性方程,得到key。点解密的时候要放《好运来》,增加解密成功的概率,唱《国歌》应该也可以。

123456789101112131415161718192021
output = '10100010010100010010101001100110000000000111101111011101010101000111110011111011'N = 39F = GF(2)ans=[]out = outputSn = [vector(F,N) for j in range(N+1)]for j in range(N+1):    Sn[j] = list(map(int,out[j:j+N]))X = matrix(F,Sn[:N])invX = (X^-1)Y = vector(F,Sn[-1])Cn = Y * invXres = ''.join(str(i) for i in Cn)ans.append(int(res[::-1],2))print (ans)print(len(ans))>> [71834525659]>> 1

用于交互的脚本

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
# -*- coding: utf-8 -*-from Crypto.Util.number import long_to_bytes,bytes_to_long,inversefrom pwn import *context.log_level = 'debug'def gcd(a, b):    while b:        a, b = b, a%b    return adef crack_unknown_increment(states, modulus, multiplier):    """    利用伪随机序列s,模数n,乘数m,恢复增数c    states:伪随机数序列s    modulus:模数n,    multiplier:乘数m    increment:增量c    return:根据n,m,s0,s1恢复c,并返回    """    increment = (states[1] - states[0]*multiplier) % modulus    return modulus, multiplier, incrementdef crack_unknown_multiplier(states, modulus):    """    利用伪随机序列s和模数n,恢复乘数m    states:伪随机数序列s    modulus:模数n,    multiplier:乘数m    return:根据n,s0,s1,s2恢复m,然后利用crack_unknown_increment恢复c    """    multiplier = (states[2] - states[1]) * inverse(states[1] - states[0], modulus) % modulus    return crack_unknown_increment(states, modulus, multiplier)def crack_unknown_modulus(states):    """    利用初值和随后LCG产生的连续的几个值,恢复模数n    modulus:模数n    states:伪随机数序列s    diffs:相邻随机数s的差值:t序列              zeroes:与t系列有关的差值,zeroes = t2*t0 - t1*t1,t0,t1,t2相邻    return:根据n,s0,s1,s2恢复m,然后利用crack_unknown_increment恢复c    """    diffs = [s1 - s0 for s0, s1 in zip(states, states[1:])]    zeroes = [t2*t0 - t1*t1 for t0, t1, t2 in zip(diffs, diffs[1:], diffs[2:])]    modulus = abs(reduce(gcd, zeroes))    return crack_unknown_multiplier(states, modulus)def lcg(seed,params):    """    LCG算法    params:(multiplier,increment,modulus)    seed:伪随机序列中第一个值s0    return:返回一个迭代器,其中的值是私钥序列    """    (m,c,n)=params    x = seed % n    yield int(x)    while True:        x = (m * x + c) % n        yield int(x)def decode(pri,pub,c,p):        """    ElGamal解密算法    pri:一方私钥    pub:另一方公钥    sharekey:双方协商密钥    c:密文    p:模数    m:明文    return:返回明文字符    """    sharekey = pow(pub,pri,p)    m=long_to_bytes(c*inverse(sharekey,p)%p)    return mclass Game:    def __init__(self, n, key, r, b):        self.n = n#40        self.key = key         self.r = r & (2 ** self.n - 1)        self.b = b#8    def out(self):        o = self.r & 1        p = self.r & self.key        q = 0        while p:            q = q + p & 1            p = p >> 1        q = q & 1        t = q << (self.n - 2) & (2 ** self.n - 1)        self.r = t | (self.r >> 1) & (2 ** self.n - 1)        return o    def next(self):        res = 0        for i in range(self.b):            o = self.out()            res |=  o << (self.b - 1 - i)        return resdef getr(s):    r = ''    for i in s:        b = bin(i)[2:].rjust(8,'0')        for each in b:            r = each+r    print int(r,2)    return int(r,2)def getk(s):    k=""    for i in s:        b = bin(i)[2:].rjust(8,'0')        for each in b:            k += each    return ksh = remote('59.110.243.101','5123')sh.recvuntil("Your choice:\n")sh.sendline("2")sh.recvuntil("Baby:")Baby = sh.recvuntil("\n")[:-1]sh.recvuntil("Easy:")Easy = sh.recvuntil("\n")[:-1]sh.recvuntil("Normal:")Normal = sh.recvuntil("\n")[:-1]sh.recvuntil("Hard:")Hard = sh.recvuntil("\n")[:-1]sh.recvuntil("Master:")Master = sh.recvuntil("\n")[:-1]sh.recvuntil("Crazy:")Crazy = sh.recvuntil("\n")[:-1]pri=[Baby,Easy,Normal,Hard,Master,Crazy](n,m,c)=crack_unknown_modulus([int(each) for each in pri])x=int(pri[0])key = lcg(x,(m,c,n))for _ in range(6):    next(key)choice = next(key)sh.recvuntil("Input the level code:\n")sh.sendline(str(choice))sh.recvuntil("Your choice:\n")sh.sendline("1")#flag=""s=[]F = 0for _ in range(9):    sh.recvuntil("Input your answer:\n")    sh.sendline("0")    ans = sh.recvuntil("The answer is ")    if 'Right' in ans:        F = 1        print("NICE")    s.append(int(sh.recvuntil("!")[:-1]))if F == 1:    sh.recvuntil("Input your answer:\n")    sh.sendline("0")    ans = sh.recvuntil("The answer is ")    s.append(int(sh.recvuntil("!")[:-1]))r = getr(s[:5])output = getk(s[:])print "r:"+str(r)print "output:"+ outputprint sk = input("k:")game = Game(40,k,r,8)for _ in range(10):    next(game)for _ in range(500):    sh.recvuntil("Input your answer:\n")    sh.sendline(str(next(game)))sh.interactive()[DEBUG] Received 0x3f bytes:    'Your coin: 500\n'    'You Win!\n'    'flag{12727f129b72e685388c6a67538ee9b0}\n'

最后五分钟出flag,太幸运了。就是没队伍,有点浪费了

玄武组

Safe_box

主要逻辑

  1. 过了PoW进行交互
  2. 1可以得到一组23*20的key
  3. 3可以得到flag的密文c
  4. 加密函数生成23*40的key,一共23组明文,每组明文加密40次,记录每次的结果
  5. 每一次的加密逻辑为b = m + Σ((a_j*i)e_i),其中a_j为组里的加密次数,j=1,2,,40;e_i为列表e里的每一个元素,i = 1,2,3,,,29

解密流程

  1. 第一组,当i=0时,a=1,b_1 = m_1 + Σ(e_i)
  2. 第二组,当i=0时,a=1,b_2 = m_2 + Σ(e_i)
  3. 第三组,当i=0时,a=1,b_3 = m_3 + Σ(e_i)
  4. 我们得到的23组信息中的每组的第一条就是b_1, b_2,b_3
  5. 所以我们只需要获得Σ(e_i)就可以还原所有的m
  6. 被加密的是pri,pri是PEM文件格式,有固定的开头、结尾格式,所以我们知道部分明文,所以我们知道m_1
  7. 利用b_1和m_1获取Σ(e_i)
  8. 再利用b_1,,,b_23和Σ(e_i) 获取所有m
  9. 再利用私钥文件对flag进行解密

exp

12345678910111213141516171819
# -*- coding: utf8 -*-from Crypto.PublicKey import RSAfrom Crypto.Util.number import *import rewith open('data.txt') as f:    data = f.read()ms = re.findall("{'a': 1, 'b': (.*?)L}",data)c = re.findall("flag:(.*)",data)m1 = b'-----BEGIN RSA PRIVATE KEY-----\\nMIICXAIB'es = int(ms[0])-bytes_to_long(m1)print espri=""for i in ms:    pri = pri + long_to_bytes(int(i)-es)print pripri = RSA.importKey(pri.replace("\\"",""))print(long_to_bytes(pow(int(c[0]),pri.d,pri.n)))

easy_wa

bytectf原题lrlr的一个part

https://blog.csdn.net/qq_33458986/article/details/100699263

calc是一个多项式在GF(2)下的平方运算,我们要做的应该是求根。

但是这里给出的既约多项式的阶不大,我们一直平方下去,很快就能回到起点。所以直接拿密文去calc就行了。

先交互,过那个恶心的PoW 跟青龙组那个一样,再看看名字,同一个出题人,凑!,输入token拿到4组密文

然后每组分别解密

12345678910111213141516171819202122232425262728293031
from os import urandom as uafrom Crypto.Util.number import *magic=32805def calc(m,p):    res=0    lens=hlen(p)    for i in bin(m)[2:]:        res*=2        res^=m if i=='1' else 0        res^=p if hlen(res) == lens else 0    return resdef check(s):    for i in s:        if i not in "flag{0123456789bcde-_}\x00":            return False    return Trueflags=[3723147309,8016759097521062564,267529443716352603115102819467183104162,110068498753042154535753131190467876514149603112955078214309283006458454378660]FLAG=""r = 2for flag in flags:    r*=2    while True:        flag=calc(flag,magic + (1<<r*8))        if check(long_to_bytes(flag)[:10]):            FLAG+=(long_to_bytes(flag))            print FLAG            break

就这么ak了网鼎杯的密码学?赵总原话:这届密码学不行。

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可联系QQ 643713081,也可以邮件至 [email protected] - source:Van1sh的小屋

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年8月25日00:42:51
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2020 网鼎杯https://cn-sec.com/archives/3093401.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息