de1ctf 部分writeup解析

1.NLFSR:
在ctf-wiki中我們可以找到一種對NLFDSR的攻擊方法——https://wiki.x10sec.org/crypto/streamcipher/fsr/nfsr/。由於對多個LFSR組合時不能實現均勻混合嗎,我們可以發現有的值和最後結果相近,我們可以據此對NLFSR中的部分LFSR進行爆破。最後我們可以對剩下的LFSR進行爆破。首先我們可以根據多個LFSR組合判斷哪些LFSR爆破。

ass=0
bs=0
cs=0
ds=0
print "%s,%s,%s,%s,%s"%("ao","bo","co","do","re")
for i in xrange(0b10000,0b100000):
	ao=int(bin(i)[-4],10)
	bo=int(bin(i)[-3],10)
	co=int(bin(i)[-2],10)
	do=int(bin(i)[-1],10)
	re=(ao*bo) ^ (bo*co) ^ (bo*do) ^ co ^ do

	print "%d,%d,%d,%d,%d"%(ao,bo,co,do,re)
	if ao==re:
		ass=ass+1
	if bo==re:
		bs=bs+1
	if co==re:
		cs=cs+1
	if do==re:
		ds=ds+1
print  "%d,%d,%d,%d"%(ass,bs,cs,ds)

我們發現結果中a和最後結果有75%相似,我們首先對a進行爆破。

def lfsr(r, m): return ((r << 1) & 0xffffff) ^ (bin(r & m).count('1') % 2)
def guess(beg, end, num, mask):
	f=open('data','r')
	data = f.read()[:1600]
	f.close()
	now = 0
	res = 0
	for i in range(beg, end):
		r = i
		cnt = 0
		jie=0
		for j in range(num * 8):
			r = lfsr(r, mask)
			lastbit=r & 1 
			if lastbit == int(data[j],10):
				cnt=cnt+1
		if cnt > now:
			now=cnt
			res = i
			print cnt, res
	return res

guess(pow(2,18),pow(2,19),100,0x505a1)

我們發現a=363445時,a所對應的lfsr和總的nlfsr結果有接近75%類似,我們已將a猜出,接下來我們觀察之前的結果發現當a爲1時,b所對應的lfsr和總的nlfsr結果有接近75%類似,當a爲0時,b所對應的lfsr的反和總的nlfsr結果有接近75%類似。由於a已經確定,我們藉助a爆破b

def lfsr(r, m): return ((r << 1) & 0xffffff) ^ (bin(r & m).count('1') % 2)
def guess(beg, end, num, mask):
 f=open('data','r')
 data = f.read()[:800]
 f.close()
 now = 0
 res = 0
 for i in range(beg, end):
  r = i
  cnt = 0
  a=363445
  for j in range(num * 8):
   r = lfsr(r, mask)
   a = lfsr(a, 0x505a1)
   lastbit=r & 1
   alastbit = a & 1
   if alastbit==1 and lastbit == int(data[j],10):
    cnt=cnt+1
   if alastbit==0 and lastbit != int(data[j],10):
    cnt=cnt+1
  if cnt > now:
   now = cnt
   res = i
   print now, res
 return res
guess(pow(2,18),pow(2,19),100,0x40f3f)

我們得到b是494934,剩下的c和d可以直接爆破獲得

def lfsr(r, m): return ((r << 1) & 0xffffff) ^ (bin(r & m).count('1') % 2)
a=363445
b=494934
ma, mb, mc, md = 0x505a1, 0x40f3f, 0x1f02, 0x31
f=open('data','r')
data = f.read()[:800]
f.close()
for ha in range(pow(2,12),pow(2,13)):
	for hah in range(pow(2,5),pow(2,6)):
		c=ha
		d=hah
		flag = True
		a=363445
		b=494934
		for j in  xrange(30 * 8):
			a = lfsr(a, ma)
			b = lfsr(b, mb)
			c = lfsr(c, mc)
			d = lfsr(d, md)
			[ao, bo, co, do] = [i & 1 for i in [a, b, c, d]]
			lastbit=(ao*bo) ^ (bo*co) ^ (bo*do) ^ co ^ do
			if  not  str(lastbit)== data[j]:
				#print j
				flag = False
				break
		if flag:
			print "c is %d,d is %d"%(ha,hah)
			

2.ECDH

這是在之前JWE上的一個漏洞,在題目中我們發現在重新輸入公鑰時沒有檢測公鑰所對應點是否在原先的橢圓曲線上。而無論在點的加法還是乘法都不涉及b,所以我們可以選擇一個不在橢圓曲線上的點改變橢圓曲線以降低密鑰的階。然而我們使用多組密鑰構成多組同餘方程。然後使用中國剩餘定理求解密鑰。首先我們來找低階的橢圓曲線上的點以及對應的階

