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)
- <+19> --> 関数呼び出し:外部コマンドを実行するsystem関数の呼び出し
- <+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 を実行していることがわかります。