1. 1. 09-注册表持久化审计 (Registry Persistence Audit)
    1. 1.1. 1. 注册表持久化总览
      1. 1.1.1. 1.1 为什么注册表持久化如此重要
      2. 1.1.2. 1.2 分类体系
    2. 1.2. 2. Run / RunOnce 系列
      1. 1.2.1. 2.1 标准 Run/RunOnce 键
      2. 1.2.2. 2.2 WOW64 (32位兼容层) Run 键
      3. 1.2.3. 2.3 RunEx 和 RunOnceEx
      4. 1.2.4. 2.4 Run 键正常值与异常值
    3. 1.3. 3. Winlogon 系列
      1. 1.3.1. 3.1 Winlogon Shell
      2. 1.3.2. 3.2 Winlogon Notify
      3. 1.3.3. 3.3 Winlogon SpecialAccounts
    4. 1.4. 4. Explorer 相关
      1. 1.4.1. 4.1 Shell Extensions
      2. 1.4.2. 4.2 Browser Helper Objects (BHO)
      3. 1.4.3. 4.3 Explorer Shell Folders / User Shell Folders
      4. 1.4.4. 4.4 Explorer Load 和 Run
    5. 1.5. 5. Boot Execute 和 Session Manager
      1. 1.5.1. 5.1 BootExecute
      2. 1.5.2. 5.2 KnownDLLs
    6. 1.6. 6. Image File Execution Options (IFEO)
      1. 1.6.1. 6.1 IFEO Debugger 劫持
      2. 1.6.2. 6.2 SilentProcessExit 监控
    7. 1.7. 7. DLL 注入类持久化
      1. 1.7.1. 7.1 AppInit_DLLs
      2. 1.7.2. 7.2 AppCert_DLLs
      3. 1.7.3. 7.3 Netsh Helper DLLs
    8. 1.8. 8. Security Provider 与 LSA
      1. 1.8.1. 8.1 Print Monitors
      2. 1.8.2. 8.2 LSA (Local Security Authority)
      3. 1.8.3. 8.3 Security Support Provider (SSP)
    9. 1.9. 9. COM 对象与服务注册表
      1. 1.9.1. 9.1 COM InprocServer32
      2. 1.9.2. 9.2 服务注册表 ImagePath 和 ServiceDLL
    10. 1.10. 10. Autoruns —— 终极自启动检测工具
      1. 1.10.1. 10.1 Autoruns 基本使用
      2. 1.10.2. 10.2 Autoruns 关键功能
      3. 1.10.3. 10.3 Autoruns 命令行自动化
    11. 1.11. 11. Registry Explorer / RECmd 离线分析
      1. 1.11.1. 11.1 离线注册表分析场景
      2. 1.11.2. 11.2 注册表 Hive 文件位置
    12. 1.12. 12. 注册表持久化 Master Checklist
      1. 1.12.1. 12.1 一键全量检查脚本
      2. 1.12.2. 12.2 速查对照表

Windows应急响应 - 09 注册表持久化审计

09-注册表持久化审计 (Registry Persistence Audit)

Windows 注册表是攻击者最青睐的持久化位置——超过 60 个已知的 autostart 注册表位置可以实现开机自启或用户登录自启。这是 Windows 与 Linux 的最大差异之一:Linux 的持久化位置相对集中(crontab、systemd、rc.local、.bashrc),而 Windows 的注册表持久化分散在数十个位置,检查遗漏就意味着后门残留。本章是 Windows 持久化排查的核心 Checklist。

前置知识01-系统基础与注册表 | 08-计划任务与服务审计

关联章节18-Registry-Run后门30-持久化综合Checklist

Linux 对照08-服务与启动项审计


1. 注册表持久化总览

1.1 为什么注册表持久化如此重要

Windows 注册表中存在 60+ 个可用于 autostart 的位置

攻击者只需修改一个注册表值,就能实现持久化

很多位置不需要管理员权限(HKCU 下的键)

传统杀毒软件对注册表持久化的检测覆盖率有限

Linux 对比:Linux 持久化主要在 crontab、systemd、/etc/profile.d/.bashrc、SSH authorized_keys 等少数位置

1.2 分类体系