q = 0xdd7860f2c4afe6d96059766ddd2b52f7bb1ab0fce779a36f723d50339ab25bbd
a = 0x4cee8d95bb3f64db7d53b078ba3a904557425e2a6d91c5dfbf4c564a3f3619fa
FF = GF(q)
su=1
while su<q:
	for b in xrange(1000,20000):
		E = EllipticCurve([FF(a), FF(b)])
		ss = str(E.order().factor()).split('*')
		for i in ss:
			if '^' not in i:
				i = int(i.strip())
				if 100 < i < 10000:
					su=su*i
					P = E.random_point() * Integer(E.order()/i)
					print i, P

注意將結果中階相同的值刪掉,且選取的階之間互斥。並保證所選階的乘積大於模P 

from pwn import *
import gmpy2
zero = (0,0)
def crt(ll):
 N=160100368002089863336612588235555840059619800749562435161043158894093919344765004036542503281
 su=0
 for i in ll:
  Mi=N/i
  Miphi=gmpy2.invert(Mi,i)
  su=(su+Mi*Miphi*ll[i])%N
 return su
def add(p1,p2):
 if p1 == zero:
  return p2
 if p2 == zero:
  return p1
 (p1x,p1y),(p2x,p2y) = p1,p2
 if p1x == p2x and (p1y != p2y or p1y == 0):
     return zero
 if p1x == p2x:
     tmp = (3 * p1x * p1x + a) * gmpy2.invert(2 * p1y , q) % q
 else:
     tmp = (p2y - p1y) * gmpy2.invert(p2x - p1x , q) % q
 x = (tmp * tmp - p1x - p2x) % q
 y = (tmp * (p1x - x) - p1y) % q
 return (int(x),int(y))

def mul(n,p):
 r = zero
 tmp = p
 while 0 < n:
     if n & 1 == 1:
         r = add(r,tmp)
     n, tmp = n >> 1, add(tmp,tmp)
 return r
def proof(a,b):
 ss="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
 print b
 for i in ss:
  for j in ss:
   for k in ss:
    for o in ss:
     jie=i+j+k+o+a
     ll=hashlib.sha256(jie).hexdigest()
     if ll==b:
      return jie
dic=上文結果{階:{點}}
shou=(30850180072163607425727221374286281042832069301111007754078234396927723013762 , 12991715571699648665747363171294057749877378927830313833387603562476546350076)
q = 0xdd7860f2c4afe6d96059766ddd2b52f7bb1ab0fce779a36f723d50339ab25bbd
a = 0x4cee8d95bb3f64db7d53b078ba3a904557425e2a6d91c5dfbf4c564a3f3619fa
io=remote("134.175.225.42",8848)
io.recvuntil("+")
tian=io.recvuntil(")")[:-1]
io.recvuntil("== ")
sh256=io.recvuntil("\n")[:-1]
print tian.encode("hex")
print sh256.encode("hex")
io.recvuntil(":")
haha=proof(tian,sh256)
io.sendline(haha[:4])
print haha
ls={}
msg="f"*128
msghex=0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
io.recvuntil("X:\n")
io.sendline(str(shou[0]))
io.recvuntil("Y:\n")
io.sendline(str(shou[1]))
io.recvuntil("Tell me your choice:\n")
io.sendline("Encrypt")
io.recvuntil("Give me your message(hex):\n")
io.sendline(msg)
io.recvuntil("The result is:\n")
miwen=int(io.recvuntil("\n")[:-1],16)
gongyao=miwen^msghex
gyzuobiao=(int(hex(gongyao)[2:66],16),int(hex(gongyao)[66:130],16))
sign=True
for j in xrange(1693+1):
 if mul(j,shou)==gyzuobiao:
  ls[1693]=j
  sign=False
  break
if sign:
 print "1693"
 io.interactive()
for i in dic:
 sign=True
 io.recvuntil("Tell me your choice:\n")
 io.sendline("Exchange")
 io.recvuntil("X:\n")
 io.sendline(str(dic[i][0]))
 io.recvuntil("Y:\n")
 io.sendline(str(dic[i][1]))
 io.recvuntil("Tell me your choice:\n")
 io.sendline("Encrypt")
 io.recvuntil("Give me your message(hex):\n")
 io.sendline(msg)
 io.recvuntil("The result is:\n")
 miwen=int(io.recvuntil("\n")[:-1],16)
 gongyao=miwen^msghex
 gyzuobiao=(int(hex(gongyao)[2:66],16),int(hex(gongyao)[66:130],16))
 for j in xrange(i+1):
  if mul(j,dic[i])==gyzuobiao:
   sign=False
   ls[i]=j
   break
 if sign:
  print i
  io.interactive()
