BUUCTF刷题记录

现在是暑假第四周,BUU现在是正在刷第三页。加油学,只要能不断超越过去的自己,就是最值得骄傲的事。

1.鸡藕椒盐味

题目

 题目给了二进制,又说打印的时候倒了一下。看到这里我的想法是把二进制顺序倒过来,得到000001010011。但验证码不仅仅是倒了一下,还有错误。题目中提到的数据还有“售价八块”,应该要从这句话找到信息。但是我并没有想到啥思路,找大佬的wp

这里也挺有趣味性的哈,题目名字是“鸡藕椒盐味”,这里是谐音梗,意思是“奇偶校验”,看一下奇偶校验的作用和过程,奇偶校验码是奇校验码和偶校验码的统称,是一种检错码,用来检验二进制数据的位错。

咱们回到题目,第一步,我们先来分析校验位数。二进制是有12个数,题目提示“售价八块”,那么根据海明验证码公式:2^r≥k+r+1  (r为校验位 ,k为信息位),根据“售价八块”我们知道,信息位是8,带入公式可知校验码是4,所以1,2,4,8位置添加相应校验码。

第二步,画表。题目中提到打印的时候倒了一下,所以信息位是倒过来的二进制,我们已知需要在1,2,4,8位置添加相应校验码,所以在对应的位置写了R1,R2,R3,R4。

 第三步,求校验位的值。

 看到这里有点懵叭,其实也比较好理解。因为题目给的二进制是12位,所以第一列的海明码位号是12位。校验位一般都是在2^n的位置,1位就是2^0,校验码为R1,2位就是2^1,校验码为R2,3位就是2^0+2^1,校验码为R1,R2,4位就是2^2,校验码为R3,...后面就是以此类推哈 。如果某一个位置是2^n,并且不是2^n相加,那就是一个单独的校验位,比如8位,8位是2^3,所以8位的校验码就是R4。知道这个,那么第二列的占用的校验位号就比较好理解啦,它的意思就是该位所用到的校验码的位号。比如,12位,12位的校验码位R3,R4,那么R3,R4对应的位号分别是4位和8位,所以12位占用的校验位号为4,8。

现在我们进行汇总,看一下每一个校验位确定了哪些位号。

 这里就是说,1位,3位,5位,7位,9位,11位,这些位号用到了校验码R1,其他校验码的也是同样的意思。现在我们用异或运算求出校验码的值,这里以R1举列。

我们知道1位,3位,5位,7位,9位,11位对应的倒过来的二进制(看第二步画表,表格中第二行的数字)我们可以得到,1位对应的是0,3位对应的是0,5位对应的是0,7位对应的是0,9位对应的是0,11位对应的是1。把这些位号异或,发现1位,3位,5位,7位,9位都是0,但11位对应的是1,对应的数字不是一样的,所以异或得到R1=1。

以此类推:R1=1,R2=0,R3=0,R4=0

可以看到来P1P2P3P4=0001,这个是验证码中的校验码,(你们可能不知道为什么突然有这个了,其实P1P2P3P4指的是1位2位4位8位的信息位,看一下第二步的画表,你们会发现1位2位4位8位的信息位是没有填的,你们把倒过的二进制按顺序填到表格里,就可以得到P1P2P3P4=0001)R1R2R3R4=1000,这个是求得的校验码

可以求得监督位(异或):(相同为0,不同为1)

 监督位不为0000,说明接收方生成的校验位和收到的校验位不同,错误的位数是监督位的十进制即9(这句话的意思是,监督位不是0000,那么就是出错的地方,现在已知监督位是1001,我们把这个转为十进制,就得到数字9,这样我们就知道9位出错了)。把D9(D9就是信息位9位,看第二步画表可以知道)就是题目中提到的错误,我们把D9的信息位0改成1,就可以了。最后,我们把改正的二进制再倒过来一次,就得到正确验证码110110100000,然后根据提示MD5hash一下就出来了。

 2.[MRCTF2020]babyRSA

 题目

