SECCON2016 京都大会 「サイバー甲子園」 に参加したよ

サイバー甲子園とは・・・http://2016.seccon.jp/news/#121

18才、高校生以下の学生を対象としたCTF大会です。 クイズ形式(Jeopardy)によるセキュリティやITの技術を競うCTFで、 出題予定のジャンルはWeb、バイナリ、ネットワーク、暗号など。 さまざまなジャンルのさまざまな難易度の問題に挑戦していただき、総得点を競います。

前使ってたLet's noteが液晶の不具合かで、画面がずっと暗いままっだったので、新しいパソコンを買ってもらいました!

これからが大変だった・・・

届いてすぐブルースクリーンになり・・・

挙句には

エクスプローラーとかが起動しなくなっt・・・

辛かった・・・

なんとかドライバ関係を解決しようと奮闘し、気づいたら3時・・・

相方のsnowと駅に8時半に待ち合わせしてたのだが・・・

f:id:akashisn:20181027124603p:plain

ごめんなさい!!!

電車の時間は余裕を持ってて、良かった・・・

京都は新幹線で通過するぐらいだから実質初めて来た

お昼はマックで食べたのだが、注文時、

・・・うん、とにかく会場につくと、

机に本がおいてあった(ありがとうございます!)

でも、CTF forビギナーズ 2016博多で3位になって貰ったんだった・・・

(あとでスタッフで美味しくいただきました)

結構奮闘して結果4位でした・・・

@Yukiくんすぐに煽るのはやめよう

WriteUp

競技中に解けたり解けなかったりの問題のWriteUp

[Sample-10pt] TRY FIRST

Question

これは練習問題です。
各問題には下記の形式のフラグがありますのでそれを入力してください。
SECCON{xxxxxx}

この問題のフラグは SECCON{Cyber_Koshien}

Answer

書いてあるのを提出するだけ

SECCON{Cyber_Koshien}

[Binary-100pt] sl is not ls

Question

slコマンドに秘められた謎を解け!

sl.zip

Answer

まず解凍

$ unzip sl.zip
Archive:  sl.zip
  inflating: sl

とにかくfileコマンド

$ file sl
sl: ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

実行してみうよう!

$ ./sl
bash: ./sl: cannot execute binary file: 実行形式エラー

は?

Bash on Windowsではだめなんかな?

あとでKaliLinuxで実行してみた

$ ./sl
bash: ./sl: そのようなファイルやディレクトリはありません

はい、32ビットのライブラリを入れよう!

$ sudo apt-get install lib32z1
$ ./sl
Error opening terminal: xterm-256color.
$ TERM='xterm-color' ./sl

これで実行できた

stringsコマンド

strings.txt

Try `./sl [-h] [OPTIONS]' for more information.
                OPTIONS: -[%s%c]
____________________ 
|  ___ ___ ___ ___ | 
|  |_| |_| |_| |_| | 
|__________________| 
   (O)        (O)    

____                 
|   \@@@@@@@@@@@     
|    \@@@@@@@@@@@@@_ 
|                  | 
   (O)       (O)     
     ++      +------ 
     ||      |+-+ |  
   /---------|| | |  
  + ========  +-+ |  
 _|--O========O~\-+  
//// \_/      \_/    
 _|--/O========O\-+  
 _|--/~O========O-+  
 _|--/~\------/~\-+  
//// \_O========O    
//// \O========O/    
//// O========O_/    

    _________________         
   _|                \_____A  
 =|                        |  
 -|                        |  
__|________________________|_ 
|__________________________|_ 
   |_D__D__D_|  |_D__D__D_|   
    \_/   \_/    \_/   \_/    
      ====        ________                ___________ 
  _D _|  |_______/        \__I_I_____===__|_________| 
   |(_)---  |   H\________/ |   |        =|___ ___|   
   /     |  |   H  |  |     |   |         ||_| |_||   
  |      |  |   H  |__--------------------| [___] |   
  | ________|___H__/__|_____/[][]~\_______|       |   
  |/ |   |-----------I_____I [][] []  D   |=======|__ 
__/ =| o |=-~~\  /~~\  /~~\  /~~\ ____Y___________|__ 
 |/-=|___|=    ||    ||    ||    |_____/~\___/        
  \_/      \O=====O=====O=====O_/      \_/            

 |/-=|___|=O=====O=====O=====O   |_____/~\___/        
  \_/      \__/  \__/  \__/  \__/      \_/            
__/ =| o |=-O=====O=====O=====O \ ____Y___________|__ 
__/ =| o |=-~O=====O=====O=====O\ ____Y___________|__ 
 |/-=|___|=   O=====O=====O=====O|_____/~\___/        
  \_/      \_O=====O=====O=====O/      \_/            
Help!
,,,,
....
 SEC
CON{
F1aG}
CON{x1
SLm}
SECCON{S
SL_l
0v3}
1v3}
CON{dum
my?}

slだ~!

 SEC
CON{
F1aG}
CON{x1
SLm}
SECCON{S
SL_l
0v3}
1v3}
CON{dum
my?}

フラグっぽいけど、dummy?らしい

Try `./sl [-h] [OPTIONS]' for more information.
                OPTIONS: -[%s%c]

オプションがあるのか・・・

