8割解けるCTF「WEST-SEC」

セキュリティ初心者の方でも楽しめるゲーム形式のセキュリティイベント

解析

gdbでプログラムの解析をしてみよう。

(1)解析するプログラム
Cで書かれた以下のプログラム(ping.c)があります。 ※拡張子は.cにすること
これは、ping 8.8.8.8 をバックグラウンドで実行するものです。

#include<stdio.h>
int main () {
    system ( "ping 8.8.8.8 >/dev/null 2>&1 &" );
}

では、コンパイルして、ping.exeという実行ファイルを作ります。

gcc -o ping.exe ping.c

※警告が出ますが、無視しましょう。

(2)静的解析
マルウェアを実行すれば、その挙動はわかります。しかし感染したり不正な行為を行うので得策とは言えません。そこで、静的解析として、gdb(The GNU Project Debugger)というLinux用の解析ツールを使います。
❶gdbのインストール

# yum -y install gdb

❷gdbの起動

# gdb ping.exe
GNU gdb (GDB) Red Hat Enterprise Linux 8.0.1-36.amzn2.0.1
Copyright (C) 2017 Free Software Foundation, Inc.
・・・
Reading symbols from ping.exe...(no debugging symbols found)...done.
(gdb)

❸使用されている関数の確認
main関数の存在があることがわかる。

(gdb) info functions
All defined functions:

Non-debugging symbols:
0x00000000004003c8  _init
0x00000000004003f0  system@plt
0x0000000000400400  _start
0x0000000000400430  deregister_tm_clones
0x0000000000400460  register_tm_clones
0x00000000004004a0  __do_global_dtors_aux
0x00000000004004c0  frame_dummy
0x00000000004004c7  main
0x00000000004004f0  __libc_csu_init
0x0000000000400550  __libc_csu_fini
0x0000000000400554  _fini
(gdb)

❹main関数の解析

(gdb) disas main
Dump of assembler code for function main:
   0x00000000004004c7 <+0>:     push   %rbp
   0x00000000004004c8 <+1>:     mov    %rsp,%rbp
   0x00000000004004cb <+4>:     mov    $0x400570,%edi
   0x00000000004004d0 <+9>:     mov    $0x0,%eax
   0x00000000004004d5 <+14>:    callq  0x4003f0 <system@plt>
   0x00000000004004da <+19>:    mov    $0x0,%eax
   0x00000000004004df <+24>:    pop    %rbp
   0x00000000004004e0 <+25>:    retq
End of assembler dump.
(gdb)
  1. <+19> --> 関数呼び出し:外部コマンドを実行するsystem関数の呼び出し
  2. <+4> --> 引数の準備:外部コマンドに渡す引数を設定

❺メモリ空間を確認
引数が格納されたアドレスを確認する。そして、4ずつ数字を増やしながら実行。

(gdb) x 0x400570
0x400570:       0x676e6970
(gdb) x 0x400574
0x400574:       0x382e3820
(gdb) x 0x400578
0x400578:       0x382e382e
(gdb) x 0x40057c
0x40057c:       0x642f3e20
(gdb) x 0x400580
0x400580:       0x6e2f7665

1つ目として、メモリの0x400570 には、0x676e6970という値が入っている。
これはリトルエンディアンなので、メモリ上には逆に並んで配置されている。
元に戻すと 70696e67
これをテキストにすると、pingとなる。
※たとえばCyberChef(https://gchq.github.io/CyberChef/)にて、Swap endiannessを使って、ビッグエンディアンからリトルエンディアン(またはその逆)を実行し、From Hexを使って、
16進数をテキストに変換するのが楽です。

同様に
382e3820 --> 20382e38 --> 8.8
382e382e --> 2e382e38 --> .8.8
642f3e20 --> 203e2f64 --> >/d
6e2f7665 --> 65762f6e --> ev/n

こうして、ping 8.8.8.8 を実行していることがわかります。