攻击取证--至此全篇完

攻击取证

取证人员通常是在发现缺陷事件后,或者是为了确定是否发生了“事件”而被叫来的人。他们通常需要受影响机器的 RAM (笔者注: Random Access Memory,随机存取存储器)的快照,以便捕获仅临时存储在内存中的加密密钥或其他信息。幸运的是,一个有才华的开发团队已经创建了一个完整的 Python 框架 Volatility ,它适合这个任务,被称为高级内存取证框架。事件响应者、取证人员和恶意软件分析师也可以将 Volatility 用于其他各种任务,包括检查内核对象、检查和转储进程信息等。

(笔者注: Volatility 是一款开源内存取证框架,能够对导出的内存镜像进行分析,通过获取内核数据结构,使用插件获取内存的详细情况以及系统的运行状态。特点:开源: Python 编写,易于和基于 python 的主机防御框架集成;支持多平台:Windows,Mac,Linux 全支持;易于扩展:通过插件来扩展 Volatility 的分析能力)

尽管 Volatility 是防御方的软件,但任何足够强大的工具都可以用于进攻或防守。我们将使用 Volatility 对目标用户执行侦察,并编写自己的攻击性插件来搜索在虚拟机(VM)上运行的防御能力较弱的进程。

假设你潜入一台机器,发现用户使用虚拟机进行敏感工作。很有可能用户还制作了虚拟机的快照作为安全措施以防出现任何错误问题,这更是好机会。我们将使用 Volatility 内存分析框架来分析快照,以了解 VM 是如何工作的以及哪些进程正在运行。我们还将调查可能存在的漏洞,以便进一步利用这些漏洞进行攻击。

我们开始吧!

安装

Volatility 已经存在了好几年,刚刚经历了一次彻底的改写。现在不仅代码库建立在 Python 3 上,而且整个框架都经过了重构,因此组件也是独立的;运行插件所需的所有情况都是自包含的。

让我们创建一个虚拟环境来处理 Volatility 。对于本例,我们在 Windows 机器上的 PowerShell 终端使用 Python 3。如果您也在 Windows 机器上工作,请确保安装了 git 。你可以在 https://git-scm.com/downloads/ 下载。

[1] PS> python3 -m venv vol3
PS> vol3/Scripts/Activate.ps1
PS> cd vol3/
[2] PS> git clone https://github.com/volatilityfoundation/volatility3.git
PS> cd volatility3/
PS> python setup.py  install
[3] PS> pip install pycryptodome

首先,我们创建一个名为 vol3 的新虚拟环境并将其激活[1]。接下来,我们进入虚拟环境目录并克隆 Volatility 3 的GitHub 存储库[2],将其安装到虚拟环境中,最后安装 pycryptodome [3],稍后我们将需要它。

要查看 Volatility 提供的插件和选项列表,请在 Windows 上使用以下命令:

PS> vol --help

在 Linux 或 Mac 上,使用虚拟环境中的 Python 可执行文件,如下所示:

$> python vol.py --help