import sympy
import random
from gmpy2 import gcd, invert
from Crypto.Util.number import getPrime, isPrime, getRandomNBitInteger, bytes_to_long, long_to_bytes
from z3 import *
flag = b"MRCTF{xxxx}"
base = 65537


def GCD(A):
    B = 1
    for i in range(1, len(A)):
        B = gcd(A[i-1], A[i])
    return B
def gen_p():
   
    sub_Q = getPrime(1024)

P = [0 for i in range(17)]
    P[0] = getPrime(128)
    for i in range(1, 17):
        P[i] = sympy.nextprime(P[i-1])
    print("P_p :", P[9])
    n = 1
    for i in range(17):
        n *= P[i]
    p = getPrime(1024)
    factor = pow(p, base, n)
    print("P_factor :", factor)
    return sympy.nextprime(p)


def gen_q():

    Q_1 = getPrime(1024)
    Q_2 = getPrime(1024)
    Q = sub_Q ** Q_2 % Q_1
    print("Q_1: ", Q_1)
    print("Q_2: ", Q_2)
    print("sub_Q: ", sub_Q)
    return sympy.nextprime(Q)


if __name__ == "__main__":
    _E = base
    _P = gen_p()
    _Q = gen_q()
    assert (gcd(_E, (_P - 1) * (_Q - 1)) == 1)
    _M = bytes_to_long(flag)
    _C = pow(_M, _E, _P * _Q)
    print("Ciphertext = ", _C)
'''
P_p : 206027926847308612719677572554991143421
P_factor : 213671742765908980787116579976289600595864704574134469173111790965233629909513884704158446946409910475727584342641848597858942209151114627306286393390259700239698869487469080881267182803062488043469138252786381822646126962323295676431679988602406971858136496624861228526070581338082202663895710929460596143281673761666804565161435963957655012011051936180536581488499059517946308650135300428672486819645279969693519039407892941672784362868653243632727928279698588177694171797254644864554162848696210763681197279758130811723700154618280764123396312330032986093579531909363210692564988076206283296967165522152288770019720928264542910922693728918198338839
Q_1:  103766439849465588084625049495793857634556517064563488433148224524638105971161051763127718438062862548184814747601299494052813662851459740127499557785398714481909461631996020048315790167967699932967974484481209879664173009585231469785141628982021847883945871201430155071257803163523612863113967495969578605521
Q_2:  151010734276916939790591461278981486442548035032350797306496105136358723586953123484087860176438629843688462671681777513652947555325607414858514566053513243083627810686084890261120641161987614435114887565491866120507844566210561620503961205851409386041194326728437073995372322433035153519757017396063066469743
sub_Q:  168992529793593315757895995101430241994953638330919314800130536809801824971112039572562389449584350643924391984800978193707795909956472992631004290479273525116959461856227262232600089176950810729475058260332177626961286009876630340945093629959302803189668904123890991069113826241497783666995751391361028949651
Ciphertext =  1709187240516367141460862187749451047644094885791761673574674330840842792189795049968394122216854491757922647656430908587059997070488674220330847871811836724541907666983042376216411561826640060734307013458794925025684062804589439843027290282034999617915124231838524593607080377300985152179828199569474241678651559771763395596697140206072537688129790126472053987391538280007082203006348029125729650207661362371936196789562658458778312533505938858959644541233578654340925901963957980047639114170033936570060250438906130591377904182111622236567507022711176457301476543461600524993045300728432815672077399879668276471832
'''
 

题目分析,根据出题脚本 ,我们已知

 Q=sub_Q^Q_2/Q_1,(纸上没写好,不是Q-2和Q-1,是Q_2和Q_1)

解题脚本

from gmpy2 import*
from libnum import*
from sympy import*