se=crt(ls)
print "yes"
io.recvuntil("Tell me your choice:\n")
io.sendline("Backdoor")
io.recvuntil("Give me the secret:\n")
io.sendline(str(se))
io.interactive()
#(腳本存在一些問題,需要多跑十幾次,原因未知)

 

3.easyrsa

參考cryptanalysis of rsa and its variants第7章,唯一的問題時我們不知道\delta是多少,我們需要爆破驗證

N= 24402191928494981635640497435944050736451453218629774561432653700273120014058697415669445779441226800209154604159648942665855233706977525093135734838825433023506185915211877990448599462290859092875150657461517275171867229282791419867655722945527203477335565212992510088077874648530075739380783193891617730212062455173395228143660241234491822044677453330325054451661281530021397747260054593565182679642519767415355255125571875708238139022404975788807868905750857687120708529622235978672838872361435045431974203089535736573597127746452000608771150171882058819685487644883286497700966396731658307013308396226751130001733
e1= 4046316324291866910571514561657995962295158364702933460389468827072872865293920814266515228710438970257021065064390281148950759462687498079736672906875128944198140931482449741147988959788282715310307170986783402655196296704611285447752149956531303574680859541910243014672391229934386132475024308686852032924357952489090295552491467702140263159982675018932692576847952002081478475199969962357685826609238653859264698996411770860260854720047710943051229985596674736079206428312934943752164281391573970043088475625727793169708939179742630253381871307298938827042259481077482527690653141867639100647971209354276568204913
e2= 1089598671818931285487024526159841107695197822929259299424340503971498264804485187657064861422396497630013501691517290648230470308986030853450089582165362228856724965735826515693970375662407779866271304787454416740708203748591727184057428330386039766700161610534430469912754092586892162446358263283169799095729696407424696871657157280716343681857661748656695962441400433284766608408307217925949587261052855826382885300521822004968209647136722394587701720895365101311180886403748262958990917684186947245463537312582719347101291391169800490817330947249069884756058179616748856032431769837992142653355261794817345492723
cipher= 5089249888618459947548074759524589606478578815336059949176718157024022678024841758856813241335191315643869492784030633661717346809979076682611760035885176766380484743187692409876479000444892361744552075578050587677106211969169204446554196613453202059517114911102484740265052582801216204900709316109336061861758409342194372241877343837978525533125320239702501424169171652846761028157198499078668564324989313965631396082388643288419557330802071756151476264735731881236024649655623821974147680672733406877428067299706347289297950375309050765330625591315867546015398294367460744885903257153104507066970239487158506328863
i=1.356
s=""
while i>1.00:
 B=[]
 B.append([1,-N,0,pow(N,2)])
 B.append([0,e1,-e1,-e1*N])
 B.append([0,0,e2,-e2*N])
 B.append([0,0,0,e1*e2])
 B=Matrix(ZZ,B)
 D=[]
 D.append([N,0,0,0])
 D.append([0,floor(N**(0.5)),0,0])
 D.append([0,0,floor(N**i),0])
 D.append([0,0,0,1])
 D=Matrix(ZZ,D)
 M=B*D
 K = M.LLL()
 v2=K[0]
 X=M.solve_left(v2)
 phi=floor((e1*X[1])/X[0])
 if phi<N:
  b=phi-N-1
  if b**2>=4*N:
   s=s+str(phi)+"\n"
 i=i-0.001
 
f=open("changshi.txt","w")
f.write(s)
f.close()
print "wancheng"

根據驗證的結果,我們一一嘗試。

