import os from binascii import hexlify, unhexlify import Crypto.Random.random as random from secret import flag coef = [239, 163, 147, 71, 163, 75, 219, 73] sbox = list(range(256)) random.shuffle(sbox) sboxi = [] for i inrange(256): sboxi.append(sbox.index(i)) defdoxor(l1,l2): return [x[0]^x[1] for x inzip(l1,l2)] deftrans(blk): res = [] for k inrange(0, 8, 8): bits = [bin(x)[2:].rjust(8,'0') for x in blk[k:k+8]] for i inrange(8): res.append(int(''.join([x[(i+1) % 8] for x in bits]),2)) res[k:k+8] = [(coef[i] * res[k+i]) % 256for i inrange(8)] return res defencrypt_block(pt, ks): cur = doxor(pt, ks[:8]) cur = [sbox[x] for x in cur] cur = trans(cur) cur = [sboxi[x] for x in cur] cur = doxor(cur, ks[8:]) return cur defencrypt(pt, k): x = 0iflen(pt)%8==0else (8-len(pt)%8) pt += [x]*x ct = '' for i inrange(0, len(pt), 8): res = encrypt_block([x for x in pt[i:i+8]], k) ct += ''.join(["{:02x}".format(xx) for xx in res]) return ct defdoout(x): iflen(x) % 16: x = (16 - len(x) % 16) * "0" + x return x defdoin(x): returnlist(unhexlify(x)) defgenkeys(): returnlist(os.urandom(2*8)) if __name__ == "__main__": print(sbox) key = genkeys() ct = encrypt(flag, key) print(ct) whileTrue: pt = doin(input()) print(doout(encrypt(pt, key)))
deftrans(blk): res = [] for k inrange(0, 8, 8): bits = [bin(x)[2:].rjust(8,'0') for x in blk[k:k+8]] for i inrange(8): res.append(int(''.join([x[(i+1) % 8] for x in bits]),2)) res[k:k+8] = [(coef[i] * res[k+i]) % 256for i inrange(8)] return res
defencrypt_block(pt, ks): cur = doxor(pt, ks[:8]) cur = [sbox[x] for x in cur] cur = trans(cur) cur = [sboxi[x] for x in cur] cur = doxor(cur, ks[8:]) return cur
defgetboxinv(s): S,Q=[],[0]*256 cntint,endex=0,False for i in s: iford(i) inrange(48,58): endex=True cntint=cntint*10+ord(i)-48 else: if endex==True: endex=False S.append(cntint) Q[cntint]=len(S)-1 cntint=0 return S,Q defs32tol8(s16): L8=[] for i inrange(0,len(s16),2): L8.append(int(s16[i:i+2],16)) return L8 defpadhex(x,b): x=hex(x)[2:] return (b-len(x))*'0'+x defpadbin(x,b): x=bin(x)[2:] return (b-len(x))*'0'+x defdoxor(l1,l2): return [x[0]^x[1] for x inzip(l1,l2)] defsumbitpros(a,x): c,d=a&x,0 while c: d+=c&1 c>>=1 return d&1
[2] 初始化部分
线性化$S$盒的函数,可以发现,我们类比于上面$\text{16 x 16}$的表格,列举出一个$\text{256 x 256}$的表格,其中$i$是我们列举的输入数字,$j$是带入上面的线性组合对应的比特系数,$k$是$S$盒输出结果构造线性函数的比特系数。最后我们得到的offset序列,例如:offser[115]就是数字$115$通过$S$盒时的最佳逼近系数。这一部分已经在一开始有了讲解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
deflinersbox(sbox): lnipt=[] offset=[[0for _ inrange(256)] for __ inrange(256)] for i inrange(256): if i%15==0: print('[lnrsbox]:'+str(i+1)+'/256') si=sbox[i] for j inrange(256): for k inrange(256): a=sumbitpros(j,i) b=sumbitpros(k,si) if a==b: offset[j][k]+=1 for i inrange(256): offset[i]=[abs(x-128)/256.0for x in offset[i]] for i inrange(256): cur=[x[i] for x in offset] lnipt.append(cur.index(max(cur))) return offset,lnipt
defguess(pt,ct,loc,gus,lnipt,coefinv): pt,ct=s32tol8(pt),s32tol8(ct) ct[loc]^=gus ct[loc]=sbox[ct[loc]] ct[loc]=ct[loc]*coefinv[loc]&255 tmp1=sumbitpros(pt[0],lnipt[1<<((14-loc)&7)]) tmp2=sumbitpros(ct[loc],128) return tmp1==tmp2 defgetkey8f(Tl,Cl,lnipt,coefinv,scale): k8f=[] for i inrange(8): print('[GettingKey]:ID='+str(i+8)) kount=[0for _ inrange(256)] for gskey inrange(256): for j inrange(scale): if guess(Tl[j],Cl[j],i,gskey,lnipt,coefinv): kount[gskey]+=1 beta=[abs(x-scale//2+0.0)/(scale+0.0) for x in kount] k8f.append(beta.index(max(beta))) return k8f
defgetkey07(pt,ct,k8f,coefinv,sbox,sinv): pt,ct=s32tol8(pt),s32tol8(ct) cur=ct cur=doxor(cur,k8f) cur=[sbox[i] for i in cur] cur=transinv(cur) cur=[sinv[i] for i in cur] k07=doxor(pt,cur) return k07 defdecrypt(ct,k07,k8f,sbox,sinv): ct=s32tol8(ct) cur=ct cur=doxor(cur,k8f) cur=[sbox[i] for i in cur] cur=transinv(cur) cur=[sinv[i] for i in cur] m=doxor(cur,k07) return m
from Crypto.Util.number import * from pwn import * from os import urandom defgetboxinv(s): S,Q=[],[0]*256 cntint,endex=0,False for i in s: iford(i) inrange(48,58): endex=True cntint=cntint*10+ord(i)-48 else: if endex==True: endex=False S.append(cntint) Q[cntint]=len(S)-1 cntint=0 return S,Q defs32tol8(s16): L8=[] for i inrange(0,len(s16),2): L8.append(int(s16[i:i+2],16)) return L8 defpadhex(x,b): x=hex(x)[2:] return (b-len(x))*'0'+x defpadbin(x,b): x=bin(x)[2:] return (b-len(x))*'0'+x defdoxor(l1,l2): return [x[0]^x[1] for x inzip(l1,l2)] defsumbitpros(a,x): c,d=a&x,0 while c: d+=c&1 c>>=1 return d&1 deftransinv(blk): res=[] blk=[(coefinv[i]*blk[i])&255for i inrange(8)] blk=[padbin(i,8)for i in blk] for i inrange(8): s="" for j inrange(-1,7): s+=blk[j][i] res.append(int(s,2)) return res deflinersbox(sbox): lnipt=[] offset=[[0for _ inrange(256)] for __ inrange(256)] for i inrange(256): if i%15==0: print('[lnrsbox]:'+str(i+1)+'/256') si=sbox[i] for j inrange(256): for k inrange(256): a=sumbitpros(j,i) b=sumbitpros(k,si) if a==b: offset[j][k]+=1 for i inrange(256): offset[i]=[abs(x-128)/256.0for x in offset[i]] for i inrange(256): cur=[x[i] for x in offset] lnipt.append(cur.index(max(cur))) return offset,lnipt defguess(pt,ct,loc,gus,lnipt,coefinv): pt,ct=s32tol8(pt),s32tol8(ct) ct[loc]^=gus ct[loc]=sbox[ct[loc]] ct[loc]=ct[loc]*coefinv[loc]&255 tmp1=sumbitpros(pt[0],lnipt[1<<((14-loc)&7)]) tmp2=sumbitpros(ct[loc],128) return tmp1==tmp2 defgetkey8f(Tl,Cl,lnipt,coefinv,scale): k8f=[] for i inrange(8): print('[GettingKey]:ID='+str(i+8)) kount=[0for _ inrange(256)] for gskey inrange(256): for j inrange(scale): if guess(Tl[j],Cl[j],i,gskey,lnipt,coefinv): kount[gskey]+=1 beta=[abs(x-scale//2+0.0)/(scale+0.0) for x in kount] k8f.append(beta.index(max(beta))) return k8f defgetkey07(pt,ct,k8f,coefinv,sbox,sinv): pt,ct=s32tol8(pt),s32tol8(ct) cur=ct cur=doxor(cur,k8f) cur=[sbox[i] for i in cur] cur=transinv(cur) cur=[sinv[i] for i in cur] k07=doxor(pt,cur) return k07 defdecrypt(ct,k07,k8f,sbox,sinv): ct=s32tol8(ct) cur=ct cur=doxor(cur,k8f) cur=[sbox[i] for i in cur] cur=transinv(cur) cur=[sinv[i] for i in cur] m=doxor(cur,k07) return m #----------MAIN BELOW----------# sh=remote("node3.buuoj.cn",29170) sbox=sh.recvline(keepends=False) C=sh.recvline(keepends=False) print(C) sbox,sinv=getboxinv(sbox) Tl,Cl=[],[] coefinv=[15,11,155,119,11,99,83,249] for i inrange(16384): if i%45==0: print('[Recving]:'+str(i+1)+'/16384') cntsend=padhex(bytes_to_long(urandom(8)),16) Tl.append(cntsend) sh.sendline(cntsend) Cl.append(sh.recvline(keepends=False)) offset,lnipt=linersbox(sbox) k8f=getkey8f(Tl,Cl,lnipt,coefinv,16384) print(k8f) k07=getkey07(Tl[0],Cl[0],k8f,coefinv,sbox,sinv) print(k07) flag=[] for i inrange(0,len(C),16): m=decrypt(C[i:i+16],k07,k8f,sbox,sinv) flag+=m print(flag) #[110, 112, 117, 99, 116, 102, 123, 55, 105, 110, 121, 83, 80, 78, 45, 99, 52, 110, 45, 98, 51, 45, 51, 64, 115, 105, 49, 121, 45, 99, 114, 52, 99, 107, 51, 100, 33, 33, 125, 1]