e = 65537
P_factor = 213671742765908980787116579976289600595864704574134469173111790965233629909513884704158446946409910475727584342641848597858942209151114627306286393390259700239698869487469080881267182803062488043469138252786381822646126962323295676431679988602406971858136496624861228526070581338082202663895710929460596143281673761666804565161435963957655012011051936180536581488499059517946308650135300428672486819645279969693519039407892941672784362868653243632727928279698588177694171797254644864554162848696210763681197279758130811723700154618280764123396312330032986093579531909363210692564988076206283296967165522152288770019720928264542910922693728918198338839
Q_1 = 103766439849465588084625049495793857634556517064563488433148224524638105971161051763127718438062862548184814747601299494052813662851459740127499557785398714481909461631996020048315790167967699932967974484481209879664173009585231469785141628982021847883945871201430155071257803163523612863113967495969578605521
Q_2 = 151010734276916939790591461278981486442548035032350797306496105136358723586953123484087860176438629843688462671681777513652947555325607414858514566053513243083627810686084890261120641161987614435114887565491866120507844566210561620503961205851409386041194326728437073995372322433035153519757017396063066469743
sub_Q = 168992529793593315757895995101430241994953638330919314800130536809801824971112039572562389449584350643924391984800978193707795909956472992631004290479273525116959461856227262232600089176950810729475058260332177626961286009876630340945093629959302803189668904123890991069113826241497783666995751391361028949651
c = 1709187240516367141460862187749451047644094885791761673574674330840842792189795049968394122216854491757922647656430908587059997070488674220330847871811836724541907666983042376216411561826640060734307013458794925025684062804589439843027290282034999617915124231838524593607080377300985152179828199569474241678651559771763395596697140206072537688129790126472053987391538280007082203006348029125729650207661362371936196789562658458778312533505938858959644541233578654340925901963957980047639114170033936570060250438906130591377904182111622236567507022711176457301476543461600524993045300728432815672077399879668276471832
P_p = 206027926847308612719677572554991143421#求出16个素数
p = []
for i in range(9):
    P_p = prevprime(P_p)
p.append(P_p)
for i in range(1, 17):
    p.append(nextprime(p[i-1]))
n = 1
phi = 1
for i in range(17):
    n *= p[i]      #求素数p的积
    phi *= (p[i]-1)    #求欧拉函数phi
d = invert(e,phi)
_P = pow(P_factor,int(d),n)     #求出_P的值
_P = nextprime(_P)
#求_Q的值
Q = pow(sub_Q,Q_2,Q_1)
_Q = nextprime(Q)
N = _P*_Q
Phi = (_Q-1)*(_P-1)
_d = invert(e,Phi)
m = pow(c,int(_d),N)
print(n2s(m))
 

3.[NPUCTF2020]EzRSA

题目

 已知e,n,c,gift,gift是(p-1)(q-1)的最小公倍数。这道题可以有两种方法得到phi。

两个数的最大公因数乘最小公倍数等于这两个数的乘积(这是一个小学知识,有兴趣大家可以去查查),所以有gcd(p-1,q-1)lcm(p-1,q-1)=(p-1)(q-1)=phi(这是第一种得到phi的方法)。在已知e,n,c的情况下,又可以求出phi,所以我们直接求d,就能解题。但我们并不知道gcd(p-1,q-1)的值,题目也没有其他关于p,q的提示,所以我们来尝试分解n。

 n可以被分解,我们得到了p,q。此时已知p,q,所以我们可以直接用phi=(p-1)(q-1)得到phi(这是第二种得到phi的方法)。为了使解题脚本更加简洁,我们直接使用第二种方法求phi。

如果直接套脚本运行会发现得不到flag,代码报错,原因是e,phi不互素。

那现在我们求一下e,phi的最大公约数,再让e除以e,phi的最大公约数,这样e,phi就互素了。

 运行成功,得到flag。

4.[MRCTF2020]Easy_RSA

题目

import sympy
from gmpy2 import gcd, invert
from random import randint
from Crypto.Util.number import getPrime, isPrime, getRandomNBitInteger, bytes_to_long, long_to_bytes
import base64

from zlib import *
flag = b"MRCTF{XXXX}"
base = 65537

def gen_prime(N):
    A = 0
    while 1:
        A = getPrime(N)
        if A % 8 == 5:
            break
    return A

def gen_p():
    p = getPrime(1024)
    q = getPrime(1024)
    assert (p < q)
    n = p * q
    print("P_n = ", n)
    F_n = (p - 1) * (q - 1)
    print("P_F_n = ", F_n)
    factor2 = 2021 * p + 2020 * q
    if factor2 < 0:
        factor2 = (-1) * factor2
    return sympy.nextprime(factor2)


