PowerSploit 权限提升指南使用 Get-ModifiableScheduledTaskFile 排查可篡改的计划任务文件【免费下载链接】PowerSploitPowerSploit - A PowerShell Post-Exploitation Framework项目地址: https://gitcode.com/gh_mirrors/po/PowerSploit导读Get-ModifiableScheduledTaskFile是 PowerSploit 权限提升模块Privesc中用于发现计划任务可劫持点的侦察函数它会枚举 Windows 上全部计划任务的 XML 定义解析出每个任务实际执行的命令与参数再结合 NTFS ACL 判断当前用户是否对这些路径中的文件拥有写权限。读完本文你将掌握该函数的完整用法、底层实现原理、输出结构以及如何通过 Pester 测试验证其行为为后续利用可写文件实现权限维持或提权打下基础。一、函数定位它在 PowerSploit 中扮演什么角色Get-ModifiableScheduledTaskFile位于 Privesc/PowerUp.ps1由 PowerUp 作者 Will Schroederharmj0y编写采用 BSD 3-Clause 许可其唯一必需的依赖是Get-ModifiablePath同样定义于 Privesc/PowerUp.ps1。在 Privesc/Privesc.psd1 的模块导出清单中该函数与Get-ModifiableRegistryAutoRun、Get-ModifiableServiceFile、Get-UnattendedInstallFile等一同被导出共同构成 PowerUp 的可修改持久化/自启动项侦察家族。它与 Get-ModifiableServiceFile 思路一致找到系统以高权限自动执行的程序路径再检查该路径下是否有一个当前用户可以写入的文件——如果有攻击者即可通过替换/修改该文件让系统在下次触发时执行恶意代码。从源码结构看PowerUp 中所有Get-Modifiable*侦察函数输出的自定义对象都遵循PowerUp.Modifiable*命名便于在Invoke-PrivescAudit中统一聚合展示见 Privesc/PowerUp.ps1 附近对Get-ModifiableScheduledTaskFile的调用。二、功能概述与使用语法SYNOPSIS 与 SYNTAX该函数的功能一句话概括为返回所有当前用户能够修改其关联文件的计划任务。函数不接受任何参数也没有管道输入语法极为简单Get-ModifiableScheduledTaskFile使用示例Get-ModifiableScheduledTaskFile该命令会枚举系统中所有计划任务并返回那些任务命令字符串中包含当前用户可修改文件的条目。加载方式PowerSploit 的 Privesc 模块清单 Privesc/Privesc.psd1 声明了PowerUp.ps1等文件而 Privesc/Privesc.psm1 会通过 dot-source 加载模块目录下所有.ps1文件。因此可以通过以下任一方式使用# 方式一导入整个 Privesc 模块 Import-Module Privesc # 方式二直接点源加载 PowerUp.ps1 Import-Module .\Privesc\PowerUp.ps1 # 方式三dot-source 整个 PowerUp 脚本 . .\Privesc\PowerUp.ps1三、工作原理从任务 XML 到可写文件的完整链路3.1 枚举计划任务定义Windows 将每个计划任务以 XML 文件形式存放在%windir%\System32\Tasks目录下该目录通常仅允许管理员与 SYSTEM 读取因此使用此函数一般需要管理员权限详见后文测试与权限前提。源码首先拼接任务目录路径并递归枚举其中所有文件跳过目录项$Path $($ENV:windir)\System32\Tasks # recursively enumerate all schtask .xmls Get-ChildItem -Path $Path -Recurse | Where-Object { -not $_.PSIsContainer } | ForEach-Object {3.2 解析 XML 并提取命令触发串对每个 XML 文件源码将其内容强转为[xml]对象并仅当任务定义了Triggers节点时才继续处理没有触发器的任务不在考虑范围内$TaskName $_.Name $TaskXML [xml] (Get-Content $_.FullName) if ($TaskXML.Task.Triggers) { $TaskTrigger $TaskXML.Task.Triggers.OuterXML注意$TaskTrigger保存的是整个Triggers节点的原始 XML 字符串最终会随结果输出方便判断该任务在什么时机开机、登录、定时等被触发。3.3 分别检查 Command 与 Arguments 两个字段任务动作ActionsExec中与文件路径相关的字段有两个Command要执行的程序和Arguments命令行参数参数中常常携带配置文件等路径。源码对两者都执行Get-ModifiablePath过滤# check schtask command $TaskXML.Task.Actions.Exec.Command | Get-ModifiablePath | ForEach-Object { ... } # check schtask arguments $TaskXML.Task.Actions.Exec.Arguments | Get-ModifiablePath | ForEach-Object { ... }每个命中项都会被封装成一个PowerUp.ModifiableScheduledTaskFile类型对象详见第四节。3.4 错误处理与执行上下文函数将$ErrorActionPreference临时改为SilentlyContinue结束后恢复原值避免枚举过程中的 ACL/权限错误刷屏单个任务解析失败时进入catch块通过Write-Verbose Error: $_记录不影响其他任务继续枚举。四、输出结构PowerUp.ModifiableScheduledTaskFile函数声明了[OutputType(PowerUp.ModifiableScheduledTaskFile)]每个输出对象包含以下属性属性类型说明TaskNameString计划任务名称即 XML 文件名同时通过Aliasproperty提供别名NameTaskFilePath嵌套对象Get-ModifiablePath返回的可修改路径对象见下表TaskTriggerString任务触发器的原始 XML 片段说明该任务的触发时机其中TaskFilePath是Get-ModifiablePath的输出对象类型PowerUp.ModifiablePath嵌套包含属性说明ModifiablePath当前用户拥有修改权限的文件/目录绝对路径IdentityReference拥有该权限的账户名或 SIDPermissions命中修改条件的权限集合如GenericWrite、WriteData/AddFile等一个典型的输出形如TaskName : MyVulnTask TaskFilePath: {ModifiablePathC:\ProgramData\App\config.ini; IdentityReferenceBUILTIN\Users; PermissionsSystem.Object[]} TaskTrigger : TriggersBootTriggerEnabledtrue/Enabled/BootTrigger/Triggers五、底层支撑Get-ModifiablePath 如何判定可修改这是整个侦察链条的核心引擎。Get-ModifiablePathPrivesc/PowerUp.ps1接收一段可能包含多个路径的字符串通过以下步骤找出当前用户可写的文件5.1 路径 tokenization分词由于任务参数往往是vuln.exe -i C:\Temp\config.ini这类混合字符串函数会用一组分隔符反复拆分目标串生成候选路径集合$SeparationCharacterSets (, , , , , , )拆分出的每个 token 先经ExpandEnvironmentVariables展开环境变量如%SystemRoot%再Test-Path判断路径存在→Resolve-Path解析为绝对路径加入候选路径不存在→ 尝试取父目录加入候选因为文件尚不存在时其父目录是否可写同样意味着可在此处创建/替换文件。5.2 ACL 权限比对对每个候选路径调用Get-Acl取其允许AccessControlType -match Allow的访问控制项并用一张权限掩码表$AccessMask覆盖GenericRead、GenericWrite、GenericAll、WriteOwner、WriteDAC、WriteData/AddFile、AppendData/AddSubdirectory等将原始权限位翻译为可读名称。5.3 可写判定与身份匹配可写判定的核心是如下对比$Comparison Compare-Object -ReferenceObject $Permissions -DifferenceObject ( GenericWrite, GenericAll, MaximumAllowed, WriteOwner, WriteDAC, WriteData/AddFile, AppendData/AddSubdirectory) -IncludeEqual -ExcludeDifferent即只要当前权限集中包含上述任一可写类权限即视为命中。随后将 ACE 的IdentityReference必要时从账户名翻译为 SID与当前用户及其所属组的全部 SID 集合比对$CurrentUserSids由WindowsIdentity.GetCurrent()的User.Value与Groups合并而来只有权限授予了当前用户本人或其所在组才会作为结果输出。这一步保证了我能改这一结论与身份真实匹配而非只看 ACL 上存在宽泛授权。六、滥用思路从可写文件到代码执行Get-ModifiableScheduledTaskFile只负责侦察不包含任何利用逻辑。但结合其输出经典的利用链路是找到某计划任务以高权限如SYSTEM运行且其Command或Arguments指向的文件当前用户可写在该文件原位置写入恶意载荷替换原文件或在父目录可写的情况下放置同名文件等待任务触发TaskTrigger字段正好揭示了触发时机或以管理员身份手动触发任务恶意代码即以任务上下文执行。需要注意在未验证的情况下本函数发现的可写文件能否实际造成代码执行取决于任务以何种权限运行、文件是否真的会被加载执行等因素实际利用前仍需人工确认任务配置。七、测试验证Pester 用例如何印证函数行为Tests/Privesc.tests.ps1 中为Get-ModifiableScheduledTaskFile编写了专门的 Pester 测试是理解其行为的最佳实证Describe Get-ModifiableScheduledTaskFile { if (-not $(Test-IsAdmin)) { Throw Get-ModifiableScheduledTaskFile Pester test needs local administrator privileges. } It Should not throw. { {Get-ModifiableScheduledTaskFile} | Should Not Throw } It Should find a vulnerable config file for a binary specified in a schtask. { try { $FilePath $(Get-Location)\$([IO.Path]::GetRandomFileName()) $Null | Out-File -FilePath $FilePath -Force $Null schtasks.exe /create /tn PowerUp /tr vuln.exe -i $FilePath /sc onstart /ru System /f $Output Get-ModifiableScheduledTaskFile | Where-Object {$_.TaskName -eq PowerUp} | Select-Object -First 1 $Null schtasks.exe /delete /tn PowerUp /f $Output.TaskFilePath.ModifiablePath | Should Be $FilePath ...这段测试还原了真实攻击场景先用schtasks.exe /create创建一个名为PowerUp的计划任务其命令串为vuln.exe -i 随机文件路径/sc onstart开机触发、/ru System以 SYSTEM 运行随后调用函数应能精确命中该任务且TaskFilePath.ModifiablePath指向那个可控文件。测试同时断言了TaskName、TaskFilePath、TaskTrigger以及嵌套的ModifiablePath、Permissions、IdentityReference字段全部存在验证了输出结构的稳定性。两点值得注意的权限前提该测试要求本地管理员权限Test-IsAdmin守卫这既因为需要读取System32\Tasks目录与创建/删除计划任务也提示了函数本身在高权限环境下信息收集更完整测试用例把随机文件直接创建在当前目录正好演示了参数中携带的路径是攻击者可写位置这一判断是如何被识别的。八、适用场景与注意事项适用场景权限提升侦察在横向/提权前期快速盘点是否存在高权限计划任务引用低权限可写文件的可利用点权限维持评估检查自己创建或系统既有的计划任务是否存在被其他低权限用户篡改的风险安全审计批量核查域内/本机计划任务的文件引用 ACL 是否合规。注意事项该函数无参数、无管道输入直接运行即可输出基于 ACL 静态判断无法保证可写文件一定能被任务实际加载执行需结合TaskTrigger与任务实际动作人工研判函数依赖Get-ModifiablePath两者同属 Privesc/PowerUp.ps1单独抽取脚本时需一并加载对%windir%\System32\Tasks的递归读取通常需要管理员权限非管理员环境下结果可能不完整该函数属于侦察类功能本身不修改任何系统状态仅读取任务 XML 与文件 ACL可安全在授权评估环境中运行。九、延伸阅读PowerUp 权限提升审计总览了解本函数在完整提权侦察流程中的位置Get-ModifiableServiceFile同一侦察思路在 Windows 服务场景的对应实现Get-ModifiableRegistryAutoRun检查注册表自启动项中的可写文件Invoke-PrivescAudit一键聚合运行全部 PowerUp 检查其中包含本函数模块导出清单与加载方式参见 Privesc/Privesc.psd1 与 Privesc/Privesc.psm1。【免费下载链接】PowerSploitPowerSploit - A PowerShell Post-Exploitation Framework项目地址: https://gitcode.com/gh_mirrors/po/PowerSploit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
