#3に引き続き、解いたのがWeb 100の”jspuzzle”です。
解凍してみると、HTMLとJavascriptが入っているので開いてみます。
どうやら、空欄を下の選択肢から埋めて、alert(1)を実行するコードを作ればいいようです。まさにパズルですね。同じ選択肢は1度しか使えません。
Scriptを読んだところ、10箇所の空欄を結合したSHA1ハッシュ値がFlagになってたので、正攻法以外では解けなさそう。なので、ちゃんとパズルとして考えていきます。
説明上、次の図のように番号を振ります。
最初5行で辞書をつくって、関数オブジェクトをつっこみ、それを最後の行で参照して、実行していることがわかります。7,8の行が実際にalert(1)を実行する箇所ということになります。
まず、“[1]”と、“{9}”[“{10}”]() が同値でないとだめであることから考えます。JavaScriptでは、オブジェクトと辞書は一緒なので、Hoge.fuga()と書いてもHoge[“fuga”]()と書いてもおなじなので、きっと{10}は文字列オブジェクトのメソッドであることがわかります。
ということは、選択肢からtoLowerCaseが{10}で、Functionが{9}、対応してfunctionが{1}であることがわかりました。
同じ原理で、“{2}”と、r[“{7}”](pattern)が同値でなければいけません。rはRegExpオブジェクトなので、{7}は選択肢から考えると”constructor”か”exec”が入ります。constructorの戻り値はまたRegExpオブジェクトなので、違うだろうと推測し、{7}にexecを入れるとr.exec(pattern)となります。では次に{6}を考えてみると、正規表現の文法上/*^_^*/は入りません、それ以外の普通の文字列はいれてしまうと、execの返り値がリストになってしまいます。なので、{6}には^[w]$をいれます。そうするとexecの返り値はnullになります。
ここで疑問がでてきます、{2}は文字列なのに、nullはどうがんばっても入れられないじゃないか!と。ところがJavaScriptは辞書のキーは全部文字列で扱いますので、参照時に自動でキャストされるため”null”で問題ありません。(最初、これはちがうなぁと思っていたので少し時間がかかりました…)。なので、{2}はnullで決まりです。
最後、{3}{4}{5}と{8}ですが、”{3}{4}{5}”と結合すると、命令になるはずなので、で”return hogehoge”となるはずです。しかし、空白は選択肢にありませんが、なんとコメントをいれるとそこは空白扱いになるのです。したがって、{3}はreturn、{4}は/*^_^*/ですね。
ここまで考えると、この新しく生成されている関数で返るオブジェクトをHogeとすると、{8}の 部分ではこういうことになります。
Hoge.{8}(1);
これがalert(1)にならなければいけません。そこで、alertを持っている親オブジェクトを考えると、window….つまりはthisです!ということはreturn thisして、alertを呼びだせばOK
結果、{5}はthis、{8}はalertですね。
殴り書きなので、読みづらいのはスルーしてください…
コメントを残す