类别 数量 代表性位置 权限需求
Run/RunOnce 8+ HKLM/HKCU Run, RunOnce, RunEx HKCU 不需管理员
Winlogon 4+ Shell, Userinit, Notify, AppSetup 需管理员
Explorer 6+ Shell Extensions, BHO, ShellIconOverlay 部分需管理员
Boot/Session 4+ BootExecute, Session Manager, SetupExecute 需管理员
Image Hijack 3+ IFEO, SilentProcessExit, GFlags 需管理员
DLL 注入 3+ AppInit_DLLs, AppCert_DLLs, Netsh Helper 需管理员
Security Provider 4+ Print Monitors, LSA, Security Packages 需管理员
COM 对象 多个 InprocServer32, LocalServer32 HKCU 不需管理员
服务 多个 ImagePath, ServiceDLL 需管理员

2. Run / RunOnce 系列

2.1 标准 Run/RunOnce 键

这是最经典、最常见的注册表持久化位置

1
2
3
4
5
6
7
8
9
10
11
12
13
# ======== HKLM Run(所有用户,开机启动) ========
# 位置:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" -ErrorAction SilentlyContinue

# ======== HKCU Run(当前用户登录启动) ========
# 位置:HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" -ErrorAction SilentlyContinue

# ======== HKLM RunOnce(一次性执行后删除) ========
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -ErrorAction SilentlyContinue

# ======== HKCU RunOnce ========
Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" -ErrorAction SilentlyContinue

2.2 WOW64 (32位兼容层) Run 键

64 位系统中,32 位程序使用不同的注册表路径

1
2
3
4
5
# 32 位 Run 键(64 位系统上的 WOW64 节点)
Get-ItemProperty "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run" -ErrorAction SilentlyContinue
Get-ItemProperty "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\RunOnce" -ErrorAction SilentlyContinue
Get-ItemProperty "HKCU:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run" -ErrorAction SilentlyContinue
Get-ItemProperty "HKCU:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\RunOnce" -ErrorAction SilentlyContinue

2.3 RunEx 和 RunOnceEx

1
2
3
4
5
6
7
# 较少使用但仍需检查
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunEx" -ErrorAction SilentlyContinue
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx" -ErrorAction SilentlyContinue

# RunServicesOnce / RunServices(旧版 Windows,XP 时代)
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServicesOnce" -ErrorAction SilentlyContinue
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunServices" -ErrorAction SilentlyContinue

2.4 Run 键正常值与异常值

正常值(示例) 异常值(示例)
"C:\Program Files\Security\antivirus.exe" "C:\Users\Admin\AppData\Local\Temp\svchost.exe"
"C:\Program Files (x86)\Adobe\Reader.exe" "powershell.exe -enc SQBuAH..."
SecurityHealth (Windows Defender) "rundll32.exe C:\Users\Public\update.dll,DllMain"
有数字签名的已知软件 "cmd.exe /c certutil -urlcache -split -f http://..."

3. Winlogon 系列

3.1 Winlogon Shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 位置:HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
# Shell 值定义用户登录后的默认 Shell
$winlogon = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"

# ======== Shell ========
# 正常值:explorer.exe
# 异常值:explorer.exe, malware.exe(逗号分隔可添加多个程序)
Write-Host "Shell: $($winlogon.Shell)"
if ($winlogon.Shell -ne 'explorer.exe') {
Write-Host "[!] Shell 值异常!" -ForegroundColor Red
}

# ======== Userinit ========
# 正常值:C:\Windows\system32\userinit.exe,
# 异常值:C:\Windows\system32\userinit.exe, C:\malware\backdoor.exe,
Write-Host "Userinit: $($winlogon.Userinit)"
if ($winlogon.Userinit -notlike 'C:\Windows\system32\userinit.exe,') {
Write-Host "[!] Userinit 值异常!" -ForegroundColor Red
}

# ======== AppSetup ========
# 通常为空
Write-Host "AppSetup: $($winlogon.AppSetup)"

