利用 Volatility 进行进攻性取证分析
1. 用户侦察
在进行取证分析时,首先可以查看系统中安装的服务。例如,通过相关命令可以获取部分服务信息:
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services WinSock2 False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services WINUSB False
接着,使用
cmdline
插件对虚拟机用户进行侦察。该插件会列出在快照拍摄时每个进程的命令行参数,这些参数能为我们了解用户的行为和意图提供线索。
PS>vol -f WinDev2007Eval-7d959ee5.vmem windows.cmdline
执行上述命令后,会得到如下类似结果:
| PID | Process | Args |
| — | — | — |
| 72 | Registry | Required memory at 0x20 is not valid (process exited?) |
| 340 | smss.exe | Required memory at 0xa5f1873020 is inaccessible (swapped) |
| 564 | lsass.exe | C:\Windows\system32\lsass.exe |
|… |… |… |
从这个列表中可以看出,大多数进程可能是系统在启动时自动启动的,而像
cmd.exe
和
notepad.exe
这样的进程通常是用户手动启动的。
为了更深入地研究运行中的进程,可以使用
pslist
插件,它会列出快照拍摄时正在运行的进程。
PS>vol -f WinDev2007Eval-7d959ee5.vmem windows.pslist
运行结果示例如下:
| PID | PPID | ImageFileName | Offset(V) | Threads | Handles | SessionId | Wow64 |
| — | — | — | — | — | — | — | — |
| 4 | 0 | System | 0xa50bb3e6d040 | 129 | - | N/A | False |
| 72 | 4 | Registry | 0xa50bb3fbd080 | 4 | - | N/A | False |
| 6452 | 4732 | OneDrive.exe | 0xa50bb4d62080 | 25 | - | 1 | True |
|… |… |… |… |… |… |… |… |
为了清晰地了解进程之间的层次关系,使用
pstree
插件,它会以树形结构展示进程的父子关系。
PS>vol -f WinDev2007Eval-7d959ee5.vmem windows.pstree
以下是部分结果示例:
PID PPID ImageFileName Offset(V) Threads Handles SessionId Wow64
4 0 System 0xa50bba7bd080 129 N/A False
* 556 492 services.exe 0xa50bba7bd080 8 0 False
** 2176 556 wlms.exe 0xa50bba7bd080 2 0 False
...
从这个结果中可以清晰地看到进程之间的父子关系,例如
userinit
进程(PID 4704)启动了
explorer.exe
进程,而
explorer.exe
进程(PID 4732)又启动了
cmd.exe
进程(PID 7092),用户从该
cmd.exe
进程启动了
notepad.exe
和
nc64.exe
进程。
2. 密码哈希获取
使用
hashdump
插件可以检查系统中的密码哈希值。
PS> vol -f WinDev2007Eval-7d959ee5.vmem windows.hashdump
执行后会得到如下结果:
| User | rid | lmhash | nthash |
| — | — | — | — |
| Administrator | 500 | aad3bXXXXXXaad3bXXXXXX | fc6eb57eXXXXXXXXXXX657878 |
| Guest | 501 | aad3bXXXXXXaad3bXXXXXX | 1d6cfe0dXXXXXXXXXXXc089c0 |
|… |… |… |… |
攻击者在渗透 Windows 机器后,恢复密码哈希是常见的目标。这些哈希值可以离线破解以尝试恢复目标的密码,或者用于“传递哈希”攻击以访问其他网络资源。可以将自己获取的哈希值作为输入,使用哈希破解工具(如在线哈希破解网站或 Kali 机器上的 John the Ripper)来尝试破解密码。
3. 漏洞侦察
使用
malfind
插件可以发现目标虚拟机是否存在可能被利用的漏洞。该插件会检查进程内存范围中是否可能包含注入的代码,它主要查找具有读写和执行权限的内存区域。
PS>vol -f WinDev2007Eval-7d959ee5.vmem windows.malfind
运行结果示例如下:
| PID | Process | Start VPN | End VPN | Tag | Protection | CommitCharge |
| — | — | — | — | — | — | — |
| 1336 | timeserv.exe | 0x660000 | 0x660fff | VadS | PAGE_EXECUTE_READWRITE | 1 |
| 2160 | MsMpEng.exe | 0x16301690000 | 0x1630179cfff | VadS | PAGE_EXECUTE_READWRITE | 269 |
|… |… |… |… |… |… |… |
在结果中,
timeserv.exe
进程(PID 1336)是
FreeDesktopClock
(PID 6484)的一部分,只要它们安装在
C:\Program Files
下,通常不会有问题,否则可能是伪装成时钟的恶意软件。
MsMpEng.exe
进程(PID 2160)是反恶意软件服务,虽然它包含可写和可执行的内存区域,但看起来并不危险,不过可以考虑向这些内存区域写入 shellcode 使其变得危险。
使用
netscan
插件可以获取机器在快照拍摄时的所有网络连接列表。
PS>vol -f WinDev2007Eval-7d959ee5.vmem windows.netscan
运行结果示例如下:
| Offset | Proto | LocalAddr | LocalPort | ForeignAdd | ForeignPort | State | PID | Owner |
| — | — | — | — | — | — | — | — | — |
| 0xa50bb7a13d90 | TCPv4 | 0.0.0.0 | 4444 | 0.0.0.0 | 0 | LISTENING | 7124 | nc64.exe |
| 0xa50bb9f4c310 | TCPv4 | 0.0.0.0 | 7680 | 0.0.0.0 | 0 | LISTENING | 1776 | svchost.exe |
|… |… |… |… |… |… |… |… |… |
从结果中可以看到一些本地机器(192.168.28.128)与一些 Web 服务器的连接,这些连接现在已经关闭。更重要的是标记为
LISTENING
的连接,由可识别的 Windows 进程(如
svchost
、
lsass
、
wininit
)拥有的连接可能是正常的,但
nc64.exe
进程是未知的,它正在监听端口 4444,值得使用之前提到的 netcat 替代品来深入探查该端口。
4. volshell 接口
除了命令行界面,还可以使用
volshell
命令在自定义 Python 外壳中使用 Volatility。这将提供 Volatility 的全部功能以及完整的 Python 外壳。以下是一个使用
volshell
在 Windows 映像上使用
pslist
插件的示例:
PS> volshell -w -f WinDev2007Eval-7d959ee5.vmem
>>> from volatility.plugins.windows import pslist
>>> dpo(pslist.PsList, primary=self.current_layer, nt_symbols=self.config['nt_symbols'])
在这个示例中,使用
-w
开关告诉 Volatility 正在分析 Windows 映像,使用
-f
开关指定映像本身。进入
volshell
接口后,可以像使用普通 Python 外壳一样使用它,导入包或编写函数,同时还能使用 Volatility 的功能。可以通过输入
volshell --help
来获取更多关于使用
volshell
的信息。
5. 自定义 Volatility 插件
Volatility 允许用户编写自定义插件,这为分析提供了更多的灵活性。下面是一个典型插件的骨架:
imports...
class CmdLine(interfaces.plugin.PluginInterface):
@classmethod
def get_requirements(cls):
pass
def run(self):
pass
def generator(self, procs):
pass
主要步骤包括创建一个继承自
PluginInterface
的新类,定义插件的要求,定义
run
方法和
generator
方法(可选)。
以创建一个检查进程是否受地址空间布局随机化(ASLR)保护的自定义插件为例。首先,创建一个名为
plugins
的目录,在该目录下创建一个
windows
目录来存放针对 Windows 机器的自定义插件。在
plugins/windows
目录下编写
aslrcheck.py
插件:
# Search all processes and check for ASLR protection
#
from typing import Callable, List
from volatility.framework import constants, exceptions, interfaces, renderers
from volatility.framework.configuration import requirements
from volatility.framework.renderers import format_hints
from volatility.framework.symbols import intermed
from volatility.framework.symbols.windows import extensions
from volatility.plugins.windows import pslist
import io
import logging
import os
import pefile
vollog = logging.getLogger(__name__)
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040
IMAGE_FILE_RELOCS_STRIPPED = 0x0001
def check_aslr(pe):
pe.parse_data_directories([
pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG']
])
dynamic = False
stripped = False
if (pe.OPTIONAL_HEADER.DllCharacteristics &
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE):
dynamic = True
if pe.FILE_HEADER.Characteristics & IMAGE_FILE_RELOCS_STRIPPED:
stripped = True
if not dynamic or (dynamic and stripped):
aslr = False
else:
aslr = True
return aslr
class AslrCheck(interfaces.plugins.PluginInterface):
@classmethod
def get_requirements(cls):
return [
requirements.TranslationLayerRequirement(
name='primary', description='Memory layer for the kernel',
architectures=["Intel32", "Intel64"]),
requirements.SymbolTableRequirement(
name="nt_symbols", description="Windows kernel symbols"),
requirements.PluginRequirement(
name='pslist', plugin=pslist.PsList, version=(1, 0, 0)),
requirements.ListRequirement(name = 'pid',
element_type = int,
description = "Process ID to include (all others are excluded)",
optional = True),
]
@classmethod
def create_pid_filter(cls, pid_list: List[int] = None) -> Callable[[interfaces.objects.
ObjectInterface], bool]:
filter_func = lambda _: False
pid_list = pid_list or []
filter_list = [x for x in pid_list if x is not None]
if filter_list:
filter_func = lambda x: x.UniqueProcessId not in filter_list
return filter_func
def _generator(self, procs):
pe_table_name = intermed.IntermediateSymbolTable.create(
self.context,
self.config_path,
"windows",
"pe",
class_types=extensions.pe.class_types)
procnames = list()
for proc in procs:
procname = proc.ImageFileName.cast("string",
max_length=proc.ImageFileName.vol.count, errors='replace')
if procname in procnames:
continue
procnames.append(procname)
proc_id = "Unknown"
try:
proc_id = proc.UniqueProcessId
proc_layer_name = proc.add_process_layer()
except exceptions.InvalidAddressException as e:
vollog.error(f"Process {proc_id}: invalid address {e} in layer {e.layer_name}")
continue
peb = self.context.object(
self.config['nt_symbols'] + constants.BANG + "_PEB",
layer_name = proc_layer_name,
offset = proc.Peb)
try:
dos_header = self.context.object(
pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
offset=peb.ImageBaseAddress,
layer_name=proc_layer_name)
except Exception as e:
continue
pe_data = io.BytesIO()
for offset, data in dos_header.reconstruct():
pe_data.seek(offset)
pe_data.write(data)
pe_data_raw = pe_data.getvalue()
pe_data.close()
try:
pe = pefile.PE(data=pe_data_raw)
except Exception as e:
continue
aslr = check_aslr(pe)
yield (0, (proc_id,
procname,
format_hints.Hex(pe.OPTIONAL_HEADER.ImageBase),
aslr,
))
在这个插件中,首先定义了一个
check_aslr
辅助函数,用于检查 PE 文件是否受 ASLR 保护。然后创建了
AslrCheck
类,它继承自
PluginInterface
,并定义了插件的要求。在
_generator
方法中,遍历每个进程,获取其 PEB 内存区域,重建 PE 文件,然后调用
check_aslr
函数检查 ASLR 保护情况,并返回包含进程 ID、进程名称、内存地址和 ASLR 保护检查结果的元组。
通过以上步骤,可以利用 Volatility 进行全面的进攻性取证分析,包括用户侦察、密码哈希获取、漏洞侦察等,同时还能根据需求编写自定义插件来满足特定的分析需求。
6. 技术点分析
在使用 Volatility 进行进攻性取证分析的过程中,涉及到多个关键技术点,下面对这些技术点进行详细分析。
6.1 进程分析技术
-
cmdline插件 :该插件通过列出进程的命令行参数,为我们了解用户的操作行为提供了线索。例如,通过观察cmd.exe和notepad.exe等进程的启动,我们可以推测用户可能进行了手动操作。 -
pslist插件 :用于获取快照时刻正在运行的进程列表,包含进程的 PID、PPID、映像文件名等信息。这有助于我们全面了解系统中正在运行的进程情况,判断是否存在异常进程。 -
pstree插件 :以树形结构展示进程的父子关系,清晰地呈现了进程之间的启动顺序和依赖关系。通过分析进程树,我们可以发现异常的进程启动链,例如某个未知进程由正常进程异常启动。
6.2 密码哈希获取技术
hashdump
插件可以提取系统中用户账户的 LM 和 NT 哈希值。攻击者可以利用这些哈希值进行离线破解或“传递哈希”攻击。在实际应用中,我们可以将获取的哈希值输入到哈希破解工具中,尝试恢复用户的明文密码。
6.3 漏洞侦察技术
-
malfind插件 :检查进程内存范围中是否存在具有读写和执行权限的区域,这些区域可能包含注入的代码。通过分析这些区域,我们可以发现潜在的恶意软件或漏洞利用代码。 -
netscan插件 :获取机器在快照时刻的所有网络连接列表,包括本地地址、端口、远程地址、端口以及连接状态等信息。通过分析网络连接情况,我们可以发现异常的网络连接,例如未知进程监听的端口或与可疑 IP 地址的连接。
6.4 自定义插件技术
Volatility 允许用户编写自定义插件,以满足特定的分析需求。自定义插件的编写需要遵循一定的规范,包括继承
PluginInterface
类、定义插件的要求、实现
run
方法和
generator
方法等。通过自定义插件,我们可以实现一些特定的功能,如检查进程的 ASLR 保护情况。
7. 操作流程总结
下面是使用 Volatility 进行进攻性取证分析的操作流程总结:
graph LR
A[开始] --> B[用户侦察]
B --> C[密码哈希获取]
C --> D[漏洞侦察]
D --> E[volshell 接口使用]
E --> F[自定义插件开发]
F --> G[结束]
7.1 用户侦察流程
-
使用
cmdline插件获取进程的命令行参数,分析用户的操作行为。 -
使用
pslist插件获取正在运行的进程列表,了解系统进程情况。 -
使用
pstree插件获取进程的父子关系,发现异常的进程启动链。
7.2 密码哈希获取流程
使用
hashdump
插件提取系统中用户账户的 LM 和 NT 哈希值,将哈希值输入到哈希破解工具中进行离线破解。
7.3 漏洞侦察流程
-
使用
malfind插件检查进程内存范围中是否存在具有读写和执行权限的区域,发现潜在的恶意软件或漏洞利用代码。 -
使用
netscan插件获取机器的网络连接列表,发现异常的网络连接。
7.4 volshell 接口使用流程
使用
volshell
命令进入自定义 Python 外壳,导入所需的插件并执行相应的操作。
7.5 自定义插件开发流程
-
创建
plugins目录和相应的子目录,存放自定义插件。 - 编写自定义插件的代码,遵循 Volatility 插件的编写规范。
- 在 Volatility 中使用自定义插件进行特定的分析。
8. 总结与展望
通过使用 Volatility 进行进攻性取证分析,我们可以全面了解系统的运行情况、用户的操作行为以及潜在的安全漏洞。用户侦察、密码哈希获取、漏洞侦察等功能为我们提供了丰富的信息,帮助我们发现系统中的异常情况。同时,自定义插件的开发为我们提供了更多的灵活性,可以根据具体需求实现特定的分析功能。
在未来的取证分析中,随着技术的不断发展,我们可以进一步优化 Volatility 的使用方法,提高分析效率和准确性。例如,结合机器学习算法对大量的取证数据进行分析,自动发现潜在的安全威胁。此外,我们还可以开发更多的自定义插件,满足不同场景下的分析需求。
总之,Volatility 是一款强大的取证分析工具,通过合理使用和开发,我们可以在进攻性取证分析中取得更好的效果。
超级会员免费看
50

被折叠的 条评论
为什么被折叠?