def gen_q():
    p = getPrime(1024)
    q = getPrime(1024)
    assert (p < q)
    n = p * q
    print("Q_n = ", n)
    e = getRandomNBitInteger(53)
    F_n = (p - 1) * (q - 1)
    while gcd(e, F_n) != 1:
        e = getRandomNBitInteger(53)
    d = invert(e, F_n)
    print("Q_E_D = ", e * d)
    factor2 = 2021 * p - 2020 * q
    if factor2 < 0:
        factor2 = (-1) * factor2
    return sympy.nextprime(factor2)


if __name__ == "__main__":
    _E = base
    _P = gen_p()
    _Q = gen_q()
    assert (gcd(_E, (_P - 1) * (_Q - 1)) == 1)
    _M = bytes_to_long(flag)
    _C = pow(_M, _E, _P * _Q)
    print("Ciphertext = ", _C)
'''
P_n =  14057332139537395701238463644827948204030576528558543283405966933509944444681257521108769303999679955371474546213196051386802936343092965202519504111238572269823072199039812208100301939365080328518578704076769147484922508482686658959347725753762078590928561862163337382463252361958145933210306431342748775024336556028267742021320891681762543660468484018686865891073110757394154024833552558863671537491089957038648328973790692356014778420333896705595252711514117478072828880198506187667924020260600124717243067420876363980538994101929437978668709128652587073901337310278665778299513763593234951137512120572797739181693
P_F_n =  14057332139537395701238463644827948204030576528558543283405966933509944444681257521108769303999679955371474546213196051386802936343092965202519504111238572269823072199039812208100301939365080328518578704076769147484922508482686658959347725753762078590928561862163337382463252361958145933210306431342748775024099427363967321110127562039879018616082926935567951378185280882426903064598376668106616694623540074057210432790309571018778281723710994930151635857933293394780142192586806292968028305922173313521186946635709194350912242693822450297748434301924950358561859804256788098033426537956252964976682327991427626735740
Q_n =  20714298338160449749545360743688018842877274054540852096459485283936802341271363766157976112525034004319938054034934880860956966585051684483662535780621673316774842614701726445870630109196016676725183412879870463432277629916669130494040403733295593655306104176367902352484367520262917943100467697540593925707162162616635533550262718808746254599456286578409187895171015796991910123804529825519519278388910483133813330902530160448972926096083990208243274548561238253002789474920730760001104048093295680593033327818821255300893423412192265814418546134015557579236219461780344469127987669565138930308525189944897421753947
Q_E_D =  100772079222298134586116156850742817855408127716962891929259868746672572602333918958075582671752493618259518286336122772703330183037221105058298653490794337885098499073583821832532798309513538383175233429533467348390389323225198805294950484802068148590902907221150968539067980432831310376368202773212266320112670699737501054831646286585142281419237572222713975646843555024731855688573834108711874406149540078253774349708158063055754932812675786123700768288048445326199880983717504538825498103789304873682191053050366806825802602658674268440844577955499368404019114913934477160428428662847012289516655310680119638600315228284298935201
Ciphertext =  40855937355228438525361161524441274634175356845950884889338630813182607485910094677909779126550263304194796000904384775495000943424070396334435810126536165332565417336797036611773382728344687175253081047586602838685027428292621557914514629024324794275772522013126464926990620140406412999485728750385876868115091735425577555027394033416643032644774339644654011686716639760512353355719065795222201167219831780961308225780478482467294410828543488412258764446494815238766185728454416691898859462532083437213793104823759147317613637881419787581920745151430394526712790608442960106537539121880514269830696341737507717448946962021
'''

首先分析一下题目,题目有定义两种函数gen_p和gen_q,然后我们已知base(相当于e),P_n(相当于gen_p函数下的模数n),P_F_n(相当于gen_p函数下的逆元phi),Q_n(相当于gen_q函数下的模数n),Q_E_D(相当于gen_q函数下的e*d),Ciphertext(相当于密文c)。

