[GKCTF 2021]XOR

简介

这题和之前做的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. n2 = c*d

2. x2 = c^{d1}

3. cl * ch % mask = n2 % mask

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值