Writeup: Beginners CTF 2019 [Web][warmup] Ramen

はじめに

まず、問題のページへ飛ぶ。

ラーメン美味しそう。そう、この問題は深夜に手を付けてはいけないので注意が必要。

サイトの観察

まずは、いろいろ触ってみる。そうすると以下のようなことがわかる。

  • ラーメンが美味しそう。
  • 検索画面があって、username で一言情報の絞り込みができる。
  • 検索は部分一致

部分一致ができるということは、SQLのLIKE文を使っているということを踏まえてもっと触ると以下のことがわかる。

  • ラーメンが美味しそう。
  • 「%」で検索すると初期表示と一緒(全件表示)である。
  • シングルクォート(「’」)を入れると、php の fetchAll() 関数でのエラーがでてくる。

ということで、これは SQLインジェクション問題という事を察することができる。

flagを探す

flag は、サーバ上のファイルとして置かれているか、データベース上にあると推測し、まずはデータベース上のデータを探す。また、サーバ上で実行されるSQLとして、次のようなSQLを想定した上でクエリを投げる。

SELECT username, comment FROM tbl WHERE username like '%(入力された文字)%'

使われている RDBMS は不明だが、製品はそう多くないので、まずはMySQLあたりを想定して、テーブル一覧の取得を試みる。
MySQL の場合、INFORMATION_SCHEMA というスキーマ内の各種テーブルから各種情報が取得できるので、次のような検索をする。

そうすることで、次の結果が得られる。

というわけで、「app.flag」と「app.members」の2つのテーブルがあることがわかったので、次は「flag」を取りに行く。
同様の手法で INFORMATION_SCHEMA.COLUMN からカラム名を確認しておく。

からの

ということで、app.flag.flag を取りに行けば良いことがわかる。
なので、次の内容を検索欄に入力し検索を行う。

' union all select flag,null from app.flag -- 

※fetchAll() は配列で返すので、2列必要なことに注意。
 値は何でも良いが、今回はnullにしておく。

結果は下記

ということで、flagの「ctf4b{a_simple_sql_injection_with_union_select}」が、美味しそうなチャシュー及び卵の黄身の画像と一緒に取り出せる。

最後に

ラーメンは飲み物

Writeup: Beginners CTF 2019 [Misc]containers

問題について

「Let’s extract files from the container. 」ということで、ファイルが1個提供される。
コンテナから取り出せということで、このファイルの中をバラして flag を得るようだということがわかる。

調査

まずは、与えられたファイルの中身を調べてみる。
こんなときは binwalk にお願いする。

