CSAW CTF 2013 Reversing 150 bikinibonanza Writeup
まずは起動してみます。すると直感で.NETプログラムだという事が分かります。
なのでとりあえずILSpyで開いてみます。
するとメソッド名が難読化されてeval_□になっています。
まずは怪しそうなボタンのクリックされた時の処理を見てみます。
private void eval_□(object obj, EventArgs eventArgs) { string strB = null; Assembly executingAssembly = Assembly.GetExecutingAssembly(); ResourceManager resourceManager = new ResourceManager(executingAssembly.GetName().Name + ".Resources", executingAssembly); DateTime now = DateTime.Now; string arg_65_0 = this.eval_□.Text; string value = string.Format("{0}", now.Hour + 1); string text = "NeEd_MoRe_Bawlz"; this.eval_□(text, Convert.ToInt32(value), ref strB); if (string.Compare(arg_65_0.ToUpper(), strB) == 0) { this.eval_□.Text = ""; this.eval_□(this.eval_□(107)); this.eval_□(); this.eval_□.Text = string.Format(this.eval_□.Text, this.eval_□(resourceManager)); this.eval_□.Image = (Bitmap)resourceManager.GetObject("Sorry You Suck"); } else { this.eval_□.Image = (Bitmap)resourceManager.GetObject("Almost There"); this.eval_□(); } }
処理が多少難読化されていますが、string.Compareで比較しているのでそこを見ていきます。
入力した文字(arg_65_0)とstrBを比較していて、strBは現在時刻のhourを使って生成していることが分かります。
同じことをするプログラムを作って入力するとkeyが出てきます。
しかし、なぜかこのkeyでは通りませんでした。
想定では正しいkeyが表示されるようですが、環境によるのか、間違ったkeyが出てきたチームが多かったみたいです。
とりあえず出てきたkeyで検索してみると、"???????????????????????"のハッシュ値らしいということが分かります。
どこかで文字化けしているような気がしてきたので、次はkeyを生成・表示しているところを見ていきました。
private unsafe string eval_□(ResourceManager resourceManager) { string @string = resourceManager.GetString("numbers"); int length = @string.Length; sbyte* ptr = (sbyte*)Marshal.StringToHGlobalAnsi(@string).ToPointer(); <Module>.eval_□(ptr, length); string text = new string((sbyte*)ptr); return this.eval_□(text); }
keyの生成は単純で、まずはリソースから"ThisIsASecretSeedYouCanSeeTheSecretSeed"というシード値を取得してきます。
次に<Module>.eval_□でこの文字列を変換して、そのmd5ハッシュ値がkeyになります。
しかし、<Module>.eval_□はネイティブコードなので、ILSpyでは解析できません。
次に、この関数をIL DASMで見てみます。
すると、この関数は 0x00001490 に配置されるらしい、という事が分かります。
OllyDbgで動かしながらそれっぽいアドレスを見るとそれっぽい処理が出てきます。
アセンブリからC#に書き直してみるとこんな感じになります。
public string Hoge(string seed) { var result = seed.ToCharArray(); for (int i = 0; i < seed.Length; i++) { result[i] = (char)(result[i] ^ 0x2); } for (int i = 0; i < seed.Length; i++) { result[i] = (char)(result[i] ^ 0xfb); } return new string(result); }
というわけで答えは key(0920303251BABE89911ECEAD17FEBF30) でした。
終わった後に他の人に聞いてみたところ、PMで運営に解き方を話したら正しいフラグを貰えたみたいです。
難易度的にはrev200よりも難しいかなーという感じでした。
今回は本当に何もできなかったので来年から本気出します。
おしまい。