AlexCTFに参加。990ptで259位。
TR1: Hello there (Trivia 10)
IRCのチャンネル名にフラグがある。
IRC: #alexctf @freenode
#alexctf: Alexandria University student held capture the flag event ctf.oddcoder.com ALEXCTF{W3_w15h_y0u_g00d_luck}
TR2: SSL 0day (Trivia 20)
It lead to memory leakage between servers and clients rending large number of private keys accessible. (one word)
heartbleed
TR3: CA (Trivia 30)
What is the CA that issued Alexctf https certificate (flag is lowercase with no spaces)
letsencrypt
TR4: Doesn’t our logo look cool ? (Trivia 40)
トップページにあるアスキーアートのロゴの中にある。
$ grep -oP '[\w{}]' logo.txt | tr -d '\n'
ALEXCTF{0UR_L0G0_R0CKS}
RE1: Gifted (Reversing 50)
stringsするとフラグがある。
$ strings gifted
(snip)
Enter the flag:
AlexCTF{Y0u_h4v3_45t0n15h1ng_futur3_1n_r3v3r5ing}
You got it right dude!
Try harder!
(snip)
RE2: C++ is awesome (Reversing 100)
特定のアドレスで動作を止めてメモリに入っているデータを見ると、文字列と数字の配列がある。
$ gdb --args ./re2 AAAA
Reading symbols from ./re2...(no debugging symbols found)...done.
(gdb) b *0x400c24
Breakpoint 1 at 0x400c24
(gdb) r
Starting program: /tmp/re2 AAAA
Breakpoint 1, 0x0000000000400c24 in ?? ()
1: x/i $pc
=> 0x400c24: lea rax,[rbp-0x50]
(gdb) x/80i $pc
=> 0x400c24: lea rax,[rbp-0x50]
0x400c28: mov rdi,rax
0x400c2b: call 0x4009f0 <std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::end()@plt>
0x400c30: mov QWORD PTR [rbp-0x20],rax
0x400c34: lea rdx,[rbp-0x20]
0x400c38: lea rax,[rbp-0x60]
0x400c3c: mov rsi,rdx
0x400c3f: mov rdi,rax
0x400c42: call 0x400d3d
0x400c47: test al,al
0x400c49: je 0x400c95
0x400c4b: lea rax,[rbp-0x60]
0x400c4f: mov rdi,rax
0x400c52: call 0x400d9a
0x400c57: movzx edx,BYTE PTR [rax]
0x400c5a: mov rcx,QWORD PTR [rip+0x20143f] # 0x6020a0
0x400c61: mov eax,DWORD PTR [rbp-0x14]
0x400c64: cdqe
0x400c66: mov eax,DWORD PTR [rax*4+0x6020c0]
0x400c6d: cdqe
(snip)
(gdb) x/s {long}0x6020a0
0x400e58: "L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A_{FL4G}_W0nt_b3_3X4ctly_th4t_345y_t0_c4ptur3_H0wev3r_1T_w1ll_b3_C00l_1F_Y0u_g0t_1t"
(gdb) x/80wx 0x6020c0
0x6020c0: 0x00000024 0x00000000 0x00000005 0x00000036
0x6020d0: 0x00000065 0x00000007 0x00000027 0x00000026
0x6020e0: 0x0000002d 0x00000001 0x00000003 0x00000000
0x6020f0: 0x0000000d 0x00000056 0x00000001 0x00000003
0x602100: 0x00000065 0x00000003 0x0000002d 0x00000016
0x602110: 0x00000002 0x00000015 0x00000003 0x00000065
0x602120: 0x00000000 0x00000029 0x00000044 0x00000044
0x602130: 0x00000001 0x00000044 0x0000002b 0x00000000
0x602140 <std::cout>: 0xf7dce988 0x00007fff 0xf7dce9b0 0x00007fff
(snip)
(gdb) q
A debugging session is active.
Inferior 1 [process 11607] will be killed.
Quit anyway? (y or n) y
数字の配列の順で文字列から文字を取り出すとフラグが得られる。
msg = "L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A_{FL4G}_W0nt_b3_3X4ctly_th4t_345y_t0_c4ptur3_H0wev3r_1T_w1ll_b3_C00l_1F_Y0u_g0t_1t"
ary = [0x24, 0x0, 0x5, 0x36, 0x65, 0x7, 0x27, 0x26, 0x2d, 0x1, 0x3, 0x0, 0xd, 0x56, 0x1, 0x3, 0x65, 0x3, 0x2d, 0x16, 0x2, 0x15, 0x3, 0x65, 0x0, 0x29, 0x44, 0x44, 0x1, 0x44, 0x2b, 0x0]
s = ''
for i in ary:
s += msg[i]
print s
$ python test.py
ALEXCTF{W3_L0v3_C_W1th_CL45535}L
RE4: unVM me (Reversing 250)
「HITCON CTF 2016 Quals 供養(Writeup)」で使ったshow_file.pyでディスアセンブルすると、5文字ごとに特定のmd5ハッシュ値と一致しているかを見ていることがわかる。
2 12 LOAD_CONST 2 (174282896860968005525213562254350376167L)
15 LOAD_CONST 3 (137092044126081477479435678296496849608L)
18 LOAD_CONST 4 (126300127609096051658061491018211963916L)
21 LOAD_CONST 5 (314989972419727999226545215739316729360L)
24 LOAD_CONST 6 (256525866025901597224592941642385934114L)
27 LOAD_CONST 7 (115141138810151571209618282728408211053L)
30 LOAD_CONST 8 (8705973470942652577929336993839061582L)
33 LOAD_CONST 9 (256697681645515528548061291580728800189L)
36 LOAD_CONST 10 (39818552652170274340851144295913091599L)
39 LOAD_CONST 11 (65313561977812018046200997898904313350L)
42 LOAD_CONST 12 (230909080238053318105407334248228870753L)
45 LOAD_CONST 13 (196125799557195268866757688147870815374L)
48 LOAD_CONST 14 (74874145132345503095307276614727915885L)
51 BUILD_LIST 13
54 STORE_NAME 1 (md5s)
(snip)
12 >> 144 SETUP_LOOP 112 (to 259)
147 LOAD_NAME 6 (range)
150 LOAD_CONST 20 (0)
153 LOAD_NAME 4 (len)
156 LOAD_NAME 3 (flag)
159 CALL_FUNCTION 1
162 LOAD_CONST 19 (5)
165 CALL_FUNCTION 3
168 GET_ITER
>> 169 FOR_ITER 86 (to 258)
172 STORE_NAME 7 (i)
13 175 LOAD_NAME 3 (flag)
178 LOAD_NAME 7 (i)
181 LOAD_NAME 7 (i)
184 LOAD_CONST 19 (5)
187 BINARY_ADD
188 SLICE+3
189 STORE_NAME 8 (s)
14 192 LOAD_NAME 9 (int)
195 LOAD_CONST 21 ('0x')
198 LOAD_NAME 0 (md5)
201 LOAD_ATTR 10 (new)
204 LOAD_NAME 8 (s)
207 CALL_FUNCTION 1
210 LOAD_ATTR 11 (hexdigest)
213 CALL_FUNCTION 0
216 BINARY_ADD
217 LOAD_CONST 22 (16)
220 CALL_FUNCTION 2
223 LOAD_NAME 1 (md5s)
226 LOAD_NAME 7 (i)
229 LOAD_CONST 19 (5)
232 BINARY_DIVIDE
233 BINARY_SUBSCR
234 COMPARE_OP 3 (!=)
237 POP_JUMP_IF_FALSE 169
文字種をいろいろ変えながらブルートフォースすると元の文字列が求まる。
from itertools import product
from hashlib import md5
hashes = [
(174282896860968005525213562254350376167L), # md5('ALEXC')
(137092044126081477479435678296496849608L), # md5('TF{dv')
(126300127609096051658061491018211963916L), # md5('5d4s2')
(314989972419727999226545215739316729360L), # md5('vj8nk')
(256525866025901597224592941642385934114L), # md5('43s8d')
(115141138810151571209618282728408211053L), # md5('8l6m1')
(8705973470942652577929336993839061582L), # md5('n5l67')
(256697681645515528548061291580728800189L), # md5('ds9v4')
(39818552652170274340851144295913091599L), # md5('1n52n')
(65313561977812018046200997898904313350L), # md5('v37j4')
(230909080238053318105407334248228870753L), # md5('81h3d')
(196125799557195268866757688147870815374L), # md5('28n4b')
(74874145132345503095307276614727915885L) # md5('6v3k}')
]
"""
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
for t in product(chars, repeat=5):
x = ''.join(t)
h = md5(x).hexdigest()
h = int(h, 16)
if h in hashes:
print "%d == md5(%r)" % (h, x)
"""
"""
chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
for t in product(chars, repeat=2):
x = 'TF{' + ''.join(t)
h = md5(x).hexdigest()
h = int(h, 16)
if h in hashes:
print "%d == md5(%r)" % (h, x)
"""
"""
chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
for t in product(chars, repeat=5):
x = ''.join(t)
h = md5(x).hexdigest()
h = int(h, 16)
if h in hashes:
print "%d == md5(%r)" % (h, x)
"""
chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
for t in product(chars, repeat=4):
x = ''.join(t) + '}'
h = md5(x).hexdigest()
h = int(h, 16)
if h in hashes:
print "%d == md5(%r)" % (h, x)
# ALEXCTF{dv5d4s2vj8nk43s8d8l6m1n5l67ds9v41n52nv37j481h3d28n4b6v3k}
CR1: Ultracoded (Cryptography 50)
与えられたテキストを適当に変換すると、モールス信号を表す文字列が得られる。
data = open('zero_one').read()
s = ''
for x in data.split():
if x == 'ZERO':
s += '0'
else:
s += '1'
s = "%x" % int(s, 2)
s = s.decode('hex')
s = s.decode('base64')
print s
$ python test.py .- .-.. . -..- -.-. - ..-. - .... .---- ..... --- .---- ... --- ..... ..- .--. ...-- .-. --- ..... . -.-. .-. ...-- - --- - -..- -
Morse Code Translator等で復号した文字列を適当に変換するとフラグが得られる。
ALEXCTFTH15O1SO5UP3RO5ECR3TOTXT
ALEXCTF{TH15_1S_5UP3R_5ECR3T_TXT}
CR3: What is this encryption? (Cryptography 150)
「OpenSSLとPythonでRSA暗号の原理を知る」と同様に、RSAの復号を行うだけ。
p=0xa6055ec186de51800ddd6fcbf0192384ff42d707a55f57af4fcfb0d1dc7bd97055e8275cd4b78ec63c5d592f567c66393a061324aa2e6a8d8fc2a910cbee1ed9
q=0xfa0f9463ea0a93b929c099320d31c277e0b0dbc65b189ed76124f5a1218f5d91fd0102a4c8de11f28be5e4d0ae91ab319f4537e97ed74bc663e972a4a9119307
e=0x6d1fdab4ce3217b3fc32c9ed480a31d067fd57d93a9ab52b472dc393ab7852fbcb11abbebfd6aaae8032db1316dc22d3f7c3d631e24df13ef23d3b381a1c3e04abcc745d402ee3a031ac2718fae63b240837b4f657f29ca4702da9af22a3a019d68904a969ddb01bcf941df70af042f4fae5cbeb9c2151b324f387e525094c41
c=0x7fe1a4f743675d1987d25d38111fae0f78bbea6852cba5beda47db76d119a3efe24cb04b9449f53becd43b0b46e269826a983f832abb53b7a7e24a43ad15378344ed5c20f51e268186d24c76050c1e73647523bd5f91d9b6ad3e86bbf9126588b1dee21e6997372e36c3e74284734748891829665086e0dc523ed23c386bb520
def egcd(a, b):
x,y, u,v = 0,1, 1,0
while a != 0:
q,r = b//a,b%a; m,n = x-u*q,y-v*q
b,a, x,y, u,v = a,r, u,v, m,n
return b, x, y
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
return None # modular inverse does not exist
else:
return x % m
d = modinv(e, (p-1)*(q-1))
m = pow(c, d, p*q)
m = "%x" % m
print m.decode('hex')
$ python test.py
ALEXCTF{RS4_I5_E55ENT1AL_T0_D0_BY_H4ND}
Fore1: Hit the core (Forensics 50)
stringsすると長い文字列が見つかる。
$ strings fore1.core
(snip)
cvqAeqacLtqazEigwiXobxrCrtuiTzahfFreqc{bnjrKwgk83kgd43j85ePgb_e_rwqr7fvbmHjklo3tews_hmkogooyf0vbnk0ii87Drfgh_n kiwutfb0ghk9ro987k5tfb_hjiouo087ptfcv}
(snip)
フラグフォーマットをヒントに、一定間隔で文字を拾うとフラグが得られる。
s = 'cvqAeqacLtqazEigwiXobxrCrtuiTzahfFreqc{bnjrKwgk83kgd43j85ePgb_e_rwqr7fvbmHjklo3tews_hmkogooyf0vbnk0ii87Drfgh_n kiwutfb0ghk9ro987k5tfb_hjiouo087ptfcv}'
print s[3::5]
$ python test.py
ALEXCTF{K33P_7H3_g00D_w0rk_up}
Fore3: USB probing (Forensics 150)
USBのパケットキャプチャファイルが与えられる。 サイズの大きなパケットを探すと、101番のパケットでPNGファイルが転送されているのが見つかる。