3.2 Winlogon Notify

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 位置:HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify
# 用于在登录事件(Logon/Logoff/Lock/Unlock)时加载 DLL
# Windows Vista+ 已弃用,但仍需检查
$notifyKey = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify"
if (Test-Path $notifyKey) {
Write-Host "[!] Winlogon Notify 键存在:" -ForegroundColor Yellow
Get-ChildItem $notifyKey | ForEach-Object {
$props = Get-ItemProperty $_.PSPath
[PSCustomObject]@{
Name = $_.PSChildName
DLLName = $props.DLLName
Logon = $props.Logon
Logoff = $props.Logoff
}
} | Format-Table -AutoSize
}

3.3 Winlogon SpecialAccounts

1
2
3
4
5
6
7
# 可以在登录界面隐藏用户账户
# HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList
$specialAccounts = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList"
if (Test-Path $specialAccounts) {
Write-Host "[!] 发现 SpecialAccounts UserList(可能隐藏了登录界面的用户):" -ForegroundColor Yellow
Get-ItemProperty $specialAccounts | Format-List
}

4. Explorer 相关

4.1 Shell Extensions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Shell Extensions 在 Explorer 中右键菜单、属性页等场景加载
# 位置较多,重点检查以下:

# ======== ShellIconOverlayIdentifiers ========
# HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers" -ErrorAction SilentlyContinue | ForEach-Object {
$clsid = (Get-ItemProperty $_.PSPath).'(Default)'
$dll = (Get-ItemProperty "HKLM:\SOFTWARE\Classes\CLSID\$clsid\InprocServer32" -ErrorAction SilentlyContinue).'(Default)'
[PSCustomObject]@{
Name = $_.PSChildName.Trim()
CLSID = $clsid
DLL = $dll
}
} | Format-Table -AutoSize

4.2 Browser Helper Objects (BHO)

1
2
3
4
5
6
7
8
9
10
11
12
13
# BHO 在 Internet Explorer 启动时加载
# 位置:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects
$bhoKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects"
if (Test-Path $bhoKey) {
Get-ChildItem $bhoKey -ErrorAction SilentlyContinue | ForEach-Object {
$clsid = $_.PSChildName
$dll = (Get-ItemProperty "HKLM:\SOFTWARE\Classes\CLSID\$clsid\InprocServer32" -ErrorAction SilentlyContinue).'(Default)'
[PSCustomObject]@{
CLSID = $clsid
DLL = $dll
}
} | Format-Table -AutoSize
}

4.3 Explorer Shell Folders / User Shell Folders

1
2
3
4
5
6
# 可以修改 Startup 文件夹的路径指向恶意目录
# HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
# HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
$shellFolders = Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -ErrorAction SilentlyContinue
Write-Host "Startup 路径: $($shellFolders.Startup)"
# 正常值应为 %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

4.4 Explorer Load 和 Run

1
2
3
4
5
6
7
8
9
10
11
12
# HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
$windowsKey = Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -ErrorAction SilentlyContinue

# Load 值 - 在用户登录时加载指定程序
if ($windowsKey.Load) {
Write-Host "[!] Windows\Load: $($windowsKey.Load)" -ForegroundColor Yellow
}

# Run 值
if ($windowsKey.Run) {
Write-Host "[!] Windows\Run: $($windowsKey.Run)" -ForegroundColor Yellow
}

5. Boot Execute 和 Session Manager

5.1 BootExecute

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 位置:HKLM\SYSTEM\CurrentControlSet\Control\Session Manager
# BootExecute 在 Windows 启动最早期执行(在任何服务之前)
$sessionMgr = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager"

# ======== BootExecute ========
# 正常值:autocheck autochk *
Write-Host "BootExecute: $($sessionMgr.BootExecute -join ', ')"
if ($sessionMgr.BootExecute -ne 'autocheck autochk *') {
Write-Host "[!] BootExecute 值异常!" -ForegroundColor Red
}

# ======== SetupExecute ========
# 通常为空
if ($sessionMgr.SetupExecute) {
Write-Host "[!] SetupExecute: $($sessionMgr.SetupExecute)" -ForegroundColor Red
}

# ======== Execute ========
if ($sessionMgr.Execute) {
Write-Host "[!] Execute: $($sessionMgr.Execute)" -ForegroundColor Red
}

5.2 KnownDLLs

1
2
3
4
5
# 位置:HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
# KnownDLLs 列表中的 DLL 从 System32 强制加载,防止 DLL 劫持
# 如果攻击者能修改此处,可以添加恶意 DLL
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs" |
Select-Object * -ExcludeProperty PS* | Format-List