现在我们要求出,解一个方程组就可以了.求q时ed-1=k*phi=k(p-1)(q-1)=k(pq-(p+q)+1)=>
(ed-1)//pq<(ed-1)//(pq-(p+q)+1)=k.
还有要注意的是p<q

P_n =  14057332139537395701238463644827948204030576528558543283405966933509944444681257521108769303999679955371474546213196051386802936343092965202519504111238572269823072199039812208100301939365080328518578704076769147484922508482686658959347725753762078590928561862163337382463252361958145933210306431342748775024336556028267742021320891681762543660468484018686865891073110757394154024833552558863671537491089957038648328973790692356014778420333896705595252711514117478072828880198506187667924020260600124717243067420876363980538994101929437978668709128652587073901337310278665778299513763593234951137512120572797739181693
P_F_n =  14057332139537395701238463644827948204030576528558543283405966933509944444681257521108769303999679955371474546213196051386802936343092965202519504111238572269823072199039812208100301939365080328518578704076769147484922508482686658959347725753762078590928561862163337382463252361958145933210306431342748775024099427363967321110127562039879018616082926935567951378185280882426903064598376668106616694623540074057210432790309571018778281723710994930151635857933293394780142192586806292968028305922173313521186946635709194350912242693822450297748434301924950358561859804256788098033426537956252964976682327991427626735740
Q_n =  20714298338160449749545360743688018842877274054540852096459485283936802341271363766157976112525034004319938054034934880860956966585051684483662535780621673316774842614701726445870630109196016676725183412879870463432277629916669130494040403733295593655306104176367902352484367520262917943100467697540593925707162162616635533550262718808746254599456286578409187895171015796991910123804529825519519278388910483133813330902530160448972926096083990208243274548561238253002789474920730760001104048093295680593033327818821255300893423412192265814418546134015557579236219461780344469127987669565138930308525189944897421753947
Q_E_D =  100772079222298134586116156850742817855408127716962891929259868746672572602333918958075582671752493618259518286336122772703330183037221105058298653490794337885098499073583821832532798309513538383175233429533467348390389323225198805294950484802068148590902907221150968539067980432831310376368202773212266320112670699737501054831646286585142281419237572222713975646843555024731855688573834108711874406149540078253774349708158063055754932812675786123700768288048445326199880983717504538825498103789304873682191053050366806825802602658674268440844577955499368404019114913934477160428428662847012289516655310680119638600315228284298935201
Ciphertext =  40855937355228438525361161524441274634175356845950884889338630813182607485910094677909779126550263304194796000904384775495000943424070396334435810126536165332565417336797036611773382728344687175253081047586602838685027428292621557914514629024324794275772522013126464926990620140406412999485728750385876868115091735425577555027394033416643032644774339644654011686716639760512353355719065795222201167219831780961308225780478482467294410828543488412258764446494815238766185728454416691898859462532083437213793104823759147317613637881419787581920745151430394526712790608442960106537539121880514269830696341737507717448946962021

import gmpy2
import sympy
base = 65537
def getp(n,phi):
    p_q=n+1-phi
    p_q_2=p_q**2-4*n
    p_q_2=gmpy2.iroot(p_q_2,2)[0]
    q=(p_q_2+p_q)//2
    p = p_q - q
    factor2 = 2021 * p + 2020 * q
    if factor2 < 0:
        factor2 = (-1) * factor2
    P = sympy.nextprime(factor2)
    return P
def getq(n,phi):
    p_q=n+1-phi
    p_q_2=p_q**2-4*n
    p_q_2=gmpy2.iroot(p_q_2,2)[0]
    q=(p_q_2+p_q)//2
    p = p_q - q
    factor2 = 2021 * p -2020 * q
    if factor2 < 0:
        factor2 = (-1) * factor2
    Q = sympy.nextprime(factor2)
    return Q