ALEXCTF{SN1FF_TH3_FL4G_0V3R_U58}
SC1: Math bot (Scripting 100)
与えられる数式を計算するだけ。evalを使うのは危険だが適当にやってしまった。
from minipwn import *
s = socket.create_connection(('195.154.53.62', 1337))
for i in xrange(500):
print recvuntil(s, ':\n')
x = recvline(s)
print x
y = eval(x[:-2])
sendline(s, str(y))
interact(s)
$ python test.py
__________
______/ ________ \______
_/ ____________ \_
_/____________ ____________\_
/ ___________ \ / ___________ \
/ /XXXXXXXXXXX\ \/ /XXXXXXXXXXX\ \
/ /############/ \############\ \
| \XXXXXXXXXXX/ _ _ \XXXXXXXXXXX/ |
__|\_____ ___ // \\ ___ _____/|__
[_ \ \ X X / / _]
__| \ \ / / |__
[____ \ \ \ ____________ / / / ____]
\ \ \ \/||.||.||.||.||\/ / / /
\_ \ \ ||.||.||.||.|| / / _/
\ \ ||.||.||.||.|| / /
\_ ||_||_||_||_|| _/
\ ........ /
\________________/
Our system system has detected human traffic from your IP!
Please prove you are a bot
Question 1 :
51592980733851622235329877819524 % 81337315219774907248751097819108 =
Question 2 :
222530311273284491939188931042597 * 5582384329582694587240599887190 =
(snip)
Question 500 :
223942165497608593390730286109841 - 285025587991694605246774446376485 =
Well no human got time to solve 500 ridiculous math challenges
Congrats MR bot!
Tell your human operator flag is: ALEXCTF{1_4M_l33t_b0t}
*** Connection closed by remote host ***
所感
解けなかった問題は以下。
- RE3: Catalyst system (Reversing 150)
- RE5: packed movement (Reversing 350)
- CR2: Many time secrets (Cryptography 100)
- CR4: Poor RSA (Cryptography 200)
- CR5: Bring weakness (Cryptography 300)
- Fore2: Mail client (Forensics 100)
- Fore4: Unknown format (Forensics 200)
- SC2: Cutie cat (Scripting 150)