$ ./sl -h
Try `./sl [-h] [OPTIONS]' for more information.
                OPTIONS: -[alFS]
$ ./sl -S

でフラグが出てきた

SECCON{SL_l0v3}

[Binary-100pt] Assembler Tanka

Question

「アセンブラ短歌」は五・七・五・七・七の三十一バイト(みそひとバイト)から成る機械語コードでプログラムを書いてみるという近未来の文化的趣味であり,近年,国内のハッカー間で密かなブームが起きています.

問題:以下のアセンブラ短歌を実行せよ

68 37 35 37 37       # 5

68 4f 4e 7b 35 33 c9 # 7

68 53 45 43 43       # 5

ba f8 03 00 00 b1 0c # 7

89 e6 f3 6e b0 7d ee # 7

参考:ディスアセンブルの結果は以下の通り。

6837353737: push 0x37373537

684f4e7b35: push 0x357b4e4f

      33c9: xor ecx, ecx

6853454343: push 0x43434553

baf8030000: mov edx, 0x3f8

      b10c: mov cl, 0xc

      89e6: mov esi, esp

      f36e: rep outsb

      b07d: mov al, 0x7d

        ee: out dx, al

ヒント:実行環境がない場合は、JavaScriptでアセンブラ短歌の実行をエミュレートするサイトがあるので探してみましょう。

-- 以下,アセンブラ短歌のホームページより引用 --
アセンブラに関する知識はセキュリティの根本を理解する上で重要であり,セキュリティ教育の一貫としてアセンブラ学習が見直されています.しかしアセンブラ・リーディング/コーディングは空洞化してしまった技術分野でもあり,学習機会の不足や独学の困難さも問題視されています.このような状況の中,半分遊びの感覚で気軽にアセンブラを学習する方法として考え出されたのが「アセンブラ短歌」です.

アセンブラ短歌には, 31バイトの限られた機械語コードでプログラミングする,5・7・5・7・7の決められた位置で区切られるようにプログラミングする,決まったバイトパターンを(韻を踏むために)決まった位置に埋め込む,あえて特定の命令を使って(もしくは使わずに)プログラミングする,といった技術が必要になります.これらのことが,どのように役に立つのでしょうか?

攻撃から守るためには,まずはどのような攻撃があり得るのか,攻撃手法を理解することは避けて通れません.攻撃方法を知らなければ,防御はできません.

そしてバッファオーバーランの脆弱性攻撃によって送り込まれるいわゆる「シェルコード」には,被攻撃側のチェックを回避するために, NUL文字や空白文字を使わない機械語コードでプログラミングする,表示可能文字のみでプログラミングする,決められたサイズでプログラミングする,といった技法が使われます.

そのような攻撃から「守る」ためには,シェルコードの解析と理解が必要です.アセンブラ短歌を修得することはそのような解析技術や,対策を考えるための基礎知識に繋がるという目的があります.

Answer

アセンブラ短歌の実行できるサイトがあるそうなので、やってみる

http://07c00.com/asmtanka_on_js/

やってみた

img

できた

SECCON{57577}

[Binary-300pt] fakeransom

Question

お願い助けて!!私の大事なファイルが暗号化されてしまったの!

binary300.zip

Answer

[Binary-200pt] guess the flag

Question

コマンドを実行し、フラグ文字列を当ててください。

フラグ文字列は SECCON{ で始まりますよ。

guessflag.zip

Answer

$ strings -e L guessflag
SECCON{Piece of cake!?}

stringsすごすぎ

SECCON{Piece of cake!?}

[Crypto-100pt] gokai?

Question

以下の文字列を頑張ってデコードしてみよう。
Vm14U1ExWXhTa2RTV0dSUVZsUnNjMVJWVm5kUk1WcFZVV3hhVG1GNlZrcFVWVkYzVUZFOVBRPT0=

Answer

5回Base64でデコードしてやる

q6.py

#!/usr/bin/env python

str = "Vm14U1ExWXhTa2RTV0dSUVZsUnNjMVJWVm5kUk1WcFZVV3hhVG1GNlZrcFVWVkYzVUZFOVBRPT0="

for i in range(5):
  str = str.decode("base64")
print(str)

これで出てくる

SECCON{BASE64}

[Crypto-100pt] very easy

Question

以下の文字列を解読してみよう。

53 45 43 43 4f 4e 7b 68 65 78 5f 64 75 6d 70 7d

Answer

asciiっぽいのでスクリプトをいい感じに書いてやる

q7.py

#!/usr/bin/env python

arr = ["53","45","43","43","4f","4e","7b","68","65","78","5f","64","75","6d","70","7d"]
flag = ""

for i in arr:
  flag += chr(int(i,16))
print(flag)
SECCON{hex_dump}

[Crypto-200pt] decode the flag

Question

フラグ文字列をopensslコマンドを使って暗号化したんだけど、暗号形式を忘れてしまいました。

openssl cipher で表示されるどれかだと思うんだけど・・・

パスワードは 53CC0NZOl6 です。

opensslcipher.zip

Answer

opensslコマンドで暗号化したそうなので、どんな暗号化方式が使えるのか調べてみる

$ openssl list-cipher-commands > crypto.txt

crypto.txt

aes-128-cbc
aes-128-ecb
aes-192-cbc
aes-192-ecb
aes-256-cbc
aes-256-ecb
base64
bf
bf-cbc
bf-cfb
bf-ecb
bf-ofb
camellia-128-cbc
camellia-128-ecb
camellia-192-cbc
camellia-192-ecb
camellia-256-cbc
camellia-256-ecb
cast
cast-cbc
cast5-cbc
cast5-cfb
cast5-ecb
cast5-ofb
des
des-cbc
des-cfb
des-ecb
des-ede
des-ede-cbc
des-ede-cfb
des-ede-ofb
des-ede3
des-ede3-cbc
des-ede3-cfb
des-ede3-ofb
des-ofb
des3
desx
rc2
rc2-40-cbc
rc2-64-cbc
rc2-cbc
rc2-cfb
rc2-ecb
rc2-ofb
rc4
rc4-40
seed
seed-cbc
seed-cfb
seed-ecb
seed-ofb

http://qiita.com/ikuwow/items/1cdb057352c06fd3d727

復号 パスワードを標準入力から取得する場合
$ openssl aes-256-cbc -d -in encrypted.txt -out decrypted.txt
enter aes-256-cbc decryption password: # パスワードを入力
パスワードをファイルから読み込む場合
$ openssl aes-256-cbc -d -in encrypted.txt -out decrypted.txt -pass file:./password.txt

なるほど・・・

ブルートフォースすればよさそう

q8.py

#!/usr/bin/env python
import commands,re

enc = open("crypto.txt","r")

for i in enc:
  cmd = "openssl {} -d -in flag.encrypted -pass file:./password.txt".format(i[:-1])
  out = commands.getoutput(cmd).split("\n")[0]  
  if out != "bad decrypt":
    if re.match("SECCON",out):
      print(out.split("\n")[0])
      print("Decrypted!")

実行したらフラグが出てくる

$ ./q8.py
SECCON{R U 4 0P3N55L M457ER?}
Decrypted!
SECCON{RDN��Q▼|��▲��2�n�� j�wY
Decrypted!
SECCON{R U 4 0P3N55L M457ER?}

[Crypto-100pt] onlineyosen

Question

online qualification will start at 10th Dec.

online.png

Answer

競技中は解けなかったけど解説のときの方法でやってみる

とにかくstrings

(一部抜粋)

SECCON
tEXtModel
onlineCTFFX
iTXtXML:com.adobe.xmp
<?xpacket begin='
' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 10.31'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
 <rdf:Description rdf:about=''
  xmlns:dc='http://purl.org/dc/elements/1.1/'>
  <dc:type>
   <rdf:Bag>
    <rdf:li>lsb</rdf:li>
   </rdf:Bag>
  </dc:type>
 </rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end='r'?>
IEND

なんだ・・・?

lsb?

LSBは十進数の1を指す。

最下位ビット(さいかいビット、least significant bit、LSBと略記)は、コンピュータにおいて二進数で最も小さな値を意味するビット位置のことである。

LSBは右端ビットとも言われる。 十進数に当てはめれば、「一の位」に相当する。

ぐぐってみた

https://www.google.co.jp/search?q=lsb+png

https://github.com/RobinDavid/LSB-Steganography

いい感じ!

LSBSteg.py

$ ./LSBSteg.py -h
Traceback (most recent call last):
  File "./LSBSteg.py", line 44, in <module>
    import cv2.cv as cv
ImportError: No module named cv2.cv

う~ん

opencvをインストールしないといけないのかな?

$ sudo apt-get install libopencv-dev
$ sudo apt-get install python-numpy
$ sudo apt-get install python-opencv
$ sudo ln /dev/null /dev/raw1394
$ ./LSBSteg.py -h
usage: LSBSteg.py [-h] [-image IMAGE] [-binary BINARY] [-steg-out STEG_OUT]
                  [-steg-image STEG_IMAGE] [-out OUT]

This python program applies LSB Steganography to an image and some type of
input

optional arguments:
  -h, --help            show this help message and exit

Hide binary with steg:
  -image IMAGE          Provide the original image
  -binary BINARY        The binary file to be obfuscated in the image
  -steg-out STEG_OUT    The resulting steganographic image

Reveal binary:
  -steg-image STEG_IMAGE
                        The steganographic image
  -out OUT              The original binary

できた!

実行してみよう!

$ ./LSBSteg.py -steg-image online.png -out output.bin

output.bin

0b101001101000101010000110100001101001111010011100111101101001000011010010110010001100101011100110110010101100011011100100110010101110100010010010110110100110100011001110011001101111101

2進数が出てくるのでこれをASCIIに変換してやると

q9.py

#!/usr/bin/env python

f = open("output.bin","rb")
Bin = f.read()
Hex = hex(int(Bin,2))
print(Hex)
$ ./q9.py
0x534543434f4e7b48696465736563726574496d3467337dL

文字まで変換したかったけど、16進数からどうやってASCIIに変換するんだ?

http://singoro.net/16henkan/

オンラインツールを使った

SECCON{HidesecretIm4g3}

[Network-100pt] gettheflag

Question

パケットのキャプチャファイルからフラグを見つけよ

gettheflag.pcap

Answer

APIにアクセスして、{"result":"success","data":{"char":"S","last":true}}のようなJSONデータを受信している

どうやらlasttrueになってるのがフラグだな~

これは$ strings gettheflag.pcap |grep trueすればフラグが出てくるそうだが、競技中はスクリプトを書いてフラグを取った(strings氏~)

ファイルをNetworkMinerでエキスポートしてスクリプトを実行した

q10.py

#!/usr/bin/env python

import json

flag = ""
file = open("export/flag.php.json","rb")
data = file.read().decode("utf-8")
json_data = json.loads(data)
flag += json_data["data"]["char"]

for i in range(1,132):
  file = open("export/flag.php["+str(i)+"].json","rb")
  data = file.read().decode("utf-8")
  json_data = json.loads(data)
  if json_data["data"]["last"] == True:
    flag += json_data["data"]["char"]
print(flag)

実行するとフラグが出てくる

$ ./q10.py
SECCON{42LbAwGV}
SECCON{42LbAwGV}

[Network-200pt] sample

Question

sample.pcap

Answer

これも競技中は解けなかったもの

requestに注目してみると

img

Ping標準のTTLの長さの64でも128でもないので、なんか怪しい・・・

並べてみた

[61,61,61,80,66,64,64,76,75,120,77,102,107,100,70,112,75,108,68,108,108,97,122]

なんかASCIIコードっぽいな~

スクリプト書いてみよう

#!/usr/bin/env python
arr = [61,61,61,80,66,64,64,76,75,120,77,102,107,100,70,112,75,108,68,108,108,97,122]
string = ""
for i in arr:
  string += chr(i)
print(string)
$ ./q11.py
===PB@@LKxMfkdFpKlDllaz

なんか違いそう・・・

う~んずらしたりするのかな?

q11.py

#!/usr/bin/env python
import sys

arr = [61,61,61,80,66,64,64,76,75,120,77,102,107,100,70,112,75,108,68,108,108,97,122]
for i in range(-61,61):
  string =""
  for ch in arr:
    string += chr(ch+i)
  if "SECCON" in string:
    print(string)
    sys.exit()
$ ./q11.py
@@@SECCON{PingIsNoGood}

あった!!

SECCON{PingIsNoGood}

[Network-200pt] get the flag

Question

ftp.zip

Answer

220 (vsFTPd 3.0.3)
USER seccon2016
331 Please specify the password.
PASS kyoto=butiful
530 Login incorrect.
SYST
530 Please login with USER and PASS.
USER seccon2016
331 Please specify the password.
PASS kyoto=beautiful
230 Login successful.
SYST
215 UNIX Type: L8
PORT 10,100,4,123,174,34
200 PORT command successful. Consider using PASV.
LIST
150 Here comes the directory listing.
226 Directory send OK.
QUIT
221 Goodbye.

こんな感じでFTPは平文でパスワードが流れる・・・

実際に、FTPでアクセスしてログインする

-r--r--r--    1 0        0            2264 Nov 08 20:44 flag.zip

とのことなので、

flag.zipをダウンロードする

flag.png

SECCON{Plain text communication is dangerous}

[Programming-100pt] megrep

Question

目grepの特訓をしてみよう。

megrep.zip

Answer

img

そんなにBzEditorで開いてほしいんだな

img1

はい・・・

SECCON{bsdbanner}

[Programming-100pt] x2.txt

Question

2倍になって文字化けしてしまったので、半分にしてみよう。

x2.txt

Answer

バイナリエディタで開いてみた

image

おそらくASCIIコードを2倍にしたんだな~

スクリプトを書いてみる

q14.py

#!/usr/bin/env python

f = open("x2.txt","rb")

print "".join(map(lambda x:chr(ord(x) / 2),list(f.read())))

f.close()
$ ./q14.py
I have a pen. I have an apple. SECCON{lshift_or_rshift}!

流石に草

SECCON{lshift_or_rshift}

[Programming-200pt] decode the trapezoid QR code

Question

qrcode.png

Answer

Gimpでまっすぐにしたら普通に読めた・・・Programingとは・・・

img

SECCON{The QR code system was invented by Denso Wave in Japan}

[Programming-100pt] sum primes

Question

暗号通信では素数が重要な要素として使われています。

その素数を使った計算問題です。

1番目の素数は2、

2番目の素数は3、

3番目の素数は5、

1番目から3番目までの素数の合計値は10です。

では、12345番目の素数から31337番目までの素数の合計値はいくつでしょう?

フラグは SECCON{合計値} です。「合計値」の部分を合計した数値に置き換えてください。


ちなみに、31337はeleetのLeet(ハッカー語)です。

Answer

スクリプトを書いてみる

追記

@shiracamusさんに修正版をいただきました

q16.py

#!/usr/bin/env python
import math

def is_prime(x):
    if x < 2: return False 
    if x == 2 or x == 3 or x == 5: return True 
    if x % 2 == 0 or x % 3 == 0 or x % 5 == 0: return False 

    prime = 7
    step = 4
    while prime <= math.sqrt(x):
        if x % prime == 0: return False

        prime += step
        step = 6 - step

    return True

sum_prime = 0
i = 2
num_prime = 0

while 1:
    if num_prime > 31337:
        break
    if is_prime(i):
        num_prime += 1
        if 12345 <= num_prime <= 31337:
            sum_prime += i
    i += 1
print sum_prime
$ ./q16.py
4716549971

あってるかな?

SECCON{4716549971}

[Web-100pt] sessionhijack

Question

admin でログインして、フラグをゲットせよ

http://10.100.7.2

Answer

http://10.100.7.2に接続し新規登録をした後ログインしてみてる。

cookieを見てみると、

JSESSIONID=70efdf2ec9b086079795c442636b55fb

となっているのでとりあえず、70efdf2ec9b086079795c442636b55fbをgoogleで検索してみるとどうやらmd5のようだ。

http://www.kiyori.co.jp/md5reverse/

上記のサイトで70efdf2ec9b086079795c442636b55fbを逆変換すると"17"ということが分かった。

おそらくuseridをmd5でハッシュ化したものをセッションとして使用していると考えられるので。

md5(1) = c4ca4238a0b923820dcc509a6f75849b

であるc4ca4238a0b923820dcc509a6f75849bEditThisCookie

などを用いてセットしてログインしてみるとflagが表示される。

SECCON{SequentialMD5}

[Trivia-100pt] blacked out PDF

Question

個人情報漏洩のお詫びのPDFファイルの中から隠されたフラグを見つけよう

owabi1.pdf

Answer

img

黒塗りされているがコピーできてしまう

お客様各位
個人情報漏洩のお詫びについて
2016年11月12日
この度、弊社では本来外部に出てはならない個人情報がインターネット上で閲覧可能に
なっているとの外部からの連絡を受け、事実関係を調査いたしましたところ、サーバの設定
ミスにより2016年11月11日から11月12日まで、一般ユーザーがインターネッ
トから閲覧可能になっていたことが判明いたしました。
一時閲覧可能になっていた情報は、個人情報(氏名、郵便番号、住所)が含まれておりまい
たことから、情報流出の対象となった全ての皆様方には、個別に書面でお詫びと説明をさせ
ていただきました。情報が流出してしまいました皆様には、大変なご迷惑とご心配をおかけ
しましたこと、深くお詫び申し上げます。
なお、今回流出した項目は以下の通りです。
氏名 郵便番号 住所
坂田胡桃 769-2906 香川県東かがわ市川股 1-11-14
森下隆吾 922-0126 石川県加賀市山中温泉河鹿町 4-15
橋口清美 329-2337 栃木県塩谷郡塩谷町泉 1-6-2
笠井竹男 770-0832 徳島県徳島市寺島本町東 4-5 寺島本町東マンション 406
加賀真里 894-2403 鹿児島県大島郡瀬戸内町実久 2-1 実久スイート 304
飯島果凛 880-0927 宮崎県宮崎市源藤町 3-16-13 ガーデン源藤町 404
横溝常吉 210-0836 神奈川県川崎市川崎区大島上町 2-19-3
藤岡伊吹 899-5307 鹿児島県姶良郡蒲生町久末 1-20-2 久末タワー302
今野貞 871-0151 大分県中津市大悟法 1-18
平本由美子 922-0864 石川県加賀市大聖寺西栄町 1-19-11
↑偽物情報 111-1111 SECCON{kuronuri_ha_dame_zettai}
弊社では、これまでも個人情報取り扱い業務にあたっては、厳格な取り扱いを求め、情報管
理の徹底に努めてまいりましたが、このような情報流出が発生したことを踏まえ、今後は更
なる再発防止策を講じて再発防止に全力で取り組んでまいります。
株式会社セクコン
代表戸締役社長 竹迫悪範

黒塗りは絶対だめ

SECCON{kuronuri_ha_dame_zettai}

[Trivia-200pt] blacked out PDF again

Question

セキュリティ制限のかかったPDFファイルの中から隠されたフラグを見つけよう

owabi2.protected.pdf

Answer

今度はコピープロテクトがかかってる

即錠★PDFというソフトで解除できるようなので

解除した

owabi2.protected.unlocked.pdf

そして同じようにコピーする

お客様各位
個人情報漏洩のお詫び(その2)について
2016年11月12日
この度、弊社では本来外部に出てはならない個人情報がインターネット上で閲覧可能に
なっているとの外部からの連絡を受け、事実関係を調査いたしましたところ、サーバの設定
ミスにより2016年11月11日から11月12日まで、一般ユーザーがインターネッ
トから閲覧可能になっていたことが判明いたしました。
一時閲覧可能になっていた情報は、個人情報(氏名、郵便番号、住所)が含まれておりまい
たことから、情報流出の対象となった全ての皆様方には、個別に書面でお詫びと説明をさせ
ていただきました。情報が流出してしまいました皆様には、大変なご迷惑とご心配をおかけ
しましたこと、深くお詫び申し上げます。
なお、今回流出した項目は以下の通りです。
氏名 郵便番号 住所
土井和人 708-1507 岡山県久米郡美咲町百々4-3
重松徳蔵 739-1741 広島県広島市安佐北区真亀 3-4-1 グリーン真亀 211
東海佳奈子 750-0074 山口県下関市彦島本村町 3-4-19 彦島本村町アパート 304
浅野綾子 285-0055 千葉県佐倉市瓜坪新田 3-19-7
秋葉良太 349-1114 埼玉県北葛飾郡栗橋町河原代 4-11
阪本紗弥 863-2424 熊本県天草市五和町手野 1-10-2 五和町手野の杜 103
沼田由依 300-2442 茨城県つくばみらい市西ノ台 2-15-8
鶴岡咲月 970-8018 福島県いわき市平四ツ波 2-9-17 平四ツ波ロイヤル 217
金野省三 891-6217 鹿児島県大島郡喜界町伊砂 1-2-5 コーポ伊砂 203
↑偽物情報 222-2222 SECCON{1234567890}
弊社では、これまでも個人情報取り扱い業務にあたっては、厳格な取り扱いを求めてまいり
ましたが、度重なる情報流出が発生したことを踏まえ、本日を情報管理体制の折り返し地点
とし、従業員一同再発防止策を読み上げ、全力で個人情報保護に取り組んでまいります。
株式会社セクコン
代表戸締役社長 竹迫悪範
SECCON{1234567890}

[Trivia-300pt] how much a fine?

Question

次に挙げる【行為】は犯罪に該当する可能性があるでしょうか?

以下に列挙する【選択肢】の中から最も可能性のある番号を選び、【フラグ形式】に変換して回答して下さい。


【行為】

a. 匿名電子掲示板サイトに、「京都すばる高校を爆破する。」と書き込んだ。

b. クラスメートの0点の答案用紙を撮影し、無断でfacebookに投稿し公開。

c. 交際相手(17歳)に、自分で裸の写真を撮影させ、LINEで送ってもらった。

d. フラれた腹いせに、元交際相手の名前と裸の画像をTwitterでツイー卜した。

e. 交際を断られ続けているのに、「つき合って」としつこくメールした。



【選択肢】

1. 無罪

2. 名誉設損罪            (罰則:懲役 3年以下、 罰金  50万円以下)

3. 著作権侵害            (罰則:懲役10年以下、 罰金1000万円以下)

4. 威力業務妨害罪          (罰則:懲役 3年以下、 罰金  50万円以下)

5. 児童ポルノ法違反         (罰則:懲役 3年以下、 罰金 300万円以下)

6. ストーカー規制法違反       (罰則:懲役 6ケ月以下、罰金  50万円以下)

7. 私事性的画像記録の被害防止法違反 (罰則:懲役 3年以下、 罰金  50万円以下)



【フラグ形式】

SECCON{(a.の選択番号)(b.の選択番号)(c.の選択番号)(d.の選択番号)(e.の選択番号)}

フラグ回答例: SECCON{12123}

Answer

a. 匿名電子掲示板サイトに、「京都すばる高校を爆破する。」と書き込んだ。・・・威力業務妨害罪

b. クラスメートの0点の答案用紙を撮影し、無断でfacebookに投稿し公開。・・・名誉設損罪

c. 交際相手(17歳)に、自分で裸の写真を撮影させ、LINEで送ってもらった。・・・児童ポルノ法違反

d. フラれた腹いせに、元交際相手の名前と裸の画像をTwitterでツイー卜した。・・・私事性的画像記録の被害防止法違反

e. 交際を断られ続けているのに、「つき合って」としつこくメールした。・・・ストーカー規制法違反

チームメイトに常識がないと言われた・・・

SECCON{42576}

[Trivia-100pt] acronym

Question

下記組織名・団体名のフルスペルを調べ、下線部の単語を下記フラグ形式に変換せよ。

組織名・団体名:

NISC: National center of Incident readiness and Strategy for ___(1)___

NICT: National Institute of Information and ___(2)___ Technology

IPA: Information-technology Promotion ___(3)___, Japan

JPCERT/CC: Japan Computer Emergency Response Team ___(4)___ Center

JC3:Japan ___(5)___ Control Center

JNSA: Japan Network Security ___(6)___

フラグ形式:

SECCON{(1)_(2)_(3)_(4)_(5)_(6)}

・括弧で囲まれた数字の部分を「組織名・団体名」の該当単語に置き換える

・単語はすべて小文字にする

・単語間はアンダーライン文字で接続する

Answer

ググった

NISC: National center of Incident readiness and Strategy for Cybersecurity

NICT: National Institute of Information and Communications Technology

IPA: Information-technology Promotion Agency, Japan

JPCERT/CC: Japan Computer Emergency Response Team Coordination Center

JC3:Japan Cybercrime Control Center

JNSA: Japan Network Security Association
SECCON{cybersecurity_communications_agency_coordination_cybercrime_association}

おわりに

サイバー甲子園は交通費支給・懇親会が豪華なのは、スポンサー様のおかげです。

スポンサー様ありがとうございます!

KaliLinuxでIDA-Demoを使う

環境

  • Linux version 4.6.0-kali1-amd64

おそらくDebian系ならこれでできると思う

IDA Demo 6.95 for Linuxをダウンロードする

$ mkdir temp
$ cd temp
$ wget https://out7.hex-rays.com/files/idademo695_linux.tgz
$ tar xvzf idademo695_linux.tgz
$ cd idademo695

ソースではなく実行形式が含まれているので

$ ./idaq

で実行できるがこのKaliLinuxのバージョンではライブラリ等が足りないので

$ ./idaq
 bash: ./idaq: そのようなファイルやディレクトリはありません

となる。

本記事はこれを実行できるように試行錯誤したものなので、

結果だけ知りたいという人は最後のコマンドを実行してください

前準備

$ apt update
$ apt upgrade

ライブラリのインストール

IDA-Demoでは32ビットのライブラリが必要なので

$ dpkg -S libgthread-2.0.so.0
libglib2.0-0:amd64: /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0.4800.1
libglib2.0-0:amd64: /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0

dpkgでライブラリが含まれているパッケージを探す今回は

$ apt install libglib2.0-0:amd64
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
libglib2.0-0 はすでに最新バージョン (2.48.1-2) です。
libglib2.0-0 は手動でインストールしたと設定されました。
アップグレード: 0 個、新規インストール: 0 個、削除: 0 個、保留: 0 個。

amd64だけではなくi386も必要なので

$ apt install libglib2.0-0:i386
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
E: パッケージ libglib2.0-0:i386 が見つかりません
E: 'libglib2.0-0' に一致するパッケージは見つかりませんでした
E: 正規表現 'libglib2.0-0' ではパッケージは見つかりませんでした

OSが64ビットなので32ビットのパッケージのリポジトリは追加されていないのでみつからない、なので

$ dpkg --add-architecture i386
$ apt update
ヒット:1 http://ftp.ne.jp/Linux/packages/kali/kali kali-rolling InRelease
取得:2 http://ftp.ne.jp/Linux/packages/kali/kali kali-rolling/main i386 Packages [13.9 MB]
取得:3 http://ftp.ne.jp/Linux/packages/kali/kali kali-rolling/non-free i386 Packages [135 kB]
取得:4 http://ftp.ne.jp/Linux/packages/kali/kali kali-rolling/contrib i386 Packages [86.7 kB]
14.1 MB を 11秒 で取得しました (1,186 kB/s)                                    
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています       
状態情報を読み取っています... 完了
パッケージはすべて最新です。

追加してからもう一度インストールする

$ apt install libglib2.0-0:i386
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
以下の追加パッケージがインストールされます:
  gcc-6-base:i386 libc6:i386 libffi6:i386 libgcc1:i386 libpcre3:i386
  libselinux1:i386 zlib1g:i386
提案パッケージ:
  glibc-doc:i386 libc-l10n:i386
以下のパッケージが新たにインストールされます:
  gcc-6-base:i386 libc6:i386 libffi6:i386 libgcc1:i386 libglib2.0-0:i386
  libpcre3:i386 libselinux1:i386 zlib1g:i386
アップグレード: 0 個、新規インストール: 8 個、削除: 0 個、保留: 0 個。
5,986 kB のアーカイブを取得する必要があります。
この操作後に追加で 16.7 MB のディスク容量が消費されます。
続行しますか? [Y/n] y

実行してみる

$ ./idaq 
./idaq: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory

まだライブラリが足りないようなので

$ ldd idaq | \grep 'not found' | awk '{ print $1 }' | xargs dpkg -S | awk '{ print $1 "i386" }' | sort | uniq
libstdc++6:amd64:i386
libx11-6:amd64:i386

足りないパッケージの32ビット版をインストールしていく

$ apt install libstdc++6:i386 libx11-6:i386
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
以下の追加パッケージがインストールされます:
  libxau6:i386 libxcb1:i386 libxdmcp6:i386
以下のパッケージが新たにインストールされます:
  libstdc++6:i386 libx11-6:i386 libxau6:i386 libxcb1:i386 libxdmcp6:i386
アップグレード: 0 個、新規インストール: 5 個、削除: 0 個、保留: 0 個。
1,281 kB のアーカイブを取得する必要があります。
この操作後に追加で 3,933 kB のディスク容量が消費されます。
続行しますか? [Y/n] y

もう一度実行してみる

$ ./idaq
This application failed to start because it could not find or load the Qt platform plugin "xcb"
in "".

Available platform plugins are: linuxfb, minimal, xcb.

Reinstalling the application may fix this problem.
中止

今度はQt関連のエラーが出る

なのでライブラリをインストールしていく

$ apt install libqt5gui5:i386
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
  libglew1.13
これを削除するには 'apt autoremove' を利用してください。
以下の追加パッケージがインストールされます:
  libbsd0:i386 libdbus-1-3:i386 libdrm-amdgpu1:i386 libdrm-intel1:i386
  libdrm-nouveau2:i386 libdrm-radeon1:i386 libdrm2:i386 libedit2:i386
  libegl1-mesa:i386 libelf1:i386 libevdev2:i386 libexpat1:i386
  libfontconfig1:i386 libfreetype6:i386 libgbm1:i386 libgcrypt20:i386
  libgl1-mesa-dri:i386 libgl1-mesa-glx:i386 libglapi-mesa:i386
  libglew1.13:i386 libglu1-mesa:i386 libgpg-error0:i386 libgraphite2-3:i386
  libgudev-1.0-0:i386 libharfbuzz0b:i386 libice6:i386 libicu57:i386
  libinput10:i386 libjpeg62-turbo:i386 libllvm3.8:i386 liblzma5:i386
  libmtdev1:i386 libpciaccess0:i386 libpcre16-3:i386 libpng16-16:i386
  libproxy1v5:i386 libqt5core5a:i386 libqt5dbus5:i386 libqt5network5:i386
  libqt5svg5:i386 libqt5widgets5:i386 libsm6:i386 libsystemd0:i386
  libtinfo5:i386 libtxc-dxtn-s2tc0:i386 libudev1:i386 libuuid1:i386
  libwacom2:i386 libwayland-client0:i386 libwayland-server0:i386
  libx11-xcb1:i386 libxcb-dri2-0:i386 libxcb-dri3-0:i386 libxcb-glx0:i386
  libxcb-icccm4:i386 libxcb-image0:i386 libxcb-keysyms1:i386
  libxcb-present0:i386 libxcb-randr0:i386 libxcb-render-util0:i386
  libxcb-render0:i386 libxcb-shape0:i386 libxcb-shm0:i386 libxcb-sync1:i386
  libxcb-util0:i386 libxcb-xfixes0:i386 libxcb-xinerama0:i386 libxcb-xkb1:i386
  libxdamage1:i386 libxext6:i386 libxfixes3:i386 libxi6:i386
  libxkbcommon-x11-0:i386 libxkbcommon0:i386 libxrender1:i386
  libxshmfence1:i386 libxxf86vm1:i386 mesa-utils:i386
提案パッケージ:
  rng-tools:i386 glew-utils:i386 libthai0:i386 libqt5libqgtk2:i386
  qt5-image-formats-plugins:i386 qtwayland5:i386
推奨パッケージ:
  qttranslations5-l10n:i386
以下のパッケージは「削除」されます:
  mesa-utils
以下のパッケージが新たにインストールされます:
  libbsd0:i386 libdbus-1-3:i386 libdrm-amdgpu1:i386 libdrm-intel1:i386
  libdrm-nouveau2:i386 libdrm-radeon1:i386 libdrm2:i386 libedit2:i386
  libegl1-mesa:i386 libelf1:i386 libevdev2:i386 libexpat1:i386
  libfontconfig1:i386 libfreetype6:i386 libgbm1:i386 libgcrypt20:i386
  libgl1-mesa-dri:i386 libgl1-mesa-glx:i386 libglapi-mesa:i386
  libglew1.13:i386 libglu1-mesa:i386 libgpg-error0:i386 libgraphite2-3:i386
  libgudev-1.0-0:i386 libharfbuzz0b:i386 libice6:i386 libicu57:i386
  libinput10:i386 libjpeg62-turbo:i386 libllvm3.8:i386 liblzma5:i386
  libmtdev1:i386 libpciaccess0:i386 libpcre16-3:i386 libpng16-16:i386
  libproxy1v5:i386 libqt5core5a:i386 libqt5dbus5:i386 libqt5gui5:i386
  libqt5network5:i386 libqt5svg5:i386 libqt5widgets5:i386 libsm6:i386
  libsystemd0:i386 libtinfo5:i386 libtxc-dxtn-s2tc0:i386 libudev1:i386
  libuuid1:i386 libwacom2:i386 libwayland-client0:i386 libwayland-server0:i386
  libx11-xcb1:i386 libxcb-dri2-0:i386 libxcb-dri3-0:i386 libxcb-glx0:i386
  libxcb-icccm4:i386 libxcb-image0:i386 libxcb-keysyms1:i386
  libxcb-present0:i386 libxcb-randr0:i386 libxcb-render-util0:i386
  libxcb-render0:i386 libxcb-shape0:i386 libxcb-shm0:i386 libxcb-sync1:i386
  libxcb-util0:i386 libxcb-xfixes0:i386 libxcb-xinerama0:i386 libxcb-xkb1:i386
  libxdamage1:i386 libxext6:i386 libxfixes3:i386 libxi6:i386
  libxkbcommon-x11-0:i386 libxkbcommon0:i386 libxrender1:i386
  libxshmfence1:i386 libxxf86vm1:i386 mesa-utils:i386
アップグレード: 0 個、新規インストール: 79 個、削除: 1 個、保留: 0 個。
40.6 MB のアーカイブを取得する必要があります。
この操作後に追加で 249 MB のディスク容量が消費されます。
続行しますか? [Y/n] y

GUIを拡張するためにGTKのライブラリもインストールする

$ apt install libgtk2.0-0:i386 gtk2-engines-murrine:i386 gtk2-engines-pixbuf:i386 
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
  libglew1.13
これを削除するには 'apt autoremove' を利用してください。
以下の追加パッケージがインストールされます:
  libatk1.0-0:i386 libavahi-client3:i386 libavahi-common-data:i386 libavahi-common3:i386 libcairo2:i386 libcomerr2:i386 libcups2:i386 libdatrie1:i386 libgail-common:i386 libgail18:i386 libgdk-pixbuf2.0-0:i386
  libgmp10:i386 libgnutls30:i386 libgssapi-krb5-2:i386 libhogweed4:i386 libidn11:i386 libjbig0:i386 libk5crypto3:i386 libkeyutils1:i386 libkrb5-3:i386 libkrb5support0:i386 libnettle6:i386 libp11-kit0:i386
  libpango-1.0-0:i386 libpangocairo-1.0-0:i386 libpangoft2-1.0-0:i386 libpixman-1-0:i386 libtasn1-6:i386 libthai0:i386 libtiff5:i386 libxcomposite1:i386 libxcursor1:i386 libxinerama1:i386 libxrandr2:i386
提案パッケージ:
  gnutls-bin:i386 krb5-doc:i386 krb5-user:i386 librsvg2-common:i386 gvfs:i386
推奨パッケージ:
  murrine-themes:i386
以下のパッケージが新たにインストールされます:
  gtk2-engines-murrine:i386 gtk2-engines-pixbuf:i386 libatk1.0-0:i386 libavahi-client3:i386 libavahi-common-data:i386 libavahi-common3:i386 libcairo2:i386 libcomerr2:i386 libcups2:i386 libdatrie1:i386
  libgail-common:i386 libgail18:i386 libgdk-pixbuf2.0-0:i386 libgmp10:i386 libgnutls30:i386 libgssapi-krb5-2:i386 libgtk2.0-0:i386 libhogweed4:i386 libidn11:i386 libjbig0:i386 libk5crypto3:i386
  libkeyutils1:i386 libkrb5-3:i386 libkrb5support0:i386 libnettle6:i386 libp11-kit0:i386 libpango-1.0-0:i386 libpangocairo-1.0-0:i386 libpangoft2-1.0-0:i386 libpixman-1-0:i386 libtasn1-6:i386 libthai0:i386
  libtiff5:i386 libxcomposite1:i386 libxcursor1:i386 libxinerama1:i386 libxrandr2:i386
アップグレード: 0 個、新規インストール: 37 個、削除: 0 個、保留: 0 個。
8,173 kB のアーカイブを取得する必要があります。
この操作後に追加で 21.6 MB のディスク容量が消費されます。
続行しますか? [Y/n] y

実行できるが何かメッセージがあるので

$ ./idaq
Gtk-Message: Failed to load module "atk-bridge"
Gtk-Message: Failed to load module "canberra-gtk-module"

それぞれインストールする

$ apt install libatk-adaptor:i386 libgail-common:i386
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
libgail-common:i386 はすでに最新バージョン (2.24.30-4) です。
libgail-common:i386 は手動でインストールしたと設定されました。
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
  libglew1.13
これを削除するには 'apt autoremove' を利用してください。
以下の追加パッケージがインストールされます:
  libatk-bridge2.0-0:i386 libatspi2.0-0:i386
以下のパッケージが新たにインストールされます:
  libatk-adaptor:i386 libatk-bridge2.0-0:i386 libatspi2.0-0:i386
アップグレード: 0 個、新規インストール: 3 個、削除: 0 個、保留: 0 個。
141 kB のアーカイブを取得する必要があります。
この操作後に追加で 495 kB のディスク容量が消費されます。
続行しますか? [Y/n] y
$ sudo apt install libcanberra-gtk-module:i386
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
  libglew1.13
これを削除するには 'sudo apt autoremove' を利用してください。
以下の追加パッケージがインストールされます:
  libasound2:i386 libcanberra-gtk0:i386 libcanberra0:i386 libltdl7:i386 libogg0:i386 libtdb1:i386 libvorbis0a:i386 libvorbisfile3:i386
提案パッケージ:
  libasound2-plugins:i386 libcanberra-pulse:i386
以下のパッケージが新たにインストールされます:
  libasound2:i386 libcanberra-gtk-module:i386 libcanberra-gtk0:i386 libcanberra0:i386 libltdl7:i386 libogg0:i386 libtdb1:i386 libvorbis0a:i386 libvorbisfile3:i386
アップグレード: 0 個、新規インストール: 9 個、削除: 0 個、保留: 0 個。
863 kB のアーカイブを取得する必要があります。
この操作後に追加で 2,251 kB のディスク容量が消費されます。
続行しますか? [Y/n] y

これで実行できる

f:id:akashisn:20181027123846j:plain

結局次のコマンドを実行すればいい

$ sudo dpkg --add-architecture i386
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install libglib2.0-0:i386 libstdc++6:i386 libx11-6:i386 libqt5gui5:i386 libgtk2.0-0:i386 gtk2-engines-murrine:i386 gtk2-engines-pixbuf:i386 libatk-adaptor:i386 libgail-common:i386 libcanberra-gtk-module:i386

UbuntuでcURL+RapidJSONを使いC++からapiを叩く

環境

ライブラリの設定

libcurlのインストール

libcurlとはcURLC言語から使えるようにしたライブラリ。Ubuntuならapt-getで簡単にインストールできる

$ sudo apt-get update
$ sudo apt-get install curl libcurl3 libcurl3-dev

RapidJSONのインストール

RapidJSONとはC言語からJSONを扱うライブラリ。Rapidとあるようにパフォーマンス重視のライブラリ。

これもUbuntuならapt-getで簡単にインストールできる

$ sudo apt-get update
$ sudo apt-get install rapidjson-dev

使い方

libcurl

GoogleにGETでリクエストしてそれを表示するだけ

//test.cpp
#include <iostream>
#include <curl/curl.h>
int main(void){
     CURL *curl;
     CURLcode res;
     curl = curl_easy_init();
     if(curl) {
          curl_easy_setopt(curl, CURLOPT_URL, "https://google.co.jp");
          res = curl_easy_perform(curl);
          if(res != CURLE_OK)
               fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res));
          curl_easy_cleanup(curl);
     }
    return 0;
}

コンパイルするときは[-lcurl]オプションをつける

$  g++ test.cpp -lcurl
# ./a.out
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://www.google.co.jp/">here</A>.
</BODY></HTML>

libcurlとRapidJSON

JSON-POSTの場合

変数に代入したいときはcallback関数を用意してあげる

これはチュウニズムネットにPOSTしてレートを取得するもの

//レスポンスデータ
{
    "userId": 2038082304583461, 
    "userInfo": {
        "characterFileName": "img/0ec6bc2a17e68e8d.png", 
        "characterLevel": 14, 
        "friendCount": 0, 
        "highestRating": 1386, 
        "level": 49, 
        "playCount": 393, 
        "playerRating": 1385, 
        "point": 569100, 
        "reincarnationNum": 0, 
        "totalPoint": 867000, 
        "trophyName": "ちぇえええええええええええええええええん", 
        "trophyType": 2, 
        "userName": "NIS", 
        "webLimitDate": "2016-08-05 04:00:00.0"
    }
}
//chunithm.cpp
#include <iostream>
#include <curl/curl.h>
#include <string>
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/filewritestream.h"

size_t callbackWrite(char *ptr, size_t size, size_t nmemb, std::string *stream)
{
  int dataLength = size * nmemb;
  stream->append(ptr, dataLength);
  return dataLength;
}
std::string curl_JSON_POST(std::string post_data,std::string url){

  CURL *curl;
  CURLcode ret;
  curl = curl_easy_init();
  std::string chunk;
  /*エラー処理*/
  if (curl == NULL) {
    std::cerr << "curl_easy_init() failed" << std::endl;
    return "error";
  }

  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data.c_str());
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callbackWrite);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk);
  ret = curl_easy_perform(curl);
  curl_easy_cleanup(curl);

  /*エラー処理*/
  if (ret != CURLE_OK) {
    std::cerr << "curl_easy_perform() failed." << std::endl;
    return "error";
  }
  return chunk;
}
std::string rate_get(std::string userid){
  std::string url = "https://chunithm-net.com/ChuniNet/GetUserInfoApi";
  std::string post_data = "{\"userId\":\"";
  post_data += userid;
  post_data += "\",\"friendCode\":0,\"fileLevel\":1}";

  std::string data = curl_JSON_POST(post_data,url);
  return data;
}
int main(){
  int rate;
  std::string userid;
  std::cout<<"userID : ";
  std::cin>>userid;
  rapidjson::Document document,doc;
  std::string data = rate_get(userid);
  if(document.Parse(data.c_str()).HasParseError() == false){
     rapidjson::Value& a = document["userInfo"];
     std::cout<<"rate:"<<(double)(a["playerRating"].GetInt())/100<<std::endl;
  }else{
     std::cout<<"error"<<std::endl;
  }
  return 0;
}
$ g++ chunithm.cpp -lcurl
$ ./a.out
userID : 2038082304583461
rate:13.85

UbuntuにApache+PHP7でWebサーバー、Postfix+Dovecot+Rainloop+MySQLでWebメール構築

環境

ポイントはApacheを先にインストールすること!

Webサーバーの構築

Apacheのインストール

$sudo apt-get update
$ sudo apt-get install apache2

http://~などでアクセスしてみて、インストールできてるか確認

PHP7のインストール

php7は標準ではインストール出来ないのでPPAを追加します

$ sudo add-apt-repository ppa:ondrej/php

php7とphp7のMySQLモジュールをインストールします

$ sudo apt-get update
$ sudo apt-get install php7.0 php7.0-mysql libapache2-mod-php7.0 php7.0-mcrypt

インストールが完了したら、Apacheを再起動して、以下のソースをwebルート(/var/www/html/)にアップロードしてブラウザからアクセスしてみます

$ sudo service apache2 restart
<?php
    phpinfo();
?>

phpの設定が表示されれば成功です

MySQLのインストール

次にMySQLをインストールします

$ sudo apt-get install mysql-server

インストールの時にrootのパスワードの設定するよう求められるので設定します。

完了したら以下のコマンドで、rootとして設定したパスワードでMySQLにアクセスできればインストール成功です。

$ mysql -u root -p

Webメールの構築

ドメイン名:hoge.com

ユーザー名/パスワード:hoge/hagehage

とする

Postfixの設定

SMTPサーバー。ポート25を使用して、外部のSMTPサーバーからのメール受信や、外部SMTPサーバーへのメール送信を行う。MTA(Message Transfer Agent)とも呼ばれる。

インストール

$ sudo apt-get install postfix

メールサーバーのタイプは[Internet Site]を選択します。 システムメール名(デフォルトのドメイン名のようなもの)はドメイン名を指定します。

設定ファイル編集

設定ファイルをコピーしてから編集

$ mv /etc/postfix/main.cf /etc/postfix/main.cf.old
$ cp /usr/share/postfix/main.cf.dist /etc/postfix/main.cf
$ vi /etc/postfix/main.cf
#基本設定
myhostname = hoge.com
mydomain = hoge.com
myorigin = $mydomain
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
relay_domains = $mydestination
home_mailbox = Maildir/ #ユーザーディレクトリ内にメールが格納される
mynetworks = 127.0.0.0/8
inet_interfaces = all
inet_protocols = ipv4

#以下コメントアウトする
#sendmail_path =       
#newaliases_path =
#mailq_path =
#setgid_group =
#html_directory =
#manpage_directory =
#sample_directory =
#readme_directory =


#SMTP-Auth設定(追記する)
#認証にはdovecotを参照させる(Dovecotと同じユーザー名/パスワードで認証可能にする)
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/dovecot-auth
smtpd_client_restrictions = permit_mynetworks, reject_unknown_client, permit
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

#スパム対策(追記する)
smtpd_etrn_restrictions = reject
smtpd_helo_required = yes
disable_vrfy_command = yes

Postfixを再起動する

$ newaliases
# /etc/init.d/postfix restart
[ ok ] Restarting postfix (via systemctl): postfix.service.

Dovecotの設定

DovecotPostfixが保存したメールをメーラーへと渡すPOP3/IMAPサーバー。

この時のDovecotの認証方法をそのままPostfixSMTP-Auth認証時に参照させる。

インストール

$ apt-get install dovecot-common dovecot-imapd dovecot-pop3d

認証方法を設定する

Dovecotの認証にはいくつかの方法があるが、最もわかりやすいパスワードフアイルを参照する方法(auth-passwdfile)で設定する。

OSのpasswdファイルと似た書式でDovecot専用のパスワードファイルを作製し参照させる。

$ vi /etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = no   #コメントを外す
auth_mechanisms = plain login  #コメントを外す 
!include auth-passwdfile.conf.ext #コメントを外す

パスワードファイルの参照先を設定

$ vi/etc/dovecot/conf.d/auth-passwdfile.conf.ext

このように書き換える

passdb {
  driver = passwd-file
  #args = scheme=CRYPT username_format=%u /etc/dovecot/users
  args = /etc/dovecot/users
}

userdb {
  driver = passwd-file
  #args = username_format=%u /etc/dovecot/users

  # Default fields that can be overridden by passwd-file
  #default_fields = quota_rule=*:storage=1G

  # Override fields from passwd-file
  #override_fields = home=/home/virtual/%u
  args = /etc/dovecot/users
}

パスワードファイルを用意

Dovecotのパスワードフアイルは暗号化してから記載する。

ユーザー名:hoge、パスワード:hagehageの時の暗号化文は以下のコマンドで取得できる。

$ doveadm pw -s DIGEST-MD5 -u hoge -p hagehage
{DIGEST-MD5}8687f71fc51f3392269ee94cbc1d33f1

参照先として指定した場所にパスワードファイルを作製する。

(ユーザー名):(暗号化済みパスワード) の形式で記載する。

$ vi /etc/dovecot/users
hoge:{DIGEST-MD5}8687f71fc51f3392269ee94cbc1d33f1

その他編集

$ vi /etc/dovecot/dovecot.conf
# 30行目:変更(IPv6をリスンしない場合)
listen = *
$ vi etc/dovecot/conf.d/10-mail.conf
# 30行目:Maildir形式に変更
mail_location = maildir:~/Maildir
$ vi /etc/dovecot/conf.d/10-master.conf 
# 96-98行目:コメント解除し追記
# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
}
$ vi /etc/dovecot/conf.d/10-ssl.conf
# 6行目:コメント解除して変更(SSLなし)
ssl = no

# 12,13行目:コメントにする
#ssl_cert = </etc/dovecot/dovecot.pem
#ssl_key = </etc/dovecot/private/dovecot.pem

再起動

Dovecotを再起動し設定を反映させる。

$ /etc/init.d/dovecot restart

動作確認

telnetで接続してPostfixDovecot認証の動作確認を行う

POP3動作確認

telnetで接続して認証確認をする。

POP3は平文なので、そのままユーザー名をパスワードを打てばいい。

$ telnet hoge.com 110
Trying 127.0.1.1...
Connected to hoge.com.
Escape character is '^]'.
+OK Dovecot ready.
USER hoge
+OK
PASS hogehoge
OK LOGGED IN.

こうなれば成功

$ telnet hoge.com 110
Trying 127.0.1.1...
Connected to hoge.com.
Escape character is '^]'.
+OK Dovecot ready.
USER hoge
+OK
PASS hogehoge
-ERR [AUTH] Authentication failed.

エラーが出たら次のコマンドを実行してエラーを確認します。

$ doveconf -n

SECCON 2015 Online CTF write up

2015/12/5~6の間SECCON 2015 Online CTFにチーム名BiPhoneでAkashi_SNとして5人で参加しました。CTFは初めてまだ1ヶ月ほどにしてはまぁ解けた方かな・・・?

ちなみに順位は240位でした。

f:id:akashisn:20181027114540j:plain

僕が解いた問題のwrite upをします。

問題はGitHubにあります

Write up

SECCON WARS 2015

https://youtu.be/8SFsln4VyEk

Youtubeのリンクがあるだけ・・・

とりあえず見てみるとStarWarsをもじったみたいな動画があり途中からQRコードが見え始める。

とにかくダウンロードしてフレームごとに分けてみる

背景だけ動いているのでもしやこれは比較明合成が使えるのではと思い

僕がよく星の写真を撮るときに使う

SiriusCompを使ってみたら

f:id:akashisn:20181027115042j:plain

はっきりと出てくるので読み取って終わり

flag:SECCON{TH3F0RC3AVVAK3N53P7}

Unzip the file

後で他の人のwrite upを見て解きました

unzipというファイルが渡されUnzip the fileとのこと

普通に解凍しようとするとパスワードがかかっているみたい・・・

$ unzip unzip.zip 
Archive:  unzip.zip
[unzip.zip] backnumber08.txt password: 
   skipping: backnumber08.txt        incorrect password
   skipping: backnumber09.txt        incorrect password
   skipping: flag                    incorrect password

backnumber08.txtをとりあえず検索してみると

backnumber08.txt

このようにヒットする

ファイルの中身がわかっているので既知平文攻撃だとわかる

これはpkcrackというツールで解析できるみたい

とりあえずソースをダウンロードして

$ cd pkcrack-1.2.2/test
pkcrack-1.2.2/test/$ sudo make

testディレクトリに移動してmakeすると./srcに実行ファイルが生成される

pkcrackの使い方は、
   -C [暗号化されたzipファイル]
   -c [暗号化されたzipファイルの中で平文がわかるファイル]
   -P [平文のファイルが入っている暗号化されていないzip]
   -p [平文のファイル]
   -d [出力先(復号したzipファイルの名前)]

以下のbacknumber08.zipbacknumber08.txtを普通にZIP圧縮したもの

~/pkcrack-1.2.2/src/$ pkcrack -C ./unzip.zip -c backnumber08.txt -P backnumber08.zip -p backnumber08.txt -d unzip_1.zip
Files read. Starting stage 1 on Mon Dec  7 14:35:35 2015
Generating 1st generation of possible key2_5299 values...done.
Found 4194304 possible key2-values.
Now we're trying to reduce these...
Lowest number: 984 values at offset 970
Lowest number: 932 values at offset 969
Lowest number: 931 values at offset 967
Lowest number: 911 values at offset 966
Lowest number: 906 values at offset 965
Lowest number: 904 values at offset 959
Lowest number: 896 values at offset 955
Lowest number: 826 values at offset 954
Lowest number: 784 values at offset 606
Lowest number: 753 values at offset 206
Done. Left with 753 possible Values. bestOffset is 206.
Stage 1 completed. Starting stage 2 on Mon Dec  7 14:35:46 2015
Ta-daaaaa! key0=270293cd, key1=b1496a17, key2=8fd0945a
Probabilistic test succeeded for 5098 bytes.
Ta-daaaaa! key0=270293cd, key1=b1496a17, key2=8fd0945a
Probabilistic test succeeded for 5098 bytes.
Stage 2 completed. Starting zipdecrypt on Mon Dec  7 14:36:14 2015
Decrypting backnumber08.txt (5315a01322ab296c211eecba)... OK!
Decrypting backnumber09.txt (83e6640cbec32aeaf10ed1ba)... OK!
Decrypting flag (34e4d2ab7fe1e2421808bab2)... OK!
Finished on Mon Dec  7 14:36:14 2015

これで暗号化されていないunzip_1.zipが生成される

$ unzip unzip_1.zip
Archive:  unzip_1.zip
replace backnumber08.txt? [y]es, [n]o, [A]ll, [N]one, [r]ename: y
 inflating: backnumber08.txt        
 inflating: backnumber09.txt        
 inflating: flag                    
$ ls
 backnumber08.zip
 unzip.zip
 backnumber08.txt
 backnumber09.txt
 flag
 unzip_1.zip
$ file flag 
 flag: Microsoft Word 2007+

flagはwordファイルだとわかる

LibreOfficeで開いてみる

何も見えないがフォントの色を変えると出てくる f:id:akashisn:20181027115741j:plain

flag:SECCON{1s_th1s_passw0rd_ weak?}

Reverse-Engineering Android APK 1

これはチームメイトが前半を解いてくれ最後は僕がflagをみつけました。

なんかいいとこ取りみたい・・・

APKファイルが渡され「じゃんけんに1000回連続で勝ち続けよ」とありました

さすがにごり押しは厳しそうなのでapkファイルについて調べてたらただの圧縮ファイルであるとわかり解凍してみる。

するとclasses.dexというファイルがあってこれがアプリの本体だとわかった。

これは、dex2jarというソフトで変換できるそうなのでやってみる

~/dex2jar-2.0$ ./d2j-dex2jar.sh classes.dex
dex2jar classes.dex -&gt; ./classes-dex2jar.jar
~/dex2jar-2.0$ ls
classes-dex2jar.jar            d2j-dex2smali.bat   d2j-smali.bat
classes.dex                     d2j-dex2smali.sh    d2j-smali.sh
d2j-baksmali.bat                d2j-jar2dex.bat     d2j-std-apk.bat
d2j-baksmali.sh                 d2j-jar2dex.sh      d2j-std-apk.sh
d2j-dex-recompute-checksum.bat  d2j-jar2jasmin.bat  d2j_invoke.bat
d2j-dex-recompute-checksum.sh   d2j-jar2jasmin.sh   d2j_invoke.sh
d2j-dex2jar.bat                 d2j-jasmin2jar.bat  lib
d2j-dex2jar.sh                  d2j-jasmin2jar.sh

するとclasses-dex2jar.jarというファイルができる

これはただのZIPファイルなので展開してみる

すると./com,./androidの2つのフォルダが出てくる

./com/example/seccon2015/rock_paper_scissors/MainActivity.classJava Decompilerというソフトで見てみると

package com.example.seccon2015.rock_paper_scissors;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import java.util.Random;

public class MainActivity
  extends Activity
  implements View.OnClickListener
{
  Button P;
  Button S;
  int cnt = 0;
  int flag;
  private final Handler handler = new Handler();
  int m;
  int n;
  Button r;
  private final Runnable showMessageTask = new Runnable()
  {
    public void run()
    {
      TextView localTextView = (TextView)MainActivity.this.findViewById(2131492946);
      MainActivity localMainActivity;
      if (MainActivity.this.n - MainActivity.this.m == 1)
      {
        localMainActivity = MainActivity.this;
        localMainActivity.cnt += 1;
        localTextView.setText("WIN! +" + String.valueOf(MainActivity.this.cnt));
      }
      for (;;)
      {
        if (1000 == MainActivity.this.cnt) {
          localTextView.setText("SECCON{" + String.valueOf((MainActivity.this.cnt + MainActivity.this.calc()) * 107) + "}");
        }
        MainActivity.this.flag = 0;
        return;
        if (MainActivity.this.m - MainActivity.this.n == 1)
        {
          MainActivity.this.cnt = 0;
          localTextView.setText("LOSE +0");
        }
        else if (MainActivity.this.m == MainActivity.this.n)
        {
          localTextView.setText("DRAW +" + String.valueOf(MainActivity.this.cnt));
        }
        else if (MainActivity.this.m &lt; MainActivity.this.n)
        {
          MainActivity.this.cnt = 0;
          localTextView.setText("LOSE +0");
        }
        else
        {
          localMainActivity = MainActivity.this;
          localMainActivity.cnt += 1;
          localTextView.setText("WIN! +" + String.valueOf(MainActivity.this.cnt));
        }
      }
    }
  };
  
  static
  {
    System.loadLibrary("calc");
  }
  
  public native int calc();
  
  public void onClick(View paramView)
  {
    if (this.flag == 1) {
      return;
    }
    this.flag = 1;
    ((TextView)findViewById(2131492946)).setText("");
    TextView localTextView1 = (TextView)findViewById(2131492944);
    TextView localTextView2 = (TextView)findViewById(2131492945);
    this.m = 0;
    this.n = new Random().nextInt(3);
    int i = this.n;
    localTextView2.setText(new String[] { "CPU: Paper", "CPU: Rock", "CPU: Scissors" }[i]);
    if (paramView == this.P)
    {
      localTextView1.setText("YOU: Paper");
      this.m = 0;
    }
    if (paramView == this.r)
    {
      localTextView1.setText("YOU: Rock");
      this.m = 1;
    }
    if (paramView == this.S)
    {
      localTextView1.setText("YOU: Scissors");
      this.m = 2;
    }
    this.handler.postDelayed(this.showMessageTask, 1000L);
  }
  
  protected void onCreate(Bundle paramBundle)
  {
    super.onCreate(paramBundle);
    setContentView(2130968600);
    this.P = ((Button)findViewById(2131492941));
    this.S = ((Button)findViewById(2131492943));
    this.r = ((Button)findViewById(2131492942));
    this.P.setOnClickListener(this);
    this.r.setOnClickListener(this);
    this.S.setOnClickListener(this);
    this.flag = 0;
  }
}

39行目にflagらしきものが・・・

$cntはカウンターだとわかった

どうやらcalc()はライブラリーから読み込んでいるらしい・・・

そういえばライブラリファイルがあったなー

./rps/lib/x86/libcalc.sofileコマンドでたたくと

$ file libcalc.so
libcalc.so: ELF 32-bit LSB shared object, 
Intel 80386, version 1 (SYSV),dynamically linked, 
BuildID[sha1]=841ccd3a86c678914a4dc1a17bd80647ca290916, stripped

32bitのelfだとわかったので、

Retargetable Decompilerというオンラインのデコンパイラーでデコンパイルしてみると

//
// This file was generated by the Retargetable Decompiler
// Website: https://retdec.com
// Copyright (c) 2015 Retargetable Decompiler &lt;info@retdec.com&gt;

// Address range: 0x400 - 0x405
int32_t Java_com_example_seccon2015_rock_1paper_1scissors_MainActivity_calc(void) {
    // 0x400
    return 7;
}

calc()はいつでも7を返すということがわかり

SECCON{" + String.valueOf((MainActivity.this.cnt + MainActivity.this.calc()) * 107) + "}"

ここを計算して

flag:SECCON{107749}

Command-Line Quiz

telnet caitsith.pwn.seccon.jp
   User:root
   Password:seccon
   すべての *.txt ファイルを読め

接続しクイズの答えもわかったが回答の仕方がわからず断念・・・

Steganography 1

MrFusion.gpjb

というファイルが渡され「Find image files in the file」とのこと

このファイルはgifファイルだとわかったので拡張子を変え表示してみるとSECCON{}としか描かれてないのに8Mはでかすぎるので

バイナリエディタで見てみるといろんなファイルフォーマットのヘッダーが含まれていたのでそれを仕様に沿って分けてみるてそれを合成すると

f:id:akashisn:20181027120511j:plain

flagかと思ってsubmitしたがincorrectばっかりだった

結局できず断念

gpjbはg(mp)p(ng)j(peg)b(mp)の略だったようでbmpが足らなかったから不正解だったみたい

後で解いてみた

binwalkという便利なコマンドがあるらしい

なんでもファイルを解析してくれるみたいfileコマンドの強いやつって感じかな?

aptでインストールできるものはバージョンが古いみたいなのでここからホームディレクトリにダウンロードして

$ cd binwalk-2.0.0.tar/binwalk-2.0.0
binwalk-2.0.0.tar/binwalk-2.0.0 $ ./configure
binwalk-2.0.0.tar/binwalk-2.0.0 $ make
binwalk-2.0.0.tar/binwalk-2.0.0 $ sudo make install

これでインストールできbinwalkで実行できる

binwalkMrFusion.gpjbを解析してみると

$ binwalk MrFusion.gif 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             GIF image data, version "89a", 1280 x 720
6943          0x1B1F          PNG image, 1280 x 720, 8-bit colormap, interlaced
7194          0x1C1A          Zlib SECCON_2015_Online_CTF data, SECCON_2015_Online_CTF, unSECCON_2015_Online_CTF size &gt;= 922950
9727          0x25FF          JPEG image data, JFIF standard  1.01
26632         0x6808          PC bitmap, Windows 3.x format, 1280 x 720 x 24
2791486       0x2A983E        GIF image data, version "89a", 1280 x 720
2794240       0x2AA300        PNG image, 1280 x 720, 8-bit colormap, interlaced
2794491       0x2AA3FB        Zlib SECCON_2015_Online_CTF data, SECCON_2015_Online_CTF, unSECCON_2015_Online_CTF size &gt;= 922950
2796217       0x2AAAB9        JPEG image data, JFIF standard  1.01
2813627       0x2AEEBB        PC bitmap, Windows 3.x format, 1280 x 720 x 24
5578481       0x551EF1        GIF image data, version "89a", 1280 x 720
5580896       0x552860        PNG image, 1280 x 720, 8-bit colormap, interlaced
5581147       0x55295B        Zlib SECCON_2015_Online_CTF data, SECCON_2015_Online_CTF, unSECCON_2015_Online_CTF size &gt;= 922950
5583378       0x553212        JPEG image data, JFIF standard  1.01
5601221       0x5577C5        PC bitmap, Windows 3.x format, 1280 x 720 x 24
8366075       0x7FA7FB        GIF image data, version "89a", 1280 x 720
8368830       0x7FB2BE        PNG image, 1280 x 720, 8-bit colormap, interlaced
8369081       0x7FB3B9        Zlib SECCON_2015_Online_CTF data, SECCON_2015_Online_CTF, unSECCON_2015_Online_CTF size &gt;= 922950
8371932       0x7FBEDC        JPEG image data, JFIF standard  1.01

このようにファイルフォーマットごとに表示してくれます

(ZlibはPNGに使われている圧縮方法なのでZlibのところは無視する)

gif→png→jpeg→bmp→gif→png→・・・のように繰り返している

#coding: UTF-8

a = [0,6943,9727,26632,2791486,2794240,2796217,2813627,5578481,5580896,5583378,5601221,8366075,8368830,8371932,8388384]
#アドレス
b = ['gif','png','jpg','bmp']
#拡張子
f = open("MrFusion.gif", "rb")
#ファイルの読み込み
for x in range(len(a)-1):
  open('result{:02d}.{}'.format(x, b[x % 4]), 'wb').write(f.read(a[x + 1] - a[x]))

pythonのコードを書いて実行

~/ctf/a$ ls
MrFusion.gif  split.py
~/ctf/a$ python split.py 
~/ctf/a$ ls
MrFusion.gif  result03.bmp  result07.bmp  result11.bmp  split.py
result00.gif  result04.gif  result08.gif  result12.gif
result01.png  result05.png  result09.png  result13.png
result02.jpg  result06.jpg  result10.jpg  result14.jpg
~/ctf/a$

分割されたファイルが出力される

最初と最後のファイルをネガポジ変換しすべてjpgに変換して

SiriusCompで比較明合成

f:id:akashisn:20181027120858j:plain

Please input flag like this format SECCON{ * **}

形式が指定されていたので

flag:SECCON{OCT 21 2015 0728}

4042

謎の文章が2005年に古代遺跡から発見された。

これは何を意味している?

no-network.txt

4042?2005?古代遺跡?ということでとりあえずググってみた

f:id:akashisn:20181027121112j:plain

東ソー? f:id:akashisn:20181027121142j:plain

おっなんかヒットした

https://www.ietf.org/rfc/rfc4042.txt

RFC4042・・・?

とりあえずググってみた

RFC4042–Google検索

f:id:akashisn:20181027121242j:plain

RFC4042 2005 年のエープリルフール発行のジョーク RFC です。 UCS4 や UCS2(Unicode) のエンコード方法である UTF-9 や UTF-18 を規定しています。 PDP-10 などの8bitベースではないマシンのためのエンコーディング…?

・・・http://www.imasy.or.jp/~yotti/rfc-joke.htmlより引用

ジョーク・・・

このファイルはUTF-9で書かれているのか・・・

rfc4042.txtにUTF-9からUCS-4に変換するコードが書かれている

/* Return UCS-4 value from UTF-9 string (C version)
* Accepts: pointer to pointer to UTF-9 string
* Returns: UCS-4 character, nonet pointer updated
*/

UINT31 UTF9_to_UCS4 (UINT9 **utf9PP)
{
  UINT9 nonet;
  UINT31 ucs4;
  for (ucs4 = (nonet = *(*utf9PP)++) &amp; 0xff;
  nonet &amp; 0x100;
  ucs4 |= (nonet = *(*utf9PP)++) &amp; 0xff)
  ucs4 &lt;&lt;= 8;
  return ucs4;
}

Last Challenge (Thank you for playing)

規則性にのっとて変換するだけ

flag:SECCON{SEEYOUNEXTYEAR}

終わり

初めてにしてはできたかな~

でも疲れた

視野は広くしないと