$ binwalk e35860e49ca3fa367e456207ebc9ff2f_containers 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
16            0x10            PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
107           0x6B            Zlib compressed data, compressed
738           0x2E2           PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
829           0x33D           Zlib compressed data, compressed
1334          0x536           PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
1425          0x591           Zlib compressed data, compressed
1914          0x77A           PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
2005          0x7D5           Zlib compressed data, compressed
2856          0xB28           PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
2947          0xB83           Zlib compressed data, compressed
3666          0xE52           PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
3757          0xEAD           Zlib compressed data, compressed
4354          0x1102          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
4445          0x115D          Zlib compressed data, compressed
5156          0x1424          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
5247          0x147F          Zlib compressed data, compressed
5846          0x16D6          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
5937          0x1731          Zlib compressed data, compressed
6722          0x1A42          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
6813          0x1A9D          Zlib compressed data, compressed
7757          0x1E4D          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
7848          0x1EA8          Zlib compressed data, compressed
8338          0x2092          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
8429          0x20ED          Zlib compressed data, compressed
9243          0x241B          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
9334          0x2476          Zlib compressed data, compressed
10319         0x284F          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
10410         0x28AA          Zlib compressed data, compressed
11042         0x2B22          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
11133         0x2B7D          Zlib compressed data, compressed
12118         0x2F56          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
12209         0x2FB1          Zlib compressed data, compressed
12809         0x3209          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
12900         0x3264          Zlib compressed data, compressed
13845         0x3615          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
13936         0x3670          Zlib compressed data, compressed
14592         0x3900          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
14683         0x395B          Zlib compressed data, compressed
15535         0x3CAF          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
15626         0x3D0A          Zlib compressed data, compressed
16440         0x4038          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
16531         0x4093          Zlib compressed data, compressed
17313         0x43A1          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
17404         0x43FC          Zlib compressed data, compressed
18218         0x472A          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
18309         0x4785          Zlib compressed data, compressed
19123         0x4AB3          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
19214         0x4B0E          Zlib compressed data, compressed
19926         0x4DD6          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
20017         0x4E31          Zlib compressed data, compressed
20869         0x5185          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
20960         0x51E0          Zlib compressed data, compressed
21742         0x54EE          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
21833         0x5549          Zlib compressed data, compressed
22465         0x57C1          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
22556         0x581C          Zlib compressed data, compressed
23408         0x5B70          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
23499         0x5BCB          Zlib compressed data, compressed
23989         0x5DB5          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
24080         0x5E10          Zlib compressed data, compressed
24810         0x60EA          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
24901         0x6145          Zlib compressed data, compressed
25753         0x6499          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
25844         0x64F4          Zlib compressed data, compressed
26788         0x68A4          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
26879         0x68FF          Zlib compressed data, compressed
27599         0x6BCF          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
27690         0x6C2A          Zlib compressed data, compressed
28504         0x6F58          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
28595         0x6FB3          Zlib compressed data, compressed
29085         0x719D          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
29176         0x71F8          Zlib compressed data, compressed
29808         0x7470          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
29899         0x74CB          Zlib compressed data, compressed
30844         0x787C          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
30935         0x78D7          Zlib compressed data, compressed
31524         0x7B24          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
31615         0x7B7F          Zlib compressed data, compressed

ということで、いくつかの PNGファイルが入っていることがわかる。

分解

引き続き binwalk を使って取り出す。

$ binwalk --dd '.*' e35860e49ca3fa367e456207ebc9ff2f_containers
(略)

先ほどと同様な表示がされるが、先ほどとの違いは「_e35860e49ca3fa367e456207ebc9ff2f_containers.extracted」というフォルダに切り出したあとのファイルがすべて格納されている。
gnomeのファイラー(nautilus)などで確認すると、アルファベットの画像が入っていることがわかる。

flag の導き出し

抽出したファイル名は、ファイルの中のオフセットの位置が16進数になっている。
数値の若い順に拾ってみると「ctf・・・」と読めるので、それが flag だろうと踏んで、並び替えてみる。
手法は悩んだけど、40個ぐらいなので手動でスプレッドシートにアドレスと文字を転記してソートをかける。
ソートしたら、「特殊貼付け」の「転地して貼り付け」で横に並べる。

するとこんな感じ。

最後に転地した文字をコピー&ペーストして、邪魔なタブを除去して得られたflag
「」提出して終わりです。

余談

並び替えするときに、桁を合わせても nautilus の並び替えだと何故か上手くソートができず、上記手法にしました。
ImageMagick等で画像結合していくのも考えたけど悲鳴を上げる量ではなかったし、どのみち画像の文字を人が目で見て手で入力する必要がでてくるので、上記手法にしました。

Writeup: Beginners CTF 2019 [Reversing][warmup] Seccompare

問題ファイルの分析

与えられたファイルを解凍すると「seccompare」 というファイルが出てくる。 このファイルを fileコマンドで確認する。

$ file seccompare
seccompare: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=4a607c82ea263205071c80295afe633412cda6f7, not stripped

出力結果から、ELF形式の実行ファイルであることがわかる。

gdbで処理の流れを確認する

まずは、gdm を使ってファイルを読み込ませる。

$ gdb ./seccompare

disasコマンドを使用して main処理の流れを確認する。