p=getp(P_n,P_F_n)
K=((Q_E_D-1)//Q_n)+1
phi=(Q_E_D-1)//K
q=getq(Q_n,phi)
e=base
d=gmpy2.invert(e,(p-1)*(q-1))
M=gmpy2.powmod(Ciphertext,d,p*q)
import binascii
print(binascii.unhexlify(hex(M)[2:]))

5.救世捷径

题目描述

 题目附件

 给附件重命名,方便我们读取,我重命名为dij.txt。

我最开始是自己手搓在找捷径哈,可以找到,没啥技术含量,然后去看了大佬们wp,知道这题使用到了dijstra算法。上脚本。运行一下就可以,但要注意一下,dij.txt文件最后一行要删除(删掉的不是最后一行的数据,是数据完了以后文件里还有一个空行,要把那个空行删掉),不然索引会有问题。

graph=[]
for i in range(27):
    graph.append([]) #在一个list中放27个list,索引0-26
for i in range(27):
    for j in range(27):
        graph[i].append(0xffff) #先将图中各个顶点之间的距离初始化为一个比较大的数
f=open('dij.txt','r').readlines()  #按行读取,每行内容是list中的一个元素,全部内容组成一个整体的list
#这里需要先手动将txt文件中的最后一行换行去掉否则会多一个'\n'
# print(f)
li=[]
for x in f:
    li.append(x.strip().split(' ')) #strip()删除字符串前后空格,这里是去掉了最后的换行符'\n',然后再按' '分割每行的每个元素,原本在同一子list中的一行元素也彼此独立出来
# print(li)
for x in li:
    graph[int(x[0])][int(x[1])]=int(x[2])
    graph[int(x[1])][int(x[0])]=int(x[2])


def try_dijstra():
    min_d=[0xffff for i in range(27)]  #记录点i到起点1的最短距离
    route=[1 for i in range(27)]  #记录前驱顶点
    isSure=[0 for i in range(27)]  #记录各点到起点距离是否已经确定
    for i in range(2,27):
        min_d[i]=graph[i][1]  #初始化一下能直连1的顶点和1的距离
    min_d[1]=0
    isSure[1]=1

    for i in range(26):
        min=0xfffff
        temp=-1
        for j in range(2,27): # 找到当前离顶点1最近的顶点加入已经确定的“顶点阵营”
            if isSure[j]==0 and min>min_d[j]:
                min=min_d[j]
                temp=j
        isSure[temp]=1
        for j in range(2,27):# 判断从顶点1开始,在经过该顶点后,再到达其邻接顶点的距离,是否比其邻接顶点原本到顶点1的距离更近,如果更近就更新最短距离
            if min_d[j]>min_d[temp]+graph[temp][j]:
                min_d[j]=min_d[temp]+graph[temp][j]
                route[j]=temp
    return (route,min_d)

route,min_d=try_dijstra()
print(min_d[26]) #最短距离
print(route) #前驱顶点

passv=[]  #存放顶点之间的“内容”(内容最后要组成flag
for i in range(27):
    passv.append([]) # 还是在一个list中放27个list
for i in range(27):
    for j in range(27):
        passv[i].append(0)  #需要将内部list中初始化出27个“位置”否则会报错索引越界
for x in li:
    passv[int(x[0])][int(x[1])]=x[3]
    passv[int(x[1])][int(x[0])]=x[3]

y=26
l=[]
while y!=1:
    print(y) #输出终点到起点的最短路径经过的顶点
    l.append(passv[y][route[y]]) #y到其前驱顶点route[y]之间的内容
    y=route[y]
print()
l=l[::-1]
for i in range(len(l)):
    print(l[i],end='')

这里补充一点dijstra算法的知识。

Dijkstra算法算是贪心思想实现的,首先把起点到所有点的距离存下来找个最短的,然后松弛一次再找出最短的,所谓的松弛操作就是,遍历一遍看通过刚刚找到的距离最短的点作为中转站会不会更近,如果更近了就更新距离,这样把所有的点找遍之后就存下了起点到其他所有点的最短距离。

你可能疑惑贪心思想又是什么,这里简单提一下。贪心思想也是一种算法,就是把大问题归纳成小问题,然后得到解决的思想,贪心算法是一种思想,没有什么固定的公式与套路。简单来说就是局部做出当前看来最好的选择。Dijkstra算法的最好选择就是最短距离。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值