6. Image File Execution Options (IFEO)

6.1 IFEO Debugger 劫持

IFEO 允许为指定可执行文件设置调试器,程序启动时会先启动调试器

攻击者利用此机制在目标程序启动时执行恶意代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 位置:HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options

# 检查所有设置了 Debugger 值的 IFEO 项
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" -ErrorAction SilentlyContinue | ForEach-Object {
$debugger = (Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue).Debugger
if ($debugger) {
[PSCustomObject]@{
Program = $_.PSChildName
Debugger = $debugger
}
}
} | Format-Table -AutoSize

# 正常情况下不应该有 Debugger 值(除非正在调试)
# 异常示例:
# sethc.exe → cmd.exe(粘滞键后门,5次 Shift 弹出 cmd)
# utilman.exe → cmd.exe(辅助功能后门,锁屏界面可执行 cmd)
# osk.exe → cmd.exe(屏幕键盘后门)
# narrator.exe → cmd.exe(讲述人后门)
# magnify.exe → cmd.exe(放大镜后门)

# 高优先级检查项
$accessibilityProgs = @('sethc.exe','utilman.exe','osk.exe','narrator.exe','magnify.exe','DisplaySwitch.exe','AtBroker.exe')
foreach ($prog in $accessibilityProgs) {
$key = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\$prog"
$debugger = (Get-ItemProperty $key -ErrorAction SilentlyContinue).Debugger
if ($debugger) {
Write-Host "[!!!] 辅助功能后门: $prog$debugger" -ForegroundColor Red
}
}

6.2 SilentProcessExit 监控

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 位置:HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit
# 当指定进程退出时,可以触发启动另一个程序
$silentExit = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit"
if (Test-Path $silentExit) {
Get-ChildItem $silentExit -ErrorAction SilentlyContinue | ForEach-Object {
$props = Get-ItemProperty $_.PSPath
[PSCustomObject]@{
MonitorProcess = $_.PSChildName
ReportingMode = $props.ReportingMode
MonitorProcess2 = $props.MonitorProcess
}
} | Format-Table -AutoSize
}

# 同时检查 IFEO 中的 GlobalFlag
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" -ErrorAction SilentlyContinue | ForEach-Object {
$globalFlag = (Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue).GlobalFlag
if ($globalFlag -band 0x200) { # FLG_MONITOR_SILENT_PROCESS_EXIT
Write-Host "[!] $($_.PSChildName) 启用了 SilentProcessExit 监控 (GlobalFlag: $globalFlag)" -ForegroundColor Yellow
}
}

7. DLL 注入类持久化

7.1 AppInit_DLLs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 位置:HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
# AppInit_DLLs 中指定的 DLL 会被加载到每个使用 user32.dll 的进程中
$appInit = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows"
Write-Host "AppInit_DLLs: $($appInit.AppInit_DLLs)"
Write-Host "LoadAppInit_DLLs: $($appInit.LoadAppInit_DLLs)"
# LoadAppInit_DLLs 为 1 时 AppInit_DLLs 才生效
# Windows 8+ 需要签名 DLL(RequireSignedAppInit_DLLs)

if ($appInit.AppInit_DLLs -and $appInit.LoadAppInit_DLLs -eq 1) {
Write-Host "[!] AppInit_DLLs 已启用:$($appInit.AppInit_DLLs)" -ForegroundColor Red
}

# 32 位节点
$appInit32 = Get-ItemProperty "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Windows" -ErrorAction SilentlyContinue
if ($appInit32.AppInit_DLLs -and $appInit32.LoadAppInit_DLLs -eq 1) {
Write-Host "[!] AppInit_DLLs (WOW64) 已启用:$($appInit32.AppInit_DLLs)" -ForegroundColor Red
}

7.2 AppCert_DLLs

1
2
3
4
5
6
7
# 位置:HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs
# 指定的 DLL 在调用 CreateProcess, CreateProcessAsUser 等 API 时被加载
$appCert = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs"
if (Test-Path $appCert) {
Write-Host "[!] AppCertDLLs 存在:" -ForegroundColor Red
Get-ItemProperty $appCert | Format-List
}

