Bugリストから脱出しました
脱出してきました.12/12と12/13の土日2日間です.
一度噂のpixivのオフィスに行ってみたいなーと思ってエントリーしてみたんですが, 実際は諸事情により既に11月にオフィスへ行っていたので2度目の来訪となりました.
選考
Github選考って要するにpixiv側で用意したリポジトリをフォークして修正してプルリクを投げるだけです. しかもこの選考用に用意されたリポジトリはびっくりするくらいダメダメなので大して深い知識とか必要はないです. 実際ぼくはエントリー翌日にオフィス来訪が決定したので一気にやる気をなくしてしまい, とりあえずあからさまにここらへん駄目だろって簡単な修正のみ投げてすぐやめてしまいました. そんなんでも通ったのでとりあえずプルリク投げればいいと思います.
ここら辺,インターン中にも「選考で何を見ているのか?」は話題にあがりました. 「このインターンでやる作業についていける最低限のスキルが有るかどうか」を確認するためだそうです. 最低限のスキルというのは「SSHでログインして」「git使って作業して」「プルリクが投げられるか」ということ. それ以外の部分(実際のコミットの内容だとか)はプラスにはなりこそすれマイナス要素にはならなかったらしいです. なるほどーという感じでした. 自分が選考を通った理由がわかった気がします.
ちなみにこの選考段階で人生で初めてPHPを触り,人生で初めてプルリクを投げました.
え? よくそんなんでお前参加したなって?
まぁなんとかなるでしょう.
駄目だったら選考で切られるだけです.
そしてこの通り.脱出してきたので駄目じゃなかったらしいです.
1日目
上記の通りさっさと課題をやめてしまったので,どれくらいの人がプルリクを投げていたのか把握していなかったのですが, 当日の参加者は12名でした.当日までにメールで回ってきた自己紹介シート(共有)には数人にしか書いていなかったので 参加者全員を把握した時には「おお,結構多いな」と思いました. ちなみにキーボードを持ち込んでる人は大体HHKBでした. 僕も自慢の改造キーボード持っていけばよかったですね.
軽く自己紹介を終えた後,作業に入る前の準備を行います. こちらにある通りインターン中は @catatsuy さんが用意してくださった環境に入って作業を行います.
READMEに従ってコマンドを打つだけでまったくコケることなく構築されていく様子はちょっと凄かったです.
apt-get
や brew
や pip
を打つだけでコケる僕にとっては超技術でした.
「Bugリストからの脱出」ということでバグを潰していきます. インターン用に用意されたpixiv本体のスナップショットリポジトリをフォークして開発環境にクローンし, issueに貼られた内容からバグ箇所を推定し修正を行います. 修正コミットをまとめてissueに対してプルリクを出し,それが受理されれば晴れて脱出!ラベルが貼られます. (プルリク内容に問題がある場合は問題箇所が指摘されて再修正となります)
バグを直すとは聞いていたんですが,意図的に仕込まれたバグなどではなく
ガチで12/11昼ごろ時点でpixiv本体に発生していた本物のバグの修正でした.
しかも修正に取り組んでいる最中に仕様が変更されていくというリアルっぷり.
え,バグがバグじゃない? よしなに? え? え?
1日目の作業時刻のリミット後,皆でKPTをやりました. 言われた時は"KPT??? なにそれおいしいの??"状態だったんですが, まぁなんかよくあるアイデア出しの手法だろうと思って軽いノリでいっぱい書きました.
開発用サーバーにログインできるのはpixiv社内のネットワークからのみなので, 当然ホテルでの修正作業はできません.作業はできませんが,issueをみることはできました. 夕飯後から寝るまでの時間に暇を持て余していたのでちょっと明日どうしようか考えていました.
2日目
作業を続けます. PHPも何もよくわかってない自分にそうそう高難易度のissueは取り組めるとは思わなかったので, 簡単な奴をいっぱい取り組むことでちょっとでも開発コード慣れ & PHP慣れしてこうかなと考えていました.
作業中に仕様が変わるくらいなので,設定された難易度ではなく自分にとっての難易度で解いていきます. 他の人にとっては難しくても自分にとっては簡単だったり,その逆もあったりします. 後者は幸いな事に他の優秀な参加者の方が模範的なプルリクを投げてくれているのでそれを参考にして, 最後に投げればよさそうかなと思いました. 脱出数(issu解決数)を競うイベントだとこの戦略は他人の解答を見ているので完全にズルなんですが, 今回はそういう感じでもないし,折角勉強になる良い教材が転がってるんだから取り組もう的なスタンスでやってました.
2日目も作業時刻リミットを超えるとKPTを行います.ここで蓄えられた知見が来年には活かされることでしょう.
最終的には5個くらい脱出できたと思います. すいません4個だったかもしれないです. 完全に自力なのはもっと少ないです. ダメダメですね,精進します.
最後に振り返りです. pixiv側からの総評が行われます. それぞれのバグに関して,どういうバグだったのか解説と参加者のプルリクが紹介されます. バグに対するプルリクの中で最も早く脱出!ラベルが貼られたものが本番に取り込まれるそうです.
まさか採用されると思っていなかった
バグの中にはPHP関係ないものもあり,一番乗りで提出したので採用されたようです. 自分が素早く解ける簡単そうなのから順に解いていったのが功を奏したというところでしょう. もっと他の人が先に提出してるんだと思ってた & 採用基準が順番だと思ってなかったので衝撃でした.
インデントやスペースなど確認しない雑なコミットを度々投げてしまいましたが, しっかりと指摘してもらったうえに「プルリク作成前に確認する癖をつけるとよい」とアドバイスまで頂けました. emacsの設定サボって2回インデントの指摘を受けた時は冷や汗をかきました.
最終日ということで最後に懇親会がありましたが,新幹線の都合で泣く泣く早めに帰ることとなりました. あ,でもピザとビールは美味しくいただいてきました.
終えてみて
SECCON 2015 ONLINE CTF参加しました
チームp3r0zで参加してました.2000点,70位です.
チームメンバーはid:oboenikui, id:yueki1993, @bonprosoftの4人. 後ろの二人は2日目からの参加です.
解いた問題
チームで解いたのは以下のとおりです.
- Start SECCON CTF
- SECCON WARS 2015
- Unzip the file
- Reverse-Engineering Android APK1
- Connect the server
- Command-Line Quiz
- Entry form
- Exec dmesg
- Decrypt it
- Reverse-Engineering Android APK 2
- Steganography 1
- Steganography 3
- 4042
- Last Challenge
この内私が担当してたのがUnzip the file, Connect the server, Command-Line Quiz, Steganography 3, 4042です. SECCON WARSとExec dmesgとSteganography1も少し関わったので書いておきます.
id:oboenikuiが担当した問題はこちらに書いてあります. oboenikui.hatenablog.com
Write Up
僕が解いた問題は他の人も解いてるのであまり意味が無いようにも思いますが, とりあえずWriteUpを載せておきます.
SECCON WARS 2015
去年もあったなぁと思いながらYoutubeみたらQRコードが浮かんでいたのですぐわかりました. STARWARSによくある後ろに流れるアレの上に浮かんでいるので,QRコードリーダーでは読み込めないので どうにかして画像を重ねる必要があります. とりあえずとっさに画面をGIFキャプチャできるソフトを探して@GifGrabberというソフトを見つけたのでGIFをとってoboenikuiに投げました. 続きは上記ブログで.
Unzip the file
結論から言うと既知平文攻撃でした. とりあえず空いていたWindowsマシン上でLhaplusを使って総当りをしかけておきながら,zipの脆弱性を探します.「既知平文攻撃」が速攻でヒットしますが,unzip.zip内にある3つのファイル"backnumber08.txt","backnumber09.txt","flag"のどれも心当たりがありません. なにか別の攻撃方法ではないかとzipの構造を調べていましたが,ふと"backnumber08"でググってみようと思いつきます. (SECCON開催当時)トップでヒットしたのはCEDECのメルマガでしたが,SECCONもメルマガを出していたことを思い出しました. SECCONのバックナンバーからbacknumber08.txtを探し, pkclackを使ってパスワードを解除しました. パス解除後に出たflagをfileコマンドでみるとまたzipなのでunzipしたら,実はdocxファイルだったことが展開内容からわかります. ということでfile.docxに名前を書き換えて開くと真っ白なドキュメントが開かれます. あれ,間違ったか,メタ情報なのかなと思いましたが,ただ白文字で書かれていただけでした.
SECCON{1s_th1s_passw0rd_ weak?}
Connect the server
コンテスト中一番の謎だったんですが,ぶっちゃけコレは僕の手柄というより多分id:yueki1993の手柄でしょう.
とりあえず問題文でアクセスしろと言われた login.pwn.seccon.jp:10000
にnetcat
とssh
を試しましたが空振りに終わりました.
% netcat login.pwn.seccon.jp:10000 Error: Couldn't resolve host "login.pwn.seccon.jp:10000" % ssh -p 10000 login.pwn.seccon.jp # 応答なし
そこで一旦放置して他の問題に取り組んでいる間にslackにyueki1993より
login.pwn.seccon.jp:10000
netcat
という謎の2行の書き込みがありました.てっきりなんとかして解けたんだと思って問題リストを見ましたが,待っても解答マークが付きません. おかしいな,と思ってURLをクリックしたらいきなりダウンロードが始まり,その中にflagが書いてありました. 別にmac付属のテキストエディタで普通に開けたので拍子抜けでした. 彼の行動と問題のアッサリ加減にコンテスト中首をひねっていました.
コンテスト後に聞いてみたところ,"まだ用事の真っ最中でできないけどどうせこれnetcatやろ"と思ってとりあえず投げたらしいです. netcatできなかったけど? と聞いて彼のmacで試してみたらダウンロードされたテキストファイルのflag以外の部分が表示されました. どうやら制御文字でflagが隠されており,それをどうやって読むかという問題だったようです.
SECCON{Sometimes_what_you_see_is_NOT_what_you_get}
Command-Line Quiz
SECCON側が用意したサーバーにログインし,置いてあるテキストファイルを開いてクイズの答えを環境変数に入れることの繰り返し. 正しい答えを環境変数に入れることで次の問題のテキストが開けるようになる仕組みです.問題の内容や答えよりどういう仕組みなのかが気になりました. クイズの内容は本当に簡単なコマンドに関するもので,"テキスト先頭一行目を開く時に使うコマンドは","テキスト末尾一行目を開く時に使うコマンドは","テキストを検索するときに使うコマンドは","テキストを編集するときに使うコマンドは"だとかだったと思います. それぞれ"head","tail","grep","awk"と答えると最後のテキストが開けて,「flag.txtはテキスト編集するコマンドを使えば開けるよ」とだけ書かれていました. とりあえずbinとsbinを覗いてawk以外にテキストの編集に使えそうなコマンドはvi, ed, sedあたりでした. 全部試すつもりでしたが,まぁawkつったらsedだろ,と一番初めに試したsedが正解でした.
SECCON{CaitSith@AQUA}
Exec dmesg
思い出したくない
僕がvirtualbox内でLinux内を探す一方でoboenikuiはisoをマウントして元のtinycorelinuxイメージとdiffをとっていました.
彼がbusybox内のenfthだと見つけてくれたので実行しましたが,ただのdmesg実行結果と差がわかりませんでした.
まだここから何ステップかあるのでは? と萎えて諦めていたら「ちょっと貸して……(目grep)……あるじゃん」と言われました.
もうやだぼくしーてぃーえふやめる
Steganography 1
gpjbってなんだ?と思いfileコマンドを使った所gifと判定されたのでgifとして開くと"SECCON{"とのみ書かれた画像が開けます.
の割には8.4MBと大きいファイルだったので中に埋め込まれているんだろうなぁとgifのファイル終端を検索します.
画像バイナリのマジックナンバー等についてはここにまとめられていて便利でした.
qiita.com
macで参戦していたのでバイナリエディタは0xEDを普段使っているのですが,何故か検索がうまくできません.
それにバイナリの切り貼りも非常にしづらかったので,面倒になってwindows使ってたid:oboenikuiに投げました
こちらも続きは上記ブログで.
誰かmacで使える便利なバイナリエディタ知らないですか? もしくはemacsのhexlモードの機能をまとめてあるページを募集です.
投げた後に「全然足りないけど……」と言われて「じゃあjpegとpngも……」と言いかけたところで問題タイトルの「MrFusion」と拡張子「gpjb」の意味を理解しました, gif, png, jpeg, bmpのfusionだったんですね.
Steganography 3
右下にペイントが開かれててこのスライドの75ページ目を思い出しました
www.slideshare.net まんまでした.SECCON{the_hidden_message_ever}
4042
問題文に書かれていた2005年と問題タイトルの4042で検索したところ,すぐにRFC4042のUTF-9というジョークが見つかりました ここに符号化方法について書いてあったので,pythonでUTF-9からUTF-8化するコードを書きました. どうやって復号するのか最初は戸惑いましたが,non-network.txtには0から7までの数字しか書かれていないので3bitであることがすぐわかります. つまり数字を3つごとに区切れば9bitのバイナリが得られます.上記URLに先頭の1bitで可変長区切りを判断し,下位8bitがUTF-8の8bitになるとあります. pythonのint関数とunichr関数が非常に便利でした.
SECCON{A_GROUP_OF_NINE_BITS_IS_CALLED_NONET}
感想
結果から言えばほぼid:oboenikuiの独壇場でしたね.
コンテスト終わった後今もモリモリ解いていますし.
自分は小スコアな問題をちょこちょこ解いていくくらいしかできなかったので,400点越えの高得点問題も解けるようにならなければと思いました. ただ,その場合メンツをみるに足りてない分野がbinary, exploitあたりだとは思うんですが苦手な分野でどうしようかなという感じです. 嫌だ何だといってられないんでとりあえずIDAとOllyDbgの使い方を覚えようと思います.
久々に土日をコンテストで溶かした気がします.
CODE RUNNER 2015 予選A 参加記
昨年に引き続き参加.
(※ この投稿は予選中に最後のプログラムを回しながら書かれたもの)
詳細なルールは公式ページを見てもらうとして, ゲームの簡単な説明としては200×200の格子点に交差しないように線分を引きまくるというゲーム. HTTP通信でサーバに頂点リストを送信し,サーバから帰ってきたスコアを基にして最終スコアを競う.
後記
放送で聞いた直大さんのアイデアが凄かったのでもうそれでいいんじゃないかな. 少なくとも(おおまかな)座標を求められることが判明したので, 以下の文章は今や完全に陳腐化しているので注意.
考察
200×200の格子点上で2つの頂点を指定して線分を引いていく. スコアに用いるのはユークリッド距離. 全頂点は40000あるのに対して,線分を引くのに使える頂点は1000頂点しかない. 如何に格子形の正方形を塗りつぶすかとして考えてみた. 線分の方向性を揃えて,できうる限り平行な線分を引きまくるのが最大値だろうか? でも頂点の位置情報とかとれないし,せいぜいが近いか遠いかくらい. 近い頂点集団で塊,をつくれるかもしれないが自分にそれが扱える気がしなかった. とりあえず線分数の最大化を狙っていく.
やったこと
スタートダッシュ (約4000点まで)
とりあえずスタートとしてペアを作りまくる戦略を取る. 1から1000まで2つずつのペアを作って交差しなければ追加. これをするだけで4000点はいった.
for i in range(0, 1000, 2): ans_list = kouho[:] ans_list.append(i) ans_list.append(i + 1) ans = ','.join(map(str, ans_list)) url = 'https://game.coderunner.jp/query?token=%s&v=%s' % (token, ans) result = query(url) if int(result) > 140: print ans, result kouho = ans_list
しかしこのやり方でできた頂点ペアはたったの60ペア. 最大が500ペアなのにこれは少ない. 使用可能な頂点のうち約1割程度しか使えていない. もっと使用する線分を増やせないか考える.
頂点の張り替え (増加なし)
使用している頂点の中から邪魔な頂点を外そうとした.
kouho = (一番scoreの良かった線分ペアのリスト) for i in range(1, len(kouho)): lest = all - set(kouho) for j in lest: try_kouho = kouho[:] try_kouho[i] = j ans = ','.join(map(str, try_kouho)) url = 'https://game.coderunner.jp/query?token=%s&v=%s' % (token, ans) result = query(url) if int(result) > score: print ans, result kouho = try_kouho score = int(result) break
しかしほとんど外せない. というか60ペア=120頂点に対して残りの880頂点張替えを試行するのは時間がかかりすぎる. 全然変動しなかったのでプログラムを動かしながら次のプログラムを書き始める.
線分の張り替え(増加なし)
試行が頂点単位だから遅いのではないか. 線分単位で張替えを考える. 使用している線分と残りの線分リストを次々に試していって追加できないかを試す. ともかく使用線分数を増やしたかった. しかしこれもほとんど変化がない.
for i in range(1, len(kouho)): # for elem in itertools.combinations(lest, 2): flag = True for j in range(0, len(lest), 2): try_kouho = kouho[:] #try_kouho[i], try_kouho[i + 1] = elem[0], elem[1] try_kouho[i], try_kouho[i + 1] = lest[j], lest[j + 1] ans = ','.join(map(str, try_kouho)) url = 'https://game.coderunner.jp/query?token=%s&v=%s' % (token, ans) result = query(url) if int(result) > score: print ans, result kouho, score = try_kouho, int(result) flag = False break if flag: continue for j in range(0, len(lest), 2): try_kouho = kouho[:] try_kouho.append(lest[j]) try_kouho.append(lest[j + 1]) ans = ','.join(map(str, try_kouho)) url = 'https://game.coderunner.jp/query?token=%s&v=%s' % (token, ans) result = query(url) if int(result) > score: print ans, result kouho, score = try_kouho, int(result)
線分の追加(6541点まで)/ 最終ver
いやいや,張り替えとか言わずにそもそもペア数が少ないっていうんだから,増やす方法はもっとあるはずだ. 実は今までひとつ隣の頂点IDの頂点としか線分を作っていなかった. きちんと線分の作り方を総当りしてやればもっと追加できる線分はあるはず.
while True: for elem in itertools.combinations(lest, 2): try_kouho = kouho[:] try_kouho.append(elem[0]) try_kouho.append(elem[1]) ans = ','.join(map(str, try_kouho)) url = 'https://game.coderunner.jp/query?token=%s&v=%s' % (token, ans) result = query(url) if int(result) > 0: print ans, result kouho, score = try_kouho, int(result) break else: print elem kouho_set = set(kouho) all = set(range(1000)) lest = list(all - kouho_set)
張り替えに使っていた時間をもっとこちらに回してやればもっと点数が稼げたはず. 最終的に272頂点,136ペアまで作ることができた. 最終成績は55位.50位ボーダーには届かなかった.
やってみたかったこと
距離が小さい線分を大量に用意して,それらを組み合わせるだけでも高得点がとれたのではないだろうか.
距離が小さいからスコアが小さくなる可能性はあるが,その分線分の交差する確率が下がり,ペア数で優位にたてるのでは.
逆に距離が大きい線分を用意して,組み合わせるパターンも試したい.
2014年の予選Aのように今後またフリーで遊べるようになったら試してみよう.
(放送を聞いた感じ距離が大きいのを基にしたほうが良さそうだった.線分の方向性を決定づけられるので.)
感想
やっぱりCODE RUNNER面白い.
でもそろそろプロコン界の有名人参加率が上がってきたようで,
上位に入ることはできなくなってきた.
本戦にギリギリいけるかもしれない,くらいになっている.
これで本戦参加枠が狭まったら参加せずに観戦するだけで終わりそうだ.
予選Bも頑張ります.
変荷重キーボードに憧れて - MINILA Air改造
これまで自宅と研究室とで2種類のキーボードを使ってきた.
自宅ではesrille new keyboard 赤軸
研究室ではFILCO Majestouch MINILA 赤軸 US配列
周囲にはHHKBもRealforce使いもいる.残念ながらKinesis使いはいない. 僕自身Kinesisは気になっているが手が小さいので海外製のKinesisのサイズは大きいのではと懸念している. もし機会があればぜひ試したい.
さておき普段使いのキーボード. 最近左手の小指が痛い.Emacs使いの職業病でもある. や,エディタに関係なくもはやAやShiftを押すのがつらい. Realforceの変荷重が羨ましくなってきた. でもRealforceは省スペースかつUS配列という僕の要望を満たしてくれない. HHKBが変荷重だったらいいのに.
仕方ないのでMINILAを改造して擬似的に変荷重にすることにした. どうせなので有線をやめて無線にしてみることに. 用意したのは以下.
- アキバで買ってきたMINILA Air
- 通販(ジェイダブルシステム)で購入した軸(青・茶・黒・白)各種10個ずつ
- はんだ付け外しに必要なもの一揃い
- 星形ドライバー
はんだ周辺に関しては大学の施設を利用し,星形ドライバーはid:oboenikuiに借りた.
参考にするためネットで情報を収集したが, MINILAを改造した例は多々あるもののMINILA Airについては全く情報がない. Bluetoothがついただけと侮る無かれ.ネジが違う. MINILA Airを開くためには星形ドライバーが必要になる.注意されたし.
その他は特に変わりはない. はんだを取り除いて,キースイッチを外し,取り替えてはんだ付けをする. 今回取り替えたキーは以下のとおり(元は赤軸)
上述の通り,基本は小指の負担を下げるための軸交換となる.
実ははんだ取りは初体験だったため,かなり苦労した. はんだ吸収線のプラスチックを溶かしたり,基盤を傷つけたり.大変な思いをした. この時点で動く保証は全くない.やる前に何かで練習しておけばと強く後悔した.
ひとしきり基板上のはんだを取り除き終えたあたりでキースイッチを引っ張ってみた.外れない. キーから延びる端子と穴との間のはんだが残っていたようで,そのままではスイッチを外せない状態になった. よそのFILCO修理記事やら動画を見る限り,ペンチか何かであっさりと取り外しているように見えたが そう上手くはいかなかった.
困り果てた挙句,再びoboenikuiに泣きつくことに. はんだを当てながらスイッチを引っ張って無理矢理外すことに成功.一人でできる作業ではない. いくつかスイッチを壊しつつも取り替え予定のキーを全て取り外すことができた.
後は用意していおいた各種スイッチをはめてはんだ付けして終了. キーボードに戻してスイッチを入れる. ひょっとしたら1万円+改造にかけた時間がパーになるかもしれない……とドキドキしていると,見事ランプが光った. Bluetoothで接続して取り替えたキーの動作確認を行った結果,全て無事うまくいったらしい.
これでタイピングに関する不満がひとつ解消された. あとタイピング周りといったらDvorakとSKKにはやく慣れるくらいだろうか. 一応数回練習はしたのだが,まだ従来のタイピング法から離れられない. 今度ちょっと何か試してみよう.
当記事は変荷重キーボードで執筆されています.
Cookpadインターンシップに行ってきた(後半)
7日間の後、後半に進むことができたので後半戦の報告です。
大学の集中講義やら勉強会の資料作りやらで間が空いてしまいました。
この記事はこちらの記事の続きです。
前半からの流れ
前半戦として7日間の講義を終え、最終日に後半に進む人の発表がありました。 募集に書いてある通り前半の様子をもとに選抜されるという説明はありましたが、 何人まで絞られるか等はこの時まで知らされていませんでした。 結果、人数は半数近く減り、後半に進むメンバーに自分の名前がありました。 以前投稿したmixiのscrap challengeまでの間東京に残れることが決定し、ホッとしたことを覚えています。 他のメンバーに関してはわかりませんが、自分は機械学習の講義に対する姿勢が評価されたようです。
後半で割り当てられる部署もその「機械学習の講義で◯」という評価を考慮した部署になるとのことでした。 選抜の評価、というのはどうも後半でどの部署に行くことになるかの重要な考慮材料になっているようです。
作業
他の人に聞いた感じだと"issueを貰って(小さい)修正をしてレビューしてもらってプルリク~"といったような、 イマドキのIT企業の開発スタイルな感じでした。 実は今まで僕自身はこの工程に従った開発をしたことがなかったため、 今回初体験となることを期待していたのもインターン応募の理由です。
しかし僕は特殊ケースだったのか、上記の開発スタイルとは違い若干研究よりな作業になりました。 まず、メンターの方からこれから取り掛かる課題について聞いた後,大学で学んだ知識をもとに話し合って方針を相談しました。 実務用の作業環境構築だったり、取り掛かる前に準備する時間があったので合間合間に情報を集めて自分なりに色々考えて、 考えをまとめた後メンターの方に提案・質問をするということを行っていました。 このやり取りはその後の作業を行う中でも終始続きました。 やっぱり自分一人じゃないのって、いいですね。
環境構築後の業務時間はほぼデータと向き合う時間となりました。 issue -> レビュー -> プルリク の流れに憧れていると書いたものの、やはりこのスタイルが一番慣れているようです。 データを見る/解析する -> まとめる -> 考察とともに報告 -> 次の解析 を数日間続けて最終日に報告をまとめてインターンを終えました。
ブログ書き始めてからずっと感じていたのですが、どうも文章を書くのが苦手になってしまったようです。 報告をまとめるのにかなり苦労しました。 世のブロガーが如何に優れているか、自分が読んできた文章が如何にありがたいものだったのかを実感しました。 今も上手く書けるようになりたいなぁと思いながら書いています。
印象
会議用の部屋に閉じこもって講義を受けていた時と違って、社員の方々と同じスペースで7日間をすごしました。 職場を見たことがあるのは数社くらいでしたが、 他と違う(ように感じた)のはエンジニアとエンジニア以外方が机を並べて働いている点でした。 (でも考えてみれば何かのプロジェクトに対してエンジニアやマネージャやデザイナーが組むのは当然のことだし、サンプルに偏りがあったかもしれないです)
あとたまたま重なっただけなのかもしれませんが人の出入りが頻繁に起こる印象です。 ただし、いわゆるエンジニア界隈の"流動が激しい"、というやつとは別です。 単純に産休やら子会社への出向とかと(人手不足による)人員増加とかいう話(だと思います)。
ああ,あとCookpadといったらキッチンですね。 すごく広くて綺麗なキッチンでした。器具も色々あって、できない料理のほうが少ない気がします。 昼に行けば毎日誰かが調理をしていました。 インターン生でもラーメンを作ったようです。 都合により僕は作りませんでしたが。
イベント事も頻繁に合った気がします。 流しそうめんもやりましたし、誕生日も祝ってもらいました。 キッチンでランチを食べてたら何かリリースがあったのかくす玉割りもしてました。 あの感じだとオフィスに数日いれば何かしらのイベントに遭遇するのではないでしょうか。 (勉強会とかを除いても)
まとめ
前半は講義だったのでCookpad社には直接影響しない、(ほぼ)インターン生のみが利益を得る内容でした。
対して実務に携わる後半は、作業内容が会社に利益を与える内容だったので「自分がどこにどういう形で求められているのか」
「何をすると他の人が喜ぶのか」を感じられる期間でした。
僕個人に関して言えばアルバイトをしているものの、成果が出るのかどうかもよく分からないし
「とりあえず試してみよう」の連続で本当にこの作業に意義があるのかなぁと疑問に思うことばかりでした。
ですが今回は後半の7日間で「着実に今自分にできることは何か」「限られたリソースで自分が出せる最大の利益は何か」
という考え方を持って行動できました。
そうやって(程度はどうあれ)成果を出してまとめられたので、ちょっとは自信がついたと思います。
「ああ、自分は社会に出てもいいんだ」と思えた体験でした。
追記(9/20)
ごはん前に仕事を頑張ろうとするとセルフ飯テロになることを学びました
Cookpadインターンシップに行ってきた(前半)
Cookpadのサマーインターンシップに行ってきました.
recruit.cookpad.com
(追記 2015/09/02)機械学習の公開資料URLを追加しました
(追記 2015/09/11)公式に講義資料が公開されたので個々のURLを消してそちらを貼ります
経緯と流れ
実は2年前にもインターンに応募していて(その時はあえなく落選でしたが),2年ぶりのリベンジ応募でした.
事前に過去のインターン記事を漁ってみてはいたのですが,今まで開催されていたのはこちらの5日間サービス開発のコースのみで 今回僕が参加することになったインターンとはまた異なる内容だったようです. recruit.cookpad.com
というわけで来年も行われるかどうかはわかりませんが,新しく始まった技術職インターンシップ体験記を書いていきます. 外部に公開されていた一部の講義資料も載せましたので,今後のご参考にどうぞ.
内容
インターンは前後半に別れていて,前半の講義形式の中で資格アリと見出された者のみが後半に進める構成. オリエンテーションやセットアップを行った後,順次日程にそって講義が行われます. 前半で学ぶ内容は以下の通り.
TDD
Rspecを使ってテスト駆動開発の基本を学びます. プロコンの問題のようなお題が出て,ソレに対してテストを書き,実装するというサイクルを繰り返します. 「TDD知ってる人ー」で皆手を挙げて,「TDDやってる人ー」でパタリと手が下がったのを覚えています. 個人的にはプロコンやってるみたいで楽しかったです. テストケースをあんなに簡単に書ける仕組みがあるならもっとやってくべきだなと思いました. ただ,今回はお題が非常にわかりやすく,テストケースが書きやすかったのですが, 「これのテストって一体何を書いたらいいんだ……?」的なケースに陥った時,本当のテスト力が試される気がします.
Rails
ちょっと昔にMVCをかじったことがある程度でした. その時はerb書きづらいなぁとしか思わなかったです.今回はhaml使いました. URLで指定した画像をタイトルと一緒に投稿するWebアプリを作りました.コメント機能もあります. JSONで叩けるAPIを用意してHerokuにデプロイすることで以降のAndroid・iOS開発にも使いました.
Android開発
Railsで作ったAPIを利用してアプリ開発をしました. モバイルアプリ開発は全くの初めてだったので若干の不安もありました. 実際に作ってみてだんだんとコツを掴んでくると,HTMLとJavaScriptのノリでいける気がする〜とか思う程度になりました. 休日に会ったAndroid開発ガチ勢にそう言ったら鼻で笑われました. contextは未だにわからない.というかいくら説明を聞いても上手く飲み込めない感じがします.
iOS開発
対してAndroidと変わらないだろう,むしろAppleのことだからAndroidよりも作りやすいだろう,とか思っていました. AutoLayoutやばかったですね.レイアウトで詰まる人が多かったように思います. かといって,じゃあAndroidみたいにソースで書いたほうが速いのかというとそんなことありえなかったので慣れるしかなさそうです. 処理の詳しいことまではあまり頭が回りませんでしたが,レイアウトさえ慣れればむしろAndroidよりラクなのかもしれません. 1日ではまだその域まで達することができませんでした.
サービス開発
唯一PCを使わない講義,という触れ込みの講義.
冒頭の通り「cookpad インターン」で過去のインターンを調べると,大体5日間の開発インターンシップが出てくると思います.
(というかそのコースしかこれまでやってなかったハズ)
その中でよく出てくる,価値仮説シート.これ周りの話でした.
新しくサービスを開発するにあたって何に気をつけるのか.
スタートアップに興味がある人には既に見知った内容だったのかもしれないです.
開発において必要な手法,知識を学んだ後,最後は実践ということで,
架空のインタビューを元に簡単なサービスのプロトタイプを作成しました.
今まで知識として聞いてはいたものの,いざやってみると勝手がわからなくて苦労しました.
機械学習
機械学習と自然言語処理に関するチュートリアルの説明を受けた後,
講師の方が用意してくださったword2vecスクリプトを使って色々遊んでいました.
本当は前処理とか学習とか出力整形とか面倒くさそうなことが大量にあるはずなのに,
そこら辺をすべてすっ飛ばしていきなりword2vecするという接待感を感じながら遊んでました.
wikipediaとcookpadそれぞれの辞書から作ったモデルで色々試そう,という内容.
他のインターン生があれこれしている中,僕は熱心に日本酒に合うつまみを探していました.
痛風,怖いですからね.
結果としてビールにおける餃子の役割を果たす日本酒に合う料理は焼売ということでした.
皆さんいいですか.これからはビールに餃子なんて不健康かつオッサンな組み合わせはNGです.
これからのへるしーぷろぐらまーは日本酒に焼売,これです.
プログラミングパラダイム
Cookpadの人も聞きたがる内容,との前評判でどんな講義なのか気になってました.
講義の最初はホントにプログラミング言語の話をしていたかと思いきや,
即座にCPUアーキテクチャの話に移り(もうわからない)さらにコンパイラの話が始まりました.
あらかた簡単な座学を行った後,演習タイム.
SpiderMonkeyの機能を一部流用してオリジナルのJavaScriptコンパイラ(のコードジェネレーター)を作ろう,という内容でした.
「"エグくする"と言ったけど,ごめん,ぜんぜんマゾくならなかった.ちょっとヌルすぎたかも」との談.
nullくなかったです.
後半若干泣きが入りそうになってひいひい言いながら実装していました.
この日一日で最も理解したことは言語処理系の実装するマン頭ヤベえということです.
まとめ
さすがcookpadのインターンシップ,内容も来る学生も凄かったです. どの日もガッツリ演習しました. 何度「はいはいはい!わからないです教えてください!」ってやったか覚えてないです. そんな中で颯爽と課題を全て終わらせて自主的に発展課題を解いてる人達はカッコ良かったですね. 僕も彼らのようになりたいなと思いながら懇親会でビール飲んでました.
同時期に総合職のインターンも行われていたらしく,ラウンジでワイワイやってる様子を見ました. 薄暗くて男しか居ないむさ苦しい部屋で必死にカタカタMacでアプリを作っている一方で, 総合職は男女和気あいあいと日の当たるラウンジでやっていたようです. 住む世界が違うと割りきっていたのであまり羨ましくはなかったのですが,どうにも対照的だったと思います.
講義する側に立って考えれば1日ないし半日で初心者から上級者まで全てをカバーしつつ 演習も行う必要があるというこの無茶ぶり.どんな内容にするか大変苦労したと思います. ありがとうございました.
さてタイトルの通り本記事はまだ半分です. 既に内容の項目で触れた通り,インターンは前後半にわかれています. 2015年のインターンシップは2015年8月18日(火)から9月9日 (水)までで, 最初の7日間が前半で,後の10日間が後半です. これを書いている今日は2015年の8月31日です.日付からお分かりの通り現在後半戦まっただ中です. こちらは実務なのでひょっとしたらほとんど書くことができないかもしれませんが, 前半との違いとか書けることは書こうと思います.
はい,というわけで後半戦頑張ってきます.
mixiのScrapChallengeに行ってきた
mixiのScrapChallenge 2015に行ってきた.
研究室でCTFゼミをやったり,セキュリティの授業に出ていたりしてはいたが,どうにもうだつが上がらない. ここは1つガチ勢に揉まれてこようではないか.
開始前
そんなわけでインターンの合間を縫って渋谷にあるmixi本社にお邪魔してきました.
渋谷って恵比寿から歩いていけるんですね.しかも11時開始,余裕じゃないですか.
そう思ってた時期が僕にもありました.
着いたのは数分前,ギリギリでしたね.
着いた時には皆席についていて,グループ分けがなされていました.
前日にブログ等で事前調査をしたところ,なんか地域で固まるらしい.
案の定id:oboenikuiと同じチームでした.これで安心して難問を投げられます.
遠方から来る人もいるために集合が遅めだったので,
今回の主旨やセキュリティに関する軽い説明を行って昼飯を食べました.
焼き肉焼き肉〜
チュートリアル
とりあえずログインしてみて,XSSを運営に報告するといういわゆるsubmit確認フェイズ.
実はこの時ログインユーザーを間違えてしまった挙句,他人のアカウントでパスも変更してしまうという失態をやらかしていました.
あの時は本当にすいませんでした.
若干時間に余裕があったので問題が公開される前だったけど,どんなページなんかなーとあちこち試してみたりとか.
スタート
いよいよ競技開始です.競技自体はSlackを通じて行われるので,以下の記述はSlackのログを元に書かれています.
あ,問題内容はオフレコなんで,とりあえず雰囲気と進行具合だけです.
大会中は進行に合わせて問題のヒントが公開され,ヒントの分だけ獲得ポイントが下がっていきます.
なんか妨害コンテンツも流れていたらしいですが,普通にいつも聞いてるBGMが流れていた気がします.(あまり覚えてない)
作業BGM探している人はニコニコで"電子ドラッグ"タグ検索するのオススメですよ.
前半戦
何時に始まるんだろう〜とかぼやぼやしている内にスタートしました.(14:00)
スコアボードから全11問の出題と把握していましたが,とりあえず5問のオープンです.
なぜか2問目,3問目から解き始めるチームメンバー達.ぼくは1問目です.
えーと,あーと,なんて戸惑っている内によそのチームがfirst acceptを取り焦る焦る.
なんとかして1問目を解いて提出した際には2問解いてたチームもあったかと.(14:36)
次に何を解けばいいのかわからなかったけど,とりあえず2問目に着手.
この辺で僕と入れ替わりに2問目から5問目にシフトしていたメンバーの提出がaccept(14:57)
うちが2問解けたくらいで別のチームが前半5問を解いて「あ,これは無理かな」と思い始める.
うんうん唸ってとりあえずこれでいいのかな,と提出した2問目が無事accept.(15:19)
後半戦
この頃にはよそのチームが解き進めたことで後半6問もオープンしていました.
大会は後半戦に進行.
ヒントの公開も進んでいき,順調に下がっていくポイント数.精神的焦りがマッハ.
この辺りで「もう俺にはわからん!」と他のメンバーにあとを任せてSQL(6~8問目)に専念.
チームメンバーも5問目をacceptします.(15:35)
oboenikuiが3問目を提出するのとほぼ同時に僕も6問目を提出し,accept.(15:47)
その後延々とSQLを叩き続け7問目,8問目と連続acceptを果たしました(16:04)(16:22)
その後,他の問題はチームメンバーに任せ,僕は9問目に取り組みます.
9問目は最後まで解くことができず,oboenikuiが10問目と11問目をacceptしました(16:23)(16:39)
そしてついに大会終了(16:40)
これ書いてて知ったんですが最後ギリギリだったんですね.
1時間近く9問目に悩まされていたせいで全くチームのことがみえていなかったのですが,
終了後に確認したら9問目以外は全て解き終わってたとのこと.我々の最終成績は10/11でした.
進行と流れ
上記のaccept状況をまとめました.時系列順だと確かこんな感じ.
開始 14:00
問1 14:36
問4 14:57
問2 15:19
問5 15:35
問3 15:47
問6 15:47
問7 16:04
問8 16:22
問10 16:23
問11 16:39
終了 16:40
誰かsecconみたいにイイカンジのスコアグラフお願いします,
と言いたいところだけど実際には正確な点数推移がわからないので無理ですね.
解説
膀胱が限界だったので競技終了後にトイレに飛び込んで帰ってきたら問題解説がスタート.
自分が解いた問題は想定解答をチェックし,解かなかった問題はそもそも何の問題なのかを確認.
つくづくSQL担当で良かったと実感.
最後まで解けなかった9問目ですが(このタイミングでは)解答聞いてもよくわかんなかった.
あとで懇親会直前に質問し直してようやく理解ができて納得.
結果発表
ついに結果発表,という緊張の時間だったはずなんですが9問目の本当の解答が気になってそれどころじゃなかったです.
それよりも9問目の方が重要でした.最優先事項.
3位,2位とチーム名に得点が発表され,最後の1位は我々のチーム
……え,何? 若干の間ぽかんともしたけど,優勝したようです.マジか.
感想とまとめ
9問目,悔しかったですね.
正しい解答を聞いた後には「ああ!」と納得し「いや,でも無理だったな……」と納得したものの,
それでもやっぱり全完したかったです.
さておき今回の勝利は一目見て「あ,よくわからん.無理そう」と思った問題をぶん投げさせてくれて, しかもそれを解答してくれたチームメンバーのおかげだと思います. あんまりチームの方針決めてませんでしたがうまくはまったかな,と.
チームメンバーとこの素晴らしい機会を与えてくれたmixiの方々に感謝です.
運営の方も仰っていましたが,実際のウェブサイトをこんな風に攻撃できる機会はあんまりないです.
常設CTF系はいっぱいありますが,scrap challengeはただflagを取りに行くよりももっと実践的に攻撃できます.
それに,まぁ……常設CTFとかは常設されてるだけあって進んでくと結構難易度高めですし……
あとやっぱりこういう機会がいっぱいあったほうがモチベーションに繋がると思います.
今後こんなにいい成績をとれることはないと思うので当分自慢させてもらいます.