写下这篇文章的原因是因为最近在学习电子取证,使用Volatility多少得看得懂输出才行
现在只是大概的了解,如果后续有时间,会把每一个板块都单独拿出来学习的
嗯,如果有时间的话
下篇看这里 -> windows相关知识总结(下)
NTFS文件系统
什么是NTFS
NTFS,全称New Technology File System,是自WindowsNT以来微软所有现代操作系统的标准文件系统
在NTFS卷上,一切皆文件
这不仅包括我们日常所见的普通文件和目录,用于描述和管理文件系统自身的元数据也同样被组织成一系列特殊的文件,这种设计极大地增强了文件系统的灵活性和可恢复性
核心元文件
这是NTFS文件系统内部使用的一组以$开头的特殊隐藏文件,用于维护整个文件系统的结构、状态和完整性
它们不像普通用户文件那样可见或可操作,而是被NTFS在后台自动创建和管理,保存着关于文件、目录、磁盘空间、日志、安全信息等的元数据
大致结构如下:
NTFS Root
├── $Mft
├── $MftMirr
├── $LogFile
├── $Volume
├── $Bitmap
├── $BadClus
├── $AttrDef
├── $Secure
├── $Extend
│ ├── $Quota
│ ├── $ObjId
│ ├── $Reparse
│ └── $UsnJrnl
├── $UpCase
├── $Boot
└── ...
$Mft
MFT,即主文件表,是NTFS文件系统的核心数据库
它本身是一个特殊文件,由一系列固定大小的文件记录(通常为1024字节)组成
卷上的每一个文件和目录都至少对应MFT中的一个文件记录,该记录包含一个头部和一系列描述文件所有信息的属性
它的主要用途是作为整个卷的索引目录
操作系统进行任何文件操作(如查找、读取、写入、权限检查)时,都必须首先查询$Mft以获取文件的元数据,包括时间戳、大小、权限以及数据在磁盘上的物理位置
我们后面会详细说明它:[MFT](#NTFS的关键结构 —— 主文件表MFT)
$MftMirr
MftMirr是主文件表的一个部分备份或镜像
它通常只包含Mft最开头的几个关键文件记录(例如描述Mft自身、LogFile等元文件的记录)
为了提高容灾能力,它在物理磁盘上的存储位置通常远离Mft
其唯一的用途是文件系统恢复
当Mft文件的起始部分发生损坏导致文件系统无法挂载时,操作系统可以利用MftMirr来定位关键的元文件,从而为修复工具提供恢复文件系统的可能性
$LogFile
该文件是NTFS日志记录功能的物理载体
它遵循预写式日志模型,即在对文件系统元数据进行任何实际更改之前,都会先将描述该操作的事务日志记录写入LogFile
它的核心用途是保证文件系统的一致性和可恢复性
在系统意外崩溃或断电后,NTFS驱动程序可以通过检查LogFile,回滚未完成的事务或完成已记录但未写入的事务,从而防止文件系统结构损坏,也可以用来恢复最近的文件操作历史
$Volume
这是一个存储卷级别信息的元文件
它的主要属性中包含了整个卷的元数据,例如卷标、NTFS版本号以及卷的状态标志位
操作系统使用此文件来识别卷的属性
其中脏位(Dirty Bit)尤为重要,表示某个数据结构或内存页是否已经被修改过但尚未写回到磁盘或永久存储中,系统在启动时会检查这个标志,如果发现上次关机是“非正常”的,就会触发chkdsk等磁盘检查工具来确保卷的一致性
$Bitmap
Bitmap是一个位图文件,它的每一个比特位都精确地对应着卷上的一个物理簇
比特位的值(0或1)用于标记其对应的簇是空闲的还是已被占用
它被文件系统用于高效地管理磁盘空间分配
当需要为新文件写入数据时,系统会查询Bitmap来快速找到连续的空闲簇
当文件被删除时,其占用的簇对应的比特位会被重置为0(空闲)
$BadClus
该文件标记了卷上所有已被检测为物理损坏或不可靠的坏簇
它以一个稀疏文件的形式存在,其$DATA属性中包含了所有坏簇的位置列表
它的作用是防止数据丢失
文件系统在分配磁盘空间时,会避开BadClus文件中标记的所有簇,以确保用户数据不会被写入到这些已知的物理损坏区域
$AttrDef
AttrDef是属性定义表,相当于MFT文件记录的模式或模板定义文件
它以结构化的形式,列出了NTFS文件系统支持的所有属性类型及其元数据,包括它们的名称、数字ID以及默认特性(如是否可以非常驻)
此文件由NTFS驱动程序在内部使用,用于在解析任何MFT文件记录时,都能正确地识别和解释其中的各种属性结构,保证了MFT的结构完整性和可扩展性
$Secure
这是一个集中存储卷上所有文件和目录的安全描述符的数据库
NTFS为了节省空间,并不会在每个MFT记录中都存一份完整的安全描述符(包含用户SID、权限ACL等),而是将唯一的描述符存储在Secure文件中,并赋予其一个ID
其他MFT记录只需引用这个ID即可
主要用途是提高权限验证效率和降低安全信息的存储冗余
通过共享安全描述符,可以显著减小MFT的体积,并允许系统更高效地缓存和查询权限信息
$Extend
Extend本身是一个目录,它作为NTFS高级功能模块的扩展容器,其下包含了多个用于支持特定功能的元文件
它为磁盘配额、对象ID、重解析点和变更日志等高级功能提供结构化的存储位置
它包含以下重要子文件:
$Quota
用于记录和管理每个用户在该卷上的磁盘空间使用限制
它以包含用户SID、空间使用量、警告阈值和硬限制等信息的结构化记录进行存储
实现Windows的磁盘配额功能,允许管理员为不同用户设置不同的磁盘空间上限
$ObjId
为一个卷上的每个文件分配一个全局唯一的对象标识符(GUID),以便快速查找
主要被分布式链接跟踪等系统服务使用,确保即使用户将文件移动或重命名,依赖该文件的快捷方式等依然能找到它
$Reparse
记录了卷上所有设置了重解析点的文件或目录
重解析点允许一个文件或目录的访问被一个特定的驱动程序拦截并进行特殊处理
它是实现多种高级文件系统功能的基础,例如符号链接、目录联接、卷挂载点以及OneDrive的占位符文件等
$UsnJrnl
其全称为Update Sequence Number Journal,即更新序列号日志
它是一个高效率的日志,记录了卷上所有文件的所有变更事件,如创建、删除、写入、重命名、权限修改等
它的主要用户是需要监控文件系统变化的应用程序,如增量备份软件、文件同步服务、以及安全审计工具。在取证分析中,它是还原文件详细活动历史的最重要数据源之一
$Boot
该文件是卷的引导扇区的一个精确副本
它包含了BIOS参数块,详细描述了该分区的物理布局,以及用于启动操作系统的初始引导代码
其核心用途是在计算机启动时,由BIOS/UEFI读取并执行,以加载操作系统的引导加载程序
同时,NTFS驱动程序也需要读取它来理解卷的几何结构
$UpCase
该文件包含了一个完整的、将所有Unicode字符映射到其对应大写形式的转换表,用于实现NTFS文件名大小写不敏感但大小写保留的特性
当进行文件名比较或查找时,文件系统会调用这个映射表来确保file.txt和FILE.TXT这样的大小写被视为同一个文件
$Recycle.Bin
这虽然不是一个元数据文件,但它是一个与文件系统紧密相关的、重要的系统隐藏目录
当用户通过图形界面删除文件时,文件并不会被物理删除,而是其MFT记录被修改,使其被移动到Recycle.Bin目录下某个以用户SID命名的子目录中,并被重命名,同时一个索引文件会记录下原始的文件名和路径
它为用户提供回收站功能,允许恢复被误删除的文件
NTFS的关键结构 —— 主文件表MFT
什么是MFT
MFT的全称是MasterFileTable ,即主文件表,它是NTFS文件系统的核心
如果NTFS格式的硬盘分区是图书馆,那么MFT就是这个图书馆的总目录卡片索引柜
这个索引柜本身也是一个特殊的文件,名为$MFT,里面存放着一张张的卡片,每一张卡片都详细记录了图书馆里某一本书(即硬盘上的一个文件或文件夹)的所有信息
没有这个总目录,操作系统就无法找到、访问或管理分区上的任何文件
MFT 的结构
文件记录
MFT 由一系列固定大小的文件记录构成,每个记录都有一个唯一的编号,从 0 开始
记录的前部是固定的头结构FILE_RECORD_SEGMENT_HEADER,用于描述该记录的状态(如是否在使用中)
其余部分则由多个可变长度的属性组成
核心属性
每个文件记录内部,由多个不同类型的属性来完整描述一个文件,下面介绍几个关键属性:
-
$STANDARD_INFORMATION (0x10)这是存储文件的核心元数据,包括安全描述符、所有者ID,以及一组MACE时间戳
这组时间戳与文件内容的改变紧密相关,被认为是最稳定的时间戳,其创建时间通常反映了文件数据首次被写入的时间,是构建原始时间线的基准,常被称为MAC(B)时间
1. M - Modified (修改时间) —— 文件内容最后一次被修改的时间
当打开一个文件,编辑其内容并保存后,这个时间戳就会更新
创建新文件时,它的修改时间与创建时间相同
2. A - Accessed (访问时间) —— 文件内容最后一次被访问读取的时间
理论上,只要一个程序打开并读取了文件内容(即使没有修改),这个时间戳就应该更新。
但是在现代Windows系统中(Vista及之后),为了提高性能,默认情况下访问时间的更新是禁用的,因此这个时间戳的参考价值有限,除非管理员手动开启了该功能
3. C - Created (创建时间) —— 文件被创建在这个文件系统上的时间
当一个文件从一个地方复制到另一个地方时,新文件的“创建时间”是复制操作发生的时间,而不是原始文件的创建时间
但当文件被移动到同一卷(例如从C盘的一个文件夹移动到另一个文件夹)时,创建时间通常不会改变
4. E - Entry Modified (MFT记录变更时间) —— 该文件在MFT中的记录本身最后一次被修改的时间
任何导致文件元数据发生变化的操作都会更新这个时间戳,例如文件重命名、文件大小改变、权限修改等。当然,修改文件内容(更新Modified时间)也同样会更新这个时间戳
-
$FILE_NAME (0x30)包括存储文件名、父目录的文件记录号、文件大小,以及另一组独立的MACE时间戳
这组时间戳反映的是文件名属性本身的状态,当文件被创建、移动或重命名时,这组时间戳会被更新
通过对比
$STANDARD_INFORMATION和$FILE_NAME两组时间戳的差异,可以用来判断文件是原地创建还是从别处复制而来一个文件记录可以有多个
$FILE_NAME属性,以支持长文件名、MS-DOS兼容的8.3短文件名与硬链接这两组时间具体变化情况如下表(访问时间在现代Windows系统中默认禁用更新,因此假设其始终不变):
操作 属性 创建时间 (C) 修改时间 (M) 访问时间 (A) MFT变更时间 (E) 原地创建文件 $STANDARD_INFORMATION✅ ✅ ❌ ✅ $FILE_NAME✅ ✅ ❌ ✅ 修改文件内容 $STANDARD_INFORMATION❌ ✅ ❌ ✅ $FILE_NAME❌ ✅ ❌ ✅ 复制文件 $STANDARD_INFORMATION❌ (继承) ❌ (继承) ❌ ✅ $FILE_NAME✅ ✅ ❌ ✅ 移动文件 (同一分区) $STANDARD_INFORMATION❌ ❌ ❌ ❌ $FILE_NAME❌ ❌ ❌ ✅ 重命名文件 $STANDARD_INFORMATION❌ ❌ ❌ ❌ $FILE_NAME❌ ❌ ❌ ✅ 读取文件 $STANDARD_INFORMATION❌ ❌ ❌ ❌ $FILE_NAME❌ ❌ ❌ ❌ -
$DATA其中存储着文件的实际数据,其存储方式有两种:
- 常驻数据(存内容):如果文件非常小(通常小于约700字节),其全部数据会直接存储在 MFT 记录内部的
$DATA属性中,无需到磁盘的其他地方去寻找 - 非常驻数据(存指针):如果文件较大,
$DATA属性中存储的则是数据运行/簇列表,这是一系列指针,详细描述了该文件的数据流在磁盘上占用了哪些不连续的簇
- 常驻数据(存内容):如果文件非常小(通常小于约700字节),其全部数据会直接存储在 MFT 记录内部的
-
$ATTRIBUTE_LIST它包含一个指针列表,指向存储该文件其他属性的额外MFT记录
当一个文件的所有属性无法在一个MFT记录中存下时(例如,文件有极多的硬链接或高度碎片化),系统会创建这个属性
MFT与文件恢复
当一个文件被删除时,NTFS的操作是:
- 在 MFT 中找到该文件对应的记录,并将其头部的
in-use标志位置为0(未使用),记录本身的内容并不会被立即清除 - 在
$Bitmap文件中(跟踪卷上所有簇使用情况的元文件),将该文件数据所占用的磁盘簇标记为未分配
这种标记删除机制使得数据恢复成为可能,恢复的成功率取决于MFT记录和原始数据簇是否被后续写入的新文件所覆盖
这就导致下面几种情况:
| 恢复场景 | MFT记录状态 | 文件数据状态 | 可恢复性 |
|---|---|---|---|
| 最佳情况 | 完好 | 完好 | 完美恢复:文件名、元数据和文件内容全部可以恢复 |
| 一般情况 | 完好 | 部分被覆盖 | 部分恢复:文件名和元数据可恢复,但文件内容不完整或已损坏 |
| 情况三 | 完好 | 完全被覆盖 | 仅元数据恢复:只能恢复文件名、大小、时间戳等“档案”信息,文件内容永久丢失 |
| 最差情况 | 被覆盖 | 完好或部分完好 | 部分恢复:文件名和元数据永久丢失,但文件内容本身可以从磁盘的“未分配空间”中被恢复出来 |
| 常驻数据 | 完好 | 数据在MFT记录中 | 完美恢复:由于文件数据本身就存储在MFT记录中,只要MFT记录未被覆盖,即使磁盘数据区被重写,文件内容依然可以被完整恢复 |
注册表
什么是注册表
Windows注册表是整个操作系统的核心数据库,是一个庞大、复杂的层级式数据库
它存储了操作系统和几乎所有应用程序运行所需的全部配置信息,从硬件驱动的设置、软件的安装路径,到桌面壁纸的图片位置,所有的一切都记录在其中
如何打开注册表
我们可以使用注册表编辑器:
win+R打开运行窗口,输入regedit,Shift+Ctrl+Enter以管理员模式打开
除了直接看注册表,它还有一个简单易用的用户界面——本地组策略,只不过家庭版通常是没有的:
win+R打开运行窗口,输入gpedit.msc打开
注册表的结构
要分析注册表,我们必须理解它的双层结构:物理层和逻辑层
注册表的配置单元(物理层 - HIVE)
在Windows9x中,注册表文件的数据信息保存在system.dat(系统)和user.dat(用户)中
但到了WindowsNT,注册表并不是一个单一的大文件,而是由一组名为配置单元 (Hive)的独立文件组成的
这些是存储在硬盘上的真实文件,在系统运行时被加载到内存中,下面是几个常见的:
SYSTEM
存储核心的系统硬件配置、服务列表、启动设置
路径:C:\Windows\System32\config\SYSTEM
SOFTWARE
存储操作系统和已安装软件的全局配置信息
路径:C:\Windows\System32\config\SOFTWARE
SAM
安全帐户管理器(Security Account Manager),存储本地用户的账户信息和密码哈希
路径:C:\Windows\System32\config\SAM
SECURITY
存储系统范围内的安全策略和用户权限分配
路径:C:\Windows\System32\config\SECURITY
NTUSER.DAT
每个用户都有一个独立的,存储该用户的个性化设置,如桌面背景、程序历史记录等
路径:C:\Users\<用户名>\NTUSER.DAT
UsrClass.dat
同样是每个用户一个,存储文件关联和COM类注册信息
路径:C:\Users\<用户名>\AppData\Local\Microsoft\Windows\UsrClass.dat
Amcache.hve
记录了近期在该系统上运行过的应用程序及其路径、安装时间等信息
路径:C:\Windows\appcompat\Programs\Amcache.hve
BCD
存储了系统的启动菜单和配置信息,决定了计算机如何启动操作系统
没有扩展名,文件名就是BCD,即Boot Configuration Data
路径:通常位于系统启动分区,例如 \Boot\BCD
注册表的根键(逻辑层 - HKEY)
regedit.exe的HKEY_...开头的顶级文件夹,是操作系统为了方便管理而创建的逻辑视图,被称为根键
这些根键将不同的Hive文件组合在一起,形成树状结构
每一个根键都是一个项(文件夹),下面有着各种项,项里又定义着各种键值对(内容)
注册表包括以下五个根键,其中只有HKLM和HKU是真实映射Hive的,其余都是它们的视图:
1. HKEY_CLASSES_ROOT(HKCR)
它负责管理文件的类型关联(决定双击文件用什么程序打开)和 COM 组件的注册信息
它是虚拟的、合并而成的视图,由HKLM\SOFTWARE\Classes和HKCU\Software\Classes这两个键合并而成
2. HKEY_CURRENT_USER(HKCU)
该根键包括当前登录用户的配置信息,包括环境变量,个人程序以及桌面设置等
它实际上是指向HKEY_USERS下当前用户SID的一个快捷方式,其内容来自当前用户的NTUSER.DAT文件
3. HKEY_LOCAL_MACHINE(HKLM)
该根键包括本地计算机的系统信息,包括硬件和操作系统信息,安全数据和计算机专用的各类软件设置信息
它主要映射了SYSTEM,SOFTWARE,SAM,SECURITY等Hive
4. HKEY_USERS(HKU)
该根键包括计算机的所有用户使用的配置数据,这些数据只有在用户登录系统时才能访问,告诉系统当前用户使用的图标,激活的程序组,开始菜单的内容以及颜色,字体
它的每个子项是一个用户的SID,此外还有.DEFAULT子项,是系统为新用户创建账户时的配置模板
5. HKEY_CURRENT_CONFIG(HKCC)
该根键包括当前硬件的配置信息,其内容**完全指向(或映射自)**以下这个更深的注册表路径:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\Current
常用注册表项
持久化机制
这是恶意软件实现开机自启、确保自身不被清除最常用的位置
开机自启(Run/RunOnce)
- 路径:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run(对所有用户生效)HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceHKCU\Software\Microsoft\Windows\CurrentVersion\Run(只对当前用户生效)HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnceHKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run(策略控制的启动项)HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
- 功能:最经典、最直接的自启动位置写入这里的程序会在用户登录或系统启动时自动执行。
- 关注点:检查所有这些
Run键下是否有指向非标准目录(如Temp、AppData)的可执行文件,或者是否有名字可疑的启动项
系统服务(Services)
- 路径:
HKLM\SYSTEM\CurrentControlSet\Services\ - 功能:将程序注册为系统服务,可以在后台运行,权限高,更隐蔽
- 关注点:
- 可疑服务名:是否有随机、无意义或拼写错误的服务名称
ImagePath:正常服务(如svchost)的ImagePath是否被篡改为指向恶意程序FailureCommand:检查服务失败后执行的命令是否被设置为恶意程序
登录辅助程序(Winlogon)
- 路径:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon - 功能:
Winlogon.exe是负责用户登录的核心进程 - 关注点:
Userinit:默认值应为C:\Windows\system32\userinit.exe,。检查末尾是否有逗号,以及后面是否跟了其他恶意程序的路径(用逗号分隔)Shell:默认值应为explorer.exe,如果被修改,意味着用户的整个桌面环境都被替换了
调试器(Image File Execution Options,IFEO)
-
路径:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ -
功能:用于在程序启动时附加调试器
-
关注点:攻击者会创建一个以正常程序命名(如
notepad.exe)的子项,然后在其中添加一个名为Debugger的键值,指向自己的恶意程序:[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\notepad.exe] "Debugger"="C:\\Path\\To\\EvilDebugger.exe"这样,每当用户尝试运行记事本时,系统会优先运行那个恶意的调试器,而真正的记事本根本不会启动
也可以用于阻止程序运行,如果调试器不存在,系统找不到指定的.exe,程序就无法启动
图像环境DLL(AppInit_DLL)
- 路径:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows - 功能:允许将一个或多个DLL注入到几乎所有加载了
user32.dll的进程中 - 关注点:检查**
AppInit_DLLs**这个键值是否为空,任何被列在这里的DLL都会被广泛注入,是恶意软件实现全局监控的常用手段
COM组件(CLSID)
- 路径:
HKCR\CLSID\ - 功能:存储系统中所有COM组件类ID(CLSID)的信息
- 关注点:检查
InprocServer32等子项的默认值,看其指向的 DLL 路径是否可疑
用户账户与凭证
本地用户信息(SAM)
-
路径:
HKLM\SAM\SAM\Domains\Account\Users -
功能:存储本地用户的账户名、SID、以及最重要的密码哈希
-
关注点:
SAM受到严格保护,无法直接读取,但可以通过内存取证工具(如hashdump)或离线分析SAM和SYSTEM文件来提取密码哈希检查
Names子键可以发现所有本地账户,包括可能被隐藏的账户
用户配置文件列表(ProfileList)
- 路径:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList - 功能:记录了本机上所有用户账户的 SID 以及其个人文件夹(Profile)的路径。
- 关注点:这是将SID和用户名对应起来的关键,可以发现系统上曾经存在过但已被删除的用户账户痕迹
用户活动痕迹
程序执行历史(UserAssist)
- 路径:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist - 功能:记录用户通过图形界面(点击图标)运行程序的历史,包括运行次数和最后运行时间
- 取证关注点:还原用户操作的关键,可以清晰地看到用户在特定时间点运行了哪些程序
最近打开的文档(RecentDocs)
- 路径:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs - 功能:记录用户最近打开过的文档和访问过的文件夹
- 关注点:了解用户最近处理了哪些文件,可能会发现恶意文档(如带宏的Word)或攻击者留下的工具
文件夹打开记录(BagMRU)
- 路径:
HKCU\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\BagMRU(新版本,主要使用)HKCU\Software\Microsoft\Windows\Shell\BagMRU(旧版本,不太使用)
- 功能:记录用户曾经打开过的所有文件夹,每一项代表一个用户访问过的文件夹,每个键的值(如
REG_BINARY数据)是一个内部结构(MRU记录+路径+配置引用),其中包含路径信息,但不是直接可见的字符串 - 关注点:它可以揭示出用户曾经访问过但现在可能已不存在的文件夹,包括网络共享、移动设备上的文件夹,同级目录下的Bags会记录文件夹的具体视图设置
USB设备使用历史(USBSTOR)
- 路径:
HKLM\SYSTEM\CurrentControlSet\Enum\USBSTOR - 功能:记录所有曾接入本机的U盘、移动硬盘等USB存储设备的厂商、型号和唯一的序列号
- 关注点:可以确定是否有未经授权的U盘接入,并可将特定U盘与数据泄露或恶意软件植入事件关联起来
系统与网络信息
网络接口与历史IP (Interfaces)
- 路径:
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\ - 功能:记录本机所有网络接口(有线网卡、无线网卡)的配置信息,包括历史上曾经获取过的IP地址、子网掩码、网关和DNS服务器
- 关注点:可以确定机器在不同时间点的网络环境,对于追踪内网漫游或确认C2连接时的源IP地址至关重要
最后关机时间 (ShutdownTime)
- 路径:
HKLM\SYSTEM\CurrentControlSet\Control\Windows\ShutdownTime - 功能:记录了系统最后一次正常关机的时间
- 关注点:帮助确定系统事件发生的时间窗口
时区信息 (TimeZoneInformation)
- 路径:
HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation - 功能:记录本机配置的时区
- 关注点:时间线分析的基准,所有从日志和文件系统中提取的时间戳都必须根据这个时区进行校正,才能得到准确的绝对时间
使用命令行编辑注册表
reg命令的基本结构
reg <操作> <注册表项路径> [参数]
增/改(add)
-
添加新项(文件夹)
在
Run键下创建一个名为MyApp的新项:reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run\MyApp" -
添加/设置键值(内容)
-
/v:指定键值名 -
/t:指定类型类型 全称 存储内容 REG_SZ 字符串值 人类可读的文本,如路径、名称、描述 REG_DWORD 32位数值 一个整数,通常用作是/否的标志或简单数字配置 REG_BINARY 二进制值 任意的、非结构化的原始字节数据 -
/d:指定数据 -
/f:如果键值已存在,强制覆盖而不提示
在
Run键下创建一个名为Pentestlab的自启动程序:reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v Pentestlab /t REG_SZ /d "C:\tools\pentestlab.exe" -
删 (delete)
-
删除键值
/v:指定要删除的键值名/f:强制删除,不进行确认提示
删除刚才创建的
Pentestlab启动项:reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v Pentestlab /f -
删除整个项(及其所有子项和键值)
删除刚才创建的MyApp项:
reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run\MyApp" /f
查 (query)
-
查询项下的所有内容
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"这条命令会列出
Winlogon这个项下所有的子项和键值 -
查询一个具体的键值
/v:指定要查询的键值名
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v Userinit -
递归查询所有子项和键值
/s:递归查询所有子项和键值
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist" /s
Windows安全机制
安全主体与身份验证
在介绍Windows安全机制之前,我们必须先理解两个基本概念:安全主体和身份验证
安全主体
安全主体是指在Windows操作系统中能够被识别和进行身份验证的任何实体
它不仅包括人类用户,还包括以下内容:
- 用户账户:包括本地用户(如
Administrator)和域用户(如CONTOSO\jdoe) - 计算机账户:加入域的计算机,如
WORKSTATION-01$ - 安全组:如
Administrators组、Everyone组等 - 系统内置账户:例如
SYSTEM、Local Service、Network Service - 进程或线程:在特定安全上下文中运行的进程或线程
简单来说,任何需要被系统识别以授予权限的对象,都是一个安全主体
完整性级别
完整性级别是安全主体的一个属性,用于防止低权限程序访问高权限资源
主要级别有:
- 低完整性级别(如Internet Explorer保护模式)
- 中等完整性级别(普通用户程序)
- 高完整性级别(管理员权限进程)
- 系统完整性级别(操作系统核心进程)
完整性级别形成了额外的访问限制层
身份验证
身份验证是核实安全主体是否确实是其所声称身份的过程,主要回答“你是谁?”这个问题
身份验证确保访问者不是冒名顶替者,常见方式包括密码核对、智能卡认证、生物识别等
需要注意的是,身份验证与授权是不同的概念,身份验证是授权的前提,但本身不等同于授权
SID
什么是SID
SID全称Security Identifier,即安全标识符,就是操作系统为每一个安全主体分配的、一个全局唯一且不可变的号码
- 唯一性:一个 SID 只会分配给一个安全主体,即使这个账户被删除,它的 SID 也不会被重新分配给新账户
- 不变性:账户可以改名,但它的 SID 永远不变
- 内部标识:用户习惯使用用户名来识别账户,但Windows内核只认SID
SID如何工作
SID是Windows安全模型的核心
创建与存储:当一个账户或组被创建时,本地安全机构(LSA)或域控制器会为其生成一个唯一的 SID,并将其存储在安全数据库中(本地账户存在注册表的SAMHive中,域账户存在活动目录中)
生成访问令牌:当一个用户成功登录时,系统会为其创建一个访问令牌 (Access Token),这个令牌就像一张临时通行证,里面包含了该用户的SID、该用户所属所有组的SID、以及该用户拥有的所有特权
访问控制:当该用户尝试访问一个资源(如文件或文件夹)时,系统会拿出用户的访问令牌,将其中的SID列表与资源的访问控制列表(ACL)进行比对,以决定是否授予访问权限
SID的结构
一个典型的、完整的 SID 结构如下:
S - 修订级别 - 颁发机构 - 域标识符 - 相对ID(RID)
我们以一个例子来分解: S-1-5-21-2127521184-1604012920-1887927527-500
-
S:固定前缀表明这是一个SID
-
1:修订级别 -
目前所有SID的版本都是1
-
5:标识符颁发机构这里的
5代表NT Authority,即由WindowsNT系统安全机构颁发,这是最常见的一种 -
21-2127521184-1604012920-1887927527:域或本地计算机标识符这是一串唯一的数字,代表创建这个SID的计算机或域,同一台电脑上的所有本地账户都会共享这一串数字
-
500:相对ID (RID)这是 SID 的最后一部分,它在上述域标识符范围内是唯一的,真正用来区分不同的账户
Windows 为一些内置账户预留了固定的 RID:
- 500:
Administrator(内置管理员账户) - 501:
Guest(来宾账户) - 普通用户通常从 1000 或 1001 开始递增
- 500:
众所周知的SID
除了上述每个账户独有的SID,Windows还预定义了一些特殊的、固定的 SID
它们在所有Windows系统上都具有相同的值和含义,代表了一些内置的身份或通用组
| SID | 通用名称 | 说明 |
|---|---|---|
S-1-5-18 |
Local System |
本地系统账户,Windows系统中的最高权限 |
S-1-5-32-544 |
Administrators |
本地管理员组,属于这个组的成员都拥有管理员权限 |
S-1-1-0 |
Everyone |
所有用户组,范围最广,包括已登录的用户和匿名用户 |
S-1-5-11 |
Authenticated Users |
已认证用户组,代表所有通过了身份验证的账户 |
S-1-5-2 |
Network |
任何通过网络登录的用户 |
S-1-5-6 |
Service |
任何以服务身份登录的实体 |
S-1-5-7 |
Interactive |
任何通过直接在本地登录的用户 |
LSA
什么是LSA
LSA,全称本地安全机构 (Local Security Authority)
它是一个受保护的Windows子系统,核心职责是在单台计算机上强制执行系统的安全策略
它是Windows 安全模型的中心,负责验证用户身份、管理用户权限并生成安全审计日志
LSA的用户模式组件体现在一个名为lsass.exe的关键系统进程中,是维持操作系统安全运行的必要进程,任何对lsass.exe的终止都会导致系统在短时间内强制关机并提示安全错误
访问令牌
访问令牌Access Token是由LSA创建的内核管理对象,描述进程或线程的安全上下文
包含的内容
用户SID:标明主体身份
组SID列表:确定主体所属的所有安全组
特权列表:决定主体可执行的系统级特殊操作,如SeDebugPrivilege
工作流程
当用户登录后,启动的每个进程都会继承该用户访问令牌的副本
当进程尝试访问受保护资源时,内核的安全引用监视器(Security Reference Monitor,SRM)会取出进程访问令牌中的SID列表,与资源的访问控制列表(Access Control List,ACL)比较,决定是否允许或拒绝访问
用户账户控制
用户账户控制(User Account Control,UAC)是基于访问令牌的“双令牌”机制
传统的Windows系统中,用户经常以管理员权限登录,这导致所有程序默认拥有高权限,增加了系统被攻击和破坏的风险
而UAC通过限制默认权限,减少系统受攻击面
当管理员账户登录系统时,系统为其创建两个访问令牌:
- 标准访问令牌(受限令牌):用于默认运行的应用程序,权限受限,防止程序执行高风险操作
- 完整访问令牌(管理员令牌):包含完整管理员权限,但只在用户明确授权时使用
普通用户账户只拥有标准令牌,无法提升权限
当用户启动需要管理员权限的程序或操作(比如安装软件)时,系统会弹出UAC提示,要求用户确认操作:
- 管理员账户:弹出提示框,用户确认后程序使用完整访问令牌运行
- 标准账户:需要输入管理员账户的用户名和密码以获得权限提升
这保证了系统操作必须经过用户授权,避免恶意软件自动提升权限
LSA的功能
用户认证
LSA是所有用户登录请求的最终处理者
无论是本地登录还是通过网络的域登录,凭证信息最终都会被传递给LSA进行验证
访问令牌生成
在用户身份验证成功后,LSA负责创建该用户的访问令牌 (_TOKEN结构)
该令牌是一个内核对象,它详细描述了用户的安全上下文,包括用户SID、所属组的SID列表、特权列表以及会话信息
安全策略管理
LSA强制执行在本地安全策略 (secpol.msc) 中定义的规则
例如密码复杂度策略、账户锁定策略以及用户权限分配
凭证缓存与管理
为了支持网络认证(如NTLM)和单点登录(SSO),lsass.exe进程的内存中会缓存多种形式的凭证数据
包括 NTLM 哈希、Kerberos 票据,以及在某些配置下(如开启WDigest认证)的可逆加密或明文形式的密码
安全审计
根据系统中配置的审计策略,LSA会生成安全事件日志(如登录成功/失败、对象访问等)
它会将这些日志发送给事件日志服务(Event Log service)进行记录
LSA认证流程
以一个典型的本地交互式登录为例,LSA 在其中的工作流程如下:
-
用户在登录界面(由
winlogon.exe管理)输入用户名和密码 -
winlogon.exe将这些凭证安全地传递给lsass.exe进程 -
lsass.exe接收到凭证后,调用相应的认证包,对于本地登录,通常是msv1_0.dll -
msv1_0.dll与安全帐户管理器(Security Account Manager, SAM)服务通信,请求验证密码SAM服务会比对提交的密码哈希与存储在SAM注册表配置单元中的哈希是否一致
-
验证成功后,LSA会创建一个包含该用户所有安全信息的访问令牌
-
LSA 将此令牌返回给
winlogon.exe,winlogon.exe再使用该令牌来启动用户的初始进程(userinit.exe),进而创建桌面环境(explorer.exe)
LSA的Protection机制
由于lsass.exe内存的敏感性,微软在Windows8.1/Server2012R2及之后版本中引入了LSA Protection机制,其技术名称为受保护的进程之光 (Protected Process Light, PPL)什么鬼名字
-
通过在注册表中设置一个特定的键值:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa下的RunAsPPL,让lsass.exe进程可以在启动时被标记为一个受保护的进程Windows 内核的内存管理器会阻止任何非受保护的进程(即使是拥有管理员权限的进程)打开
lsass.exe的句柄并请求读取其内存或注入代码只有拥有微软特定签名的、同样是受保护的进程(如杀毒软件)才能对其进行访问
-
此保护机制仅对活动的操作系统有效,对于通过物理采集或虚拟机快照获得的离线内存镜像进行分析时LSA Protection无效,仍然可以使用Volatility等工具解析
lsass.exe的内存
授权机制
在Windows安全机制中,ACL(Access Control List,访问控制列表) 和 ACE(Access Control Entry,访问控制条目) 是实现授权控制的基础结构,用于定义和限制安全主体对系统对象的访问权限
访问控制列表 —— ACL
ACL 是附加在受保护对象(如文件、进程、注册表键、线程等)上的权限集合,用于控制哪些用户或组能够对该对象执行哪些操作
ACL 分为两种类型:
DACL
全称Discretionary ACL,自由访问控制列表
用于指定允许或拒绝某个主体访问对象的权限,是授权控制的核心部分
SACL
全称System ACL,系统访问控制列表
用于指定系统是否应审计某个主体对对象的访问(例如记录成功或失败的访问尝试),用于安全审计
访问控制条目 —— ACE
ACL 由一个或多个 ACE 组成,每条 ACE 定义一个安全主体对对象的某种访问规则。ACE 是描述“谁能做什么”的最小授权单元。
主要组成字段
| 字段 | 描述 |
|---|---|
| SID(Security Identifier) | 指定该条权限适用的安全主体(用户或用户组) |
| Type(类型) | 标识是“允许访问”还是“拒绝访问” |
| Access Mask(访问掩码) | 描述具体的权限(如读取、写入、执行、删除等) |
| Flags(标志) | 控制是否可继承、是否用于审计等附加属性 |
常见类型
| ACE 类型 | 描述 |
|---|---|
ACCESS_ALLOWED_ACE_TYPE |
允许某个 SID 执行指定操作 |
ACCESS_DENIED_ACE_TYPE |
拒绝某个 SID 执行指定操作 |
SYSTEM_AUDIT_ACE_TYPE |
审计某个 SID 的访问行为(记录日志) |
ACE 匹配与权限判断流程
当一个用户(或进程)尝试访问某个对象时,系统会进行如下判断流程:
- 获取该用户的访问令牌(包含 SID 和所属组列表)
- 读取目标对象的 DACL,依序遍历其中的 ACE
- 将访问令牌中的 SID 与每条 ACE 的 SID 进行比对
- 遇到匹配的 Deny 类型 ACE → 立即拒绝访问
- 遇到匹配的 Allow 类型 ACE → 记录允许的操作权限
- 继续匹配,直到所有 ACE 遍历完成或提前拒绝
- 如果请求的权限未被任何 ACE 显式允许 → 拒绝访问
注意:ACE 在 DACL 中的顺序非常重要,Deny ACE 一般优先于 Allow ACE
继承机制与显式权限
ACE 还可以具有继承性:
- 显式ACE:直接定义在对象上的权限
- 继承ACE:从上层容器(如文件夹)继承而来,可自动应用到子对象
- 继承标志包括:
OBJECT_INHERIT_ACE:继承给子对象CONTAINER_INHERIT_ACE:继承给子容器INHERIT_ONLY_ACE:仅供继承使用,不适用于当前对象;NO_PROPAGATE_INHERIT_ACE:仅继承一级,不再向下传递
这些继承规则支持管理员一次性配置整个目录或注册表项的权限,提升安全管理效率
权限掩码常见值
| 权限 | 描述 |
|---|---|
READ |
读取对象数据(如文件内容、注册表值) |
WRITE |
修改对象数据 |
EXECUTE |
执行对象 |
DELETE |
删除对象 |
READ_CONTROL |
读取对象的安全描述符(但不包含 DACL) |
WRITE_DAC |
修改对象的 DACL |
WRITE_OWNER |
修改对象的所有者 |
FULL_CONTROL |
拥有全部权限(等价于管理员完全控制) |
对象安全描述符
对象的安全信息不仅包括ACL,还包括以下结构,一起被称为安全描述符:
| 字段 | 含义 |
|---|---|
| 所有者 | 对象的拥有者,默认有修改权限 |
| 主组 | 通常在POSIX/UNIX环境兼容性使用 |
| DACL | 授权控制 |
| SACL | 审计控制 |
通过GetSecurityInfo、SetSecurityInfo等 API,可以查询或修改对象的安全描述符