(gdb) disas main
Dump of assembler code for function main:
   0x00000000004005e7 <+0>:	push   %rbp
   0x00000000004005e8 <+1>:	mov    %rsp,%rbp
   0x00000000004005eb <+4>:	sub    $0x40,%rsp
   0x00000000004005ef <+8>:	mov    %edi,-0x34(%rbp)
   0x00000000004005f2 <+11>:	mov    %rsi,-0x40(%rbp)
   0x00000000004005f6 <+15>:	mov    %fs:0x28,%rax
   0x00000000004005ff <+24>:	mov    %rax,-0x8(%rbp)
   0x0000000000400603 <+28>:	xor    %eax,%eax
   0x0000000000400605 <+30>:	cmpl   $0x1,-0x34(%rbp)
   0x0000000000400609 <+34>:	jg     0x400630 <main+73>
   0x000000000040060b <+36>:	mov    -0x40(%rbp),%rax
   0x000000000040060f <+40>:	mov    (%rax),%rax
   0x0000000000400612 <+43>:	mov    %rax,%rsi
   0x0000000000400615 <+46>:	lea    0x168(%rip),%rdi        # 0x400784
   0x000000000040061c <+53>:	mov    $0x0,%eax
   0x0000000000400621 <+58>:	callq  0x4004e0 <printf@plt>
   0x0000000000400626 <+63>:	mov    $0x1,%eax
   0x000000000040062b <+68>:	jmpq   0x4006e1 <main+250>
   0x0000000000400630 <+73>:	movb   $0x63,-0x30(%rbp)
   0x0000000000400634 <+77>:	movb   $0x74,-0x2f(%rbp)
   0x0000000000400638 <+81>:	movb   $0x66,-0x2e(%rbp)
   0x000000000040063c <+85>:	movb   $0x34,-0x2d(%rbp)
   0x0000000000400640 <+89>:	movb   $0x62,-0x2c(%rbp)
   0x0000000000400644 <+93>:	movb   $0x7b,-0x2b(%rbp)
   0x0000000000400648 <+97>:	movb   $0x35,-0x2a(%rbp)
   0x000000000040064c <+101>:	movb   $0x74,-0x29(%rbp)
   0x0000000000400650 <+105>:	movb   $0x72,-0x28(%rbp)
   0x0000000000400654 <+109>:	movb   $0x31,-0x27(%rbp)
   0x0000000000400658 <+113>:	movb   $0x6e,-0x26(%rbp)
   0x000000000040065c <+117>:	movb   $0x67,-0x25(%rbp)
   0x0000000000400660 <+121>:	movb   $0x73,-0x24(%rbp)
   0x0000000000400664 <+125>:	movb   $0x5f,-0x23(%rbp)
   0x0000000000400668 <+129>:	movb   $0x31,-0x22(%rbp)
   0x000000000040066c <+133>:	movb   $0x73,-0x21(%rbp)
   0x0000000000400670 <+137>:	movb   $0x5f,-0x20(%rbp)
   0x0000000000400674 <+141>:	movb   $0x6e,-0x1f(%rbp)
   0x0000000000400678 <+145>:	movb   $0x30,-0x1e(%rbp)
   0x000000000040067c <+149>:	movb   $0x74,-0x1d(%rbp)
   0x0000000000400680 <+153>:	movb   $0x5f,-0x1c(%rbp)
   0x0000000000400684 <+157>:	movb   $0x65,-0x1b(%rbp)
   0x0000000000400688 <+161>:	movb   $0x6e,-0x1a(%rbp)
   0x000000000040068c <+165>:	movb   $0x30,-0x19(%rbp)
   0x0000000000400690 <+169>:	movb   $0x75,-0x18(%rbp)
   0x0000000000400694 <+173>:	movb   $0x67,-0x17(%rbp)
   0x0000000000400698 <+177>:	movb   $0x68,-0x16(%rbp)
   0x000000000040069c <+181>:	movb   $0x7d,-0x15(%rbp)
   0x00000000004006a0 <+185>:	movb   $0x0,-0x14(%rbp)
   0x00000000004006a4 <+189>:	mov    -0x40(%rbp),%rax
   0x00000000004006a8 <+193>:	add    $0x8,%rax
   0x00000000004006ac <+197>:	mov    (%rax),%rdx
   0x00000000004006af <+200>:	lea    -0x30(%rbp),%rax
   0x00000000004006b3 <+204>:	mov    %rdx,%rsi
   0x00000000004006b6 <+207>:	mov    %rax,%rdi
   0x00000000004006b9 <+210>:	callq  0x4004f0 <strcmp@plt>
   0x00000000004006be <+215>:	test   %eax,%eax
   0x00000000004006c0 <+217>:	jne    0x4006d0 <main+233>
   0x00000000004006c2 <+219>:	lea    0xcb(%rip),%rdi        # 0x400794
   0x00000000004006c9 <+226>:	callq  0x4004c0 <puts@plt>
   0x00000000004006ce <+231>:	jmp    0x4006dc <main+245>
   0x00000000004006d0 <+233>:	lea    0xc5(%rip),%rdi        # 0x40079c
   0x00000000004006d7 <+240>:	callq  0x4004c0 <puts@plt>
   0x00000000004006dc <+245>:	mov    $0x0,%eax
   0x00000000004006e1 <+250>:	mov    -0x8(%rbp),%rcx
   0x00000000004006e5 <+254>:	xor    %fs:0x28,%rcx
   0x00000000004006ee <+263>:	je     0x4006f5 <main+270>
   0x00000000004006f0 <+265>:	callq  0x4004d0 <__stack_chk_fail@plt>
   0x00000000004006f5 <+270>:	leaveq 
   0x00000000004006f6 <+271>:	retq   
