2023年第三届陕西省大学生网络安全技能大赛本科高校组

Crypto

奇怪的sar

第一步常规的lcg算法

n1 =  137670797028117726329534659376416493367957852768263083700434198723955223922183386928456013703791817601151754417828367188186912209697081337658512940425529211281290630976671911327606706953154608427885071841566358882014021242768190762103365969320014710368160869517966437591299370072284930202718943785099916898209
enc =  [101737402423360536260958229788866250367716256968287178187558336481872788309727545478736771692477306412259739856568227009850831432381180909815512654609798228982433082928392936844193974517574281026029228179913579225687286945054175762659252515268270399329404664775893089132101252158524000295899895962104782878103, 37355684997487259669354747104430314505839306993101096210478266975184357608742619438151118843905165289324251734149329596611854110739738607745107961453008343886403511257039401245484528985856920723694142989180291902939107642020398816995584650913417698279936585230648639613028793148102494100898288564799111024672, 58677759595639211550435023449462812079890625834313820227189340593596480924226619376872336960357021314847975570175387751632125898437020801920862764666175594874885587518469384576361008639967382152477408865298759987606155830674598034578657554841283906976808719095766296677147076808250022898199866472085742989883, 61841632061818470036288407041172200048676249787061823756736224887116113640875444187463656719652972233582538657844183320242896612625995507633237074900538692102956750184024574603018257213912795847625926653585010890014291951218199774765624860625726555381815237888483974246173727262881650634287497285246796321130, 7618244158597756867387754433401378508070531356170836765779245254233413235386172690733378371343899289510629513166609513857423499004879497768588665836034791151090648182168421570449377835494883902907064269417199065924565304966242954268460876762295575715334403142360198583318323418975108290758222653083011275844, 106276841058222138994123556391380518368163552919305398852484130331884811278068151915582752795463570013359693610495645946230044828403849434903415989487924763756589202218361370725532394478569304449884620166937809374355282324069422109879874964479199929174533104879048175102339134830614476339153367475243140156049, 54574757236475194407137831004617398270525645136836468973535243574661043352422598443323384197261529289829451787586618886007968913414366545291507686451774653217577858375086817168124727394445167274831801876424578654786480330913650363551771258617533162477541882336257099777912519011890593910515860435759936717781, 15567087904962670212229825713697043597876172881256160613623383896576159414077875401117959132252949501643234465895697270909085179587988268864498823765197994781747034644583869111599516151129007414228897958635533561248099927507725880289417298814703767549313482346652043188826434944367260731729064673486516315207, 10757138067445225320504771816863593606847219020279502671965413470243269270456133564739090471033889069283122519782525412134604896073598293410977787230108853737796640474070194546344190858079847734817109910030714675258996740807873872365037296486121580542250452443305370358407408558223735250474249180772656905880, 68097848963949068260912124852455363245291187860801223898468533992003737157497436432969031551088942445561676359631354280979357356539429863946694570097104716411407829017684705171462511875250672979623888463245258237680782731827727876526411531354910982579164963119481534453651300645314177478026462894232377307020]

