资讯动态

内存取证实战:用Volatility系统化分析easy_mem_3镜像

发布时间:2026/9/14 9:20:26 来源:尧图企业网站定制
1. 从一道题聊起内存取证到底在查什么如果你接触过CTF比赛或者做过应急响应大概率见过“内存取证”这个说法。简单说就是把一台运行中的电脑的内存镜像Memory Dump内存转储文件拿下来然后在这一坨字节里还原出当时系统里发生了什么——跑了哪些进程、建立了什么网络连接、用户打开了什么文件、甚至密码和密钥藏在哪里。这次要拆解的是一道名为easy_mem_3的题目。看到这个名字你应该能猜到它属于入门级内存取证题编号是3意味着前面还有更基础的1和2。但别小看这种“入门级”它恰恰覆盖了内存取证最核心、最高频的那些操作镜像识别、进程排查、网络连接分析、文件提取和字符串搜索。把这套流程跑顺了绝大多数实际应急响应里的内存分析需求你也能应付个七七八八。这篇博文不会给你贴一道题的“标准答案”因为那个没有意义。我要做的是带你完整走一遍内存取证的分析链路告诉你每一步为什么要这么做、常见坑在哪里、怎么用工具高效地拿到结论。无论你是准备打CTF还是在做蓝队排查这套方法论都通用。我先说结论easy_mem_3这类题考查的核心就是你能不能通过系统性的排查从海量内存数据里锁定与“恶意行为”或“flag”相关的蛛丝马迹。而要做到这一点你需要具备的不仅仅是敲命令的能力更是“带着问题去分析”的思路。2. 解题全景拿到镜像后的第一件事不是跑工具很多人拿到内存镜像后的第一反应是赶紧跑一个volatility插件看看能扫出什么。我劝你别这样。没有目标的扫描十有八九会把人淹没在几万条输出里越看越乱。正确做法是先建立三个层面的认知第一个层面这是什么镜像。它来自什么操作系统Windows 7 还是 Windows 1032位还是64位内核版本是多少这些决定了你后续选哪个profile配置文件而选错了profile所有插件都会报错或者给出完全错误的结果。第二个层面题目想考什么。CTF里的内存取证题flag通常藏在这几个地方某个进程的命令行参数里比如攻击者执行了echo flag{xxx}某个进程的内存空间里比如记事本里打开过包含flag的文本环境变量里有些题目会把flag写进临时变量剪贴板里用户复制过flag某个被删除文件的残留内容里网络连接的另一端可能连着一个C2服务器flag就在通信内容里。第三个层面系统里当时发生了什么。你要通过进程树、网络连接、文件操作去还原一条完整的故事线。比如某个进程是通过PowerShell启动的然后它创建了一个子进程这个子进程又去访问了外网IP同时还在临时目录下释放了一个文件。这一连串行为串起来基本就是攻击路径而flag往往就藏在这条路径的某个节点上。我把这个流程画成一个固定的套路你以后遇到任何内存取证题都可以套用识别镜像系统与profile先看进程列表找启动时间异常的、路径奇怪的、名字可疑的进程看命令行参数和环境变量这里经常直接出flag看网络连接找可疑的外联扫文件找被释放或残留的关键文件用memdump或dumpfiles把可疑进程或文件导出来用strings配合搜索交叉验证补全证据链。这套顺序不是我拍脑袋定的而是在大量实践里提炼出来的“最小必要步骤”。每一步的输出都会给下一步提供线索环环相扣。3. 镜像识别与Profile匹配不知道系统版本一切白搭3.1 用Volatility 2做镜像信息识别内存取证用得最多的工具是Volatility它有两个主要版本Volatility 2基于Python 2和Volatility 3基于Python 3。虽然Volatility 3已经出了很久但在CTF领域Volatility 2 依然是个绕不开的选择原因有两个一是老一辈教程和插件生态都基于它二是它对老版本Windows镜像的支持非常成熟。拿到镜像后第一步永远是识别镜像的基本信息。Volatility 2 里对应的命令是vol.py -f easy_mem_3.raw imageinfoimageinfo会根据内存特征数据给出可能匹配的操作系统版本和架构比如Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64输出里会出现几个候选项它做的事情是扫描内存中的内核结构特征然后把匹配度最高的几个列出来。通常建议直接选第一个但如果后续操作报错就换下一个试试。这一步为什么不能省因为Volatility的每个插件都依赖一个“正确的profile”来确定内核结构体的偏移地址。Windows各版本的结构体定义并不完全一致你用Win10的配置去解析Win7的镜像得到的进程列表就是乱七八糟的甚至会直接崩溃。3.2 Volatility 3 的镜像信息获取方式如果你使用的是Volatility 3对应的命令则是vol.py -f easy_mem_3.raw windows.infoVolatility 3 不再有“profile”的概念而是改用一套基于符号文件的机制插件会在运行时自动匹配系统版本。它也会输出系统版本、内核地址、处理器数量等信息。需要提醒一下Volatility 3 对较老的镜像比如XP、2003支持并不好如果遇到这类镜像还是老老实实开个Python 2环境用Volatility 2。而easy_mem_3这种带“easy”标签的题基本都是Win7或Win10镜像两个工具都能处理。3.3 实操中遇到的profile坑有一次我拿到一个镜像imageinfo给了一长串建议我贪省事直接选了第一个Win7SP1x64结果运行pslist的时候输出为空。排查了半天最后换用Win2008R2SP0x64才正常。后来我养成了一个习惯每换一个镜像先用pslist快速验证profile是否正常。如果pslist能列出进程说明Profile选对了如果输出为空、报错、或者时间明显异常立刻换下一个试试。这个验证方法成本极低但能帮你省下大量排查时间。提示遇到imageinfo识别不出profile的情况可以先跑一下kdbgscanVolatility 2它会扫描内核调试器数据块有时候能给出更精确的结果。4. 进程排查还原系统里的“人物关系”4.1 pslist、psscan、psxview的三重奏进程分析是内存取证的核心环节。Volatility提供了多个查看进程的插件很多人只用了pslist这远远不够。pslist遍历内核的进程链表适合看进程的父子关系、启动时间、退出时间。它是“按图索骥”的好工具。psscan在物理内存中扫描进程对象可以找到已经被断链的隐藏进程。psxview对比多种来源的进程信息检测进程是否被Rootkit隐藏。实战中优先跑pslist把整体情况摸清楚然后再用psscan对可疑点做补充验证。如果pslist和psscan的结果差异很大说明系统里可能存在隐藏进程这时候要重点盯住差异项。vol.py -f easy_mem_3.raw --profileWin7SP1x64 pslist vol.py -f easy_mem_3.raw --profileWin7SP1x64 psscan输出大概长这样Offset(V) Name PID PPID Thds Hnds Sess Wow64 Start Exit ------------------ -------------------- ----- ------ ------ -------- ------ ------ ------------------ ------------------ 0xfffffa80014db040 System 4 0 87 517 ------ 0 2024-01-01 08:23:45 UTC0000 0xfffffa80026b2060 smss.exe 260 4 2 29 ------ 0 2024-01-01 08:23:46 UTC0000看列表时我的优先级是先看PPID异常的进程再看启动时间晚于系统启动时间很多的进程最后看名称可疑的进程比如svchost.exe出现在Temp目录下那基本就是问题进程。4.2 命令行参数和环境变量flag的高发区进程列表本身信息有限真正出东西的是cmdline和envars。vol.py -f easy_mem_3.raw --profileWin7SP1x64 cmdline vol.py -f easy_mem_3.raw --profileWin7SP1x64 envarscmdline用于查看每个进程的启动参数。很多恶意软件通过命令行传入参数有时候参数里就直接带着flag。比如你可能会看到notepad.exe PID: 1234 Command line : notepad.exe C:\Users\admin\Desktop\flag.txt这告诉你flag很可能在记事本打开过的文件里。而envars可以查看进程的环境变量flag有时候会被写成环境变量形式比如FLAGflag{xxxx}这在CTF题里并不少见。4.3 实操心得关注被起奇怪名字的进程在实际做题过程中比较常见的flag藏匿方式是这样题目会创建一个看起来像系统进程的进程但名字做了改动比如svch0st.exe、expl0rer.exe或者直接放在C:\Windows\Temp目录下。看到这类进程先记录PID后面提取进程内存时要重点处理。我也遇到过把flag放在“已退出进程”内存里的情况。这很坑因为这要求你在pslist中注意到 Exit 时间不为空的进程。如果发现有进程已经退出了一定要用malfind或memdump把它残留的内存导出来里面常常有完整的flag。5. 网络连接分析从netscan挖出关键线索5.1 netscan到底扫的是什么网络连接分析是排查恶意行为的必经之路。easy_mem_3能关联到“netscan内存取证”这个热词说明这道题的网络连接分析是重要一环。在Volatility 2中对应的插件是vol.py -f easy_mem_3.raw --profileWin7SP1x64 netscan输出内容包括本地IP、本地端口、远程IP、远程端口、连接状态和对应的进程PID。Offset(P) Proto Local Address Foreign Address State PID ------------------ ------ ----------------------------- --------------------- --------------- ---- 0x1a33b5a0 TCP 192.168.1.100:49156 45.77.23.44:8080 ESTABLISHED 1234这里面大有文章可做。状态为ESTABLISHED且连接到一个陌生外部地址的进程极有可能在与C2服务器通信。即使题目是CTF这个“C2”也经常是攻击者的服务器IPflag可能就藏在通信内容里。状态为LISTENING的端口则可能是后门或木马开的监听端口。5.2 如何验证可疑连接对应的进程netscan已经给出了PID但光知道PID还不够你需要通过以下几步交叉验证第一用pslist或psscan确认这个PID对应的进程名和路径。如果路径在Temp或AppData目录下基本可以断定有问题。第二用cmdline查看这个进程的启动参数。这一步经常能直接看到奇怪的东西比如连同一条URL一起启动。第三用memdump导出这个进程的内存然后用strings搜索关键词。这是最关键的一步因为内存里可能残留着通信内容片段。5.3 netscan之外的补充连接记录与DNS请求netscan查的是当前活跃的网络连接但如果连接已经关闭还需要看下面两个东西connscan扫描物理内存中残留的TCP连接对象即使连接已经断开也可能留下记录通过strings对整个镜像搜索域名或IPDNS请求记录、浏览器的缓存都可能包含相关信息。如果你在使用Volatility 3对应的模块是vol.py -f easy_mem_3.raw windows.netscan输出格式与Volatility 2的netscan基本一致。这里有个实战小技巧如果远程IP是内网地址比如10.x.x.x、192.168.x.x那这个连接很可能不是外联C2而是题目环境里的内部通信flag藏在这里面的概率会低一些。相反如果是公网IP尤其是云服务商网段就要重点关注。5.4 实战一次完整的连接排查流程我以easy_mem_3的一道典型解法为例演示完整的排查思路。假设netscan输出里有一条记录0x1a33b5a0 TCP 192.168.1.100:49156 45.77.23.44:8080 ESTABLISHED 1234第一步回头看pslist确认PID 12340xfffffa80123ab040 powershell.exe 1234 2222 9 380 ------ 0 2024-01-01 09:00:03 UTC0000好一个PowerShell进程父进程是2222。继续查2222是什么发现是explorer.exe也就是说用户手动打开了PowerShell。第二步查看这个PowerShell的命令行vol.py -f easy_mem_3.raw --profileWin7SP1x64 cmdline -p 1234如果输出里带了一个地址基本就锁定目标了。第三步导出进程内存vol.py -f easy_mem_3.raw --profileWin7SP1x64 memdump -p 1234 --dump-dir./output然后对1234.dmp跑strings并按关键字过滤strings -el 1234.dmp | grep -iE flag|http|key|secret-el参数很关键它是搜索UTF-16LE编码的字符串。Windows系统内部字符串默认使用UTF-16LE如果你只搜ASCII很多信息会直接漏掉。这是内存取证里被问得最多的一个问题为什么flag搜不到多半就是因为没搜UTF-16编码的字符串。6. 文件系统中的秘密扫描、导出与还原6.1 从filescan到dumpfiles进程和网络给了你“动态”的线索但很多时候证据是以文件形式躺在内存里的。比如用户打开过的文档、被加载过的DLL、临时目录下的可疑脚本。用filescan扫描文件对象vol.py -f easy_mem_3.raw --profileWin7SP1x64 filescan这条命令会输出物理内存中检测到的所有文件对象输出量非常大通常需要配合grep来过滤。我常用的过滤条件是vol.py -f easy_mem_3.raw --profileWin7SP1x64 filescan | grep -iE tmp|temp|flag|secret|desktop|download如果命中了可疑文件记住它的偏移地址输出第一列用它来导出文件vol.py -f easy_mem_3.raw --profileWin7SP1x64 dumpfiles -Q 0x000000001e0b1c40 --dump-dir./output-Q参数后面跟的是物理内存偏移量。导出后检查文件类型file output/*如果是文本文件直接打开如果是压缩包或二进制文件再做进一步分析。6.2 在进程内存中提取字符串除了独立文件另一大信息源是被进程加载进内存的文本数据。最典型的例子是题目让你打开了一个flag.txt然后这个文件的内容被记事本读进了内存。你虽然在文件系统里找不到这个文件但它就静静躺在notepad.exe的堆内存里。操作方式是先用pslist找到notepad.exe的PID然后用memdump导出vol.py -f easy_mem_3.raw --profileWin7SP1x64 memdump -p 4567 --dump-dir./output导出后对镜像做字符串提取strings -el output/4567.dmp 4567_strings.txt cat 4567_strings.txt | grep flag如果运气好flag会直接出现如果运气不好就扩大搜索范围把flag改成{或者}来定位。大括号本身就是很好的搜索特征。6.3 实操注意文件导出失败的常见原因dumpfiles偶尔会导出失败尤其是文件页面被换出或覆盖时。遇到这种情况可以换memdump把整个进程的内存导出来再处理。另一个常见原因是偏移地址填错一定要用filescan输出的第一列数值不要自己手算。如果镜像特别大memdump生成的dump文件也会很大对内存和磁盘都是考验。建议在处理前整理一下磁盘空间避免跑到一半报磁盘已满。7. 绕过隐藏与权限malfind、hashdump与注册表7.1 malfind找出进程内存中的注入代码所谓进程注入通俗讲就是恶意代码把自己“塞”进了一个正常进程的身体里让杀毒软件和调查人员不容易发现。内存取证里malfind是专门用来找这类注入代码的。vol.py -f easy_mem_3.raw --profileWin7SP1x64 malfind运行后它会扫描每个进程的内存区域找出带有“可写可执行RWX”属性的区域并尝试判断其中是否含有shellcode或恶意代码。输出中会标注进程PID和虚拟地址你可以结合strings对这些内存区域做进一步分析。CTF的easy_mem_3未必有Rootkit这么深的内容但malfind是面试和实际工作中必问的一个功能建议你提前跑熟。7.2 hashdump与注销密码有时候flag不会直接出现在明文里而是藏在账号密码的哈希里。比如一段密码就是flag。这种情况可以用vol.py -f easy_mem_3.raw --profileWin7SP1x64 hashdump它会从注册表的SAMSecurity Account Manager中导出用户密码哈希。拿到哈希后可以用hashcat或在线彩虹表进行破解。比如输出Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::后半段是NTLM哈希如果题目设计得比较直接破出来的明文就是flag。7.3 注册表信息不能忽视的“系统记忆”Volatility可以把注册表信息从内存中提取出来。它可以把SYSTEM和SOFTWARE等注册表配置单元导出成文件然后你在宿主机上离线分析。vol.py -f easy_mem_3.raw --profileWin7SP1x64 dumpregistry --dump-dir./output分析时优先看这些位置启动项Run、RunOnce——恶意软件常驻的入口用户最近打开的文件记录UserAssist网络共享连接MountedDevices、Network。有个比较坑的点是Windows 10镜像的注册表配置单元非常大直接dumpregistry时可能耗时很长。可以先确认镜像系统版本再决定是否要全量导出或者用Volatility 3的windows.registry.printkey来针对性地查看关键键值。8. 常用工具对照Volatility 2与Volatility 3的选择既然说到了工具索性把选择思路讲透。有些人非2不用有些人非3不碰其实没必要互相攻击。对比维度Volatility 2Volatility 3Python环境Python 2.7Python 3.xProfile机制需手工指定自动匹配系统老系统支持XP/2003好一般Win10/Server2016支持一般好插件生态成熟大量第三方脚本起步稍晚在追赶CTF适用度经典题目大多基于v2新题越来越多用v3两条建议第一CTF优先学Volatility 2。因为大量经典题目、教程、writeup都用的是v2你拿v3去复现老题很容易对不上。而且v2的profile机制能帮你更好地理解内存结构。第二实战优先用Volatility 3。实际环境里Windows 10居多Volatility 3的系统兼容性更好符号机制也更智能不需要手动去试profile。对于easy_mem_3我推荐你两个都装好哪个能跑就用哪个。别在这种事情上花太多时间纠结。9. 镜像获取与格式兼容的坑讲到这里很多人会问环境污染问题怎么办我先说结论题目给什么格式就用什么格式分析。easy_mem_3这种题基本是直接提供.raw或.mem文件。这个格式允许你直接使用Volatility进行分析。不过实际工作中不太一样。你拿到的往往是E01、DD或VMEMVMware虚拟机内存等不同格式。VMware虚拟机的.vmem文件Volatility 可以直接识别但E01这类取证格式就需要用ewfmount等工具先将镜像挂载为原始格式再用Volatility分析。如果遇到.vmem文件有时还需要额外使用vmware-vdiskmanager或内存转换工具来提取原始内存。创建镜像的好习惯是先在干净的机器上验证一遍工具链再对题目镜像做分析。仓促上阵很容易被各种兼容性问题耽误时间。10. 字符串搜索与编码问题为什么你总是搜不到flag字符串搜索是整个内存取证中最简单也最实用的技巧。但有三个高频坑我这里单独拎出来说一下。第一编码问题。Windows系统里很多字符串是UTF-16LE存储的你只用普通字符串搜索是搜不出来的。正确的做法是strings -el image.raw | grep flag这个-el参数就是我前面提到的UTF-16LE搜索。如果你不确定目标字符串是什么编码就先分别跑一遍ASCII和UTF-16LE的搜索再不行试试UTF-8。第二大小写问题。flag可能被写成Flag、FLAG、FlAg。建议统一用-i参数忽略大小写strings -el image.raw | grep -i flag第三完整flag可能被拆开。比如flag{xxx}中的{和}之间存在换行符或特殊字符导致单条搜索结果不完整。遇到这种情况可以搜索flag或者{附近的内容然后把上下文手动拼起来。有些取证比赛为了增加难度还会故意把flag拆成几段分别存在不同进程里你需要到多个位置提取并拼接。11. 常见问题排查速查表我把实操中最常遇到的问题整理成下面这张表你以后遇到类似报错直接对照处理。现象可能原因解决方法imageinfo报错Volatility 2与Python环境不兼容确认使用的是Python 2.7且安装了正确依赖pslist输出为空Profile选错换一个imageinfo建议的profile或使用kdbgscan插件运行报Invalid offset镜像被修改或工具版本不匹配确认镜像完整性换用Volatility 3strings搜不到flag编码问题加上-el参数搜索UTF-16LE或-e l搜索小端模式dumpfiles导出失败文件已被换出或覆盖改用memdump导出整个进程内存netscan没有输出镜像较老或连接已断开尝试connscan并配合strings全局搜索内存镜像巨大分析卡死内存/磁盘资源不足缩小搜索范围单独处理可疑进程拿到E01格式镜像不是原始raw格式挂载或转换成raw后再分析这些坑我基本都踩过一遍写出来是希望你能少走弯路。12. 实操完整链路从镜像到flag的一站式流程为了让你有一个整体感我把一整套实操流程完整串一遍。你以后做任何内存取证题都可以按这个标准流程走。第一步准备工作目录mkdir easy_mem_3_lab cd easy_mem_3_lab mkdir raw output cp /path/to/easy_mem_3.raw raw/第二步识别镜像vol.py -f raw/easy_mem_3.raw imageinfo假设返回Win7SP1x64后续命令都加上--profileWin7SP1x64。第三步进程排查vol.py -f raw/easy_mem_3.raw --profileWin7SP1x64 pslist vol.py -f raw/easy_mem_3.raw --profileWin7SP1x64 psscan vol.py -f raw/easy_mem_3.raw --profileWin7SP1x64 cmdline记录下所有可疑进程的PID。第四步网络排查vol.py -f raw/easy_mem_3.raw --profileWin7SP1x64 netscan vol.py -f raw/easy_mem_3.raw --profileWin7SP1x64 connscan把可疑连接对应的PID记录下来。第五步文件排查vol.py -f raw/easy_mem_3.raw --profileWin7SP1x64 filescan | grep -iE tmp|temp|flag|secret|desktop第六步提取可疑文件或进程内存vol.py -f raw/easy_mem_3.raw --profileWin7SP1x64 dumpfiles -Q OFFSET --dump-dir./output vol.py -f raw/easy_mem_3.raw --profileWin7SP1x64 memdump -p PID --dump-dir./output第七步字符串搜索strings -el output/*.dmp | grep -iE flag|secret|key|http strings -el output/*.img 2/dev/null | grep -iE flag|secret|key|http第八步如果还没找到考虑malfind、hashdump、注册表分析vol.py -f raw/easy_mem_3.raw --profileWin7SP1x64 malfind vol.py -f raw/easy_mem_3.raw --profileWin7SP1x64 hashdump vol.py -f raw/easy_mem_3.raw --profileWin7SP1x64 dumpregistry --dump-dir./output把每一步的结果汇总在一起尽量串出一条完整的时间线即系统怎么被攻破、恶意代码如何运行、flag在哪里出现。13. 环境搭建建议很多人学习内存取证时卡在环境搭建这一步——Volatility 2对Python 2的依赖很别扭插件装的也是很老套的方式。分享一下我现在的环境装一个Python 2.7的虚拟环境再在同机上保留Volatility 3的独立环境两边互不干扰。Volatility 2的安装需要明确一点它本身是纯Python写的可以直接运行。依赖项包括pycrypto、distorm3等虽然比较老但通常仍能安装成功。如果pycrypto编译报错可以换成pycryptodome很多发行版的Volatility 2分支已经支持了。Volatility 3的安装则简单得多直接用pip install volatility3它自动处理Python 3的依赖。在这两个工具链就绪后建议找几个公开的内存取证样本练手。CTF比赛题目是最理想的练习材料因为出题人设计好了明确的flag你能直观验证自己的分析结果。我自己一般是打CTF时顺手把内存镜像留一份赛后复盘用不同工具重新分析对比慢慢就积累出了一套自己的“肌肉记忆”。14. 分析与报告结论要落在证据链上最后想说的是取证分析不只是拿到flag更重要的是能说清楚“为什么”。真正专业的分析需要整理出以下内容可疑进程的PID、名称、路径、命令行关键网络连接的本地/远程IP和端口可疑文件在内存中的偏移地址和提取后的哈希值通过时间戳串起的事件时间线字符串搜索命中的关键内容以及它们对应的进程或文件。这样一份报告出来不管是应急响应还是CTF比赛都非常有价值。做内存取证这几年我最深的体会是工具永远是容易学的难的是分析思维。你可以花五分钟学会netscan的用法但要在几万个对象里找到真正可疑的那一个靠的是经验和逻辑。希望这篇easy_mem_3的拆解能给你一个足够清晰的分析框架。剩下的就是动手去跑一个真实的镜像把每一步都踩一遍踩过的坑会变成你自己的武器库。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价