简介
这题和之前做的dfs类似,算是个高级版的爆破吧,是个挺好的例子,前面的脚本可以解决第一部分,5space signin(未知低位的dfs和coppersmith)_a5555678744的博客-CSDN博客在这里就不赘述了。重点来说说本题的第二部分。
题解
参照知乎大佬的算法,自己手敲了个自己比较容易看懂的版本
[GKCTF] GKCTF x DASCTF应急挑战杯 个人(or团队) Crypto方向 writeup - 知乎
from Crypto.Util.number import *
from hashlib import md5
'''
a = getPrime(512)
b = getPrime(512)
c = getPrime(512)
d = getPrime(512)
d1 = int(bin(d)[2:][::-1] , 2)
n1 = a*b
x1 = a^b
n2 = c*d
x2 = c^d1
flag = md5(str(a+b+c+d).encode()).hexdigest()
print("n1 =",n1)
print("x1 =",x1)
print("n2 =",n2)
print("x2 =",x2)
'''
n1 = 83876349443792695800858107026041183982320923732817788196403038436907852045968678032744364820591254653790102051548732974272946672219653204468640915315703578520430635535892870037920414827506578157530920987388471203455357776260856432484054297100045972527097719870947170053306375598308878558204734888246779716599
x1 = 4700741767515367755988979759237706359789790281090690245800324350837677624645184526110027943983952690246679445279368999008839183406301475579349891952257846
n2 = 65288148454377101841888871848806704694477906587010755286451216632701868457722848139696036928561888850717442616782583309975714172626476485483361217174514747468099567870640277441004322344671717444306055398513733053054597586090074921540794347615153542286893272415931709396262118416062887003290070001173035587341
x2 = 3604386688612320874143532262988384562213659798578583210892143261576908281112223356678900083870327527242238237513170367660043954376063004167228550592110478
要搞定这种算法题,首先要确定约束条件,这些条件里面有的看似没有什么意义,但是却很关键,所以也很头疼。
首先设一些量,cl是c的低位,ch是c的高位,dl和dh同理
这道题里的约束有
1.
2.
3.
4. 不确定位全部填1时,c*d > n2
5. 不确定位全部填0时,c*d < n2
有了这些约束后,耐心地写算法。
n1 = 65288148454377101841888871848806704694477906587010755286451216632701868457722848139696036928561888850717442616782583309975714172626476485483361217174514747468099567870640277441004322344671717444306055398513733053054597586090074921540794347615153542286893272415931709396262118416062887003290070001173035587341
x1 = 3604386688612320874143532262988384562213659798578583210892143261576908281112223356678900083870327527242238237513170367660043954376063004167228550592110478
cl_list, dl_list, ch_list, dh_list = [1], [1], [1], [1]
x1_bits = [int(x) for x in f'{x1:0512b}'[::-1]]
print(x1_bits)
print('\n')
mask = 2
for i in range(1,256):
mask*=2
scl_list, sdl_list, sch_list, sdh_list = [], [], [], []
list数组存的是对四个变量的可能情况
s_list则是临时使用的用于迭代的四个变量
x1_bits就是把x1的二进制按位分开
mask跟每一轮处理位数相关了,mask*2就是要处理下一个位了
这里不太一样的就是,由于我们一开始就可以确定最高位和最低位必定是1,那么就可以直接从第二位开始,这样数值上也更方便。
随后按照约束写出如下循环:
for j in range(len(cl_list)):
for cl in range(2):
for dl in range(2):
for ch in range(2):
for dh in range(2):
if (cl ^ dh == x1_bits[511-i] and ch ^ dl == x1_bits[i]):
temp1 = ((mask // 2 * cl + cl_list[j]) * (mask // 2 * dl + dl_list[j]))%mask
temp2 = n1 % mask
if (temp1 == temp2):
g1 = bin(ch_list[j])[2:] + bin(ch)[2:] + '1' * (510 - 2 * i) + bin(cl)[2:] + bin(cl_list[j])[2:].zfill(i)
g1 = int(g1, 2)
g2 = bin(dh_list[j])[2:] + bin(dh)[2:] + '1' * (510 - 2 * i) + bin(dl)[2:] + bin(dl_list[j])[2:].zfill(i)
g2 = int(g2, 2)
if(g1 * g2 < n1):
continue
g1 = bin(ch_list[j])[2:] + bin(ch)[2:] + '0' * (510 - 2 * i) + bin(cl)[2:] + bin(cl_list[j])[2:].zfill(i)
g1 = int(g1, 2)
g2 = bin(dh_list[j])[2:] + bin(dh)[2:] + '0' * (510 - 2 * i) + bin(dl)[2:] + bin(dl_list[j])[2:].zfill(i)
g2 = int(g2, 2)
if (g1 * g2 > n1):
continue
scl_list.append(mask // 2 * cl + cl_list[j])
sch_list.append(ch_list[j]*2 + ch)
sdl_list.append(mask // 2 * dl + dl_list[j])
sdh_list.append(dh_list[j] * 2 + dh)
cl_list,dl_list,ch_list,dh_list = scl_list,sdl_list,sch_list,sdh_list
这里要特别注意低位的补零问题,高位零不补可以,但是低位如果最高位是零,会使高位整体往下降一级,所以必须要用zfill(i)来填充。
分析的细节就不说了,总之就是按照五重约束来构造算法。
这样就得到c,d的低位和高位了,拼接起来
d=int(bin(ch_list[0])[2:]+bin(cl_list[0])[2:].zfill(256),2)
c=int(bin(dh_list[0])[2:]+bin(dl_list[0])[2:].zfill(256),2)
完整的题解代码如下:
import itertools
n1 = 65288148454377101841888871848806704694477906587010755286451216632701868457722848139696036928561888850717442616782583309975714172626476485483361217174514747468099567870640277441004322344671717444306055398513733053054597586090074921540794347615153542286893272415931709396262118416062887003290070001173035587341
x1 = 3604386688612320874143532262988384562213659798578583210892143261576908281112223356678900083870327527242238237513170367660043954376063004167228550592110478
cl_list, dl_list, ch_list, dh_list = [1], [1], [1], [1]
x1_bits = [int(x) for x in f'{x1:0512b}'[::-1]]
print(x1_bits)
print('\n')
mask = 2
for i in range(1,256):
mask*=2
scl_list, sdl_list, sch_list, sdh_list = [], [], [], []
for j in range(len(cl_list)):
for cl in range(2):
for dl in range(2):
for ch in range(2):
for dh in range(2):
if (cl ^ dh == x1_bits[511-i] and ch ^ dl == x1_bits[i]):
temp1 = ((mask // 2 * cl + cl_list[j]) * (mask // 2 * dl + dl_list[j]))%mask
temp2 = n1 % mask
if (temp1 == temp2):
g1 = bin(ch_list[j])[2:] + bin(ch)[2:] + '1' * (510 - 2 * i) + bin(cl)[2:] + bin(cl_list[j])[2:].zfill(i)
g1 = int(g1, 2)
g2 = bin(dh_list[j])[2:] + bin(dh)[2:] + '1' * (510 - 2 * i) + bin(dl)[2:] + bin(dl_list[j])[2:].zfill(i)
g2 = int(g2, 2)
if(g1 * g2 < n1):
continue
g1 = bin(ch_list[j])[2:] + bin(ch)[2:] + '0' * (510 - 2 * i) + bin(cl)[2:] + bin(cl_list[j])[2:].zfill(i)
g1 = int(g1, 2)
g2 = bin(dh_list[j])[2:] + bin(dh)[2:] + '0' * (510 - 2 * i) + bin(dl)[2:] + bin(dl_list[j])[2:].zfill(i)
g2 = int(g2, 2)
if (g1 * g2 > n1):
continue
scl_list.append(mask // 2 * cl + cl_list[j])
sch_list.append(ch_list[j]*2 + ch)
sdl_list.append(mask // 2 * dl + dl_list[j])
sdh_list.append(dh_list[j] * 2 + dh)
cl_list,dl_list,ch_list,dh_list = scl_list,sdl_list,sch_list,sdh_list
print(cl_list)
print(dl_list)
print(ch_list)
print(dh_list)
d=int(bin(ch_list[0])[2:]+bin(cl_list[0])[2:].zfill(256),2)
c=int(bin(dh_list[0])[2:]+bin(dl_list[0])[2:].zfill(256),2)
print(c)
print(d)
print(c * d - n1)
print(((c ^ int(bin(d)[2:][::-1],2)) - x1))
a=7836147139610655223711469747200164069484878894626166870664740637786609468164555354874619497753277560280939259937394201154154977382033483373128424196987617
b=10703774182571073361112791376032380096360697926840362483242105878115552437021674861528714598089603406032844418758725744879476596359225265333530235803365847
c=8046925436710204192438304055874778865895416996970843869698858865603953411170369526997784224210491769140388046960966644628154489203286940293881427188058327
d=8113427789020078526682817916943942153489187786107307958765586032610741354289280539264853469783621315049385549884903133806294183614352084988365109630250683
print(bin(c ^ int(bin(d)[2:][::-1],2)))
import hashlib
flag = hashlib.md5(str(a+b+c+d).encode()).hexdigest()
print("flag{%s}"%flag)