7.3 Netsh Helper DLLs

1
2
3
4
5
# 位置:HKLM\SOFTWARE\Microsoft\NetSh
# netsh.exe 启动时加载这些 Helper DLL
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\NetSh" -ErrorAction SilentlyContinue |
Select-Object * -ExcludeProperty PS* | Format-List
# 检查是否有指向非系统目录的 DLL

8. Security Provider 与 LSA

8.1 Print Monitors

1
2
3
4
5
6
7
8
9
10
11
12
# 位置:HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors
# Print Monitor DLL 以 SYSTEM 权限加载
Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Control\Print\Monitors" -ErrorAction SilentlyContinue | ForEach-Object {
$driver = (Get-ItemProperty $_.PSPath).Driver
[PSCustomObject]@{
Monitor = $_.PSChildName
Driver = $driver
FullPath = if ($driver -and -not [System.IO.Path]::IsPathRooted($driver)) {
"C:\Windows\System32\$driver"
} else { $driver }
}
} | Format-Table -AutoSize

8.2 LSA (Local Security Authority)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# ======== Authentication Packages ========
# HKLM\SYSTEM\CurrentControlSet\Control\Lsa
$lsa = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"

# Authentication Packages - 认证包
# 正常值:msv1_0
Write-Host "Authentication Packages: $($lsa.'Authentication Packages' -join ', ')"

# Security Packages - 安全包
# 正常值:可能包含 kerberos, msv1_0, schannel, wdigest, tspkg, pku2u
Write-Host "Security Packages: $($lsa.'Security Packages' -join ', ')"

# Notification Packages - 密码变更通知
# 正常值:scecli
# Mimikatz 的 mimilib.dll 会添加到此处
Write-Host "Notification Packages: $($lsa.'Notification Packages' -join ', ')"
if ($lsa.'Notification Packages' -notcontains 'scecli' -or ($lsa.'Notification Packages').Count -gt 1) {
Write-Host "[!] Notification Packages 可能被篡改(检查是否包含 mimilib)" -ForegroundColor Yellow
}

# ======== LSA Extensions ========
# HKLM\SYSTEM\CurrentControlSet\Control\LsaExtensionConfig\LsaSrv
$lsaExt = "HKLM:\SYSTEM\CurrentControlSet\Control\LsaExtensionConfig\LsaSrv"
if (Test-Path $lsaExt) {
$extensions = (Get-ItemProperty $lsaExt).Extensions
Write-Host "LSA Extensions: $($extensions -join ', ')"
}

8.3 Security Support Provider (SSP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 位置:HKLM\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\Security Packages
# 以及上面的 Security Packages
# SSP DLL 在 LSASS 进程中加载,可以截取认证凭据

# 检查加载到 LSASS 中的模块
# 需要管理员权限
$lsassProc = Get-Process lsass -ErrorAction SilentlyContinue
if ($lsassProc) {
$modules = $lsassProc.Modules | Select-Object ModuleName, FileName
# 检查是否有非系统 DLL
$modules | Where-Object {
$_.FileName -notlike 'C:\Windows\System32\*' -and
$_.FileName -notlike 'C:\Windows\SysWOW64\*' -and
$_.FileName -notlike 'C:\Program Files\*'
} | Format-Table -AutoSize
}

9. COM 对象与服务注册表

9.1 COM InprocServer32

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# COM DLL 持久化:修改已有 COM 对象的 InprocServer32 指向恶意 DLL
# 或在 HKCU 中创建同名 COM 对象(HKCU 优先于 HKLM)

# 检查 HKCU 中所有 InprocServer32
Get-ChildItem "HKCU:\SOFTWARE\Classes\CLSID" -Recurse -ErrorAction SilentlyContinue |
Where-Object { $_.PSChildName -eq 'InprocServer32' } | ForEach-Object {
$dll = (Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue).'(Default)'
$clsid = $_.PSPath -replace '.*\\(\\{.*?\\})\\.*', '$1'
if ($dll) {
[PSCustomObject]@{
CLSID = $clsid
DLL = $dll
Location = 'HKCU'
}
}
} | Format-Table -AutoSize

9.2 服务注册表 ImagePath 和 ServiceDLL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 服务二进制路径
# HKLM\SYSTEM\CurrentControlSet\Services\<name>\ImagePath

# 服务 DLL(svchost 托管的服务)
# HKLM\SYSTEM\CurrentControlSet\Services\<name>\Parameters\ServiceDll

# 检查所有 svchost 服务的 ServiceDll
Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services" | ForEach-Object {
$serviceDll = (Get-ItemProperty "$($_.PSPath)\Parameters" -ErrorAction SilentlyContinue).ServiceDll
if ($serviceDll) {
$signed = $null
if (Test-Path $serviceDll) {
$signed = (Get-AuthenticodeSignature $serviceDll -ErrorAction SilentlyContinue).Status
}
[PSCustomObject]@{
Service = $_.PSChildName
ServiceDll = $serviceDll
Exists = Test-Path $serviceDll
Signed = $signed
}
}
} | Where-Object { $_.Signed -ne 'Valid' -or -not $_.Exists } | Format-Table -AutoSize

