首页/安全/应急响应速查/Windows 计划任务排查

Windows 计划任务排查

任务计划是 Windows 侧最常用的持久化方式:列出全部任务与触发器、动作,重点盯非微软路径与隐藏任务。

应急响应速查安全更新于 2026-10-13

Windows 计划任务是什么

任务计划程序由 TaskScheduler 服务驱动,是 Windows 上最常用的持久化手段之一。一个任务由触发器和动作两部分组成:触发器决定什么时候跑(开机、登录、空闲、指定时间、事件触发),动作决定跑什么(程序、脚本、COM 处理器)。任务定义以 XML 文件存放在 C:\Windows\System32\Tasks,并同步镜像到注册表,因此删掉一边还会残留另一边,排查时两边都要看。

基本信息

命令行工具schtasks /query /fo LIST /v;/tn 指定任务;/xml 导出定义
PowerShellGet-ScheduledTask、Get-ScheduledTaskInfo、Export-ScheduledTask
定义存放C:\Windows\System32\Tasks 下的 XML 文件,同时镜像到注册表路径
运行身份可用 SYSTEM、指定服务账号或普通用户,权限决定动作能做什么
触发器类型开机、登录、空闲、定时与重复间隔、事件触发、会话状态变化
隐藏属性任务可设置隐藏,界面上看不见,但命令行仍能枚举出来

典型使用场景

  • 终端出现可疑外联后核对任务动作,确认是否被写入定时回连
  • 钓鱼附件执行后的主机排查,任务计划是最常见的落地持久化之一
  • 确认任务动作指向的程序路径、签名与运行账号是否合理
  • 排查按固定间隔触发的异常行为,定位对应的任务定义
  • 清理前导出全部任务 XML,作为处置证据与恢复依据

枚举任务与动作

枚举任务与动作
Get-ScheduledTask | Select-Object TaskName, TaskPath, State | Sort-Object TaskPath | Format-Table -AutoSize
Get-ScheduledTask | Where-Object State -ne 'Disabled' | ForEach-Object {
  $a = ($_.Actions | ForEach-Object { $_.Execute + ' ' + $_.Arguments }) -join '; '
  Write-Output ('{0}{1} :: {2}' -f $_.TaskPath, $_.TaskName, $a)   # 任务名与动作一次打印
}
schtasks /query /tn '\SuspiciousTask' /fo LIST /v                    # 单任务详情
schtasks /query /xml ONE /tn '\SuspiciousTask' > D:\evidence\task.xml   # 导出原始 XML 留证

关键字段读法

字段含义异常信号
TaskName / TaskPath任务名与所在文件夹任务名仿冒 OneDrive、Edge、系统更新,却不在微软目录下
Task To Run实际执行的程序与参数脚本落在用户目录或临时目录,或使用编码命令
Run As User运行身份普通业务机器上出现 SYSTEM 或新创建的本地账号
Schedule Type触发器类型开机、登录与每几分钟重复组合,是保活的典型配置
Last Result上次执行返回码动作指向的文件已不存在却仍在触发,说明已被部分清理
Author创建者作者字段与运维团队不符,或为空
Hidden是否隐藏被设为隐藏的任务要优先核对内容
动作里出现 powershell -EncodedCommand、mshta、rundll32、regsvr32 或 wscript 这类写法时属于高危信号:编码命令本身就是为了规避关键字检测,需要先导出 XML、再解码参数内容,最后才谈删除。
删除任务要两边一起:schtasks /delete /tn 会同时处理 XML 与注册表镜像;如果只手工删掉 System32\Tasks 下的文件,任务计划程序界面仍可能残留条目。清理后重新枚举一遍确认。

批量导出与清理

批量导出与清理
New-Item -ItemType Directory -Force -Path 'D:\evidence\tasks' | Out-Null
Get-ScheduledTask | ForEach-Object { $n = $_.TaskName -replace '[\\/:*?"<>|]','_';
  Export-ScheduledTask -TaskName $_.TaskName -TaskPath $_.TaskPath | Out-File "D:\evidence\tasks\$n.xml" }  # 全量留证
Get-ScheduledTaskInfo -TaskName 'SuspiciousTask' | Format-List        # 看上次运行结果与时间
Disable-ScheduledTask -TaskName 'SuspiciousTask'                      # 先禁用观察影响
Unregister-ScheduledTask -TaskName 'SuspiciousTask' -Confirm:$false   # 确认后注销
Get-ScheduledTask | Where-Object TaskName -eq 'SuspiciousTask'        # 复查是否已清
任务动作里的脚本文件本身也要清理,并且要核对它是否被其他入口(服务、Run 键、WMI 订阅)引用:只注销任务而留下脚本,常被下一次触发重新建回来。

触发器排查要点

  • 开机或登录触发:保活首选,重启后自动恢复执行,排查时要问「谁在重启后还活着」
  • 重复间隔:设置每 5 或 10 分钟重复一次,绕过本就只执行一次的设定
  • 空闲触发:等用户不操作时执行,行为更隐蔽,日志时间点看起来毫无规律
  • 事件触发:订阅系统事件日志或其他任务完成事件,几乎没有显式的时间规律
  • 起始时间与过期设置:起始时间已过去很久却仍在重复,说明是长期潜伏
  • 多动作组合:一个任务挂多个动作,删掉一个后还有另一个继续执行
任务的凭据保存方式同样要看:以「存储的密码」运行的任务,意味着攻击者已掌握该账号的明文口令;注销任务却不改密码,通道依然敞着。

易错点

  • 只看任务名:任务名可以取成 OneDrive 或系统更新样式,必须落到动作路径与作者字段上判断
  • 漏掉隐藏任务与子文件夹:任务可以手工建在 \Microsoft\Windows 之类的目录里,靠肉眼翻界面容易漏
  • 只注销任务不删脚本:动作脚本留在磁盘上,其他持久化入口仍可调用它
  • 看到 Last Result 非零就忽略:动作指向文件已不存在反而说明脚本被清理过,是追踪清理是否彻底的线索
  • 只在当前用户上下文枚举:部分任务属于其他账号,需以管理员身份运行并可读系统任务目录

数据来源与参考

  • Microsoft Learn:schtasks 命令
  • Microsoft Learn:Get-ScheduledTask

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