17、利用 Volatility 进行进攻性取证分析

利用 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 用户侦察流程
  1. 使用 cmdline 插件获取进程的命令行参数,分析用户的操作行为。
  2. 使用 pslist 插件获取正在运行的进程列表,了解系统进程情况。
  3. 使用 pstree 插件获取进程的父子关系,发现异常的进程启动链。
7.2 密码哈希获取流程

使用 hashdump 插件提取系统中用户账户的 LM 和 NT 哈希值,将哈希值输入到哈希破解工具中进行离线破解。

7.3 漏洞侦察流程
  1. 使用 malfind 插件检查进程内存范围中是否存在具有读写和执行权限的区域,发现潜在的恶意软件或漏洞利用代码。
  2. 使用 netscan 插件获取机器的网络连接列表,发现异常的网络连接。
7.4 volshell 接口使用流程

使用 volshell 命令进入自定义 Python 外壳,导入所需的插件并执行相应的操作。

7.5 自定义插件开发流程
  1. 创建 plugins 目录和相应的子目录,存放自定义插件。
  2. 编写自定义插件的代码,遵循 Volatility 插件的编写规范。
  3. 在 Volatility 中使用自定义插件进行特定的分析。
8. 总结与展望

通过使用 Volatility 进行进攻性取证分析,我们可以全面了解系统的运行情况、用户的操作行为以及潜在的安全漏洞。用户侦察、密码哈希获取、漏洞侦察等功能为我们提供了丰富的信息,帮助我们发现系统中的异常情况。同时,自定义插件的开发为我们提供了更多的灵活性,可以根据具体需求实现特定的分析功能。

在未来的取证分析中,随着技术的不断发展,我们可以进一步优化 Volatility 的使用方法,提高分析效率和准确性。例如,结合机器学习算法对大量的取证数据进行分析,自动发现潜在的安全威胁。此外,我们还可以开发更多的自定义插件,满足不同场景下的分析需求。

总之,Volatility 是一款强大的取证分析工具,通过合理使用和开发,我们可以在进攻性取证分析中取得更好的效果。

本资源集提供了针对小型无人机六自由度非线性动力学模型的MATLAB仿真环境,适用于多个版本(如2014a、2019b、2024b)。该模型完整描述了飞行器在三维空间中的六个独立运动状态:绕三个坐标轴的旋转(滚转、俯仰、偏航)与沿三个坐标轴的平移(前后、左右、升降)。建模过程严格依据牛顿-欧拉方程,综合考虑了重力、气动力、推进力及其产生的力矩对机体运动的影响,涉及矢量运算与常微分方程求解等数学方法。 代码采用模块化与参数化设计,使用者可便捷地调整飞行器的结构参数(包括几何尺寸、质量特性、惯性张量等)以匹配不同机型。程序结构清晰,关键步骤配有详细说明,便于理解模型构建逻辑与仿真流程。随附的示例数据集可直接加载运行,用户可通过修改参数观察飞行状态的动态响应,从而深化对无人机非线性动力学特性的认识。 本材料主要面向具备一定数学与编程基础的高校学生,尤其适合计算机、电子信息工程、自动化及相关专业人员在课程项目、专题研究或毕业设计中使用。通过该仿真环境,学习者能够将理论知识与数值实践相结合,掌握无人机系统建模、仿真与分析的基本技能,为后续从事飞行器控制、系统仿真等领域的研究或开发工作奠定基础。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值