10. Autoruns —— 终极自启动检测工具

10.1 Autoruns 基本使用

Autoruns(Sysinternals)是检查所有自启动项的最全面工具

覆盖所有已知的 autostart 位置(远超手动检查能力)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
:: GUI 版本
autoruns.exe

:: 命令行版本(适合自动化和远程分析)
autorunsc.exe -a * -c -h -s -v -vt -o C:\IR\autoruns_output.csv

:: 参数说明:
:: -a * 检查所有类别
:: -c CSV 输出
:: -h 显示文件哈希
:: -s 验证数字签名
:: -v 验证签名(与 -s 组合)
:: -vt 提交到 VirusTotal 检查
:: -o 输出文件路径
:: -m 隐藏 Microsoft 签名的条目(只看非 Microsoft 的)
:: -nobanner 不显示 banner

10.2 Autoruns 关键功能

VirusTotal 集成

菜单 Options → Scan Options → Check VirusTotal.com

自动提交所有自启动项的哈希到 VirusTotal

红色标记为已知恶意

Compare 功能

先导出基线:File → Save → baseline.arn

事件后导出:File → Save → incident.arn

对比:File → Compare → 选择 baseline.arn

新增的自启动项会高亮显示

Hide Microsoft Entries

Options → Hide Microsoft Entries

隐藏 Microsoft 签名的条目,快速聚焦到第三方/可疑项

10.3 Autoruns 命令行自动化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 自动化收集并分析
$autorunsPath = "C:\Tools\autorunsc.exe"
$outputCsv = "C:\IR\autoruns_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"

# 收集所有自启动项(不含 Microsoft 签名的)
& $autorunsPath -a * -c -h -s -m -nobanner -accepteula > $outputCsv

# 导入分析
$autoruns = Import-Csv $outputCsv

# 找出未签名的条目
$unsigned = $autoruns | Where-Object { $_.'Signer' -eq '' -or $_.'Signer' -eq '(Not verified)' }
Write-Host "[!] 未签名的自启动项 ($($unsigned.Count)):" -ForegroundColor Yellow
$unsigned | Select-Object 'Entry Location', 'Entry', 'Image Path', 'Launch String' | Format-Table -AutoSize

# 找出 VirusTotal 检测率 > 0 的条目
$detected = $autoruns | Where-Object {
$_.'VirusTotal' -and $_.'VirusTotal' -ne '0|0' -and $_.'VirusTotal' -notlike '0|*'
}
if ($detected) {
Write-Host "[!!!] VirusTotal 检测到恶意的自启动项:" -ForegroundColor Red
$detected | Select-Object 'Entry', 'Image Path', 'VirusTotal' | Format-Table -AutoSize
}

11. Registry Explorer / RECmd 离线分析

11.1 离线注册表分析场景

当需要分析离线取证镜像(而非活跃系统)时使用

Registry Explorer(Eric Zimmerman):GUI 工具

RECmd:命令行批处理分析

1
2
3
4
5
:: RECmd 批量检查已知持久化位置
RECmd.exe --bn BatchExamples\RECmd_Batch_MC.reb -d C:\IR\RegistryHives\ --csv C:\IR\output

:: 加载离线 Hive 文件
:: Registry Explorer 中 File → Load hive → 选择 SAM/SYSTEM/SOFTWARE 等文件

