Volatility を使用してアプリケーション、ネットワーク接続、カーネルモジュール、ファイルなどの状況を特定します。
コンピュータのオペレーティングシステムとアプリケーションは、さまざまなタスクを実行するために主メモリ(RAM)を使用します。この揮発性メモリには、実行中のアプリケーション、ネットワーク接続、カーネルモジュール、開いているファイル、およびほぼすべての他の内容に関する大量の情報が含まれていますが、これらの情報はコンピュータが再起動するたびに消去されます。
メモリフォレンジックは、メモリからこれらの価値のある情報を見つけて抽出する方法です。Volatility は、この種の情報を処理するためにプラグインを使用するオープンソースツールです。しかし、1 つの問題があります:これらの情報を処理する前に、物理メモリをファイルにダンプする必要がありますが、Volatility にはその機能がありません。
したがって、この記事は 2 つの部分に分かれています:
- 第一部は、物理メモリを取得し、それをファイルにダンプすることに関するものです。
- 第二部は、Volatility を使用してこのメモリダンプから情報を読み取り、処理します。
私はこのチュートリアルで以下のテストシステムを使用しましたが、これは任意の Linux ディストリビューションで動作します:
$ cat /etc/redhat-release
Red Hat Enterprise Linux release 8.3 (Ootpa)
$
$ uname -r
4.18.0-240.el8.x86_64
$
注意事項: 部分1では、カーネルモジュールをコンパイルしてロードすることが含まれます。心配しないでください:それほど難しくはありません。
一部のガイドライン:
以下の手順に従ってください。
生産システムや主要なコンピュータでこれらの手順を試さないでください。
これらのツールの使い方に慣れるまで、常にテスト用の仮想マシン(VM)を使用して試してください。
必要なパッケージのインストール#
開始する前に、必要なツールをインストールします。Debian ベースのディストリビューションを頻繁に使用する場合は、apt-get コマンドを使用できます。これらのパッケージは、コードをコンパイルするために必要なカーネル情報とツールを提供します:
$ yum install kernel-headers kernel-devel gcc elfutils-libelf-devel make git libdwarf-tools python2-devel.x86_64-y
部分 1:LiME を使用してメモリを取得し、ファイルにダンプする#
メモリを分析する前に、使用するメモリダンプが必要です。実際のフォレンジック活動では、これは破損したり侵入されたシステムから来る可能性があります。これらの情報は通常、侵入がどのように発生したかとその影響を分析するために収集され、保存されます。利用可能なメモリダンプがない場合は、テスト VM のメモリダンプを取得し、それを使用してメモリフォレンジックを実行できます。
Linux メモリエクストラクター(LiME)は、Linux システム上でメモリを取得するために一般的に使用されるツールです。以下のコマンドを使用して LiME を取得します:
$ git clone https://github.com/504ensicsLabs/LiME.git
$
$ cd LiME/src/
$
$ ls
deflate.c disk.c hash.c lime.h main.c Makefile Makefile.sample tcp.c
$
LiME カーネルモジュールのビルド#
src フォルダー内で make コマンドを実行します。これにより、.ko 拡張子のカーネルモジュールが作成されます。理想的には、make が終了すると、lime.ko ファイルが lime-.ko という形式で名前が変更されます。
$ make
make -C /lib/modules/4.18.0-240.el8.x86_64/build M="/root/LiME/src" modules
make[1]: Entering directory '/usr/src/kernels/4.18.0-240.el8.x86_64'
<< 省略 >>
make[1]: Leaving directory '/usr/src/kernels/4.18.0-240.el8.x86_64'
strip --strip-unneeded lime.ko
mv lime.ko lime-4.18.0-240.el8.x86_64.ko
$
$
$ ls -l lime-4.18.0-240.el8.x86_64.ko
-rw-r--r--. 1 root root 25696 Apr 17 14:45 lime-4.18.0-240.el8.x86_64.ko
$
$ file lime-4.18.0-240.el8.x86_64.ko
lime-4.18.0-240.el8.x86_64.ko: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), BuildID[sha1]=1d0b5cf932389000d960a7e6b57c428b8e46c9cf, not stripped
$
LiME カーネルモジュールのロード#
今、システムメモリを取得するためにカーネルモジュールをロードする時が来ました。insmod コマンドはカーネルモジュールをロードするのに役立ちます。モジュールがロードされると、システム上で主メモリ(RAM)を読み取り、メモリの内容をコマンドラインで指定された path ディレクトリのファイルにダンプします。もう 1 つの重要なパラメータは format です。lime の形式を保持します。カーネルモジュールを挿入した後、lsmod コマンドを使用して本当にロードされたかどうかを確認します。
$ lsmod | grep lime
$
$ insmod ./lime-4.18.0-240.el8.x86_64.ko "path=../RHEL8.3_64bit.mem format=lime"
$
$ lsmod | grep lime
lime 16384 0
$
path コマンドに指定されたファイルが作成されているはずで、ファイルサイズはシステムの物理メモリ(RAM)サイズと同じであるはずです(驚くことではありません)。メモリダンプを取得したら、rmmod コマンドを使用してそのカーネルモジュールを削除できます:
$
$ ls -l ~/LiME/RHEL8.3_64bit.mem
-r--r--r--. 1 root root 4294544480 Apr 17 14:47 /root/LiME/RHEL8.3_64bit.mem
$
$ du -sh ~/LiME/RHEL8.3_64bit.mem
4.0G /root/LiME/RHEL8.3_64bit.mem
$
$ free -m
total used free shared buff/cache available
Mem: 3736 220 366 8 3149 3259
Swap: 4059 8 4051
$
$ rmmod lime
$
$ lsmod | grep lime
$
メモリダンプには何が含まれていますか?#
このメモリダンプファイルは、file コマンドを使用して見ることができるように、単なる生データです。手動で理解することはできません。はい、ここにはいくつかの ASCII 文字がありますが、エディタでこのファイルを開いて読むことはできません。hexdump の出力は、最初の数バイトが EmiL であることを示しています。これは、上記のコマンドラインでリクエストされた形式が lime であるためです:
$ file ~/LiME/RHEL8.3_64bit.mem
/root/LiME/RHEL8.3_64bit.mem: data
$
$ hexdump -C ~/LiME/RHEL8.3_64bit.mem | head
00000000 45 4d 69 4c 01 00 00 00 00 10 00 00 00 00 00 00 |EMiL............|
00000010 ff fb 09 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 b8 fe 4c cd 21 44 00 32 20 00 00 2a 2a 2a 2a 2a |..L.!D.2 ..*****|
00000030 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a |****************|
00000040 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 20 00 20 |************* . |
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000080 00 00 00 00 00 00 00 00 00 00 00 00 70 78 65 6c |............pxel|
00000090 69 6e 75 78 2e 30 00 00 00 00 00 00 00 00 00 00 |inux.0..........|
000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
$
部分 2:Volatility を取得し、メモリダンプを分析する#
分析するためのサンプルメモリダンプができたので、以下のコマンドを使用して Volatility ソフトウェアを取得します。Volatility は Python 3 で再構築されていますが、このチュートリアルでは Python 2 で書かれた元の Volatility パッケージを使用しています。Volatility 3 を試したい場合は、適切な Git リポジトリからダウンロードし、以下のコマンドで Python 3 を使用してください:
$ git clone https://github.com/volatilityfoundation/volatility.git
$
$ cd volatility/
$
$ ls
AUTHORS.txt contrib LEGAL.txt Makefile PKG-INFO pyinstaller.spec resources tools vol.py
CHANGELOG.txt CREDITS.txt LICENSE.txt MANIFEST.in pyinstaller README.txt setup.py volatility
$
Volatility は特定の機能を実現するために 2 つの Python ライブラリを使用しているため、以下のコマンドを使用してそれらをインストールします。そうしないと、Volatility ツールを実行するときにいくつかのインポートエラーが表示される可能性があります。これらは無視できますが、実行しているプラグインがこれらのライブラリを必要とする場合、その場合はツールがエラーを報告します:
$ pip2 install pycrypto
$ pip2 install distorm3
Volatility の Linux プロファイルをリストする#
最初に実行する Volatility コマンドは、利用可能な Linux プロファイルをリストします。Volatility コマンドの主要なエントリポイントは vol.py スクリプトです。Python 2 インタプリタを使用してこれを呼び出し、--info オプションを提供します。出力を絞り込むために、Linux で始まる文字列を探します。ご覧のとおり、リストされている Linux プロファイルはあまり多くありません:
$ python2 vol.py --info | grep ^Linux
Volatility Foundation Volatility Framework 2.6.1
LinuxAMD64PagedMemory - Linux-specific AMD 64-bit address space.
$
自分の Linux プロファイルを構築する#
Linux ディストリビューションは多様であり、異なるアーキテクチャ用に構築されています。これが、プロファイルが必要な理由です。Volatility は、メモリダンプがどのシステムおよびアーキテクチャから取得されたかを知る必要があります。これらの情報を見つけるためのいくつかの Volatility コマンドがありますが、この方法は時間がかかります。スピードを上げるために、以下のコマンドを使用してカスタム Linux プロファイルを構築できます:
Volatility リポジトリの tools/linux ディレクトリに移動し、make コマンドを実行します:
$ cd tools/linux/
$
$ pwd
/root/volatility/tools/linux
$
$ ls
kcore Makefile Makefile.enterprise module.c
$
$ make
make -C //lib/modules/4.18.0-240.el8.x86_64/build CONFIG_DEBUG_INFO=y M="/root/volatility/tools/linux" modules
make[1]: Entering directory '/usr/src/kernels/4.18.0-240.el8.x86_64'
<< 省略 >>
make[1]: Leaving directory '/usr/src/kernels/4.18.0-240.el8.x86_64'
$
新しい module.dwarf ファイルが作成されているはずです。また、/boot ディレクトリにある System.map ファイルも必要です。これは、現在実行中のカーネルに関連するすべてのシンボルを含んでいます:
$ ls
kcore Makefile Makefile.enterprise module.c module.dwarf
$
$ ls -l module.dwarf
-rw-r--r--. 1 root root 3987904 Apr 17 15:17 module.dwarf
$
$ ls -l /boot/System.map-4.18.0-240.el8.x86_64
-rw-------. 1 root root 4032815 Sep 23 2020 /boot/System.map-4.18.0-240.el8.x86_64
$
$
カスタムプロファイルを作成するには、Volatility ディレクトリに戻り、以下のコマンドを実行します。最初のパラメータはカスタム.zip ファイルを提供し、ファイル名は自分で命名します。私は通常、オペレーティングシステムとカーネルバージョンを使用して命名します。次のパラメータは前に作成した module.dwarf ファイルで、最後のパラメータは /boot ディレクトリにある System.map ファイルです:
$
$ cd volatility/
$
$ zip volatility/plugins/overlays/linux/Redhat8.3_4.18.0-240.zip tools/linux/module.dwarf /boot/System.map-4.18.0-240.el8.x86_64
adding: tools/linux/module.dwarf (deflated 91%)
adding: boot/System.map-4.18.0-240.el8.x86_64 (deflated 79%)
$
これでカスタムプロファイルが準備できたので、前述の場所で.zip ファイルが作成されたかどうかを確認します。Volatility がこのカスタムプロファイルを検出したかどうかを確認するために、再度 --info コマンドを実行します。今、リストされた内容の中に新しいプロファイルが表示されるはずです:
$
$ ls -l volatility/plugins/overlays/linux/Redhat8.3_4.18.0-240.zip
-rw-r--r--. 1 root root 1190360 Apr 17 15:20 volatility/plugins/overlays/linux/Redhat8.3_4.18.0-240.zip
$
$
$ python2 vol.py --info | grep Redhat
Volatility Foundation Volatility Framework 2.6.1
LinuxRedhat8_3_4_18_0-240x64 - A Profile for Linux Redhat8.3_4.18.0-240 x64
$
$
Volatility の使用を開始する#
これで、実際のメモリフォレンジックを行う準備が整いました。Volatility はカスタムプラグインで構成されており、メモリダンプに対して情報を取得できます。コマンドの一般的な形式は次のとおりです:
python2 vol.py -f <memory-dump-file-taken-by-Lime> <plugin-name> --profile=<name-of-our-custom-profile>
この情報を使用して、linux_banner プラグインを実行し、メモリダンプから正しいディストリビューション情報を識別できるかどうかを確認します:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_banner --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
Linux version 4.18.0-240.el8.x86_64 ([[email protected]][4]) (gcc version 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC)) #1 SMP Wed Sep 23 05:13:10 EDT 2020
$
Linux プラグインを見つける#
ここまで順調に進んでいるので、すべての Linux プラグインの名前を見つける方法が気になるかもしれません。簡単なテクニックがあります:--info コマンドを実行し、linux_文字列を取得します。さまざまな目的に使用できるさまざまなプラグインがあります。ここに一部を示します:
$ python2 vol.py --info | grep linux_
Volatility Foundation Volatility Framework 2.6.1
linux_apihooks - Checks for userland apihooks
linux_arp - Print the ARP table
linux_aslr_shift - Automatically detect the Linux ASLR shift
<< 省略 >>
linux_banner - Prints the Linux banner information
linux_vma_cache - Gather VMAs from the vm_area_struct cache
linux_volshell - Shell in the memory image
linux_yarascan - A shell in the Linux memory image
$
linux_psaux プラグインを使用して、メモリダンプ時にシステム上で実行されているプロセスを確認します。リストの最後のコマンドに注意してください:それは、ダンプの前に実行した insmod コマンドです。
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_psaux --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
Pid Uid Gid Arguments
1 0 0 /usr/lib/systemd/systemd --switched-root --system --deserialize 18
2 0 0 [kthreadd]
3 0 0 [rcu_gp]
4 0 0 [rcu_par_gp]
861 0 0 /usr/libexec/platform-python -Es /usr/sbin/tuned -l -P
869 0 0 /usr/bin/rhsmcertd
875 0 0 /usr/libexec/sssd/sssd_be --domain implicit_files --uid 0 --gid 0 --logger=files
878 0 0 /usr/libexec/sssd/sssd_nss --uid 0 --gid 0 --logger=files
<< 省略 >>
11064 89 89 qmgr -l -t unix -u
227148 0 0 [kworker/0:0]
227298 0 0 -bash
227374 0 0 [kworker/u2:1]
227375 0 0 [kworker/0:2]
227884 0 0 [kworker/0:3]
228573 0 0 insmod ./lime-4.18.0-240.el8.x86_64.ko path=../RHEL8.3_64bit.mem format=lime
228576 0 0
$
システムのネットワーク状態を知りたいですか?linux_netstat プラグインを実行して、メモリダンプ中のネットワーク接続の状態を見つけます:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_netstat --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
UNIX 18113 systemd/1 /run/systemd/private
UNIX 11411 systemd/1 /run/systemd/notify
UNIX 11413 systemd/1 /run/systemd/cgroups-agent
UNIX 11415 systemd/1
UNIX 11416 systemd/1
<< 省略 >>
$
次に、linux_mount プラグインを使用して、メモリダンプ中にどのファイルシステムがマウントされていたかを確認します:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_mount --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
tmpfs /sys/fs/cgroup tmpfs ro,nosuid,nodev,noexec
cgroup /sys/fs/cgroup/pids cgroup rw,relatime,nosuid,nodev,noexec
systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime
sunrpc /var/lib/nfs/rpc_pipefs rpc_pipefs rw,relatime
/dev/mapper/rhel_kvm--03--guest11-root / xfs rw,relatime
tmpfs /dev/shm tmpfs rw,nosuid,nodev
selinuxfs /sys/fs/selinux selinuxfs rw,relatime
<< 省略 >>
cgroup /sys/fs/cgroup/net_cls,net_prio cgroup rw,relatime,nosuid,nodev,noexec
cgroup /sys/fs/cgroup/cpu,cpuacct cgroup rw,relatime,nosuid,nodev,noexec
bpf /sys/fs/bpf bpf rw,relatime,nosuid,nodev,noexec
cgroup /sys/fs/cgroup/memory cgroup ro,relatime,nosuid,nodev,noexec
cgroup /sys/fs/cgroup/cpuset cgroup rw,relatime,nosuid,nodev,noexec
mqueue /dev/mqueue mqueue rw,relatime
$
どのカーネルモジュールがロードされているかを知りたいですか?Volatility はこれに対しても linux_lsmod プラグインを提供しています:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_lsmod --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
ffffffffc0535040 lime 20480
ffffffffc0530540 binfmt_misc 20480
ffffffffc05e8040 sunrpc 479232
<< 省略 >>
ffffffffc04f9540 nfit 65536
ffffffffc0266280 dm_mirror 28672
ffffffffc025e040 dm_region_hash 20480
ffffffffc0258180 dm_log 20480
ffffffffc024bbc0 dm_mod 151552
$
どのファイルがどのプロセスによって開かれているかを知りたいですか?linux_bash プラグインを使用してこれらの情報をリストできます:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_bash --profile=LinuxRedhat8_3_4_18_0-240x64 -v
Volatility Foundation Volatility Framework 2.6.1
Pid Name Command Time Command
-------- -------------------- ------------------------------ -------
227221 bash 2021-04-17 18:38:24 UTC+0000 lsmod
227221 bash 2021-04-17 18:38:24 UTC+0000 rm -f .log
227221 bash 2021-04-17 18:38:24 UTC+0000 ls -l /etc/zzz
227221 bash 2021-04-17 18:38:24 UTC+0000 cat ~/.vimrc
227221 bash 2021-04-17 18:38:24 UTC+0000 ls
227221 bash 2021-04-17 18:38:24 UTC+0000 cat /proc/817/cwd
227221 bash 2021-04-17 18:38:24 UTC+0000 ls -l /proc/817/cwd
227221 bash 2021-04-17 18:38:24 UTC+0000 ls /proc/817/
<< 省略 >>
227298 bash 2021-04-17 18:40:30 UTC+0000 gcc prt.c
227298 bash 2021-04-17 18:40:30 UTC+0000 ls
227298 bash 2021-04-17 18:40:30 UTC+0000 ./a.out
227298 bash 2021-04-17 18:40:30 UTC+0000 vim prt.c
227298 bash 2021-04-17 18:40:30 UTC+0000 gcc prt.c
227298 bash 2021-04-17 18:40:30 UTC+0000 ./a.out
227298 bash 2021-04-17 18:40:30 UTC+0000 ls
$
どのファイルがどのプロセスによって開かれているかを知りたいですか?linux_lsof プラグインを使用してこれらの情報をリストできます:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_lsof --profile=LinuxRedhat8_3_4_18_0-240x64
Volatility Foundation Volatility Framework 2.6.1
Offset Name Pid FD Path
------------------ ------------------------------ -------- -------- ----
0xffff9c83fb1e9f40 rsyslogd 71194 0 /dev/null
0xffff9c83fb1e9f40 rsyslogd 71194 1 /dev/null
0xffff9c83fb1e9f40 rsyslogd 71194 2 /dev/null
0xffff9c83fb1e9f40 rsyslogd 71194 3 /dev/urandom
0xffff9c83fb1e9f40 rsyslogd 71194 4 socket:[83565]
0xffff9c83fb1e9f40 rsyslogd 71194 5 /var/log/messages
0xffff9c83fb1e9f40 rsyslogd 71194 6 anon_inode:[9063]
0xffff9c83fb1e9f40 rsyslogd 71194 7 /var/log/secure
<< 省略 >>
0xffff9c8365761f40 insmod 228573 0 /dev/pts/0
0xffff9c8365761f40 insmod 228573 1 /dev/pts/0
0xffff9c8365761f40 insmod 228573 2 /dev/pts/0
0xffff9c8365761f40 insmod 228573 0 /root/LiME/src/lime-4.18.0-240.el8.x86_64.ko
$
Linux プラグインスクリプトの場所にアクセスする#
メモリダンプを読み取り、これらの情報を処理することで、さらに多くの情報を得ることができます。Python を知っていて、これらの情報がどのように処理されているかに興味がある場合は、すべてのプラグインが保存されているディレクトリに移動し、興味のあるものを選択して、Volatility がこれらの情報をどのように取得しているかを確認できます:
$ ls volatility/plugins/linux/
apihooks.py common.py kernel_opened_files.py malfind.py psaux.py
apihooks.pyc common.pyc kernel_opened_files.pyc malfind.pyc psaux.pyc
arp.py cpuinfo.py keyboard_notifiers.py mount_cache.py psenv.py
arp.pyc cpuinfo.pyc keyboard_notifiers.pyc mount_cache.pyc psenv.pyc
aslr_shift.py dentry_cache.py ld_env.py mount.py pslist_cache.py
aslr_shift.pyc dentry_cache.pyc ld_env.pyc mount.pyc pslist_cache.pyc
<< 省略 >>
check_syscall_arm.py __init__.py lsmod.py proc_maps.py tty_check.py
check_syscall_arm.pyc __init__.pyc lsmod.pyc proc_maps.pyc tty_check.pyc
check_syscall.py iomem.py lsof.py proc_maps_rb.py vma_cache.py
check_syscall.pyc iomem.pyc lsof.pyc proc_maps_rb.pyc vma_cache.pyc
$
$
私が Volatility を好む理由は、さまざまなセキュリティプラグインを提供しているからです。これらの情報は手動で取得するのが難しいです:
linux_hidden_modules - 隠れたカーネルモジュールを見つけるためにメモリを切り出す
linux_malfind - 疑わしいプロセスマッピングを探す
linux_truecrypt_passphrase - キャッシュされたTruecryptパスフレーズを回復する
Volatility は、メモリダンプ内でシェルを開くこともできるため、上記のすべてのコマンドの代わりにシェルコマンドを実行して同じ情報を取得できます:
$ python2 vol.py -f ~/LiME/RHEL8.3_64bit.mem linux_volshell --profile=LinuxRedhat8_3_4_18_0-240x64 -v
Volatility Foundation Volatility Framework 2.6.1
Current context: process systemd, pid=1 DTB=0x1042dc000
Welcome to volshell! Current memory image is:
file:///root/LiME/RHEL8.3_64bit.mem
To get help, type 'hh()'
>>>
>>> sc()
Current context: process systemd, pid=1 DTB=0x1042dc000
>>>
次のステップ#
メモリダンプは、Linux の内部を理解するための良い方法です。Volatility のすべてのプラグインを試して、それらの出力を詳細に調査してください。その後、これらの情報が侵入やセキュリティ問題を特定するのにどのように役立つかを考えてください。これらのプラグインの動作を深く理解し、改善を試みてください。やりたいことのプラグインが見つからなかった場合は、自分で作成して Volatility に提出し、他の人が使用できるようにしてください。
参考文献#
オープンソースツールを使用した Linux メモリフォレンジック [1]
このオープンソースツールを使用して Linux メモリフォレンジックを実行する [2]