MMI = lambda A, n,s=1,t=0,N=0: (n < 2 and t%N or MMI(n, A%n, t, s-A//n*t, N or n),-1)[n<1] #逆元计算
d=MMI(enc[1]-enc[0],n1)
a=(enc[2]-enc[1])*d%n1
b=(enc[1]-a*enc[0])%n1
seed=(enc[0]-b)*MMI(a,n1)%n1
print(seed)
#39428646082513135314545544161912595458975375891528176714825766497155482031976852156313956476772023258684487799640179241987139554034654104867011313090105438798561154654679825702410748780286094326639330840289843154525176685892323447168072417654823748596238888125898914210332775882916911771786984574407163323116

很直接的想法,由低到高逐位爆破。已知异或的结果,每位只有两种情况,即异或结果为0,则pq对应位置不是00就是11,异或结果为1,不是01就是10。那么就只有4种异或情况,可以爆破4种情况,通过seed和n来判断是哪种情况,在用一个列表进行保存,循环1024次遍历出p,q。

from Crypto.Util.number import *
from tqdm import *

n =  24044063028844014127418595700558729326190738802687551098858513077613750188240082663594575453404975706225242363463089392757425008423696150244560748490108425645064339883915929498539109384801415313004805586193044292137299902797522618277016789979196782551492020031695781792205215671106103568559626617762521687128199445018651010056934305055040748892733145467040663073395258760159451903432330506383025685265502086582538667772105057401245864822281535425692919273252955571196166824113519446568745718898654447958192533288063735350717599092500158028352667339959012630051251024677881674246253876293205648190626145653304572328397
c =  14883053247652228283811442762780942186987432684268901119544211089991663825267989728286381980568977804079766160707988623895155236079459150322336701772385709429870215701045797411519212730389048862111088898917402253368572002593328131895422933030329446097639972123501482601377059155708292321789694103528266681104521268192526745361895856566384239849048923482217529011549596939269967690907738755747213669693953769070736092857407573675987242774763239531688324956444305397953424851627349331117467417542814921554060612622936755420459029769026126293588814831034143264949347763031994934813475762839410192390466491651507733968227
seed=39428646082513135314545544161912595458975375891528176714825766497155482031976852156313956476772023258684487799640179241987139554034654104867011313090105438798561154654679825702410748780286094326639330840289843154525176685892323447168072417654823748596238888125898914210332775882916911771786984574407163323116
e=65537
pre_sol = [(1, 1)]

for i in tqdm(range(1, 1024)):
    cur_pow = (1 << (i+1))
    cur_sol = []
    for pre_p, pre_q in pre_sol:
        for s in range(2):
            for t in range(2):
                cur_p = pre_p + s * (1 << i)
                cur_q = pre_q + t * (1 << i)
                if (cur_p ^ cur_q == seed % cur_pow and cur_p * cur_q % cur_pow == n % cur_pow):
                    cur_sol.append((cur_p, cur_q))
    pre_sol = cur_sol

for p,q in pre_sol:
    if n%p==0 or n%q==0:
        assert p*q==n
        phi = (p-1)*(q-1)
        d = inverse(e,phi)
        print(long_to_bytes(pow(c,d,n)))
 #flag{y0u_kn0w_Pruning_and_lcg}

HaM3

p,q的比特位是64位,转为10进制是20位或19位。那么\(PP=10^{60}*p+10^{40}*q+10^{20}*q+p\),同理\(QQ=10^{60}*q+10^{40}*p+10^{20}*p+q\),那么PP*QQ的前20位是p*q的前20位,因为两式相乘最高次是120,其次是100,那么相差的20位没有变化。同理,两式相乘的最低次是0,倒数第二次方是20,也是相差的低20位没有变化,那么我们大概可以知道前20位和后20位的数。而p*q的总比特位是128,转为10进制是39位。
但是我们的p和q的十进制位数必然不可能同为20或19,那样不能保证PP和QQ都是素数。所以我们取n的前19位和后18位,中间还有2位可以进行爆破,最后得到p,q,求出PP,QQ。

#该脚本在sagemath运行
from Crypto.Util.number import *
import gmpy2
nbit = 64
n = 142672086626283587048017713116658568907056287246536918432205313755474498483915485435443731126588499776739329317569276048159601495493064346081295993762052633
high = str(n)[:19]
low = str(n)[-18:]
for i in range(100):
        pq = int(high +  str(i) + low)
        f = factor(pq)
        if len(f) == 2 and f[0][0].nbits() == 64:
            p = f[0][0]
            q = f[1][0]
            print(p,q)
c = 35771468551700967499031290145813826705314774357494021918317304230766070868171631520643911378972522363861624359732252684003796428570328730483253546904382041
e = 65537
PP = int(str(p) + str(q) + str(q) + str(p))
QQ = int(str(q) + str(p) + str(p) + str(q))
fai_n = (PP-1)*(QQ-1)
d = gmpy2.invert(e,fai_n)
m = pow(c,d,PP*QQ)
print(long_to_bytes(m))
#flag{HaMbu2g3r_1S_2ea1ll_D3lci0U3_By_R3A!!}

BigDataEnc

import pickle
from secret import flag
from Crypto.Util.number import *

N = 128
assert flag.startswith(b'flag{') and flag.endswith(b'}')


class BigDataEnc:
    def __init__(self, N):
        self.a = 1
        self.b = 1
        self.N = N

    def enc(self, flag):
        bits = bin(bytes_to_long(flag))[2:]
        LEN = len(bits)
        assert LEN == 254
        for i in range(LEN):
            t = getPrime(self.N)
            if int(bits[i]):
                self.b *= pow(t, 20)
                self.a *= pow(t, 23 + i)
            else:
                self.a *= pow(t, 20)
                self.b *= pow(t, 23 + i)

    def save(self):
        file_a = open('a', 'wb')
        file_b = open('b', 'wb')
        pickle.dump(str(self.a), file_a)
        pickle.dump(str(self.b), file_b)
        file_a.close()
        file_b.close()


CheckIn = BigDataEnc(N)
CheckIn.enc(flag[5:-1])
CheckIn.save()

代码概述

产生\(g_0\)~\(g_{253}\)个128比特位的素数

根据flag的二进制值进行判断

若为1:\(a*=g_i^{23+i},b*=g_i^{20}\).

若为0:\(a*=g_i^{20},b*=g_i^{23+i}\).

思路

主要目的就是求出b/a的分子分母。

首先化简一下,考虑到a和b有公因数

\[假设:\frac{b}{a}=\frac{g_0^{23+i}*\cdots*g_i^{23+i}*\cdots*g_{253}^{20}}{g_0^{20}*\cdots*g_i^{20}*\cdots*g_{253}^{20+253}} \]

\[那么必然含义公因数(g_0*g_1*\cdots*g_{253})^{20} \]

\[所以设aa为分母,bb为分子 \]

\[aa=g_m^{3+m}*\cdots*g_j^{3+j} \]

\[bb=g_n^{3+n}*\cdots*g_i^{3+i} \]

那么我们可以得到254个素数的乘积\(g_0*g_1*\cdots*g_{253}\).

\[x=iroot(b//bb,20)[0] \]

那么aa与x存在公因数\(g_m*\cdots*g_j\).

\[xa=gcd(aa,x) \]

就可以求出\(g_m^m*\cdots*g_j^j\).

\[tmp=aa//xa^3 \]

然后就可以通过下面式子判断是0还是1

\[tmp\pmod {xa^i}是否等于0 \]

如果模运算为0,则二进制位是1。如果不为0,说明i的值大于tmp里面的最小次方,二进制位是0。并且更新tmp的值为\(tmp//g_k^k\).
exp:

a=
b=
aa=(b/a后的分母部分)
bb=(b/a后的分子部分)

x=iroot(b//bb,20)[0]
xa=gcd(aa,x)
xb=gcd(bb,x)
tmpa=aa//(xa^3)
tmpb=bb//(xb^3)
assert xa*xb==x

#use a
xa=gcd(aa,xx)
tmp=aa//(xa^3)
for i in range(0,255):
    if tmp%(xa^i)==0:
        print(0,end='')
        continue
    else:
        tmp=tmp//(xa^(i-1))
        gi=xa//gcd(tmp,xa)
        xa=xa//gi
        tmp=tmp*(xa^(i-1))
        print(1,end='')
#011011100110011011000110110010101100101001100010011000000110111001110010011100000110111011000010011010101100010001101000011011000110110001101000110001000110000001110000011001000111000011000110011011001100101001100110011000100111000001110010011011100110011

同理,也可以通过b来求解

#use b
xb=gcd(bb,x)
tmp=bb//(xb^3)
for i in range(0,255):
    if i==0:
        print(0,end='')
        continue
    if temp%(xb^i)==0:
        print(1,end='')
        continue
    else:
        tmp=tmp//(xb^(i-1))
        gi=xb//gcd(tmp,xb)
        xb=xb//gi
        tmp=tmp*(xb^(i-1))
        print(0,end='')
#011011100110011011000110110010101100101001100010011000000110111001110010011100000110111011000010011010101100010001101000011011000110110001101000110001000110000001110000011001000111000011000110011011001100101001100110011000100111000001110010011011100110011

参考无趣的浅的大佬博客:https://blog.csdn.net/qq_41626232/article/details/131023819?spm=1001.2014.3001.5502

Blockchain

被销毁的flag

给了交易地址信息https://sepolia.etherscan.io/tx/0x7007fdbcf4da81e656a6233d358cc5902b4a75f2b31a02d152e57be05fd5c6dd

可以清楚的看到合约已经销毁

点进去可以看到有两个交易记录

第一个是我们看到的合约销毁的记录,第二个就是合约创建的记录

点击第二条记录,查看交易记录

可以看到有一个输入数据,转为字节看看

发现flag,但是中间有乱码,直接删除提交。

flag{S0met1m4s_d4t0ry_c4n_n0t_d4t0ry}
还有一种方法是进行反编译(网站:https://ethervm.io/decompile)

将零去掉,然后把两连接转字符。

posted @ 2023-06-03 20:25  L00kback  阅读(143)  评论(5编辑  收藏  举报
Title