11.2 注册表 Hive 文件位置

Hive 文件路径 内容
HKLM\SAM C:\Windows\System32\config\SAM 本地用户账户
HKLM\SECURITY C:\Windows\System32\config\SECURITY LSA Secrets
HKLM\SOFTWARE C:\Windows\System32\config\SOFTWARE 软件配置
HKLM\SYSTEM C:\Windows\System32\config\SYSTEM 系统配置/服务
HKCU (NTUSER.DAT) C:\Users\<user>\NTUSER.DAT 用户设置
HKCU (UsrClass.dat) C:\Users\<user>\AppData\Local\Microsoft\Windows\UsrClass.dat 用户 COM/文件类型

12. 注册表持久化 Master Checklist

12.1 一键全量检查脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<#
.SYNOPSIS
注册表持久化全量检查脚本
.DESCRIPTION
检查 60+ 个已知的注册表自启动位置
#>

function Check-RegValue {
param([string]$Path, [string]$Description)
if (Test-Path $Path) {
$props = Get-ItemProperty $Path -ErrorAction SilentlyContinue
$values = $props.PSObject.Properties | Where-Object {
$_.Name -notlike 'PS*' -and $_.Name -ne '(Default)'
}
if ($values) {
Write-Host " [!] $Description" -ForegroundColor Yellow
Write-Host " Path: $Path" -ForegroundColor DarkGray
foreach ($v in $values) {
Write-Host " $($v.Name) = $($v.Value)" -ForegroundColor White
}
}
}
}

function Check-RegDefault {
param([string]$Path, [string]$Description, [string]$ExpectedValue)
$val = (Get-ItemProperty $Path -ErrorAction SilentlyContinue).'(Default)'
if ($val -and $val -ne $ExpectedValue) {
Write-Host " [!] $Description" -ForegroundColor Red
Write-Host " Expected: $ExpectedValue | Found: $val" -ForegroundColor Yellow
}
}

Write-Host "============================================" -ForegroundColor Cyan
Write-Host " 注册表持久化全量检查 (60+ 位置)" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan

# ---- Category 1: Run/RunOnce ----
Write-Host "`n[Category 1] Run/RunOnce 系列" -ForegroundColor Magenta
Check-RegValue "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "HKLM Run"
Check-RegValue "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "HKCU Run"
Check-RegValue "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" "HKLM RunOnce"
Check-RegValue "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce" "HKCU RunOnce"
Check-RegValue "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run" "HKLM Run (WOW64)"
Check-RegValue "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\RunOnce" "HKLM RunOnce (WOW64)"
Check-RegValue "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx" "HKLM RunOnceEx"
Check-RegValue "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run" "HKLM Policy Run"
Check-RegValue "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run" "HKCU Policy Run"

# ---- Category 2: Winlogon ----
Write-Host "`n[Category 2] Winlogon 系列" -ForegroundColor Magenta
$wl = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -ErrorAction SilentlyContinue
if ($wl.Shell -ne 'explorer.exe') { Write-Host " [!] Winlogon Shell: $($wl.Shell)" -ForegroundColor Red }
if ($wl.Userinit -and $wl.Userinit -ne 'C:\Windows\system32\userinit.exe,') { Write-Host " [!] Winlogon Userinit: $($wl.Userinit)" -ForegroundColor Red }
if ($wl.AppSetup) { Write-Host " [!] Winlogon AppSetup: $($wl.AppSetup)" -ForegroundColor Red }

# ---- Category 3: IFEO ----
Write-Host "`n[Category 3] Image File Execution Options" -ForegroundColor Magenta
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" -ErrorAction SilentlyContinue | ForEach-Object {
$dbg = (Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue).Debugger
if ($dbg) { Write-Host " [!] IFEO: $($_.PSChildName) → $dbg" -ForegroundColor Red }
}

# ---- Category 4: Boot/Session ----
Write-Host "`n[Category 4] Boot Execute / Session Manager" -ForegroundColor Magenta
$sm = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -ErrorAction SilentlyContinue
if ($sm.BootExecute -ne 'autocheck autochk *') { Write-Host " [!] BootExecute: $($sm.BootExecute)" -ForegroundColor Red }
if ($sm.SetupExecute) { Write-Host " [!] SetupExecute: $($sm.SetupExecute)" -ForegroundColor Red }

