青龙组
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) |
题中我们的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
主要逻辑
- 过了PoW进行交互
- 1可以得到一组23*20的key
- 3可以得到flag的密文c
- 加密函数生成23*40的key,一共23组明文,每组明文加密40次,记录每次的结果
- 每一次的加密逻辑为b = m + Σ((a_j*i)e_i),其中a_j为组里的加密次数,j=1,2,,40;e_i为列表e里的每一个元素,i = 1,2,3,,,29
解密流程
- 第一组,当i=0时,a=1,b_1 = m_1 + Σ(e_i)
- 第二组,当i=0时,a=1,b_2 = m_2 + Σ(e_i)
- 第三组,当i=0时,a=1,b_3 = m_3 + Σ(e_i)
- 我们得到的23组信息中的每组的第一条就是b_1, b_2,b_3
- 所以我们只需要获得Σ(e_i)就可以还原所有的m
- 被加密的是pri,pri是PEM文件格式,有固定的开头、结尾格式,所以我们知道部分明文,所以我们知道m_1
- 利用b_1和m_1获取Σ(e_i)
- 再利用b_1,,,b_23和Σ(e_i) 获取所有m
- 再利用私钥文件对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的小屋
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论