InterKosenCTF Writeup [初のイベント型CTFに参戦]
学校の先輩に誘われて、初めてリアルタイムで開催されているCTFに参加してみました(といっても、ksnctfのVillager Aくらいしか解いたことがないので実質CTF処女です)。 3日間の開催でしたが、1日目は早々にして寝落ちしたため、3日目はアマチュア無線の試験を受けに行っていたため取り組めたのは1日だけでした。その1日は先輩と一緒に新宿のルノアールで一日中CTFをやっていました(ルノアールさん長居してごめんなさい)。
webとかcryptoとかはそもそも全く見たこともなかったので解法の検討が全くつきませんでした。なので先輩に任せっきりでした(ごめんなさい)。私が唯一行けそうだなーと思ったのはreversingとpwnだけだったので基本的にその2つだけに集中して取り組みました。 それで、結局解けたのはreversingの100pt問題、「flag generator」だけでした。他の人の参考に、というよりかは解いただけで放置してしまうのはもったいない気がするのでこうして記録しておこうと思った次第です。
問題で渡されたのはx86_64 Linux向けのELFバイナリでした。 実行しても何も表示されず... とりあえず逆アセンブルして読んで見る。
0000000000401152 <r>: 401152: 55 push rbp 401153: 48 89 e5 mov rbp,rsp 401156: 8b 05 f0 2e 00 00 mov eax,DWORD PTR [rip+0x2ef0] # 40404c <s> 40115c: 69 c0 6d 4e c6 41 imul eax,eax,0x41c64e6d 401162: 05 39 30 00 00 add eax,0x3039 401167: 25 ff ff ff 7f and eax,0x7fffffff 40116c: 89 05 da 2e 00 00 mov DWORD PTR [rip+0x2eda],eax # 40404c <s> 401172: 8b 05 d4 2e 00 00 mov eax,DWORD PTR [rip+0x2ed4] # 40404c <s> 401178: 5d pop rbp 401179: c3 ret 000000000040117a <main>: 40117a: 55 push rbp 40117b: 48 89 e5 mov rbp,rsp 40117e: 48 83 ec 50 sub rsp,0x50 401182: 64 48 8b 04 25 28 00 mov rax,QWORD PTR fs:0x28 401189: 00 00 40118b: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax 40118f: 31 c0 xor eax,eax 401191: c7 45 d0 35 59 8f 60 mov DWORD PTR [rbp-0x30],0x608f5935 401198: c7 45 d4 91 64 50 57 mov DWORD PTR [rbp-0x2c],0x57506491 40119f: c7 45 d8 57 55 36 27 mov DWORD PTR [rbp-0x28],0x27365557 4011a6: c7 45 dc a1 de e3 54 mov DWORD PTR [rbp-0x24],0x54e3dea1 4011ad: c7 45 e0 d5 4e 5a 75 mov DWORD PTR [rbp-0x20],0x755a4ed5 4011b4: c7 45 e4 b7 2e f4 17 mov DWORD PTR [rbp-0x1c],0x17f42eb7 4011bb: c7 45 e8 59 90 4f 4a mov DWORD PTR [rbp-0x18],0x4a4f9059 4011c2: c7 45 ec 27 e8 08 1a mov DWORD PTR [rbp-0x14],0x1a08e827 4011c9: c7 45 f0 1f 39 9d 0d mov DWORD PTR [rbp-0x10],0xd9d391f 4011d0: c7 45 f4 aa 33 e5 59 mov DWORD PTR [rbp-0xc],0x59e533aa 4011d7: c7 45 c8 7e 16 dc 25 mov DWORD PTR [rbp-0x38],0x25dc167e 4011de: c7 45 cc 0a 00 00 00 mov DWORD PTR [rbp-0x34],0xa 4011e5: c7 45 c0 00 00 00 00 mov DWORD PTR [rbp-0x40],0x0 4011ec: c7 45 c4 00 00 00 00 mov DWORD PTR [rbp-0x3c],0x0 4011f3: c7 45 bc 00 00 00 00 mov DWORD PTR [rbp-0x44],0x0 4011fa: 83 7d c4 00 cmp DWORD PTR [rbp-0x3c],0x0 4011fe: 75 10 jne 401210 <main+0x96> 401200: bf 00 00 00 00 mov edi,0x0 401205: e8 46 fe ff ff call 401050 <time@plt> 40120a: 89 05 3c 2e 00 00 mov DWORD PTR [rip+0x2e3c],eax # 40404c <s> 401210: b8 00 00 00 00 mov eax,0x0 401215: e8 38 ff ff ff call 401152 <r> 40121a: 89 45 bc mov DWORD PTR [rbp-0x44],eax 40121d: 8b 45 bc mov eax,DWORD PTR [rbp-0x44] 401220: 39 45 c8 cmp DWORD PTR [rbp-0x38],eax 401223: 75 07 jne 40122c <main+0xb2> 401225: c7 45 c4 01 00 00 00 mov DWORD PTR [rbp-0x3c],0x1 40122c: 83 7d c4 00 cmp DWORD PTR [rbp-0x3c],0x0 401230: 74 35 je 401267 <main+0xed> 401232: 8b 45 c0 mov eax,DWORD PTR [rbp-0x40] 401235: 48 98 cdqe 401237: 8b 54 85 d0 mov edx,DWORD PTR [rbp+rax*4-0x30] 40123b: 8b 45 bc mov eax,DWORD PTR [rbp-0x44] 40123e: 31 d0 xor eax,edx 401240: 89 45 bc mov DWORD PTR [rbp-0x44],eax 401243: 48 8d 45 bc lea rax,[rbp-0x44] 401247: 48 89 c6 mov rsi,rax 40124a: 48 8d 3d b3 0d 00 00 lea rdi,[rip+0xdb3] # 402004 <_IO_stdin_used+0x4> 401251: b8 00 00 00 00 mov eax,0x0 401256: e8 e5 fd ff ff call 401040 <printf@plt> 40125b: 83 45 c0 01 add DWORD PTR [rbp-0x40],0x1 40125f: 8b 45 c0 mov eax,DWORD PTR [rbp-0x40] 401262: 3b 45 cc cmp eax,DWORD PTR [rbp-0x34] 401265: 74 0c je 401273 <main+0xf9> 401267: bf 01 00 00 00 mov edi,0x1 40126c: e8 ef fd ff ff call 401060 <sleep@plt> 401271: eb 87 jmp 4011fa <main+0x80> 401273: 90 nop 401274: b8 00 00 00 00 mov eax,0x0 401279: 48 8b 4d f8 mov rcx,QWORD PTR [rbp-0x8] 40127d: 64 48 33 0c 25 28 00 xor rcx,QWORD PTR fs:0x28 401284: 00 00 401286: 74 05 je 40128d <main+0x113> 401288: e8 a3 fd ff ff call 401030 <__stack_chk_fail@plt> 40128d: c9 leave 40128e: c3 ret 40128f: 90 nop
適当にジャンプ命令をnopで埋めてみたりしていたら、何やらよくわからない文字が出力されました。 この文字は一体どこからきているのだろうとアセンブラを見てみると 40121aでr()の返り値がDWORD PTR [rbp-0x44]に代入されてそれを元に演算した結果が出力されていると分かりました。 なのでDWORD PTR [rbp-0x44]が正しい文字になるようにしてあげればよいのです。
じゃあ正しい文字になるような値ってなんだよとまたアセンブラを見直してみると最初にnopで埋めていたジャンプ命令の前にcmp DWORD PTR [rbp-0x38],eaxというのがあったのでここからDWORD PTR [rbp-0x38]がその値であると分かりました。
それでこの値をDWORD PTR [rbp-0x44]に入れてstep実行してみると「KOSE」という文字が出力されたのでよっしゃと思い続く処理もステップ実行してみたのですが、その後の文字はうまくASCIIにはなっていませんでした。
それでなにがいけないのかともう一度見直して、そもそもこのr()の返り値は40404cを元に計算されていることを発見し、またこの40404cはループ毎に変化する値であることが分かりました。それで、じゃあ最初のr()を実行し終わった後だけ手動で40404cとDWORD PTR [rbp-0x44]にDWORD PTR [rbp-0x38]の値をいれてステップ実行してみると次のような出力を得られました。
0x45534f4b 0x14654434e 0x25f53497b 0x353494854 0x44145525f 0x55f594c4c 0x645525f41 0x753524556 0x83f474e49 0x90000007d
最後の7dは「}」なので、これはFLAGだ!と思いどうにかこねくり回してFLAGにするのだと思い眺めてみると、MSBが0から9の値で変化していることに気づきました。これがあるせいでうまく文字に出来なかったのですが、これを除いて文字にしてみると見事FLAGが取得できました。
KOSENCTF{IS_THIS_REALLY_A_REVERSING?}
結局1問しか解けませんでしたが、初めて自力で解けたので結構感動しました。CTF面白いね!運営の皆さんありがとうございました。