ksnctf write-up #3
問題3 Crawling Chaos
https://ksnctf.sweetduet.info/problem/3
考察
- ソースコード表示してスクリプト箇所を確認
- スクリプトをconsole.log()で実行し、難読化を復号
- JavaScriptのロジックを確認
解法
スクリプトをconsole.log()で実行すると、
$(function(){ $("form").submit(function(){ var t=$('input[type="text"]').val(); var p=Array(70,152,195,284,475,612,791,896,810,850,737,1332,1469,1120,1470,832,1785,2196,1520,1480,1449); var f=false; if(p.length==t.length){ f=true; for(var i=0;i<p.length;i++) if(t.charCodeAt(i)*(i+1)!=p[i]) f=false; if(f)alert("(」・ω・)」うー!(/・ω・)/にゃー!"); } if(!f)alert("No"); return false; }); });"
が得られる。(インデント・改行は追加したもの)
このスクリプトから、
- formタグがsubmitされる
- 入力した文字数が配列pの数と同じであること
- 入力した文字列をcharCodeAtメソッドで文字コードに変換して(i番目+1)をかけた数値が配列pのi番目と同じであること
- 正解なら"(」・ω・)」うー!(/・ω・)/にゃー!"
- 不正解なら"No"とアラートで出す
- 配列pのi番目の数値を(i+1)で割って文字にすると答えがでそう
がわかる。
charCodeAtメソッド
文字列の中から指定の位置にある文字の文字コードを返す。
パラメータ:int インデックス
戻り値:指定された位置の文字の文字コード(整数)
変換スクリプト
p = [70,152,195,284,475,612,791,896,810,850,737,1332,1469,1120,1470,832,1785,2196,1520,1480,1449] for i in range(len(p)): print(chr(int((p[i] / (i+1)))),end="")
python3で改行なしでprintする
print関数のendオプションに「""」を指定する
print("文字列", end="")
JavaScriptの振り返り
問題のスクリプトは、JavaScriptを(」・ω・)」うー!(/・ω・)/にゃー!に変換するものらしい。
(」・ω・)」うー!(/・ω・)/にゃー!encode
(」・ω・)」うー!(/・ω・)/にゃー!encode - kusano-k’s blog
(ᒧᆞωᆞ)=(/ᆞωᆞ/); (ᒧᆞωᆞ).ᒧうー=-!!(/ᆞωᆞ/).にゃー; (〳ᆞωᆞ)=(ᒧᆞωᆞ); (〳ᆞωᆞ).〳にゃー=- -!(ᒧᆞωᆞ).ᒧうー; (ᒧᆞωᆞ).ᒧうーー=(〳ᆞωᆞ).〳にゃー- -!(ᒧᆞωᆞ).ᒧうー; (〳ᆞωᆞ).〳にゃーー=(ᒧᆞωᆞ).ᒧうーー- -(〳ᆞωᆞ).〳にゃー; (ᒧᆞωᆞ).ᒧうーー=(〳ᆞωᆞ).〳にゃーー- -!(ᒧᆞωᆞ).ᒧうー; (〳ᆞωᆞ).〳にゃーー=(ᒧᆞωᆞ).ᒧうーー- -(〳ᆞωᆞ).〳にゃー; (ᒧᆞωᆞ).ᒧうーーー=(〳ᆞωᆞ).〳にゃーー- -!(ᒧᆞωᆞ).ᒧうー; (〳ᆞωᆞ).〳にゃーーー=(ᒧᆞωᆞ).ᒧうーーー- -(〳ᆞωᆞ).〳にゃー; (ᒧᆞωᆞ).ᒧうーーー=(〳ᆞωᆞ).〳にゃーーー- -!(ᒧᆞωᆞ).ᒧうー; (〳ᆞωᆞ).〳にゃーーー=(ᒧᆞωᆞ).ᒧうーーー- -(〳ᆞωᆞ).〳にゃー; ー=''; (ᒧᆞωᆞ).ᒧうーーー=!(ᒧᆞωᆞ).ᒧうー+ー;
- varを付けないで宣言した変数はグローバル変数になる
- グローバル変数をパーレン「( )」で囲っても代入できる
- 変数名やプロパティ名にマルチバイト文字が使用可能
- スクリプトの冒頭で、記号変数に数値等を代入
(ᒧᆞωᆞ) = /ᆞωᆞ/ (ᒧᆞωᆞ).ᒧうー = -0 (〳ᆞωᆞ) = /ᆞωᆞ/ (〳ᆞωᆞ).〳にゃー = 1 (ᒧᆞωᆞ).ᒧうーー = 2 (〳ᆞωᆞ).〳にゃーー = 3 (ᒧᆞωᆞ).ᒧうーー = 4 (〳ᆞωᆞ).〳にゃーー= 5 (ᒧᆞωᆞ).ᒧうーーー = 6 (〳ᆞωᆞ).〳にゃーーー = 7 (ᒧᆞωᆞ).ᒧうーーー = 8 (〳ᆞωᆞ).〳にゃーーー = 9 ー="" (ᒧᆞωᆞ).ᒧうーーー = "true"
- 文字列をコードとして評価する
- eval関数でも可能だが、console.logとかに置き換えられるとナンセンス
- Functionコンストラクタも文字列をコードとして評価可能
hoge = Function("return 10 * 10;"); # 置き換え var hoge = function () { return 10 + 10; }
-
- Functionコンストラクタの即時実行関数
Function("return 10 + 10;")();
-
- Number.constructor === Function
Number.constructor("return 10 + 10;")(); Array.constructor("return 10 + 10;")(); Object.constructor("return 10 + 10;")();
参考にしたサイト
難読化JavaScriptの作り方