// make flag accessible for local debugging purposes only // also the nginx is at a private ip that isn't 127.0.0.1 // it's not that easy to get the flag :D app.post("/flag", (req, res) => { if (!["127.0.0.1", "::ffff:127.0.0.1"].includes(req.socket.remoteAddress)) { res.status(400).type("text/plain").send("You don't get the flag!"); } else { res.type("text/plain").send(flag); } });
app.listen(port, () => { console.log(`Server listening on port ${port}`); });
這題是個 ssrf 題,目標要想辦法 POST
127.0.0.1:8080/FLAG。不過可以看到它已經擋掉了各種 ip
繞法,還有 dns rebinding 等等的都不能用。不過很容易能發現它可以吃
redirect,所以給個 302 redirect 到 /flag
應該就能過了吧...?
測試一下只會發現它 redirect 之後就變成了 GET
request,所以去翻了翻 node-fetch 的 source 可以看到是這幾行在作怪。它遇到
303 或是 301/302+POST 的時候就會強制把 method
改回 GET。不過看到這個地方能知道它把
307/308 也都算在 redirect 的 status code,所以只要弄個
307 或是 308 的 redirect 就能拿 flag 了。
functionqueryMiddleware(req, res, next) { console.log(req.cookies) res.locals.search = req.cookies.search || "the quick brown fox jumps over the lazy dog"; // admin is a cool kid if (req.cookies.admin === adminSecret) { res.locals.search = flag; } next(); }
app.get("/q", queryMiddleware, (req, res) => { const query = req.query.q || "h"; // h let status; if (res.locals.search.includes(query)) { status = "succeeded, but please give me sustenance if you want to be able to see your search results because I desperately require sustenance"; } else { status = "failed"; } res.redirect( "/?m=" + encodeURIComponent( `your search that took place at ${Date.now()} has ${status}` ) ); });
app.listen(port, () => { console.log(`Server listening on port ${port}`); });
withopen("flag.txt", "r") as f: flag = f.read().strip()
alpha = string.ascii_lowercase
defencrypt(msg, key): ret = "" i = 0 for c in msg: if c in alpha: ret += alpha[(alpha.index(key[i]) + alpha.index(c)) % len(alpha)] i = (i + 1) % len(key) else: ret += c return ret
inner = alpha + "_" noise = inner + "{}"
print("Welcome to the vinegar factory! Solve some crypto, it'll be fun I swear!")
i = 0 whileTrue: if i % 50 == 49: fleg = flag else: fleg = "actf{" + "".join(random.choices(inner, k=random.randint(10, 50))) + "}" start = "".join(random.choices(noise, k=random.randint(0, 2000))) end = "".join(random.choices(noise, k=random.randint(0, 2000))) key = "".join(random.choices(alpha, k=4)) print(f"Challenge {i}: {start}{encrypt(fleg + 'fleg', key)}{end}") x = input("> ") if x != fleg: print("Nope! Better luck next time!") break i += 1
defdecrypt(msg, key): ret = "" i = 0 for c in msg: if c in alpha: ret += alpha[(alpha.index(c) - alpha.index(key[i])) % len(alpha)] i = (i + 1) % len(key) else: ret += c return ret
defencrypt(msg, key): ret = "" i = 0 for c in msg: if c in alpha: ret += alpha[(alpha.index(key[i]) + alpha.index(c)) % len(alpha)] i = (i + 1) % len(key) else: ret += c return ret
deffind_key(ct_cand): try: return"".join( [ alpha[(alpha.index(c) - alpha.index(d)) % len(alpha)] for c, d inzip(ct_cand, "actf") ] ) except: pass
# io = process(['python', 'main.py']) io = remote("challs.actf.co", 31333) for _ inrange(50): io.recvregex(r"Challenge \d+: ".encode()) ct = io.recvlineS().strip() # io.recvuntil(b'Challenge ') # print(ct) lb_idxs = [i for i, c inenumerate(ct) if c == "{"] cands = [(i, ct[i - 4 : i]) for i in lb_idxs if i >= 4] print(len(cands)) for i, c in cands: key = find_key(c) ifnot key: continue # print(c, key) msg = decrypt(ct[i - 4 :], key) if"fleg"in msg: msg = msg[: msg.index("fleg")] if msg.count("{") == 1and msg.count("}") == 1: print(_, msg) io.sendline(msg.encode()) break else: print("no found")
funcmain() { flag := "actf{REDACTEDREDACTEDREDACTED!!}" rand.Seed(12345) // the actual seed is not 12345 // drastically slow down naive brute force for i := 0; i < 100000; i += 1 { rand.Uint64() } for i := 0; i < 4; i += 1 { fmt.Printf("flag chunk: %d\n", binary.LittleEndian.Uint64([]byte(flag)[i*8:i*8+8])^rand.Uint64()) } gap := 0 for i := 0; i < 607; i += 1 { fmt.Println(rand.Uint64()) for j := 0; j < gap; j += 1 { rand.Uint64() } gap = (gap + 1) % 13 } }
一個 golang 的題目,把 flag 和一些隨機數 xor 了,然後輸出 607 個
output,其中跳過了一些輸出。題目很明顯是要讓我們 predict random
的輸出,所以需要去看 go 的 source code。
defrand_uint64(): global tap, feed tap -= 1 if tap < 0: tap += rngLen feed -= 1 if feed < 0: feed += rngLen x = vec[feed] + vec[tap] vec[feed] = x return x
polys = [] gap = 0 for _ inrange(4): rand_uint64() for i, num inenumerate(nums): polys.append(rand_uint64() - num) for _ inrange(gap): rand_uint64() gap = (gap + 1) % 13 M, v = Sequence(polys).coefficient_matrix() print(v.T) A = M[:, :-1] b = -M[:, -1] tmp = A.solve_right(b).list() for j, term inenumerate(v.list()[:-1]): i = gens.index(term) vec[i] = tmp[j] # print(vec)
tap = 0 feed = rngLen - rngTap tap = (tap - 100000) % rngLen feed = (feed - 100000) % rngLen for ct in flagct: print(int(int(ct) ^^ int(rand_uint64())).to_bytes(8, "little").decode(), end="")
from Crypto.Util.number import * from gmpy2 import powmod from itertools import combinations, product from tqdm import tqdm
n = 900070490622067320191637256322689412527951600989690014040742293402515652299807355416973524079799412242303695005849373445039400849591465597575071172369743191868426614517714438100741689051321511330353068870085391955380005924193452388879170080569217611534666723431228876665400462326676136834184598097637612462138913958737759322989904101853151206852072163254977079626441345648695044414743061561749348880019607938930572091154083635100263637181513759943165217032366307235262290149121982361740356299744695043277615922872281013512722579789196565526621382570308445038543830946971870143416647314522450656476380450926273955034941922166822345239863969969054173792809511555294506499479460733800203789975490744756171199513541914459052812970878813532508200185561086389173320140400837553390150640118664644728326976956623287728071670363574828765499081630098395101207132121557269428414754204021602411843144222862499913321787608802795431375613453451646357431858538087082423774836125541442108814662883958785416540932102786177408197877642161771714550028264013960050526390792232071691880271991611403599658754594252925331797512039370218705211962522382739680885820067113131946086305783275655204391316332325661610449937310593926456756974934432806107508584687 e = 65537 c = 785019041003063094605338644855048946920785904799316056061128856210648574008947823318103541165223596391441869599653542367469582749735833238881174760706303204193239490503494128261465176354669635814736470937192039240288549501040533102957388190144367063971050093258087028919607189745941929361743460532173075128757057170184845810592063392093611909588608434601111240804241210939629912198253922278311726074613374311364714503593835714701261515902458295964850200883428876941854713297600424159346665228238295844165261930957085099153766532230753418227132506795445835713828219025117217211988132423808868878491252074351084194298227654253015597086572860607173699553442586206642744564518363534136736457282374055689877416438808797889637908338960048452523853477755423540348739016013753910186174575168439451877576061110984631119994270572126858635951627682166569924669328090525845842805274374629938562576743743090674720310052196389604757172761607674745732712177986201837422518542301831341463977319044721933558836609327149863674429302791872305204502140781352055289953107204260973578971800635948027688728015052061073091633479965577903274852755170355267952134264963602557305761624298274953157061326235764865240265336589063356964395136173662984407099988044 ans = bytes_to_long( b'\xc0K*/\xfb{\xfd\xa36\xfe\'\xfc(l\xa5\xe1Nf\x17\xad\x9eZ"\xbd\xc2%rs\xbe\xb9\xf3\xc5e6\xeb\x9e\xceD\x86.\x03\xb2s\x95\xc2\xac}\xee \x9f\xb9\xbb\x87\x1c\x0b\t\x01D7\xcd\x05\xdcp\x84\x07K\xab\xc9\x14\x9e\x8b\xd5\x8e\xe4\xaeB\n(\r\xe3c\xbd\x97\xe9\x93&h5\xdf9\xaf%~\x9f&J\xf02\x9e\xd9JJe\xd6i\x85)\xd2\xb5\'\xe1x\xb6\xc5K\x84M\xbc_\x01\'\x80\xb5\xf5\x7f\xa1\x96\xbe\xe7\xb3R\xaa\xe7\xe0\x9c\xd4\xed\xde\n<\xdc\x16q\x10w\x8f\x1d\xa3XH\xe2M"C\xfa\x03\xdb\xf4\x00\xa0\xaf\x93=\x9fm\xb5\x94\xfa\xec\xf8\nd\xb1\x17\x8d\x84\x9f\xdfD\xb0FU\xd3\xc07q+\xcc|\xb7\xe7\x8dlk.\xa6S\xa3\x18\xbfi\x8e\xc2SW\\\xb4\x03o\xdd\xeb\xa41\x7fv\x8e\x07aka\x91i\xeb\xe0\xa6*\x17\x1f_*6\x90x\xcd\xaa$\xf9x\xadt\x00\xea\x01\x19\x11\xa9\xdd\xb6\xfa\x1e6\xa8<\x92\xf3w(\xbf;v\xe5\x92\n\xcd\x8ckD\xb1\x82\xe9\x16\x85\xbf\xbf81\xf6.\x9a\xbe\xe7\xf66+\xf4u\xce\xcf#\xb4i\x966\xbf\x96\xee568r\xc8\xd0\xfa\xf7\xfe\xd8>\x97j^\xbbc[\xc0\xe4\xf5\x9d\xb5\xac\xab2\xed\x90\x9cvf\x1a\xaa\xe2\xb27!h\xa5\xac\x0c\xff\xc8\x86F\x86\xaff\xdb\xc6\xc4\x94\xbd[\xf5\xf2\x85!\x1f\xf6\xb1.9\xc2\xf0>H\xd6 L\x9d\xe8\xf7V"\xfe"1\xf3I\xa9\xa9]\x10\x97&\xf6\xbb\xb3\xf4a_\x98\x85\x15v\xd4U\xfd\xeayj\xf4\x08b\xd95b\xf7\xcfI\xfc\x08k1\x8e\xc6\x98\xabY\x16fNRS-\x05<\xee\xe5\xc4\xe0\xad\x8aE\x03jL\xd5m~\x81\xfeqjw;0\xe5K\x889\xa9T\xa8\xc1/:\x96_\xee\x16\xe0\xca\xa6qm\xcb\xa5&\xd4\x94o\xa9\x94\xc6{sm\xc7\xf9\xff\xfe \xb3\xc0\x02\xc3\xe5O\xe8\xe7\x1d\xe0\xf4i\x07\xda\x97=\xfd\xc0\x0eW\xc0;\x8e(\x93\\G\x9bf\xd8\xcf0\x85' )
ce = powmod(c, e, n) # build table to speed up the calculations # ce_pows[i] = powmod(ce, 1<<i, n) # ce_pows_inv[i] = powmod(ce, -(1<<i), n) ce_pows = [None] * 4096 ce_pows[0] = ce ce_pows_inv = [None] * 4096 ce_pows_inv[0] = powmod(ce, -1, n) for i inrange(1, 4096): ce_pows[i] = (ce_pows[i - 1] * ce_pows[i - 1]) % n ce_pows_inv[i] = (ce_pows_inv[i - 1] * ce_pows_inv[i - 1]) % n assert ce_pows[87] == powmod(ce, 1 << 87, n) assert ce_pows_inv[63] == powmod(ce, -(1 << 63), n)
l = (powmod(ans, e, n) * powmod(c, -1, n)) % n tbl = {} for x in tqdm(range(4096), desc="build x table"): # ex = 1 << x # tbl[powmod(ce, ex, n) * l % n] = (x, -1) # tbl[powmod(ce, -ex, n) * l % n] = (x, +1) tbl[ce_pows[x] * l % n] = (x, -1) tbl[ce_pows_inv[x] * l % n] = (x, +1)
# for y, z in tqdm( # combinations(range(4096), 2), desc="search y z", total=4096 * 4095 // 2 # ): # # ey = 1 << y # # ez = 1 << z # # for yy, zz in product([1, -1], repeat=2): # # t = powmod(ce, yy * ey + zz * ez, n) # # if t in tbl: # # print(tbl[t], y, z) # for (s1, t1), (s2, t2) in product([(+1, ce_pows), (-1, ce_pows_inv)], repeat=2): # t = t1[y] * t2[z] % n # if t in tbl: # print(tbl[t], (y, s1), (z, s2)) #
# found (2439, -1) (981, -1) (2311, 1) m = ans * powmod(c, -(-(1 << 2439) - (1 << 981) + (1 << 2311)), n) % n print(long_to_bytes(m)) # actf{the_earthquake_in_the_room}
from Crypto.Util.number import bytes_to_long, long_to_bytes from Crypto.Util.Padding import pad from Crypto.Random import get_random_bytes from Crypto.Cipher import AES from secret import flag, d
assertlen(flag) < 256
n = 0xbb7bbd6bb62e0cbbc776f9ceb974eca6f3d30295d31caf456d9bec9b98822de3cb941d3a40a0fba531212f338e7677eb2e3ac05ff28629f248d0bc9f98950ce7e5e637c9764bb7f0b53c2532f3ce47ecbe1205172f8644f28f039cae6f127ccf1137ac88d77605782abe4560ae3473d9fb93886625a6caa7f3a5180836f460c98bbc60df911637fa3f52556fa12a376e3f5f87b5956b705e4e42a30ca38c79e7cd94c9b53a7b4344f2e9de06057da350f3cd9bd84f9af28e137e5190cbe90f046f74ce22f4cd747a1cc9812a1e057b97de39f664ab045700c40c9ce16cf1742d992c99e3537663ede6673f53fbb2f3c28679fb747ab9db9753e692ed353e3551 e = 0x10001 assertpow(2,e*d,n)==2
enc = pow(bytes_to_long(flag),e,n) print(enc)
k = get_random_bytes(32) iv = get_random_bytes(16) cipher = AES.new(k, AES.MODE_CBC, iv)
while1: try: i = int(input("Enter message to sign: ")) assert(0 < i < n) print("signed message (encrypted with military-grade aes-256-cbc encryption):") print(cipher.encrypt(pad(long_to_bytes(pow(i,d,n)),16))) except: print("bad input, exiting")
# for i in range(1500, 1800): # l = len(oracle(pow(2,e*i,n)*enc%n)) # print(i,l,'=' * 10 if l ==256 else '') # exit()
# for i in range(800): # t = randint(2**1800, 2**1830) # l = len(oracle(pow(t, e, n) * enc % n)) # print(t, l, "=" * 10 if l < 272 else "") # if l < 272: # break # exit()
bound = 2 ** (8 * (223 + 16 + 16))
# def check(a): # # true if a*flag<bound # c = pow(a,e,n)*enc%n # ret = len(oracle(c))<272 # # assert ((a*bytes_to_long(flag))<bound) == ret # return ret # l = 1<<281 # r = 1<<282 # while r-l>=5: # print((r-l).bit_length(),l,r) # m=(l+r)//2 # if check(m): # l=m # else: # r=m # for i in range(l,r): # print(long_to_bytes(bound//i)) # print(f'{l = }') # print(f'{r = }')
# actf{the_letters_in_rsa_and_aes_for l = 5106591256318838407683905460243764336959660291605761992637034245320889588676402619004 r = 5106591256318838407683905460243764336959660291605761992637034245320889588676402619008
# flag_approx = bound//((l+r)//2) # old_l, old_r = l,r # l=1<<417 # r=1<<421 # t = ((l+r)//2)*flag_approx//n # l = (bound+(t*n))//(bound//old_l) # r = (bound+(t*n))//(bound//old_r) # def check2(a): # # true if (a*flag-t*n)<2^(8*223) # c = pow(a,e,n)*enc%n # ret = len(oracle(c))<272 # # assert ((a*bytes_to_long(flag)%n)<bound) == ret # # assert ((a*bytes_to_long(flag)-t*n)<bound) == ret # return ret # while r-l>=5: # t = ((l+r)//2)*flag_approx//n # print((r-l).bit_length(),l,r) # m=(l+r)//2 # print(long_to_bytes((bound+t*n)//m)) # if check2(m): # l=m # else: # r=m # for i in range(l,r): # print(long_to_bytes((bound+t*n)//i)) # print(f'{l = }') # print(f'{r = }') # print(f'{t = }') # exit()
# actf{the_letters_in_rsa_and_aes_form_aries_if_you_th l = 2876915576175161902638735420558619565332739305188016554901418502200422028281993863555513736990118237206528734750545634674214476 r = 2876915576175161902638735420558619565332739305188016554901418502200422028281993863555513736990118237206528734750545634674214479 t = 3004922629270658762035610041417503039161
# flag_approx = (bound+t*n)//((l+r)//2) # old_l, old_r = l,r # l = 2788595730112793363482939389816956118716055518453142516805245452365645530130649255772251254919244903425930540175264534619647173682810044137923730268625279210651085031363408490342314 # r = 1<<601 # def check2(a): # # true if (a*flag-t*n)<2^(8*223) # c = pow(a,e,n)*enc%n # ret = len(oracle(c))<272 # # assert ((a*bytes_to_long(flag)%n)<bound) == ret # # assert ((a*bytes_to_long(flag)-t*n)<bound) == ret # return ret # while r-l>=5: # t = ((l+r)//2)*flag_approx//n # print((r-l).bit_length(),l,r) # m=(l+r)//2 # print(long_to_bytes((bound+t*n)//m)) # if check2(m): # l=m # else: # r=m # for i in range(l,r): # print(long_to_bytes((bound+t*n)//i)) # print(f'{l = }') # print(f'{r = }') # print(f'{t = }') # actf{the_letters_in_rsa_and_aes_form_aries_if_you_throw_in_the_letter_i l = 2788595730112793363482939389816956118717067625592558569122109372914710315564288760672236727384979003609179452086888918931820942394290026713628077108950197119875557345838695855595297 r = 2788595730112793363482939389816956118717067625592558569122109372914710315564288760672236727384979003609179452086888918931820942394290026713628077108950197119875557345838695855595299 t = 2912673031734900662395316884955179464520550584548675450510737837150340214830893378637155375253
# flag_approx = (bound+t*n)//((l+r)//2) # print(long_to_bytes(flag_approx)) # old_l, old_r = l,r # l=1<<772 # r=1<<774 # # t = ((l+r)//2)*flag_approx//n # # l = (bound+(t*n))//(bound//old_l) # # r = (bound+(t*n))//(bound//old_r) # def check2(a): # # true if (a*flag-t*n)<2^(8*223) # c = pow(a,e,n)*enc%n # ret = len(oracle(c))<272 # # assert ((a*bytes_to_long(flag)%n)<bound) == ret # # assert ((a*bytes_to_long(flag)-t*n)<bound) == ret # return ret # while r-l>=5: # t = ((l+r)//2)*flag_approx//n # print((r-l).bit_length(),l,r) # m=(l+r)//2 # print(long_to_bytes((bound+t*n)//m)) # if check2(m): # l=m # else: # r=m # for i in range(l,r): # print(long_to_bytes((bound+t*n)//i)) # print(f'{l = }') # print(f'{r = }') # print(f'{t = }') # actf{the_letters_in_rsa_and_aes_form_aries_if_you_throw_in_the_letter_i_because_that_represents l = 24840289476811342962383671815400040884110176273867145778224832608416815242982030181294054541258343647207804706536065233120593270847750168599425772831619927338434418889926878315235329955265232757350783242378659093019491194921254464013 r = 24840289476811342962383671815400040884110176273867145778224832608416815242982030181294054541258343647207804706536065233120593270847750168599425772831619927338434418889926878315235329955265232757350783242378659093019491194921254464016 t = 25945546885231068689701081185467205998159541945356011842376833249771582355386007995626913844230778454571428210808075349499667131598098150206112170
# flag_approx = (bound+t*n)//((l+r)//2) # print(long_to_bytes(flag_approx)) # old_l, old_r, old_t = l,r, t # l=1<<838 # r=1<<839 # # t = ((l+r)//2)*flag_approx//n # # l = (bound+(t*n))//(bound//old_l) # # r = (bound+(t*n))//(bound//old_r) # assert r > l # def check2(a): # # true if (a*flag-t*n)<2^(8*223) # c = pow(a,e,n)*enc%n # ret = len(oracle(c))<272 # # assert ((a*bytes_to_long(flag)%n)<bound) == ret # # assert ((a*bytes_to_long(flag)-t*n)<bound) == ret # return ret # while r-l>=5: # t = ((l+r)//2)*flag_approx//n # print((r-l).bit_length(),l,r) # m=(l+r)//2 # print(long_to_bytes((bound+t*n)//m)) # if check2(m): # l=m # else: # r=m # for i in range(l,r): # print(long_to_bytes((bound+t*n)//i)) # print(f'{l = }') # print(f'{r = }') # print(f'{t = }')
# actf{the_letters_in_rsa_and_aes_form_aries_if_you_throw_in_the_letter_i_because_that_represents_yourself l = 1832889850782397517082802171755189663406212347562527955378281744907439616857248067557309485708214209151091283518633170408049856462283054627491650905580659510813855170585637869897105855355559911173232727735746231855035969403764159886371703173313087968656 r = 1832889850782397517082802171755189663406212347562527955378281744907439616857248067557309485708214209151091283518633170408049856462283054627491650905580659510813855170585637869897105855355559911173232727735746231855035969403764159886371703173313087968660 t = 1914443452977158129230475067287573602778082100812605911269977627778078974619449456949834070683484894171059782628560370507794649112063505421027889511470023283214637956
# flag_approx = (bound+t*n)//((l+r)//2) # print(long_to_bytes(flag_approx)) # old_l, old_r, old_t = l,r, t # l = 1641550959518889204327060753293133298008071251322882615948833979994084362247932504494195196993273913632675611712933151143263106391572187617869133125707375497901514599490881950415967558553268221821769522254021292561850184626270325883529964926864747294627750945092499738589283659636318017597208125381434986915053393458318580088945335 # r=1<<1098 # # t = ((l+r)//2)*flag_approx//n # # l = (bound+(t*n))//(bound//old_l) # # r = (bound+(t*n))//(bound//old_r) # # assert r > l # def check2(a): # # true if (a*flag-t*n)<2^(8*223) # c = pow(a,e,n)*enc%n # ret = len(oracle(c))<272 # # assert ((a*bytes_to_long(flag)%n)<bound) == ret # # assert ((a*bytes_to_long(flag)-t*n)<bound) == ret # return ret # while r-l>=5: # t = ((l+r)//2)*flag_approx//n # print((r-l).bit_length(),l,r) # m=(l+r)//2 # print(long_to_bytes((bound+t*n)//m)) # if check2(m): # l=m # else: # r=m # for i in range(l,r): # print(long_to_bytes((bound+t*n)//i)) # print(f'{l = }') # print(f'{r = }') # print(f'{t = }') # actf{the_letters_in_rsa_and_aes_form_aries_if_you_throw_in_the_letter_i_because_that_represents_yourself_or_something_anyway_aries_is_a l = 1641550959518889204327060753293133298008071251322882615948833979994084362247932504494195196993273913632681730558092679835228121341433243540949243987915147127849677136846882565338958226278649038823205104414044774715949933967582465105018476900904220193700402953822673097109499902642615543847061004141051682855031147214750129290918080 r = 1641550959518889204327060753293133298008071251322882615948833979994084362247932504494195196993273913632681730558092679835228121341433243540949243987915147127849677136846882565338958226278649038823205104414044774715949933967582465105018476900904220193700402953822673097109499902642615543847061004141051682855031147214750129290918084 t = 1714591024571289765034361255424594471911146425175316747999600736043131001671162537597658924124232553096177195992917086193888676229220158251370110767248247595500193148598359476602370638082754919433992991681389215815122070005167052535264288005381
# flag_approx = (bound+t*n)//((l+r)//2) # print(long_to_bytes(flag_approx)) # old_l, old_r, old_t = l,r, t # l=1<<1285 # r=1<<1286 # def check2(a): # # true if (a*flag-t*n)<2^(8*223) # c = pow(a,e,n)*enc%n # ret = len(oracle(c))<272 # # assert ((a*bytes_to_long(flag)%n)<bound) == ret # # assert ((a*bytes_to_long(flag)-t*n)<bound) == ret # return ret # while r-l>=5: # t = ((l+r)//2)*flag_approx//n # print((r-l).bit_length(),l,r) # m=(l+r)//2 # print(long_to_bytes((bound+t*n)//m)) # if check2(m): # l=m # else: # r=m # for i in range(l,r): # print(long_to_bytes((bound+t*n)//i)) # print(f'{l = }') # print(f'{r = }') # print(f'{t = }') # actf{the_letters_in_rsa_and_aes_form_aries_if_you_throw_in_the_letter_i_because_that_represents_yourself_or_something_anyway_aries_is_a_zodiac_sign_which_means_ l = 666107660458521541243215380951301474471376783825069107540423190425830915819095059072783324270868747829914983293073984498648548239892701754120954022763348528827144288600910102150524277984534841259233362446572662579749754548735798085478723700878977275859193617117626584040997931893710659862766269044625821599440962995816206934851402878867308816484181672266848496485789052244938919564218556 r = 666107660458521541243215380951301474471376783825069107540423190425830915819095059072783324270868747829914983293073984498648548239892701754120954022763348528827144288600910102150524277984534841259233362446572662579749754548735798085478723700878977275859193617117626584040997931893710659862766269044625821599440962995816206934851402878867308816484181672266848496485789052244938919564218560 t = 695745818548997146031596961508412710479974796693483588149882908704652154192883781979725829302780831947777349792683773656501063892778546886016728210171523148041289029707894329352734942032856303222697711791538372881954963927888035144482697872123563845558079741796255149413779106085785919654526962152479
# flag_approx = (bound+t*n)//((l+r)//2) # print(long_to_bytes(flag_approx)) # old_l, old_r, old_t = l,r, t # l = 1<<1483 # r = 1<<1484 # def check2(a): # # true if (a*flag-t*n)<2^(8*223) # c = pow(a,e,n)*enc%n # ret = len(oracle(c))<272 # # assert ((a*bytes_to_long(flag)%n)<bound) == ret # # assert ((a*bytes_to_long(flag)-t*n)<bound) == ret # return ret # while r-l>=5: # t = ((l+r)//2)*flag_approx//n # print((r-l).bit_length(),l,r) # m=(l+r)//2 # print(long_to_bytes((bound+t*n)//m)) # if check2(m): # l=m # else: # r=m # for i in range(l,r): # print(long_to_bytes((bound+t*n)//i)) # print(f'{l = }') # print(f'{r = }') # print(f'{t = }') # actf{the_letters_in_rsa_and_aes_form_aries_if_you_throw_in_the_letter_i_because_that_represents_yourself_or_something_anyway_aries_is_a_zodiac_sign_which_means_that_the_two_cryptosystem l = 267598435290787038785000518495795120189849974672934179871183761785819731525904252652413031666450265973305896047938823832697254554301986387284630118698155981810683872110970285526174947445552543232243974184723958049427881810663230582200255812436177259804355666659724978056721027294663099056249229465532402729717101567493772041449273109906137898884048531080358329322204154324632623223688183898761232674157828198036000046114160288830071154212772171004 r = 267598435290787038785000518495795120189849974672934179871183761785819731525904252652413031666450265973305896047938823832697254554301986387284630118698155981810683872110970285526174947445552543232243974184723958049427881810663230582200255812436177259804355666659724978056721027294663099056249229465532402729717101567493772041449273109906137898884048531080358329322204154324632623223688183898761232674157828198036000046114160288830071154212772171008 t = 279505106240123948314692378726509954547271822804357682452053593873927350472230939979456465118962227769441882090514511424351871563696988439390086360047718062578852779448454190663619562767700670755823394892188031298541165717859458230518462852962028646241370589564316273908127650239233769370282485093186817517870805516498704392695546184367558461283956438479400269
# flag_approx = (bound+t*n)//((l+r)//2) # print(long_to_bytes(flag_approx)) # old_l, old_r, old_t = l,r, t # l = 37627211912131687436880096876625049684468713732826036184018796780027148519869517942380374884047967048529738110102006623977571758627661600240209535896478099139294943940878294104947956966484015477951993823825938355432089671303813860801233153000276564710210040974091374642782381797237017228192690672034305536770456175912978554765853141809394223146030540577361882758257024263795290797461531379807476170514773878546706221800506607390255108719046874067517161347352491642359527544712521974723367428591189 # r = 1<<1650 # def check2(a): # # true if (a*flag-t*n)<2^(8*223) # c = pow(a,e,n)*enc%n # ret = len(oracle(c))<272 # # assert ((a*bytes_to_long(flag)%n)<bound) == ret # # assert ((a*bytes_to_long(flag)-t*n)<bound) == ret # return ret # while r-l>=5: # t = ((l+r)//2)*flag_approx//n # print((r-l).bit_length(),l,r) # m=(l+r)//2 # print(long_to_bytes((bound+t*n)//m)) # if check2(m): # l=m # else: # r=m # for i in range(l,r): # print(long_to_bytes((bound+t*n)//i)) # print(f'{l = }') # print(f'{r = }') # print(f'{t = }') # actf{the_letters_in_rsa_and_aes_form_aries_if_you_throw_in_the_letter_i_because_that_represents_yourself_or_something_anyway_aries_is_a_zodiac_sign_which_means_that_the_two_cryptosystems_are_mutually_compat l = 37627211912131687436880096876625049684468713732826036184018796780027148519869517942380374884047967048529738110102006623977571758627661600240210045683337130273185646423098679641576284718479986845914702724858502608406366221216399640190136769973825389380224750350410931391235696995751369134377248114592949267795163878364566636274103396943436516316606805635839776350312421759557164899000598078446570536486167268596290795596315472605141980079921097275480182920985271706716386979011369171224402535501425 r = 37627211912131687436880096876625049684468713732826036184018796780027148519869517942380374884047967048529738110102006623977571758627661600240210045683337130273185646423098679641576284718479986845914702724858502608406366221216399640190136769973825389380224750350410931391235696995751369134377248114592949267795163878364566636274103396943436516316606805635839776350312421759557164899000598078446570536486167268596290795596315472605141980079921097275480182920985271706716386979011369171224402535501429 t = 39301417631951703372894850038833823442285039026377811974765973372540562221465166236770753926271406427128064125853191238244457659724408756343102758233753469109598056133902659979888314998168416185052894160029440609089834407012611374547011641438400179447567523126310861827755103897257481528119680930686087174050522529534408569889254230417736847110349538456361530915392910677954130362896077098818312412305374553912
flag_approx = (bound + t * n) // ((l + r) // 2) print(long_to_bytes(flag_approx)) old_l, old_r, old_t = l, r, t l = 29808651182044202395161526438638499250467356820897103531466031080260466160601883954693978944153326581783908053680903595797444054912456745352533173167065465127079388979022228255354226131333720370147445313147194503816092984939561291128584036208838516222101490903987863746756463864580139223725509855111940761693194501219827742441025311558982608754381223637395316591827489626870115876892571490203325886163175102100856225880104171923577478616732083534202578515203236185114385838437398198094825347721266244693242373000953079413142535344107394366253873704069 r = 1 << 1829
defcheck2(a): # true if (a*flag-t*n)<2^(8*223) c = pow(a, e, n) * enc % n ret = len(oracle(c)) < 272 # assert ((a*bytes_to_long(flag)%n)<bound) == ret # assert ((a*bytes_to_long(flag)-t*n)<bound) == ret return ret
while r - l >= 5: t = ((l + r) // 2) * flag_approx // n print((r - l).bit_length(), l, r) m = (l + r) // 2 print(long_to_bytes((bound + t * n) // m)) if check2(m): l = m else: r = m for i inrange(l, r): print(long_to_bytes((bound + t * n) // i)) print(f"{l = }") print(f"{r = }") print(f"{t = }") # actf{the_letters_in_rsa_and_aes_form_aries_if_you_throw_in_the_letter_i_because_that_represents_yourself_or_something_anyway_aries_is_a_zodiac_sign_which_means_that_the_two_cryptosystems_are_mutually_compatble_i_think??} l = 29808651182044202395161526438638499250467356820897103531466031080260783293606069621827836156023219505031710214972591154711778724939067129078710617176460493666413542664493500557305544946799944222030130240871659822347851065661225370784228758147361629860146897117123496676822166885856619806201561733366867191494545671933761987571558156959049338056122848543586209411166987777284805523034512605321989508974682785326098985409612370630249252664835995069056301180003198475442771626340450638944750614623717983490400570960186063590346158522905988477341410194303 r = 29808651182044202395161526438638499250467356820897103531466031080260783293606069621827836156023219505031710214972591154711778724939067129078710617176460493666413542664493500557305544946799944222030130240871659822347851065661225370784228758147361629860146897117123496676822166885856619806201561733366867191494545671933761987571558156959049338056122848543586209411166987777284805523034512605321989508974682785326098985409612370630249252664835995069056301180003198475442771626340450638944750614623717983490400570960186063590346158522905988477341410194306 t = 31134973590030204511543097623588600229937365385836644522874327062576751468365379230629613557610735762428591993992911414874152831780705308218764828836582235263164478058266177542766364541592854102122398394352597371052054914660910742101741376154393006897145863520270550999839248820825693725475425474569621353403864176434140151517198771682069231414945158723762019615563223885222568539026325966427318379966491800642867958894619869388328023617980136998935939463245795948
from pwn import * import ast from Crypto.Util.number import long_to_bytes from subprocess import check_output
# context.log_level = 'debug'
n = 0xBB7BBD6BB62E0CBBC776F9CEB974ECA6F3D30295D31CAF456D9BEC9B98822DE3CB941D3A40A0FBA531212F338E7677EB2E3AC05FF28629F248D0BC9F98950CE7E5E637C9764BB7F0B53C2532F3CE47ECBE1205172F8644F28F039CAE6F127CCF1137AC88D77605782ABE4560AE3473D9FB93886625A6CAA7F3A5180836F460C98BBC60DF911637FA3F52556FA12A376E3F5F87B5956B705E4E42A30CA38C79E7CD94C9B53A7B4344F2E9DE06057DA350F3CD9BD84F9AF28E137E5190CBE90F046F74CE22F4CD747A1CC9812A1E057B97DE39F664AB045700C40C9CE16CF1742D992C99E3537663EDE6673F53FBB2F3C28679FB747AB9DB9753E692ED353E3551 e = 0x10001 c = 8702343735025266604493255023455944506448203943421139140860292426782509680048873569587596911548140388664137318807031840409098358526949080521742044811655775937519290500584015066858945832554481838588845652546365303337275177311841968984511864709414904338587040274646253896911291865516895328016639201704613064462056129248165695806001948541939983934752397658730589917722952341689278968790138018539025744727334202968601465562656795710345742329370762196560147624069504644216320910078454455520823319751612174752365432199529820974601209221975964155055716974539394252799602068585830290371624396504384131654854623710049511046664 io = remote("challs.actf.co", 31500) # POW were added after I solved it the first way io.recvuntil(b'proof of work: ') out = check_output(io.recvlineS(),shell=True).strip() io.sendlineafter(b'solution: ', out)
defManger_Attack(c): f1 = 2 whileTrue: val = (pow(f1, e, n) * c) % n if oracle(val): f1 = 2 * f1 else: break print('first') f12 = f1 // 2 f2 = ((n + B) // B) * f12 whileTrue: val = (pow(f2, e, n) * c) % n if oracle(val): break else: f2 += f12 print('second') m_min = (n + f2 - 1) // f2 m_max = (n + B) // f2 # note the ERRATA from https://github.com/GDSSecurity/mangers-oracle while m_min < m_max: print(long_to_bytes(m_min)) f_tmp = (2 * B) // (m_max - m_min) I = (f_tmp * m_min) // n f3 = (I * n + m_min - 1) // m_min val = (pow(f3, e, n) * c) % n if oracle(val): m_max = (I * n + B) // f3 else: m_min = (I * n + B + f3 - 1) // f3 return m_min
defbuild_payload(writes: dict, written=0) -> bytes: ws = sorted(writes.items(), key=lambda t: t[1]) s = "" for offset, val in ws: assert val - written >= 0, "wtf" s += f"%{val - written}c" t = "hhn"if val - written < 256else"hn" s += f"%{offset}${t}" written += val - written return s.encode()
lepickle = bytes.fromhex(input("Enter hex-encoded pickle: ")) iflen(lepickle) > 400: print("your pickle is too large for my taste >:(") else: SafeUnpickler(io.BytesIO(lepickle)).load()
interface.question( "Welcome to CaaSio: Please Stop Edition! Enter your calculation:\n", function (input) { interface.close(); if ( input.length < 215 && /^[\x20-\x7e]+$/.test(input) && !/[.\[\]{}\s;`'"\\_<>?:]/.test(input) && !input.toLowerCase().includes("import") ) { try { const val = vm.runInNewContext(input, {}); console.log("Result:"); console.log(val); console.log( "See, isn't the calculator so much nicer when you're not trying to hack it?" ); } catch (e) { console.log("your tried"); } } else { console.log( "Third time really is the charm! I've finally created an unhackable system!" ); } } );
這題是 node.js 的 vm escape 加上繞 regex filter
的題目,vm escape 部分很好處理,就直接利用 {} 拿 foreign 的
Function 去拿 process 解決: