setodaNoteCTF Writeup[Rev]
Rev
Helloworld
50
気が付くと椅子に座っていた。簡単なテストから始めよう。ガラスを隔てて真正面に白衣の女が立っている。 君が優秀であることを示してくれ。声は天井のスピーカーから聞こえてくるようだ。 心配はいらない。そばにある端末が起動する。どちらにしてもすぐに済む。 添付されたファイルを解析してフラグを得てください。 ファイルは「infected」というパスワード付き ZIP になっています。
ZIPをパスワードinfectedで解凍
VirusTotalで若干検知ありなので、仮想マシンで実行してみる
メッセージに従って引数を渡したり試したらクリア
>~\helloworld.exe Nice try, please set some word when you run me. >~\helloworld.exe a Good job, but please set 'flag' when you run me. >~\helloworld.exe flag flag{xxxxx}`
ELF
80
監獄というより研究室のような施設だった。見る角度が大切なんだ。ガラスで隔てたられた部屋を 白衣の男が歩いている。すべてを疑ってみることから始める。そばにある端末の電源が入る。 手を動かして検証するというのは実に大事なことだ。 添付されたファイルを解析してフラグを入手してください。
ファイルコマンドで見ると、dataとなっていて、詳細不明
$ file elf elf: data
stringsでみてみる
$ strings elf XXXX /lib64/ld-linux-x86-64.so.2 puts __cxa_finalize __libc_start_main libc.so.6 GLIBC_2.2.5 _ITM_deregisterTMCloneTable __gmon_start__ _ITM_registerTMCloneTable u/UH NDIOSZ]FH wEICAJIUH []A\A]A^A_ ;*3$" GCC: (Debian 10.2.1-6) 10.2.1 20210110 :
フラグっぽいものはない
ファイル名がelfであり、stringsコマンドの結果にgcc、libc.so.6などがあるので、elfファイルっぽい
XXXXがやや気になる
ファイルをバイナリエディタでみると、先頭が不自然に以下になっている
このせいでファイルタイプが不明なのでは?
(gccやghidraもうまく読み込めず)
58 58 58 58 XXXX
ELFファイルという前提で、以下に書き換える
7F 45 4C 46 .ELF
ghidraで開けるようになった
権限をつけ、実行してみる
$ chmod 755 elf $ ./elf flag{xxxxx}
(参考)odコマンドで先頭64バイト表示(ビックエンディアン指定)
(バイトオーダーしていないとリトルエンディアンになるっぽい)
$ od -Ax -tx --endian=big -N 64 elf 000000 7f454c46 02010100 00000000 00000000 000010 03003e00 01000000 50100000 00000000 000020 40000000 00000000 50310000 00000000 000030 00000000 40003800 0b004000 1c001b00 000040
Passcode
ひとまず、stringsコマンドで見てみる
$ strings passcode : Invalid passcode. Invalid passcode. Too short. Invalid passcode. Too long. 20150109 The passcode has been verified. :
日付のような文字列が怪しいので試す
$ ./passcode Enter the passcode: 20150109 The passcode has been verified. Flag is : flag{xxxxx}
Passcode2
150
予想以上の結果だった。今日もガラス越しに対象が目を覚ます。ここまでうまくいったことはかつてない。 端末に今日のデータを送信する。今度こそうまくいくかもしれない。 添付されたファイルを解析してフラグを得てください。
ghidraで開く
以下のコードが関係ありそう
パスコードは11桁
パスコードがそのままフラグ
undefined8 FUN_00101175(void) { int iVar1; undefined8 uVar2; size_t sVar3; byte local_124 [4]; undefined local_120; undefined local_11f; undefined local_11e; undefined local_11d; undefined local_11c; undefined local_11b; undefined local_11a; undefined local_119; undefined8 local_118; undefined8 local_110; undefined8 local_108; undefined8 local_100; undefined8 local_f8; undefined8 local_f0; undefined8 local_e8; undefined8 local_e0; undefined8 local_d8; undefined8 local_d0; undefined8 local_c8; undefined8 local_c0; undefined8 local_b8; undefined8 local_b0; undefined8 local_a8; undefined8 local_a0; undefined8 local_98; undefined8 local_90; undefined8 local_88; undefined8 local_80; undefined8 local_78; undefined8 local_70; undefined8 local_68; undefined8 local_60; undefined8 local_58; undefined8 local_50; undefined8 local_48; undefined8 local_40; undefined8 local_38; undefined8 local_30; undefined8 local_28; undefined8 local_20; ulong local_10; local_118 = 0; local_110 = 0; local_108 = 0; local_100 = 0; local_f8 = 0; local_f0 = 0; local_e8 = 0; local_e0 = 0; local_d8 = 0; local_d0 = 0; local_c8 = 0; local_c0 = 0; local_b8 = 0; local_b0 = 0; local_a8 = 0; local_a0 = 0; local_98 = 0; local_90 = 0; local_88 = 0; local_80 = 0; local_78 = 0; local_70 = 0; local_68 = 0; local_60 = 0; local_58 = 0; local_50 = 0; local_48 = 0; local_40 = 0; local_38 = 0; local_30 = 0; local_28 = 0; local_20 = 0; local_124[0] = 0x18; local_124[1] = 0x1f; local_124[2] = 4; local_124[3] = 0x79; local_120 = 0x4f; local_11f = 0x5a; local_11e = 4; local_11d = 0x18; local_11c = 0x1a; local_11b = 0x1b; local_11a = 0x1e; local_119 = 0; printf("Enter the passcode: "); iVar1 = __isoc99_scanf("%255[^\n]%*[^\n]",&local_118); if (iVar1 == -1) { uVar2 = 1; } else { __isoc99_scanf(&DAT_0010202c); if ((char)local_118 == '\0') { printf("Invalid passcode."); } else { sVar3 = strlen((char *)&local_118); if (sVar3 < 0xb) { printf("Invalid passcode. Too short."); } else { sVar3 = strlen((char *)&local_118); if (sVar3 < 0xc) { sVar3 = strlen((char *)&local_118); if (sVar3 == 0xb) { local_10 = 0; while ((sVar3 = strlen((char *)local_124), local_10 < sVar3 && (*(byte *)((long)&local_118 + local_10) == (local_124[local_10] ^ 0x2a)))) { local_10 = local_10 + 1; } sVar3 = strlen((char *)local_124); if (local_10 == sVar3) { puts("The passcode has been verified.\n"); printf("Flag is : flag{\%s}",&local_118); ★mdファイル変換でエラーとなるので\%としている } else { printf("Invalid passcode. Nice try."); } } else { printf("Invalid passcode."); } } else { printf("Invalid passcode. Too long."); } } } putchar(10); uVar2 = 0; } return uVar2; }
特に以下がポイントで、これを満たすパスコードを探す
if (sVar3 == 0xb) { local_10 = 0; while ((sVar3 = strlen((char *)local_124), local_10 < sVar3 && (*(byte *)((long)&local_118 + local_10) == (local_124[local_10] ^ 0x2a)))) { local_10 = local_10 + 1; } sVar3 = strlen((char *)local_124); if (local_10 == sVar3) { puts("The passcode has been verified.\n");
Excelで計算したが、local_124[local_10] ^ 0x2aは10進数で以下のように変化するハズ
XOR(DEC) XOR(bin) 50 110010 53 110101 46 101110 83 1010011
11桁だとオーバーフローさせる?(難しい)
(ブレークポイントをどこに設定するかがわかれば)gdbでデバッグしながら試してみるというのはできそう
$ echo 12345678901 | ./passcode2 Enter the passcode: Invalid passcode. Nice try.
総当たりも考えたが、11桁だと難しそう
(ここまで)
(解けていない)
(追記)ASCIIに直すとフラグがでてくるとのこと
https://muchipopo.com/ctf/setoda-writeup/#toc4
もう少しだったと思う反面、local_124[3]より後ろのlocal_120からがghidraでは
別変数に見えていたのでやっぱり気づかなかったかな・・・
local_124[0] = 0x18; local_124[1] = 0x1f; local_124[2] = 4; local_124[3] = 0x79; local_120 = 0x4f; local_11f = 0x5a; local_11e = 4; local_11d = 0x18; :
to_analyze
200
あの施設はなんだったのだろう。ふとした瞬間に思い出す。「秘密情報が含まれているファイルを入手した。 特定の環境で実行した場合のみ情報が表示される仕組みのようだが条件が特定できない。 解析してみてくれないか。」同僚から連絡が入る。端末を開き受信データを確認する。 今日の解析対象が画面に表示される。 添付されたファイルを解析してフラグを入手してください。 ファイルは「infected」というパスワード付き ZIP になっています。
思つくのは(マルウェアとかで聞いたことがあるのは)
・タイムゾーン設定
・OS言語設定
・特定のフォルダに特定のファイルがある
とか?
ghidraにて見たが、わからず
(解けていない)
(追記).NETで作られているので、デコンパイラILSPYなどで解析できるとのこと
https://muchipopo.com/ctf/setoda-writeup/#toc4