0x00 概述
Volatility是一款開源內(nèi)存取證框架,能夠?qū)?dǎo)出的內(nèi)存鏡像進(jìn)行分析,通過獲取內(nèi)核數(shù)據(jù)結(jié)構(gòu)砸脊,使用插件獲取內(nèi)存的詳細(xì)情況以及系統(tǒng)的運(yùn)行狀態(tài)。
特點:
- 開源:Python編寫纬霞,易于和基于python的主機(jī)防御框架集成凌埂。
- 支持多平臺:Windows,Mac诗芜,Linux全支持
- 易于擴(kuò)展:通過插件來擴(kuò)展Volatility的分析能力
0x01 安裝
安裝分為三步走:
- 下載
- 安裝必要的python依賴文件
- 安裝本體
下載
你可以在Release中找到對應(yīng)你系統(tǒng)(Mac瞳抓,Win,Linux)的源代碼伏恐,當(dāng)然也可以通過github去獲取源碼:
git clone https://github.com/volatilityfoundation/volatility.git
依賴
如果只是用Volatility本體的話孩哑,這些依賴是沒必要裝的,但是如果你想用某些插件翠桦,還是把以下這些必備的依賴包裝上吧横蜒。
Distorm3:牛逼的反編譯庫
pip install distorm3
Yara:惡意軟件分類工具
pip install yara
PyCrypto:加密工具集
pip install pycrypto
PIL:圖片處理庫
pip install pil
OpenPyxl:讀寫excel文件
pip install openpyxl
ujson:JSON解析
pip install ujson
安裝
如果你用的是獨立的win、linux销凑、mac執(zhí)行文件丛晌,那就不必安裝了。只要用python去執(zhí)行就好斗幼。
若是下載了壓縮文件茵乱,那你可以選擇直接運(yùn)行python主程序,也可以選擇使用python setup.py install
的方式將Volatility以一個庫的形式安裝在系統(tǒng)的特定位置上孟岛,從而以后我們可以將Volatility作為一個庫在其他腳本中去引用其namespace瓶竭。
0x02 使用
此處以在Linux上使用為例講解Volatility的使用方法。
其大體流程如下:
創(chuàng)建用戶配置文件
Volatility需要從用戶配置文件中讀取內(nèi)核的相關(guān)信息渠羞,通過這些信息來定位內(nèi)存中的關(guān)鍵信息并對其進(jìn)行解析斤贰。因此我們需要獲取用戶配置文件,且這些配置文件需與你要分析的內(nèi)核版本相匹配次询,其中包含了內(nèi)核數(shù)據(jù)結(jié)構(gòu)以及調(diào)試符號荧恍。
通常我們可以從github上獲取已經(jīng)整理好的用戶配置信息,當(dāng)然我們也能夠自己來編譯屯吊。以下就是自己編譯用戶配置文件的過程送巡。
首先我們得裝一些工具。
dwarfdump&GCC/Make&KernelHeaders:調(diào)試文件導(dǎo)出工具盒卸、編譯工具以及待分析系統(tǒng)內(nèi)核頭文件
sudo apt-get install dwarfdump build-essential linux-header-'uname -r'
創(chuàng)建vtypes
vtypes是內(nèi)核數(shù)據(jù)結(jié)構(gòu)骗爆,為創(chuàng)建該數(shù)據(jù)結(jié)構(gòu),我們需要檢查我們的源碼并針對我們要分析的系統(tǒng)內(nèi)核編譯module.c
文件蔽介,這將會為我們生成一個名為module.dwarf
文件摘投,該文件包含了我們所需的內(nèi)核調(diào)試信息煮寡。
具體可以這么做:
cd volatility/tools/linux
make
獲取符號表
一般我們可以在/boot
目錄下找到該System.map
文件。該文件包含系統(tǒng)的符號信息犀呼。
制作用戶配置文件
隨后對moudle.dwarf
以及system.map
文件打包成一個zip文件幸撕,隨后將該zip文件放在volatility/plugins/overlays/linux
下。
sudo zip volatility/volatility/plugins/overlays/linux/Ubuntu1404.zip volatility/tools/linux/module.dwarf /boot/System.map-'uname -r'
使用用戶配置文件
隨后就可以通過以下命令來查看用戶配置文件的名字了外臂。
python vol.py --info|grep Linux
這里面的LinuxUbuntu1404x64
就是隨后要用的配置文件名了坐儿,一般用在選項--profile
之后。
獲取內(nèi)存鏡像
Volatility并不會抓取內(nèi)存宋光,因此建議使用lime(Linux Mem Extractor)挑童,從intel硬件或虛擬機(jī)上抓取內(nèi)存,當(dāng)然他也支持安卓系統(tǒng)內(nèi)存抓取跃须。
下載內(nèi)存抓取工具Lime
git clone https://github.com/504ensicsLabs/LiME.git
編譯工具
cd lime/src
make
加載內(nèi)核模塊
sudo insmod lime-`uname -r`.ko "path=<outfile | tcp:<port>> format=<raw|padded|lime> [dio=<0|1>]"
其中 path參數(shù)可以為輸出文件outfile站叼,用于本地保存或tcp:<port>用于遠(yuǎn)程監(jiān)聽。format:raw是將所有系統(tǒng)RAM空間串聯(lián)起來菇民,padded是將非系統(tǒng)RAM空間以0填充尽楔,而lime則是將每段空間前填充固定大小的頭部,該頭部包含地址空間信息第练。dio則用于是否啟用Direct IO阔馋。
我們則是:
sudo insmod lime-`uname -r`.ko "path=/home/crazydog/ubuntu.lime format=lime"
PS:這一步會使得系統(tǒng)非常卡頓娇掏,大家使用時請不要使用在生產(chǎn)系統(tǒng)上防止對正常應(yīng)用造成影響呕寝。
使用插件
一般我們這么用我們的Volatility:
python vol.py -f /home/crazydog/ubuntu.lime --profile=LinuxUbuntu1404x64 linux_ifconfig <plugin_opytions>
一般我們可以使用的插件如下。
# 查看那些針對Linux設(shè)計的插件
# python vol.py --info 插件那一節(jié)中不帶前綴的是windows的插件婴梧,帶linux前綴的是linux的插件下梢,帶mac前綴的……
python vol.py --info | grep -i linux_
linux_apihooks - Checks for userland apihooks
linux_arp - Print the ARP table
linux_banner - Prints the Linux banner information
linux_bash - Recover bash history from bash process memory
linux_bash_env - Recover a process' dynamic environment variables
linux_bash_hash - Recover bash hash table from bash process memory
linux_check_afinfo - Verifies the operation function pointers of network protocols
linux_check_creds - Checks if any processes are sharing credential structures
linux_check_evt_arm - Checks the Exception Vector Table to look for syscall table hooking
linux_check_fop - Check file operation structures for rootkit modifications
linux_check_idt - Checks if the IDT has been altered
linux_check_inline_kernel - Check for inline kernel hooks
linux_check_modules - Compares module list to sysfs info, if available
linux_check_syscall - Checks if the system call table has been altered
linux_check_syscall_arm - Checks if the system call table has been altered
linux_check_tty - Checks tty devices for hooks
linux_cpuinfo - Prints info about each active processor
linux_dentry_cache - Gather files from the dentry cache
linux_dmesg - Gather dmesg buffer
linux_dump_map - Writes selected memory mappings to disk
linux_dynamic_env - Recover a process' dynamic environment variables
linux_elfs - Find ELF binaries in process mappings
linux_enumerate_files - Lists files referenced by the filesystem cache
linux_find_file - Lists and recovers files from memory
linux_getcwd - Lists current working directory of each process
linux_hidden_modules - Carves memory to find hidden kernel modules
linux_ifconfig - Gathers active interfaces
linux_info_regs - It's like 'info registers' in GDB. It prints out all the
linux_iomem - Provides output similar to /proc/iomem
linux_kernel_opened_files - Lists files that are opened from within the kernel
linux_keyboard_notifiers - Parses the keyboard notifier call chain
linux_ldrmodules - Compares the output of proc maps with the list of libraries from libdl
linux_library_list - Lists libraries loaded into a process
linux_librarydump - Dumps shared libraries in process memory to disk
linux_list_raw - List applications with promiscuous sockets
linux_lsmod - Gather loaded kernel modules
linux_lsof - Lists file descriptors and their path
linux_malfind - Looks for suspicious process mappings
linux_memmap - Dumps the memory map for linux tasks
linux_moddump - Extract loaded kernel modules
linux_mount - Gather mounted fs/devices
linux_mount_cache - Gather mounted fs/devices from kmem_cache
linux_netfilter - Lists Netfilter hooks
linux_netscan - Carves for network connection structures
linux_netstat - Lists open sockets
linux_pidhashtable - Enumerates processes through the PID hash table
linux_pkt_queues - Writes per-process packet queues out to disk
linux_plthook - Scan ELF binaries' PLT for hooks to non-NEEDED images
linux_proc_maps - Gathers process memory maps
linux_proc_maps_rb - Gathers process maps for linux through the mappings red-black tree
linux_procdump - Dumps a process's executable image to disk
linux_process_hollow - Checks for signs of process hollowing
linux_psaux - Gathers processes along with full command line and start time
linux_psenv - Gathers processes along with their static environment variables
linux_pslist - Gather active tasks by walking the task_struct->task list
linux_pslist_cache - Gather tasks from the kmem_cache
linux_pstree - Shows the parent/child relationship between processes
linux_psxview - Find hidden processes with various process listings
linux_recover_filesystem - Recovers the entire cached file system from memory
linux_route_cache - Recovers the routing cache from memory
linux_sk_buff_cache - Recovers packets from the sk_buff kmem_cache
linux_slabinfo - Mimics /proc/slabinfo on a running machine
linux_strings - Match physical offsets to virtual addresses (may take a while, VERY verbose)
linux_threads - Prints threads of processes
linux_tmpfs - Recovers tmpfs filesystems from memory
linux_truecrypt_passphrase - Recovers cached Truecrypt passphrases
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_arp
ARP表
linux_banner
系統(tǒng)信息
linux_check_inline_kernel
內(nèi)核內(nèi)聯(lián)hook
linux_check_evt_arm
在ARM處理器上,以Exception Vector Table來查看系統(tǒng)調(diào)用表的鉤子
linux_check_tty
檢查偽終端
linux_hidden_modules
檢查隱藏的模塊塞蹭,可用在某些內(nèi)核經(jīng)rootkit掃描
linux_ifconfig
檢查打開的網(wǎng)卡信息孽江。
linux_lsmod
列出內(nèi)核模塊。這里我希望列出我加載進(jìn)去的lime.ko
這是假設(shè)你的lsmod已經(jīng)被人hook了番电,這個時候可以使用它來進(jìn)行取證唤冈。
全部的模塊如下:
linux_netstat
查看其中的TCP端口
總之功能強(qiáng)大厦幅。
輸出
對于不同的插件,Volatility取證得出的結(jié)果可以以不同的方式輸出嗤练。輸出方式包含:
- text 以表的形式文本輸出
- dot 以點陣圖形式輸出
- html
- json 可用于不同的api之間數(shù)據(jù)交換
- sqlite 存到數(shù)據(jù)庫中
- quick 以|符號分隔地輸出文本
- xlsx 以excel文件輸出
一般我們可以-h
命令來獲取不同插件的輸出格式蒿褂。如
python vol.py linux_pstree -h
Module Output Options: dot, greptext, html, json, sqlite, text, xlsx
---------------------------------
Module PSTree
---------------------------------
Print process list as a tree
以html輸出
python vol.py --profile=LinuxUbuntu1404_Manualx64 linux_pstree -f /home/crazydog/workspace/miscellaneous/Ubuntu1404.lime --output=html --output-file=pstree1.html
結(jié)果如下:
以json文件輸出
python vol.py --profile=LinuxUbuntu1404_Manualx64 linux_pstree -f /home/crazydog/workspace/miscellaneous/Ubuntu1404.lime --output=json --output-file=pstree1.json
結(jié)果如下:
以sqlite輸出
python vol.py --profile=LinuxUbuntu1404_Manualx64 linux_pstree -f /home/crazydog/workspace/miscellaneous/Ubuntu1404.lime --output=sqlite --output-file=pstree.db
sqlite3 pstree.db
SQLite version 3.8.2 2013-12-06 14:53:30
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .schema
CREATE TABLE linux_pstree( id INTEGER, "Offset" TEXT, "Name" TEXT, "Level" TEXT, "Pid" TEXT, "Ppid" TEXT, "Uid" TEXT, "Gid" TEXT, "Euid" TEXT);
sqlite> select * from linux_pstree limit 5;
1|18446612137572106240|init|init|1|0|0|0|18446612137528196244
2|18446612135375493200|ureadahead|.ureadahead|337|1|0|0|18446612133204786132
3|18446612133205114880|upstart-udev-br|.upstart-udev-br|465|1|0|0|18446612135375781588
4|18446612133213175808|systemd-udevd|.systemd-udevd|471|1|0|0|18446612137544357140
5|18446612133194321536|upstart-file-br|.upstart-file-br|523|1|0|0|18446612133204784596
sqlite>
自研插件的格式化輸出功能
我們自己寫的插件里面通過定義我們要顯示的數(shù)據(jù)以及其類型來定義數(shù)據(jù)的輸出琐凭。
我們可以按照以下模板來重寫默認(rèn)的渲染器以及主次一個新的渲染器呜投。
以下轉(zhuǎn)自volatility的wiki
import volatility.plugins.common as common
import volatility.utils as utils
from volatility.renderers import TreeGrid
from volatility.renderers.basic import Address, Hex
class MyPlugin(common.AbstractWindowsCommand):
"""My test plugin"""
def calculate(self):
"""Body of the plugin goes here"""
addr_space = utils.load_as(self._config)
## gather some data from the memory dump using the address space
## then yield each result to the generator/render functions
data = [
[0xFFFFFFFF80004210, "testing123", 400, 6500],
[0xFFFFFFFF80008726, "testing345", 800, 124400],
]
for result in data:
yield result
def render_dot(self, outfd, data):
"""Here we can override the default dot renderer"""
...
def render_test(self, outfd, data):
"""Here we register a new handler invoked with --output=test"""
...
def unified_output(self, data):
"""This standardizes the output formatting"""
## make sure the number of columns (4) and their data types match
## what calculate() and generator() yields
return TreeGrid([("Offset", Address),
("Name", str),
("ID", int),
("Count", Hex),
self.generator(data))
def generator(self, data):
"""This yields data according to the unified output format"""
## the variables "unpacked" here must match what calculate() yields
for offset, name, id, count in data:
## make sure to wrap each variable according to its data type
yield (0, [Address(offset), str(name), int(id), Hex(count)])
0x03 小Bug
在使用的過程中發(fā)現(xiàn)volatility存在一個小bug锦茁,linux_pstree
在輸出的時候會遇到一些問題,具體問題以及山寨的解決方案如github issue所見撞牢。
0x04 優(yōu)缺點
優(yōu)點
- 能夠直接獲取內(nèi)存對內(nèi)存離線取證
- 可針對多個平臺進(jìn)行分析
- 程序跨平臺
- 能夠應(yīng)對應(yīng)用層的攻擊率碾,如rootkit掃描叔营,端口掃描等
缺點
- 需要編譯和安裝的依賴較多
- 雖然可以自主制作用戶配置文件屋彪,但是抓取內(nèi)存需要在受害主機(jī)上安裝內(nèi)存抓取模塊所宰,該模塊需要LKM支持以及需要GCC編譯,擁有l(wèi)inux內(nèi)核的頭文件畜挥,要求苛刻仔粥,取證可能會因主機(jī)的實際情況出現(xiàn)阻礙。