Windows应急响应/25-IFEO与AppInit-DLLs后门
本篇覆盖三种基于注册表的DLL/进程劫持后门:IFEO Debugger、AppInit_DLLs、AppCert_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
| 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
|
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
|
攻击流程:
设置目标进程的 GlobalFlag = 0x200
在 SilentProcessExit\<target.exe> 下配置 MonitorProcess
当目标进程正常退出时,Windows自动启动MonitorProcess指定的程序
攻击示例:
1 2 3 4 5 6
| reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\notepad.exe" /v GlobalFlag /t REG_DWORD /d 512 /f
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
| 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
| $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"> <TargetObject condition="contains">Image File Execution Options</TargetObject> <TargetObject condition="end with">Debugger</TargetObject> <TargetObject condition="end with">GlobalFlag</TargetObject> <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
| 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
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
| $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)"
$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
| $path = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" if (-not (Test-Path "$path\AppCertDLLs")) { New-Item -Path "$path\AppCertDLLs" -Force }
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
| autorunsc.exe -accepteula -a * -c -h -s -v -vt > C:\IR\autoruns_full.csv
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
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 }
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 }
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 }
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 } }
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 schemaversion="4.90"> <EventFiltering> <RuleGroup name="IFEO_AppInit_AppCert" groupRelation="or"> <RegistryEvent onmatch="include"> <TargetObject condition="contains all">Image File Execution Options;Debugger</TargetObject> <TargetObject condition="contains all">Image File Execution Options;GlobalFlag</TargetObject> <TargetObject condition="contains">SilentProcessExit</TargetObject> <TargetObject condition="end with">\AppInit_DLLs</TargetObject> <TargetObject condition="end with">\LoadAppInit_DLLs</TargetObject> <TargetObject condition="contains">AppCertDLLs</TargetObject> </RegistryEvent> </RuleGroup> </EventFiltering> </Sysmon>
|
Hayabusa / Sigma 检测规则关键字:
Image File Execution Options + Debugger
SilentProcessExit + MonitorProcess
AppInit_DLLs 值变更
AppCertDLLs 键创建
6.1 清除IFEO劫持
删除Debugger值:
1 2 3 4 5 6 7 8 9 10 11 12
| $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
$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
| 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
$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 — 所有持久化位置速查