在本章中,我们将从命令行使用 Volatility ,但是您可能会遇到各种各样的框架。例如,请参阅 Volatility 的 Volumetric 项目,一个免费的基于 web 的 Volatility GUI( https://github.com/volatilityfoundation/volumetric/ )。您可以深入到 Volumetric 项目中的代码示例,看看如何在自己的程序中使用 Volatility 。此外,您还可以使用 volshell 接口,它为您提供了对 Volatility 框架的访问,并作为一个普通的交互式 Python shell 工作。

在下面的示例中,我们将使用 Volatility 命令行。为了节省空间,将输出编辑为仅显示已讨论的输出,因此请注意,您的输出将有更多的行和列。

现在让我们深入研究一些代码,看看框架内部:

PS> cd volatility/framework/plugins/windows/
PS> ls
_init__.py    driverscan.py memmap.py       psscan.py  vadinfo.py
bigpools.py   filescan.py   modscan.py      pstree.py  vadyarascan.py
cachedump.py  handles.py    modules.py      registry/  verinfo.py
callbacks.py  hashdump.py   mutantscan.py   ssdt.py    virtmap.py
cmdline.py    info.py       netscan.py      strings.py
dlllist.py    lsadump.py    poolscanner.py  svcscan.py
driverirp.py  malfind.py    pslist.py       symlinkscan.py

这个清单显示了 Windows plugin 目录中的 Python 文件。我们强烈建议您花一些时间查看这些文件中的代码。您将看到形成 Volatility 插件结构的循环模式。这将有助于你理解这个框架,但更重要的是,它会让你了解一个防御者的心态和意图。通过了解防御者的能力以及他们是如何完成目标的,你将使自己成为一个更有能力的黑客,并更好地了解如何保护自己不被发现。

现在我们已经准备好了分析框架,我们需要一些内存图像来分析。最简单的方法是拍摄自己的 Windows 10 虚拟机的快照。

首先,打开 Windows 虚拟机并启动一些进程(例如,记事本、计算器和浏览器);我们将检查内存并跟踪这些进程是如何启动的。然后,使用您选择的虚拟机监控程序拍摄快照。在管理程序存储虚拟机的目录中,您将看到名称以 .vmem 或 .mem 结尾的新快照文件。让我们开始侦察吧!

请注意,您还可以在网上找到许多内存图像。本章中我们看到的一个图像是 PassMark Software 提供的([https://www .osforensics.com/tools/volatility-workbench.html/](https://www .osforensics.com/tools/volatility-workbench.html/))。Volatility Foundation 网站也有一些图像可以使用(https://github.com/volatilityfoundation/volatility/wiki/Memory-Samples/

通用侦察

让我们大致了解一下我们正在分析的机器。 windows.info 插件可以显示内存示例的操作系统和内核信息:

[1] PS>vol -f WinDev2007Eval-Snapshot4.vmem windows.info
Volatility 3 Framework 1.2.0-beta.1
Progress:   33.01               Scanning primary2 using PdbSignatureScanner
Variable        Value
Kernel Base     0xf80067a18000
DTB             0x1aa000
primary 0       WindowsIntel32e
memory_layer    1 FileLayer
KdVersionBlock  0xf800686272f0
Major/Minor     15.19041
MachineType     34404
KeNumberProcessors      1
SystemTime      2020-09-04 00:53:46
NtProductType   NtProductWinNt
NtMajorVersion  10
NtMinorVersion  0
PE MajorOperatingSystemVersion  10
PE MinorOperatingSystemVersion  0
PE Machine      34404

我们使用 -f 选项和要使用的 Windows 插件, windows.info ,指定快照文件名[1]。 Volatility 读取并分析内存文件,并输出有关此 Windows 计算机的通识信息。我们可以看到,我们正在处理一个 Windows 10.0 虚拟机 ,它有一个单处理器和一个内存层。

在查看插件代码时,您可能会发现在内存映像文件上尝试几个插件很有实践教育意义。花时间阅读代码并查看相应的输出将向您展示代码应该如何工作以及防御者大体上的心态。

接下来是 registry.printkey 插件,可以打印注册表中某个键的值。注册表有大量有价值的信息, Volatility 提供了一种找到我们想要的所有值的方法。在这里,我们寻找已安装的服务。键 /ControlSet001/Services 显示 Service Control Manager (服务控制管理器)数据库,其中列出了所有已安装的服务:

PS>vol -f WinDev2007Eval-7d959ee5.vmem windows.registry.printkey --key 'ControlSet001\Services'
Volatility 3 Framework 1.2.0-beta.1
Progress:   33.01               Scanning primary2 using PdbSignatureScanner
... Key                                         Name    Data       Volatile
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services .NET CLR Data      False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services Appinfo            False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services applockerfltr      False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services AtomicAlarmClock   False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services Beep               False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services fastfat            False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services MozillaMaintenance False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services NTDS               False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services Ntfs               False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services ShellHWDetection   False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services SQLWriter          False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services Tcpip              False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services Tcpip6             False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services terminpt           False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services W32Time            False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services WaaSMedicSvc       False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services WacomPen           False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services Winsock            False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services WinSock2           False
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services WINUSB             False

此输出显示计算机上已安装服务的列表(因空间原因而缩略了)。

用户侦察

现在让我们对虚拟机的用户进行一些侦察。 cmdline 插件列出了创建快照时每个进程正在运行的命令行参数。这些进程给我们一个关于用户行为和意图的提示。

PS>vol -f WinDev2007Eval-7d959ee5.vmem windows.cmdline
Volatility 3 Framework 1.2.0-beta.1
Progress:   33.01               Scanning primary2 using PdbSignatureScanner
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
624     winlogon.exe    winlogon.exe
2160    MsMpEng.exe     "C:\ProgramData\Microsoft\Windows Defender\platform\4.18.2008.9-0\
MsMpEng.exe"
4732    explorer.exe    C:\Windows\Explorer.EXE
4848    svchost.exe     C:\Windows\system32\svchost.exe -k ClipboardSvcGroup -p
4920    dllhost.exe     C:\Windows\system32\DllHost.exe /Processid:{AB8902B4-09CA-4BB6-B78D-
A8F59079A8D5}
5084    StartMenuExper  "C:\Windows\SystemApps\Microsoft.Windows. . ."
5388    MicrosoftEdge.  "C:\Windows\SystemApps\Microsoft.MicrosoftEdge_. . ."
6452    OneDrive.exe    "C:\Users\Administrator\AppData\Local\Microsoft\OneDrive\OneDrive.exe" 
/background
6484    FreeDesktopClo  "C:\Program Files\Free Desktop Clock\FreeDesktopClock.exe"
7092    cmd.exe         "C:\Windows\system32\cmd.exe" [1]
3312    notepad.exe     notepad [2]
3824    powershell.exe  "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
6448    Calculator.exe  "C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_. . ."
6684    firefox.exe     "C:\Program Files (x86)\Mozilla Firefox\firefox.exe"
6432    PowerToys.exe   "C:\Program Files\PowerToys\PowerToys.exe"
7124    nc64.exe        Required memory at 0x2d7020 is inaccessible (swapped)
3324    smartscreen.ex  C:\Windows\System32\smartscreen.exe -Embedding
4768    ipconfig.exe    Required memory at 0x840308e020 is not valid (process exited?)

该列表显示进程 ID 、进程名和命令行以及启动进程的参数。您可以看到,大多数进程都是由系统本身启动的,很可能是在引导时启动的。 cmd.exe [1]和 notepad.exe [2]进程是用户启动进程的典型。

让我们用 pslist 插件更深入地研究正在运行的进程,它列出了拍摄快照时正在运行的进程。

PS>vol -f WinDev2007Eval-7d959ee5.vmem windows.pslist
Volatility 3 Framework 1.2.0-beta.1
Progress:   33.01               Scanning primary2 using PdbSignatureScanner
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
6484    4732    FreeDesktopClo  0xa50bbb847300  1       -       1       False
6212    556     SgrmBroker.exe  0xa50bbb832080  6       -       0       False
1636    556     svchost.exe     0xa50bbadbe340  8       -       0       False
7092    4732    cmd.exe         0xa50bbbc4d080  1       -       1       False
3312    7092    notepad.exe     0xa50bbb69a080  3       -       1       False
3824    4732    powershell.exe  0xa50bbb92d080  11      -       1       False
6448    704     Calculator.exe  0xa50bb4d0d0c0  21      -       1       False
4036    6684    firefox.exe     0xa50bbb178080  0       -       1       True
6432    4732    PowerToys.exe   0xa50bb4d5a2c0  14      -       1       False
4052    4700    PowerLauncher.  0xa50bb7fd3080  16      -       1       False
5340    6432    Microsoft.Powe  0xa50bb736f080  15      -       1       False
8564    4732    python-3.8.6-a  0xa50bb7bc2080  1       -       1       True
7124    7092    nc64.exe        0xa50bbab89080  1       -       1       False
3324    704     smartscreen.ex  0xa50bb4d6a080  7       -       1       False
7364    4732    cmd.exe         0xa50bbd8a8080  1       -       1       False
8916    2136    cmd.exe         0xa50bb78d9080  0       -       0       False
4768    8916    ipconfig.exe    0xa50bba7bd080  0       -       0       False

这里我们看到了实际的进程及其内存偏移量。为了节省空间,所以省略了一些列。下面列出了几个有趣的进程,包括我们在 cmdline 插件的输出中看到的 cmd 和 notepad 进程。

最好将进程看作一个层次结构,这样我们就可以知道是什么进程启动了其他进程。为此,我们将使用到 pstree 插件:

PS>vol -f WinDev2007Eval-7d959ee5.vmem windows.pstree
Volatility 3 Framework 1.2.0-beta.1
Progress:   33.01               Scanning primary2 using PdbSignatureScanner
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
** 1796  556      svchost.exe     0xa50bba7bd080   13       0       False
** 776   556      svchost.exe     0xa50bba7bd080   15       0       False
** 8     556      svchost.exe     0xa50bba7bd080   18       0       False
*** 4556   8      ctfmon.exe      0xa50bba7bd080   10       1       False
*** 5388 704      MicrosoftEdge.  0xa50bba7bd080   35       1       False
*** 6448 704      Calculator.exe  0xa50bba7bd080   21       1       False
*** 3324 704      smartscreen.ex  0xa50bba7bd080    7       1       False
** 2136  556      vmtoolsd.exe    0xa50bba7bd080   11       0       False
*** 8916 2136     cmd.exe         0xa50bba7bd080   0        0       False
**** 4768 8916    ipconfig.exe    0xa50bba7bd080   0        0       False
* 4704           624    userinit.exe      0xa50bba7bd080  0   1 False
** 4732         4704     explorer.exe     0xa50bba7bd080  92  1 False
*** 6432        4732     PowerToys.exe    0xa50bba7bd080  14  1 False
**** 5340       6432      Microsoft.Powe  0xa50bba7bd080  15  1 False
*** 7364        4732     cmd.exe          0xa50bba7bd080  1   - False
**** 2464       7364      conhost.exe     0xa50bba7bd080  4   1 False
*** 7092        4732     cmd.exe          0xa50bba7bd080  1   - False
**** 3312       7092      notepad.exe     0xa50bba7bd080  3   1 False
**** 7124       7092      nc64.exe        0xa50bba7bd080  1   1 False
*** 8564        4732     python-3.8.6-a   0xa50bba7bd080  1   1 True
**** 1036       8564      python-3.8.6-a  0xa50bba7bd080  5   1 True

现在我们得到了一个更清晰的画面。每行中的星号表示进程的父子关系。例如, userinit 进程(PID 4704)生成了 explorer.exe 进程。同样, explorer.exe 进程(PID 4732)启动 cmd.exe 进程(PID 7092)。从这个进程中,用户启动了 notepad.exe 和另一个名为 nc64.exe 的进程。

现在让我们用 hashdump 插件检查密码:

PS> vol -f WinDev2007Eval-7d959ee5.vmem windows.hashdump
Volatility 3 Framework 1.2.0-beta.1
Progress:   33.01               Scanning primary2 using PdbSignatureScanner
User               rid     lmhash                            nthash
Administrator      500     aad3bXXXXXXaad3bXXXXXX fc6eb57eXXXXXXXXXXX657878
Guest              501     aad3bXXXXXXaad3bXXXXXX 1d6cfe0dXXXXXXXXXXXc089c0
DefaultAccount     503     aad3bXXXXXXaad3bXXXXXX 1d6cfe0dXXXXXXXXXXXc089c0
WDAGUtilityAccount 504     aad3bXXXXXXaad3bXXXXXX ed66436aXXXXXXXXXXX1bb50f
User              1001     aad3bXXXXXXaad3bXXXXXX 31d6cfe0XXXXXXXXXXXc089c0
tim               1002     aad3bXXXXXXaad3bXXXXXX afc6eb57XXXXXXXXXXX657878
admin             1003     aad3bXXXXXXaad3bXXXXXX afc6eb57XXXXXXXXXXX657878

输出显示帐户用户名及其密码的 LM 和 NT 散列。攻击者的一个共同目标是在入侵后恢复 Windows 机器上的密码哈希值。这些散列可以脱机破解以试图恢复目标的密码,也可以用于传递散列攻击以获得对其他网络资源的访问。无论目标用户是只在虚拟机上执行高风险操作的偏执用户,还是试图将其用户的某些活动包含到虚拟机的企业用户,查看系统上的虚拟机或快照都是在获得对主机硬件的访问权限后尝试恢复这些散列的最佳时机。

Volatility 使得这一复苏过程极为容易。

我们已经混淆了输出中的散列。您可以使用自己的输出作为散列破解工具的输入,以找到进入 VM 的方法。有几个在线哈希破解网站;或者,你可以在你的 kali 机上使用 John the Ripper 。

(笔者注: John the Ripper 是一个快速的密码破解工具,用于在已知密文的情况下尝试破解出明文,支持目前大多数的加密算法,如 DES、MD4、MD5 等。它支持多种不同类型的系统架构,包括 Unix、Linux、Windows、DOS 模式、 BeOS 和 OpenVMS ,主要目的是破解不够牢固的 Unix/Linux 系统密码。除了在各种 Unix 系统上最常见的几种密码哈希类型之外,它还支持 Windows LM 散列,以及社区增强版本中的许多其他哈希和密码。它是一款开源软件。Kali中自带John。)

漏洞侦察

现在,让我们使用 Volatility 来发现目标 VM 是否存在可以利用的漏洞。 malfind 插件检查可能包含注入代码的进程内存范围。 Potential 是这里的关键词——插件正在寻找具有读、写和执行权限的内存区域。调查这些进程是值得的,因为它们可能帮助我们能够利用一些已经可用的恶意软件。或者,我们可以用自己的恶意软件覆盖这些区域。

PS>vol -f WinDev2007Eval-7d959ee5.vmem windows.malfind
Volatility 3 Framework 1.2.0-beta.1
Progress:   33.01               Scanning primary2 using PdbSignatureScanner
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
2160 MsMpEng.exe     0x16303090000 0x1630318ffff VadS PAGE_EXECUTE_READWRITE  256
2160 MsMpEng.exe     0x16304a00000 0x16304bfffff VadS PAGE_EXECUTE_READWRITE  512
6484 FreeDesktopClo  0x2320000     0x2320fff     VadS PAGE_EXECUTE_READWRITE  1
5340 Microsoft.Powe  0x2c2502c0000 0x2c2502cffff VadS PAGE_EXECUTE_READWRITE  15

我们遇到了一些潜在的问题。 timeserv.exe 进程(PID 1336)是 FreeDesktopClock (PID 6484)免费软件的一部分。只要他们被安装到 C:\Program Files 目录下,这些不一定是问题。否则,该进程可能是伪装成时钟的恶意软件。

使用搜索引擎,你会发现进程 MsMpEng.exe (PID 2160)是一个防恶意软件服务。尽管这些进程包含可写和可执行的内存区域,但它们看起来并不危险。也许我们可以通过在这些内存区域中编写 shellcode 来使这些进程变得危险,所以值得注意它们。

netscan 插件提供了快照时计算机拥有的所有网络连接的列表,如下所示。任何看起来可疑的东西我们都可以用来发动袭击。

PS>vol -f WinDev2007Eval-7d959ee5.vmem windows.netscan
Volatility 3 Framework 1.2.0-beta.1
Progress:   33.01               Scanning primary2 using PdbSignatureScanner
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 [1]
0xa50bb9f4c310 TCPv4 0.0.0.0         7680 0.0.0.0 0            LISTENING   1776 svchost.exe
0xa50bb9f615c0 TCPv4 0.0.0.0        49664 0.0.0.0 0            LISTENING   564  lsass.exe
0xa50bb9f62190 TCPv4 0.0.0.0        49665 0.0.0.0 0            LISTENING   492  wininit.exe
0xa50bbaa80b20 TCPv4 192.168.28.128  50948 23.40.62.19    80    CLOSED [2]
w0xa50bbabd2010 TCPv4 192.168.28.128 50954 23.193.33.57   443   CLOSED
0xa50bbad8d010 TCPv4 192.168.28.128  50953 99.84.222.93   443   CLOSED
0xa50bbaef3010 TCPv4 192.168.28.128  50959 23.193.33.57   443   CLOSED
0xa50bbaff7010 TCPv4 192.168.28.128  50950 52.179.224.121 443   CLOSED
0xa50bbbd240a0 TCPv4 192.168.28.128    139   0.0.0.0 0            LISTENING

我们看到一些来自本地机器(192.168.28.128)的连接,显然到一些 web 服务器[2];这些连接现在已经关闭。更重要的是标记为 LISTENING 的连接。那些属于可识别的 Windows 进程( svchost , lsass , wininit )的进程可能没有问题,但 nc64.exe 进程是未知的[1]。它正在侦听端口4444,通过使用第2章中的 netcat 替代品来探测该端口对它进行更深入的研究也是很有价值的。

volshell 接口

(笔者注: volshell ,内存镜像中的shell )

除了命令行界面,您还可以使用 volshell 命令在自定义 Python shell 中使用 Volatility 。这为您提供了 Volatility 的所有功能以及完整的 Python shell 。下面是一个在 Windows 映像上使用 volshell 利用 pslist 插件的例子:

PS> volshell -w -f WinDev2007Eval-7d959ee5.vmem [1]
>>> from volatility.plugins.windows import pslist [2]
>>> dpo(pslist.PsList, primary=self.current_layer, nt_symbols=self.config['nt_symbols']) [3]
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
6484    4732    FreeDesktopClo  0xa50bbb847300  1       -       1       False
...

在这个简短的示例中,我们使用 -w 选项来告诉 Volatility 我们正在分析一个 Windows 图像,使用 -f 选项来指定图像本身[1]。一旦进入 volshell 接口,我们就可以像使用普通的 Python shell 一样使用它。也就是说,您可以像往常一样导入包或编写函数,但是现在您还在 shell 中嵌入了 Volatility 。我们导入 pslist 插件[2]并利用 dpo 函数显示插件[3]的输出。

你可以通过输入 volshell --help 找到更多关于使用 volshell 的信息。

自定义 Volatility 插件

我们刚刚看到了如何使用 Volatility 插件来分析存在漏洞的 VM 快照,通过检查正在使用的命令和进程来分析用户,并转储密码散列。但是由于您可以编写自己的自定义插件,所以只有您的想象力才能限制您可以用 Volatility 做什么。如果您需要根据从标准插件找到的线索中获得额外的信息,那么您可以制作自己的插件。

只要您遵循 Volatility 团队的模式,就可以很容易地创建插件。您甚至可以让您的新插件调用其他插件,从而使您的工作更加容易。

让我们来看看一个典型插件的框架:

imports . . .
[1] class CmdLine(interfaces.plugin.PluginInterface):
    @classmethod
    [2] def get_requirements(cls):
        pass
    [3] def run(self):
        pass
    [4] def generator(self, procs):
        pass

这里的主要步骤是创建从 PluginInterface [1]继承的新类,定义插件的需求[2],定义 run 类函数[3],以及定义 generator 类函数[4]。 generator 类函数是可选的,但是将它与 run 类函数分离是您将在许多插件中看到的有用模式。通过分离它并将其作为 Python 生成器使用,您可以获得更快的结果,并使代码更容易理解。

让我们遵循这个通用模式来创建一个自定义插件,该插件将检查不受 address space layout randomization (ASLR,地址空间布局随机化)保护的进程。 ASLR 混合了脆弱进程的地址空间,这影响了堆、栈和其他操作系统分配的虚拟内存位置。这意味着攻击者无法确定在攻击时受害进程的地址空间是如何布置的。 Windows Vista 是第一个支持 ASLR 的 Windows 版本。在 Windows XP 等较旧的内存镜像中,默认情况下不会启用 ASLR 保护。现在,在最新的电脑 (Windows 10) 中,几乎所有的进程都受到了保护。

ASLR 并不意味着攻击者就一定失败了,但它使工作变得更加复杂。作为侦察进程的第一步,我们将创建一个插件来检查流程是否受到 ASLR 的保护。

让我们开始吧。创建一个名为 plugins 的目录。在该目录下,创建一个名为 windows 目录,以存放用于 Windows 机器的自定义插件。如果您创建插件以 Mac 或 Linux 机器为目标,请分别创建一个名为 maclinux 的目录。

现在,在 plugins/windows 目录下,让我们编写我们的 ASLR 检查插件, 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

我们首先处理所需的导入,再加上用于分析 Portable Executable file (PE,可移植可执行文件)的 pefile 库。现在让我们编写一个辅助函数来进行分析:

[1] def check_aslr(pe):
    pe.parse_data_directories([
        pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG']
    ])
    dynamic = False
    stripped = False
[2] if (pe.OPTIONAL_HEADER.DllCharacteristics &
        IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE):
        dynamic = True
[3] if pe.FILE_HEADER.Characteristics & IMAGE_FILE_RELOCS_STRIPPED:
        stripped = True
[4] if not dynamic or (dynamic and stripped):
        aslr = False
    else:
        aslr = True
    return aslr

我们将一个 PE 文件对象传递给 check_aslr 函数[1],解析它,然后检查它是否已经用 DYNAMIC 基础设置编译[2],以及是否存在文件重定位数据段[3]。如果它不是动态的,或者可能编译为动态的但没有重定位数据段,那么 PE 文件也就不受 ASLR 保护[4]。

check_aslr 辅助函数已经准备好了,让我们创建我们的 AslrCheck 类:

[1] class AslrCheck(interfaces.plugins.PluginInterface):
    @classmethod
    def get_requirements(cls):
        return [
        [2] requirements.TranslationLayerRequirement(
                name='primary', description='Memory layer for the kernel',
                architectures=["Intel32", "Intel64"]),
            [3] requirements.SymbolTableRequirement(
                name="nt_symbols", description="Windows kernel symbols"),
        [4] requirements.PluginRequirement(
                name='pslist', plugin=pslist.PsList, version=(1, 0, 0)),
        [5] requirements.ListRequirement(name = 'pid',
             element_type = int,
             description = "Process ID to include (all others are excluded)",
             optional = True),
            ]

创建插件的第一步是从 PluginInterface 对象继承[1]。接下来,定义需求。通过查看其他插件,您可以很好地了解自己需要什么。每个插件都需要内存层,我们首先定义这个需求[2]。除了内存层,我们还需要符号表[3]。您会发现几乎所有插件都会使用这两个需求。

为了从内存中获取所有进程并从进程中重新创建PE文件[4],我们还需要 pslist 插件。然后,我们将从每个进程传递重新创建的 PE 文件,并检查它是否有 ASLR 保护。

我们可能想要检查给定进程 ID 的单个进程,因此我们创建另一个可选设置,允许我们传入一个进程 ID 列表,以限制只检查那些进程[5]。

@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

为了处理可选的进程 ID ,我们使用一个类函数创建一个过滤函数,该函数为列表中的每个进程 ID 返回 False ;也就是说,我们询问过滤函数的问题是是否过滤掉一个进程,所以只有 PID 不在列表中时才返回 True :

def _generator(self, procs):
        pe_table_name = intermed.IntermediateSymbolTable.create( [1]
            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( [2]
                    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() [3]
            pe_data.close()
            try:
                pe = pefile.PE(data=pe_data_raw) [4]
            except Exception as e:
                continue
            aslr = check_aslr(pe) [5]
            yield (0, (proc_id, [6]
                        procname,
                        format_hints.Hex(pe.OPTIONAL_HEADER.ImageBase),
                        aslr,
                        ))

我们创建了一个名为 pe_table_name [1]的特殊数据结构,用于循环内存中的每个进程。然后我们得到与每个进程相关联的Process Environment Block (PEB,进程环境块)内存区域,并将其放入对象中[2]。 PEB 是当前进程的数据结构,它包含了关于进程的大量信息。我们向该区域写入一个类文件对象 (pe_data) [3],使用 pefile 库创建一个 PE 对象[4],并将其传递给 check_aslr 辅助函数[5]。最后,我们生成包含进程 ID 、进程名、进程内存地址的信息元组,以及来自 ASLR 保护检查[6]的 Boolean (布尔值)结果。

现在我们创建 run 类函数,它不需要任何参数,因为所有的设置都被填充到 config 对象中:

    def run(self):
     1 procs = pslist.PsList.list_processes(self.context,
                                             self.config["primary"],
                                             self.config["nt_symbols"],
                                             filter_func =
                self.create_pid_filter(self.config.get('pid', None)))
     2 return renderers.TreeGrid([
            ("PID", int),
            ("Filename", str),
            ("Base", format_hints.Hex),
            ("ASLR", bool)],
            self._generator(procs))

我们使用 pslist 插件获取进程列表[1],并使用 TreeGrid 渲染器从生成器返回数据[2]。许多插件都使用 TreeGrid 渲染器。它确保我们为每个分析的进程得到一行结果。

(笔者注: TreeGrid 是一种 DHTML 控件,其完全使用 JavaScript 语言编写,用以在HTML页面上展示具有层次结构的数据项 ,其核心技术为多叉树。)

Kicking the Tires

让我们看一看在 Volatility 网站上提供的其中一个有效映像: Malware - Cridex 。对于您的自定义插件,提供 -p 选项与您的 plugins 文件夹路径:

PS>vol -p .\plugins\windows -f cridex.vmem aslrcheck.AslrCheck
Volatility 3 Framework 1.2.0-beta.1
Progress:    0.00               Scanning primary2 using PdbSignatureScanner
PID     Filename        Base    ASLR
368     smss.exe        0x48580000      False
584     csrss.exe       0x4a680000      False
608     winlogon.exe    0x1000000       False
652     services.exe    0x1000000       False
664     lsass.exe       0x1000000       False
824     svchost.exe     0x1000000       False
1484    explorer.exe    0x1000000       False
1512    spoolsv.exe     0x1000000       False
1640    reader_sl.exe   0x400000        False
788     alg.exe         0x1000000       False
1136    wuauclt.exe     0x400000        False

如您所见,这是一台 Windows XP 机器,在任何进程上都没有 ASLR 保护。

下面是纯净的全新的 Windows 10 机器的结果:

PS>vol -p .\plugins\windows -f WinDev2007Eval-Snapshot4.vmem aslrcheck.AslrCheck
Volatility 3 Framework 1.2.0-beta.1
Progress:   33.01               Scanning primary2 using PdbSignatureScanner
PID     Filename        Base    ASLR
316     smss.exe        0x7ff668020000  True
428     csrss.exe       0x7ff796c00000  True
500     wininit.exe     0x7ff7d9bc0000  True
568     winlogon.exe    0x7ff6d7e50000  True
592     services.exe    0x7ff76d450000  True
600     lsass.exe       0x7ff6f8320000  True
696     fontdrvhost.ex  0x7ff65ce30000  True
728     svchost.exe     0x7ff78eed0000  True
Volatility was unable to read a requested page:
Page error 0x7ff65f4d0000 in layer primary2_Process928 (Page Fault at entry 0xd40c9d88c8a00400 
in page entry)

 * Memory smear during acquisition (try re-acquiring if possible)
 * An intentionally invalid page lookup (operating system protection)
 * A bug in the plugin/volatility (re-run with -vvv and file a bug)

No further results will be produced

这里没什么可看的。每个列出的进程都受到 ASLR 的保护。然而,我们也看到了 memory smear ,内存污染。当拍摄内存映像时,内存存储的内容发生变化时,就会发生 memory smear 。这会导致内存表描述与内存本身不匹配;或者,虚拟内存指针可能引用无效数据。黑客攻击就会困难。正如错误描述所说,您可以尝试重新获取映像(寻找或创建一个新的快照)。

(笔者注: memory smear ,在内存采集过程中,运行中系统对数据的修改。)

让我们检查 PassMark Windows 10 样本内存映像:

PS>vol -p .\plugins\windows -f WinDump.mem aslrcheck.AslrCheck
Volatility 3 Framework 1.2.0-beta.1
Progress:    0.00               Scanning primary2 using PdbSignatureScanner
PID     Filename        Base    ASLR
356     smss.exe        0x7ff6abfc0000  True
2688    MsMpEng.exe     0x7ff799490000  True
2800    SecurityHealth  0x7ff6ef1e0000  True
5932    GoogleCrashHan  0xed0000        True
5380    SearchIndexer.  0x7ff6756e0000  True
3376    winlogon.exe    0x7ff65ec50000  True
6976    dwm.exe         0x7ff6ddc80000  True
9336    atieclxx.exe    0x7ff7bbc30000  True
9932    remsh.exe       0x7ff736d40000  True
2192    SynTPEnh.exe    0x140000000     False
7688    explorer.exe    0x7ff7e7050000  True
7736    SynTPHelper.ex  0x7ff7782e0000  True

几乎所有进程都受到保护。只有一个进程 SynTPEnh.exe 不受 ASLR 保护。在线搜索显示,这是 Synaptics Pointing Device 的一个软件组件,可能用于触摸屏。只要这个进程被安装在 c:\Program Files 中,就没有问题的,但它可能值得以后去弄清楚。

在本章中,您看到了您可以利用 Volatility 框架的强大功能来查找关于用户行为和连接的更多信息,以及分析任何进程运行内存中的数据。您可以使用这些信息来更好地理解目标用户和机器,以及理解防御者的心态。

Onward! (前进吧)

现在您应该已经注意到, Python 是一种非常适合黑客编程的语言,特别是当您考虑到许多可用的库和基于 Python 的框架时。虽然黑客拥有大量的工具,但没有什么能替代编写自己的工具,因为这能让你更深入地了解其他工具在做什么。

继续前进,为您的特殊需求编写一个自定义工具。无论它是 Windows 的 SSH 客户端, web scraper (笔者注: Web Scraper ,一个插件,轻量数据爬取利器),还是命令和控制系统, Python 都帮你搞定了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值