# ---- Category 5: DLL Injection ----
Write-Host "`n[Category 5] DLL 注入类" -ForegroundColor Magenta
$appInit = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -ErrorAction SilentlyContinue
if ($appInit.AppInit_DLLs) { Write-Host " [!] AppInit_DLLs: $($appInit.AppInit_DLLs) (Load=$($appInit.LoadAppInit_DLLs))" -ForegroundColor Yellow }
if (Test-Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs") { Write-Host " [!] AppCertDLLs 存在" -ForegroundColor Red }

# ---- Category 6: LSA ----
Write-Host "`n[Category 6] LSA / Security Providers" -ForegroundColor Magenta
$lsa = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -ErrorAction SilentlyContinue
Write-Host " Authentication Packages: $($lsa.'Authentication Packages' -join ', ')"
Write-Host " Notification Packages: $($lsa.'Notification Packages' -join ', ')"
Write-Host " Security Packages: $($lsa.'Security Packages' -join ', ')"

# ---- Category 7: Print Monitors ----
Write-Host "`n[Category 7] Print Monitors" -ForegroundColor Magenta
Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Control\Print\Monitors" -ErrorAction SilentlyContinue | ForEach-Object {
$drv = (Get-ItemProperty $_.PSPath).Driver
if ($drv -and $drv -notlike '*spl*' -and $drv -notlike '*win*' -and $drv -ne 'msonppmon.dll') {
Write-Host " [?] Monitor: $($_.PSChildName) → $drv" -ForegroundColor Yellow
}
}

# ---- Category 8: HKCU COM ----
Write-Host "`n[Category 8] HKCU COM Objects" -ForegroundColor Magenta
$hkcuCOM = Get-ChildItem "HKCU:\SOFTWARE\Classes\CLSID" -ErrorAction SilentlyContinue
if ($hkcuCOM.Count -gt 0) {
Write-Host " [!] HKCU 中发现 $($hkcuCOM.Count) 个 COM 注册" -ForegroundColor Yellow
}

# ---- Category 9: Explorer ----
Write-Host "`n[Category 9] Explorer 相关" -ForegroundColor Magenta
$winKey = Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -ErrorAction SilentlyContinue
if ($winKey.Load) { Write-Host " [!] HKCU Windows\Load: $($winKey.Load)" -ForegroundColor Red }
if ($winKey.Run) { Write-Host " [!] HKCU Windows\Run: $($winKey.Run)" -ForegroundColor Red }

# ---- Category 10: WMI ----
Write-Host "`n[Category 10] WMI Event Subscriptions" -ForegroundColor Magenta
$wmiFilters = Get-CimInstance -Namespace root/Subscription -ClassName __EventFilter -ErrorAction SilentlyContinue
$wmiConsumers = Get-CimInstance -Namespace root/Subscription -ClassName __EventConsumer -ErrorAction SilentlyContinue
if ($wmiFilters -or $wmiConsumers) {
Write-Host " [!] WMI Filters: $($wmiFilters.Count) | Consumers: $($wmiConsumers.Count)" -ForegroundColor Yellow
}

Write-Host "`n============================================" -ForegroundColor Cyan
Write-Host " 检查完成。建议同时运行 Autoruns 进行交叉验证" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan

12.2 速查对照表

持久化类别 注册表路径 正常值 异常示例
Run HKLM\...\Run 已知安全软件 指向 Temp/AppData 的 EXE
Shell Winlogon\Shell explorer.exe explorer.exe, mal.exe
Userinit Winlogon\Userinit userinit.exe, userinit.exe, backdoor.exe,
IFEO IFEO\sethc.exe (不存在) Debugger = cmd.exe
BootExecute Session Manager autocheck autochk * 额外条目
AppInit_DLLs ...\Windows (空) C:\evil\inject.dll
LSA Notification Lsa scecli scecli, mimilib
COM 劫持 HKCU\...\CLSID\{...} (不存在) InprocServer32 → evil.dll


上一章 目录 下一章
08-计划任务与服务审计 Windows应急响应 10-PowerShell日志与脚本分析