import gmpy2
phizonghe=上個程序文件內容
N= 24402191928494981635640497435944050736451453218629774561432653700273120014058697415669445779441226800209154604159648942665855233706977525093135734838825433023506185915211877990448599462290859092875150657461517275171867229282791419867655722945527203477335565212992510088077874648530075739380783193891617730212062455173395228143660241234491822044677453330325054451661281530021397747260054593565182679642519767415355255125571875708238139022404975788807868905750857687120708529622235978672838872361435045431974203089535736573597127746452000608771150171882058819685487644883286497700966396731658307013308396226751130001733
e1= 4046316324291866910571514561657995962295158364702933460389468827072872865293920814266515228710438970257021065064390281148950759462687498079736672906875128944198140931482449741147988959788282715310307170986783402655196296704611285447752149956531303574680859541910243014672391229934386132475024308686852032924357952489090295552491467702140263159982675018932692576847952002081478475199969962357685826609238653859264698996411770860260854720047710943051229985596674736079206428312934943752164281391573970043088475625727793169708939179742630253381871307298938827042259481077482527690653141867639100647971209354276568204913
e2= 1089598671818931285487024526159841107695197822929259299424340503971498264804485187657064861422396497630013501691517290648230470308986030853450089582165362228856724965735826515693970375662407779866271304787454416740708203748591727184057428330386039766700161610534430469912754092586892162446358263283169799095729696407424696871657157280716343681857661748656695962441400433284766608408307217925949587261052855826382885300521822004968209647136722394587701720895365101311180886403748262958990917684186947245463537312582719347101291391169800490817330947249069884756058179616748856032431769837992142653355261794817345492723
cipher= 5089249888618459947548074759524589606478578815336059949176718157024022678024841758856813241335191315643869492784030633661717346809979076682611760035885176766380484743187692409876479000444892361744552075578050587677106211969169204446554196613453202059517114911102484740265052582801216204900709316109336061861758409342194372241877343837978525533125320239702501424169171652846761028157198499078668564324989313965631396082388643288419557330802071756151476264735731881236024649655623821974147680672733406877428067299706347289297950375309050765330625591315867546015398294367460744885903257153104507066970239487158506328863
phi=0
for i in phizonghe:
    a=1
    b=gmpy2.mpz(phi-N-1)
    c=gmpy2.mpz(N)
    delat=pow(b,2)-4*a*c
    if gmpy2.iroot(delat,2)[1]:
        phi=i
        break

print phi
d1=gmpy2.invert(e1,phi)
d2=gmpy2.invert(e2,phi)
m1=pow(cipher,d1,N)
m2=pow(cipher,d2,N)
print hex(m1)
print hex(m2)

4.Homomorphic

參考論文https://arxiv.org/pdf/1906.07127.pdf,我們對明文一個個進行碰撞驗證

from pwn import *
import copy
import gmpy2
def proof(a,b):
 ss="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
 print b
 for i in ss:
  for j in ss:
   for k in ss:
    for o in ss:
     jie=i+j+k+o+a
     ll=hashlib.sha256(jie).hexdigest()
     if ll==b:
      return jie
def Roundq(A):
 q=pow(2,54)
 for i in range(len(A)):
  A[i]=A[i]%q
  if A[i]>(q/2):
   A[i]=A[i]-q
 return A
io=remote("106.52.135.150",8848)
#io=remote("106.52.180.168",8848)
io.recvuntil("+")
tian=io.recvuntil(")")[:-1]
io.recvuntil("== ")
sh256=io.recvuntil("\n")[:-1]
print tian.encode("hex")
print sh256.encode("hex")
io.recvuntil(":")
haha=proof(tian,sh256)
io.sendline(haha[:4])
print haha
io.recvuntil("The enc flag is: \n")
flags=io.recvuntil("Tel")[1:-5]
flagli=flags.split("]\n[")
jishu=0
flagc0=[]
flagc1=[]
while jishu<len(flagli):
 flaglj=flagli[jishu].split(",")
 flagcx=[]
 for i in flaglj:
  flagcx.append(int(i))
 flaglj=flagli[jishu+1].split(",")
 flagcy=[]
 for i in flaglj:
  flagcy.append(int(i))
 flagc0.append(flagcx)
 flagc1.append(flagcy)
 jishu=jishu+2
for hh in xrange(7,20):
 for kk in  xrange(32,128):
  c0=copy.deepcopy(flagc0[hh])
  c1=copy.deepcopy(flagc1[hh])
  c0[0]=c0[0]-kk*70368744177664
  cab=(Roundq(c0),Roundq(c1))
  for i in range(len(cab[0])):
   cab[0][i]=10*cab[0][i]
   cab[1][i]=10*cab[1][i]
  cab=(Roundq(cab[0]),Roundq(cab[1]))
  s0=str(cab[0][0])
  for i in range(1,len(cab[0])):
   s0=s0+","+str(cab[0][i])
  s1=str(cab[1][0])
  for i in range(1,len(cab[1])):
   s1=s1+","+str(cab[1][i])
  io.recvuntil("l me your choice:\n")
  io.sendline("Decrypt")
  io.recvuntil("Please input c0(Separated by commas):\n")
  io.sendline(s0)
  io.recvuntil("Please input c1(Separated by commas):\n")
  io.sendline(s1)
  io.recvuntil("The index:\n")
  io.sendline(str(0))
  io.recvuntil("The result is: \n")
  jie=io.recvuntil("\n")[:-1]
  if int(jie)==0:
   print jie,kk,hh
   break
io.interactive()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章