Windows应急响应 - 25 IFEO与AppInit-DLLs后门

Windows应急响应/25-IFEO与AppInit-DLLs后门

本篇覆盖三种基于注册表的DLL/进程劫持后门:IFEO DebuggerAppInit_DLLsAppCert_DLLs

这些技术均利用Windows加载器的合法机制实现持久化,隐蔽性较强

关联:22-DLL劫持与侧加载

一、IFEO Debugger 劫持

1.1 原理概述

IFEO = Image File Execution Options(映像劫持)

注册表位置:

1
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<target.exe>

当设置 Debugger 值时,Windows在启动 <target.exe> 时会先启动Debugger指定的程序,并将原程序路径作为参数传入

攻击者将 Debugger 设为恶意程序路径,用户以为启动的是正常程序,实际执行的是后门

合法用途:开发者附加调试器(如 vsjitdebugger.exe

1.2 攻击示例

劫持记事本启动计算器(演示用):

1
2
# 创建 IFEO 劫持 —— 管理员权限
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\notepad.exe" /v Debugger /t REG_SZ /d "C:\Windows\System32\calc.exe" /f

验证:双击打开notepad.exe,实际弹出的是calc.exe

实战中攻击者常劫持的目标:

sethc.exe(粘滞键) → 替换为cmd.exe实现无密码RDP后门

utilman.exe(辅助功能) → 登录界面获取SYSTEM shell

osk.exe(屏幕键盘)

narrator.exe(讲述人)

magnify.exe(放大镜)

劫持辅助功能实现RDP后门:

1
2
3
# 经典粘滞键后门
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" /v Debugger /t REG_SZ /d "C:\Windows\System32\cmd.exe" /f
# RDP登录界面连按5次Shift即可弹出SYSTEM权限的cmd

1.3 GlobalFlag 与 SilentProcessExit 监控滥用

这是IFEO的高级利用方式,比直接设置Debugger更隐蔽

原理:利用 GlobalFlag + SilentProcessExit 实现”进程退出时触发恶意程序”

涉及两个注册表位置:

1
2
3
4
5
6
7
8
位置1:IFEO下设置GlobalFlag
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<target.exe>
GlobalFlag = 0x200 (FLG_MONITOR_SILENT_PROCESS_EXIT)

位置2:SilentProcessExit下设置监控动作
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\<target.exe>
ReportingMode = 1
MonitorProcess = C:\malware\payload.exe

攻击流程:

  1. 设置目标进程的 GlobalFlag = 0x200

  2. SilentProcessExit\<target.exe> 下配置 MonitorProcess

  3. 当目标进程正常退出时,Windows自动启动MonitorProcess指定的程序

攻击示例:

1
2
3
4
5
6
# 步骤1:设置 GlobalFlag
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\notepad.exe" /v GlobalFlag /t REG_DWORD /d 512 /f

# 步骤2:设置 SilentProcessExit 监控
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\notepad.exe" /v ReportingMode /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\notepad.exe" /v MonitorProcess /t REG_SZ /d "C:\temp\beacon.exe" /f

优势:不影响目标程序的正常运行,只在退出时触发,更难被发现

ATT&CK:T1546.012 - Image File Execution Options Injection

1.4 检测IFEO劫持

枚举所有IFEO中设置了Debugger的项:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 查询所有带 Debugger 值的 IFEO 项
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" |
ForEach-Object {
$dbg = (Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue).Debugger
$gf = (Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue).GlobalFlag
if ($dbg -or $gf) {
[PSCustomObject]@{
Target = $_.PSChildName
Debugger = $dbg
GlobalFlag = if($gf){"0x{0:X}" -f $gf}else{"N/A"}
}
}
} | Format-Table -AutoSize

枚举SilentProcessExit配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查询 SilentProcessExit 监控
$spePath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit"
if (Test-Path $spePath) {
Get-ChildItem $spePath | ForEach-Object {
$props = Get-ItemProperty $_.PSPath
[PSCustomObject]@{
Target = $_.PSChildName
ReportingMode = $props.ReportingMode
MonitorProcess = $props.MonitorProcess
}
} | Format-Table -AutoSize
} else {
Write-Host "[OK] SilentProcessExit 键不存在,无此类持久化" -ForegroundColor Green
}

Sysmon 检测规则(Event ID 12/13 — 注册表操作):

1
2
3
4
5
6
7
8
9
10
11
<RuleGroup groupRelation="or">
<RegistryEvent onmatch="include">
<!-- IFEO Debugger 设置 -->
<TargetObject condition="contains">Image File Execution Options</TargetObject>
<TargetObject condition="end with">Debugger</TargetObject>
<!-- GlobalFlag 设置 -->
<TargetObject condition="end with">GlobalFlag</TargetObject>
<!-- SilentProcessExit 监控 -->
<TargetObject condition="contains">SilentProcessExit</TargetObject>
</RegistryEvent>
</RuleGroup>

二、AppInit_DLLs 持久化

2.1 原理概述

注册表位置:

1
2
3
4
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
AppInit_DLLs = C:\path\to\malicious.dll (REG_SZ,多个DLL用逗号或空格分隔)
LoadAppInit_DLLs = 1 (REG_DWORD,必须为1才生效)
RequireSignedAppInit_DLLs = 0 (REG_DWORD,0=不要求签名)

机制:每个加载了 user32.dll 的进程在初始化时都会自动加载 AppInit_DLLs 中指定的DLL

由于绝大多数GUI程序都加载user32.dll,因此恶意DLL会被注入到几乎所有用户界面进程中

ATT&CK:T1546.010 - AppInit DLLs

2.2 64位与32位区分

64位系统上存在两个位置:

1
2
3
4
5
64位进程读取:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows

32位进程读取(WOW64重定向):
HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Windows

排查时两个路径都必须检查

2.3 攻击示例

设置AppInit_DLLs:

1
2
3
4
5
6
7
8
# 启用AppInit_DLLs加载(需管理员权限)
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "LoadAppInit_DLLs" -Value 1 -Type DWord

# 禁用签名检查
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "RequireSignedAppInit_DLLs" -Value 0 -Type DWord

# 设置恶意DLL路径
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "AppInit_DLLs" -Value "C:\temp\evil.dll" -Type String

效果:之后所有新启动的GUI进程都会加载 C:\temp\evil.dll

注意:Windows 8+ 开启 Secure Boot 时,RequireSignedAppInit_DLLs 默认为1,未签名DLL不会被加载

2.4 检测AppInit_DLLs

PowerShell快速检查:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 检查64位路径
$win64 = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows"
Write-Host "=== 64-bit AppInit_DLLs ===" -ForegroundColor Cyan
Write-Host "AppInit_DLLs : $($win64.AppInit_DLLs)"
Write-Host "LoadAppInit_DLLs : $($win64.LoadAppInit_DLLs)"
Write-Host "RequireSignedAppInit : $($win64.RequireSignedAppInit_DLLs)"

# 检查32位路径(WOW64)
$win32 = Get-ItemProperty "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Windows" -ErrorAction SilentlyContinue
if ($win32) {
Write-Host "`n=== 32-bit (WOW64) AppInit_DLLs ===" -ForegroundColor Cyan
Write-Host "AppInit_DLLs : $($win32.AppInit_DLLs)"
Write-Host "LoadAppInit_DLLs : $($win32.LoadAppInit_DLLs)"
Write-Host "RequireSignedAppInit : $($win32.RequireSignedAppInit_DLLs)"
}

判断标准:

AppInit_DLLs 为空 → 正常

AppInit_DLLs 非空 且 LoadAppInit_DLLs = 1高危,需立即调查

LoadAppInit_DLLs = 0 → DLL不会被加载,但仍需关注(攻击者可能稍后启用)

三、AppCert_DLLs 持久化

3.1 原理概述

注册表位置:

1
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs

机制:此键下列出的DLL会在每次调用以下API时被加载:

CreateProcess

CreateProcessAsUser

CreateProcessWithLoginW

CreateProcessWithTokenW

WinExec

即:每当系统创建新进程时,AppCertDLLs中的DLL都会被加载到新进程的地址空间

ATT&CK:T1546.009 - AppCert DLLs

3.2 攻击示例

设置AppCert_DLLs:

1
2
3
4
5
6
7
8
# 创建AppCertDLLs键(默认不存在)
$path = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager"
if (-not (Test-Path "$path\AppCertDLLs")) {
New-Item -Path "$path\AppCertDLLs" -Force
}

# 添加恶意DLL
New-ItemProperty -Path "$path\AppCertDLLs" -Name "MyDll" -Value "C:\temp\cert_evil.dll" -PropertyType String -Force

与AppInit_DLLs的区别:

AppInit_DLLs → 注入到加载user32.dll的进程(GUI进程)

AppCert_DLLs → 注入到所有通过CreateProcess创建的新进程(范围更广)

AppCert_DLLs键默认不存在,出现即高度可疑

3.3 检测AppCert_DLLs

PowerShell检查:

1
2
3
4
5
6
7
$certPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs"
if (Test-Path $certPath) {
Write-Host "[!] AppCertDLLs 键存在 —— 高度可疑!" -ForegroundColor Red
Get-ItemProperty $certPath | Format-List
} else {
Write-Host "[OK] AppCertDLLs 键不存在(正常状态)" -ForegroundColor Green
}

重点:此键在正常Windows系统中不应存在,存在即需深入调查

四、三种技术对比

技术 注册表路径 注入范围 默认状态 ATT&CK
IFEO Debugger Image File Execution Options\<exe>\Debugger 替换特定程序 键存在但无Debugger值 T1546.012
IFEO SilentProcessExit SilentProcessExit\<exe>\MonitorProcess 进程退出时触发 键不存在 T1546.012
AppInit_DLLs Windows NT\CurrentVersion\Windows\AppInit_DLLs 所有GUI进程 值为空,LoadAppInit=0 T1546.010
AppCert_DLLs Session Manager\AppCertDLLs 所有CreateProcess 键不存在 T1546.009

五、综合检测方案

5.1 Autoruns检测

Sysinternals Autoruns 可以检测以上所有三种持久化

命令行版本:

1
2
3
4
5
6
7
8
# Autoruns命令行 —— 导出所有自启动项
autorunsc.exe -accepteula -a * -c -h -s -v -vt > C:\IR\autoruns_full.csv

# 筛选IFEO和AppInit相关项
Import-Csv C:\IR\autoruns_full.csv |
Where-Object {
$_.'Entry Location' -match 'Image File Execution|AppInit|AppCert|SilentProcessExit'
} | Format-Table 'Entry Location','Image Path','Signer' -AutoSize

5.2 一键排查脚本

综合检查IFEO、AppInit_DLLs、AppCert_DLLs:

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
function Check-IFEOAndDllBackdoors {
Write-Host "=" * 60 -ForegroundColor Yellow
Write-Host "IFEO / AppInit_DLLs / AppCert_DLLs 后门排查" -ForegroundColor Yellow
Write-Host "=" * 60 -ForegroundColor Yellow

# --- 1. IFEO Debugger ---
Write-Host "`n[1] IFEO Debugger 检查" -ForegroundColor Cyan
$ifeoPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options"
$found = $false
Get-ChildItem $ifeoPath -ErrorAction SilentlyContinue | ForEach-Object {
$props = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue
if ($props.Debugger) {
Write-Host " [!] $($_.PSChildName) → Debugger = $($props.Debugger)" -ForegroundColor Red
$found = $true
}
if ($props.GlobalFlag -band 0x200) {
Write-Host " [!] $($_.PSChildName) → GlobalFlag 含 FLG_MONITOR_SILENT_PROCESS_EXIT" -ForegroundColor Red
$found = $true
}
}
if (-not $found) { Write-Host " [OK] 未发现IFEO Debugger劫持" -ForegroundColor Green }

# --- 2. SilentProcessExit ---
Write-Host "`n[2] SilentProcessExit 检查" -ForegroundColor Cyan
$spePath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit"
if (Test-Path $spePath) {
Get-ChildItem $spePath | ForEach-Object {
$p = Get-ItemProperty $_.PSPath
Write-Host " [!] $($_.PSChildName) → MonitorProcess = $($p.MonitorProcess)" -ForegroundColor Red
}
} else {
Write-Host " [OK] SilentProcessExit 键不存在" -ForegroundColor Green
}

# --- 3. AppInit_DLLs (64-bit) ---
Write-Host "`n[3] AppInit_DLLs 检查 (64-bit)" -ForegroundColor Cyan
$w64 = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows"
if ($w64.AppInit_DLLs -and $w64.AppInit_DLLs.Trim() -ne "") {
Write-Host " [!] AppInit_DLLs = $($w64.AppInit_DLLs)" -ForegroundColor Red
Write-Host " LoadAppInit_DLLs = $($w64.LoadAppInit_DLLs)" -ForegroundColor Red
} else {
Write-Host " [OK] AppInit_DLLs 为空" -ForegroundColor Green
}

# --- 4. AppInit_DLLs (32-bit WOW64) ---
Write-Host "`n[4] AppInit_DLLs 检查 (32-bit WOW64)" -ForegroundColor Cyan
$w32path = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Windows"
if (Test-Path $w32path) {
$w32 = Get-ItemProperty $w32path
if ($w32.AppInit_DLLs -and $w32.AppInit_DLLs.Trim() -ne "") {
Write-Host " [!] AppInit_DLLs = $($w32.AppInit_DLLs)" -ForegroundColor Red
Write-Host " LoadAppInit_DLLs = $($w32.LoadAppInit_DLLs)" -ForegroundColor Red
} else {
Write-Host " [OK] WOW64 AppInit_DLLs 为空" -ForegroundColor Green
}
}

# --- 5. AppCert_DLLs ---
Write-Host "`n[5] AppCert_DLLs 检查" -ForegroundColor Cyan
$certPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs"
if (Test-Path $certPath) {
Write-Host " [!] AppCertDLLs 键存在!" -ForegroundColor Red
Get-ItemProperty $certPath | Format-List
} else {
Write-Host " [OK] AppCertDLLs 键不存在(正常)" -ForegroundColor Green
}

Write-Host "`n" + "=" * 60 -ForegroundColor Yellow
}

Check-IFEOAndDllBackdoors

5.3 Sysmon综合检测配置

监控所有三种技术的注册表操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- Sysmon配置片段 —— IFEO/AppInit/AppCert 监控 -->
<Sysmon schemaversion="4.90">
<EventFiltering>
<RuleGroup name="IFEO_AppInit_AppCert" groupRelation="or">
<RegistryEvent onmatch="include">
<!-- IFEO Debugger 和 GlobalFlag -->
<TargetObject condition="contains all">Image File Execution Options;Debugger</TargetObject>
<TargetObject condition="contains all">Image File Execution Options;GlobalFlag</TargetObject>
<!-- SilentProcessExit -->
<TargetObject condition="contains">SilentProcessExit</TargetObject>
<!-- AppInit_DLLs -->
<TargetObject condition="end with">\AppInit_DLLs</TargetObject>
<TargetObject condition="end with">\LoadAppInit_DLLs</TargetObject>
<!-- AppCert_DLLs -->
<TargetObject condition="contains">AppCertDLLs</TargetObject>
</RegistryEvent>
</RuleGroup>
</EventFiltering>
</Sysmon>

Hayabusa / Sigma 检测规则关键字:

Image File Execution Options + Debugger

SilentProcessExit + MonitorProcess

AppInit_DLLs 值变更

AppCertDLLs 键创建

六、应急处置(Remediation)

6.1 清除IFEO劫持

删除Debugger值:

1
2
3
4
5
6
7
8
9
10
11
12
# 删除特定程序的IFEO Debugger
$target = "notepad.exe"
$path = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\$target"
Remove-ItemProperty -Path $path -Name "Debugger" -ErrorAction SilentlyContinue
Remove-ItemProperty -Path $path -Name "GlobalFlag" -ErrorAction SilentlyContinue

# 删除 SilentProcessExit 配置
$spePath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\$target"
if (Test-Path $spePath) {
Remove-Item -Path $spePath -Recurse -Force
Write-Host "[+] 已删除 SilentProcessExit\$target" -ForegroundColor Green
}

6.2 清除AppInit_DLLs

清空DLL列表并禁用加载:

1
2
3
4
5
6
7
8
9
10
11
12
# 64-bit
Set-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "AppInit_DLLs" -Value "" -Type String
Set-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" -Name "LoadAppInit_DLLs" -Value 0 -Type DWord

# 32-bit (WOW64)
$wow64 = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Windows"
if (Test-Path $wow64) {
Set-ItemProperty $wow64 -Name "AppInit_DLLs" -Value "" -Type String
Set-ItemProperty $wow64 -Name "LoadAppInit_DLLs" -Value 0 -Type DWord
}

Write-Host "[+] AppInit_DLLs 已清除,LoadAppInit_DLLs 已禁用" -ForegroundColor Green

6.3 清除AppCert_DLLs

删除整个AppCertDLLs键:

1
2
3
4
5
6
7
8
$certPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs"
if (Test-Path $certPath) {
# 先备份
reg export "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs" C:\IR\AppCertDLLs_backup.reg /y
# 再删除
Remove-Item -Path $certPath -Recurse -Force
Write-Host "[+] AppCertDLLs 键已删除(备份在 C:\IR\)" -ForegroundColor Green
}

6.4 处置后验证

重新运行5.2节的综合检查脚本,确认所有项均为 [OK]

检查恶意DLL文件是否仍存在于磁盘上,若存在则采集hash后删除

通过重启验证:重启后再次检查,确保持久化确实被清除

关联调查:恶意DLL的hash → VirusTotal查询 → 判断攻击组织 / 恶意软件家族

七、防御加固建议

Secure Boot:启用Secure Boot后,RequireSignedAppInit_DLLs 强制为1,未签名DLL无法通过AppInit_DLLs加载

注册表审计:对IFEO、AppInit、AppCert相关键开启审计(SACL),记录所有修改

Sysmon部署:使用5.3节的配置持续监控

权限控制:限制对 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion 的写入权限

应用白名单:WDAC / AppLocker 可限制未授权DLL的加载

关联参考:

22-DLL劫持与侧加载 — DLL劫持的其他形式

09-注册表持久化审计 — 注册表持久化全面审计

30-持久化综合Checklist — 所有持久化位置速查


上一章 目录 下一章
24-启动文件夹与快捷方式 Windows应急响应 26-PowerShell-Profile后门