End of assembler dump.

0x4005e7〜0x40062b で初期処理と、起動時の引数がなかったときの usage表示をする処理。
0x400630〜 flag をメモリ内に生成して 0x4006b9 で strcmp して合否の判断をしている模様。

実際に実行させて flag を得るまで

とりあえず、strcmp をしている 0x4006b9 にブレークポイントを置く。
アドレス指定なので、アドレスの前にアスタリスクをつける。

(gdb) break *0x4006b9
Breakpoint 1 at 0x4006b9

次に、実行をさせるが usage が表示されないようにダミーの引数(“hoge”)を与えておく。

(gdb) r hoge
Starting program: /home/nekotaro/ctf/seccompare/seccompare hoge

Breakpoint 1, 0x00000000004006b9 in main ()
(gdb)

ブレークポイントで無事停止。
必須ではないが、disas すると「=>」 の矢印マークがついて、ブレークポイントで止まっている場所を確認できる。

(gdb) disas main
Dump of assembler code for function main:
   0x00000000004005e7 <+0>:	push   %rbp
   0x00000000004005e8 <+1>:	mov    %rsp,%rbp
   0x00000000004005eb <+4>:	sub    $0x40,%rsp
  (中略)
   0x00000000004006b6 <+207>:	mov    %rax,%rdi
=> 0x00000000004006b9 <+210>:	callq  0x4004f0 <strcmp@plt>
   0x00000000004006be <+215>:	test   %eax,%eax

strcmpに渡そうとしている第1引数と第2引数を確認する。
第1引数は rdi の先に、第2引数は rsi の先にある。

(gdb) x/s $rdi
0x7fffffffdf70:	"ctf4b{5tr1ngs_1s_n0t_en0ugh}"
(gdb) x/s $rsi
0x7fffffffe3d9:	"hoge"

ということで、無事 flag の「ctf4b{5tr1ngs_1s_n0t_en0ugh}」を得ることができた。

ちなみに、余談だがx64のSystem V では、関数(ここれはstrcmp)に渡す引数の対応付はは下記の通り。(第7引数以降はスタックに積まれる)

引数レジスタ
第1引数rdi
第2引数rsi
第3引数rdx
第4引数rcx
第5引数r8
第6引数r9

確認

最後に実際に動作を確認してみる。

$ ./seccompare ctf4b{5tr1ngs_1s_n0t_en0ugh}
correct

無事 correct が表示されたので、flagの提出をしておしまい。