计划任务执行由谁决定 | Windows 应急响应
2024-1-4 11:25:15 Author: 格格巫和蓝精灵(查看原文) 阅读量:9 收藏

0x00 简介

由于 Windows 不开源,而 Windows 的某一项服务可能受多个配置项影响,所以很多研究员通过逆向的方式,分析服务调用过程,推测执行流程,例如

https://mp.weixin.qq.com/s/ktGug1VbSpmzh9CEGKbbdw

https://mp.weixin.qq.com/s/aS5MRwnYR5pqE1PmKiH24w

这里不搞这么复杂,我们通过查询资料得知,计划任务的配置既存在于计划任务文件之中,又存在于注册表之中

接下来我们通过简单的实验,确定一下到底是计划任务文件还是注册表在决定着计划任务的执行结果,还是相互同步修改的?

测试环境: Windows Server 2016

不同操作系统的情况可能不同

整体思路如下:

创建两个计划任务,一个修改文件,一个修改注册表,之后观察两个计划任务的执行情况

计划任务文件地址

C:\Windows\System32\Tasks

注册表位置

注册表相关的在此位置
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Schedule

计划任务的 id、index、SD 在此位置
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree

计划任务的具体配置在此位置
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{id}

0x01 修改文件测试

1. 创建计划任务

taskschd.msc 打开任务计划程序,这名字有点绕口,后续称为计划任务程序

添加一个操作: 执行 cmd

将触发器设置为每 3 分钟执行一次

稍作等待

成功执行计划任务

2. 查看计划任务文件

计划任务文件地址

C:\Windows\System32\Tasks
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2024-01-04T01:53:37.7714703</Date>
    <Author>WIN-2MTJ8IQ5VEA\Administrator</Author>
    <URI>\test1</URI>
  </RegistrationInfo>
  <Triggers>
    <CalendarTrigger>
      <Repetition>
        <Interval>PT3M</Interval>
        <Duration>P1D</Duration>
        <StopAtDurationEnd>false</StopAtDurationEnd>
      </Repetition>
      <StartBoundary>2024-01-04T01:51:41</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <RunLevel>LeastPrivilege</RunLevel>
      <UserId>WIN-2MTJ8IQ5VEA\Administrator</UserId>
      <LogonType>InteractiveToken</LogonType>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>C:\Windows\System32\calc.exe</Command>
    </Exec>
    <Exec>
      <Command>C:\Windows\System32\cmd.exe</Command>
    </Exec>
  </Actions>
</Task>

3. 查看注册表

先获取该计划任务的 id

{E44EFFC6-29A1-470C-9553-52531D9962B5}

Tasks 上点击编辑 -> 查找

其中 Actions 就是计划任务执行的操作,是一个二进制值

4. 修改计划任务文件

删除掉执行 cmd 的操作,即删除

<Exec>
  <Command>C:\Windows\System32\cmd.exe</Command>
</Exec>

计划任务程序并没有发生改变,等待下次计划任务执行

多次执行结果都是 计算机和 cmd 都执行了

此时查看注册表

并没有发生变化

5. 尝试重启服务器

当然,也可以尝试重启计划任务服务,虚拟机,重启服务器方便很多

依旧是两个操作都执行了

注册表没有被修改

6. 小结

看来计划任务文件不是决定计划任务执行结果的主因

0x02 修改注册表测试

1. 创建计划任务

删除掉 test1 ,创建一个一摸一样的 test2 ,这次两分钟执行一次

2. 查看计划任务文件

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2024-01-04T02:17:38.3850798</Date>
    <Author>WIN-2MTJ8IQ5VEA\Administrator</Author>
    <URI>\test2</URI>
  </RegistrationInfo>
  <Triggers>
    <CalendarTrigger>
      <Repetition>
        <Interval>PT2M</Interval>
        <Duration>P1D</Duration>
        <StopAtDurationEnd>false</StopAtDurationEnd>
      </Repetition>
      <StartBoundary>2024-01-04T02:17:29</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <RunLevel>LeastPrivilege</RunLevel>
      <UserId>WIN-2MTJ8IQ5VEA\Administrator</UserId>
      <LogonType>InteractiveToken</LogonType>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>C:\Windows\System32\calc.exe</Command>
    </Exec>
    <Exec>
      <Command>C:\Windows\System32\cmd.exe</Command>
    </Exec>
  </Actions>
</Task>

3. 查看并修改注册表

修改计划任务注册表需要 SYSTEM 权限,通过 SysinternalsSuite 套件中的 psexec64.exeSYSTEM 权限启动注册表编辑器,就可以编辑了

https://learn.microsoft.com/zh-cn/sysinternals/downloads/sysinternals-suite

PsExec64.exe -i -s regedit

尝试删除掉 C:\Windows\System32\cmd.exe

刷新计划任务程序

原本的计划任务不见了

查看计划任务文件

计划任务文件没有被修改

我们设置的计划任务是 2 分钟执行一次,不急,让子弹飞一会儿

修改后虽然看不见了,依旧可以执行,观察多次执行结果都是如此

4. 重启服务器

在总的计划任务状态里还是能看见的

重启后,该计划任务不再运行,计划任务文件没有被更改

注册表对计划任务的影响很大,但是修改后,重启服务后导致不再计划任务运行,可能是修改后 HASH 校验过不去?

5. 注册表中将操作清空

计划任务程序依旧显示为空

6. 小结

注册表对计划任务影响很大,修改后不会立即生效,会在计划任务服务重启后生效

具体修改后,重启计划任务服务后执行直白,可能是因为 HASH 校验吧,也可能是因为我们修改二进制值格式不对,接下来我们来探究

0x03 修改注册表中字符串值

既然二进制值修改有问题,我修改字符串试试

1. 创建计划任务

创建计划任务 test3

2. 修改注册表

将创建时间中的 2:44:58 修改为 2:40:58

这次刷新计划任务程序,非但没有小时,创建时间还被更改成功了,看来计划任务程序的内容是从注册表中拿的

目前能够成功执行,根据之前的测试结果,计划任务服务此时并不会加载注册表的修改

计划任务文件并没有被修改

3. 重启服务器

重启后,不仅创建时间被修改了没变回来,计划任务可以正常执行

计划任务文件并没有被修改

4. test2 使用 test3 的 Actions

如果我将 test3Actions 用给 test2 ,会不会把 test2 救活呢?

获取 test3Actions

找到 test2 ,替换

test2 回来了,删除 test3 ,看看 test2 会不会立即生效

等了一会儿,没有执行

5. 重启服务器

重启服务器后成功执行

也就是说刚才我们修改二进制数据修改的不对,只要字符格式正确,应该就可以显示

0x04 Fuzz Actions 格式

1. 修改注册表 Actions

直接用 test2 就好

可以考虑从结尾一个字符一个字符删除,之后每次去刷新计划任务程序,查看是否显示

但是稍加观察,也可以发现,每个操作的程序路径结尾有九个00 ,由于我们知道计划任务中操作的实际内容,那直接尝试删除到九个00

刷新后,计划任务程序中 test2 还在,操作处果然只剩下一个操作了

计划任务文件并没有被更改

这下可以等一等接下来的计划任务执行了

之后的多次执行结果都是计算器和cmd 均执行,计划任务文件没有被更改

2. 重启服务器

通过注册表对计划任务的修改开始生效,只执行了计算器

计划任务文件没有被更改,内容如下

3. 尝试重启计划任务服务

任务管理器中直接重启是不行的,需要通过 SYSTEM 权限打开任务管理器

PsExec64.exe -i -s taskmgr /v

这回启动后, pid 就变了

计划任务文件依旧没有改变

0x05 不显示的计划任务会执行吗?

这里说的并不是指修改 SD 那种,就是单纯的将 Actions 去掉一个 00

1. 修改注册表

新建一个 test4

去掉一个 00

计划任务程序处已经消失了,但是还在执行计算器,这是因为注册表修改的计划任务会在计划任务服务重启后生效

2. 重启计划任务服务

计划任务没有再次执行,计划任务文件没有被更改

3.  命令行执行计划任务

schtasks /query /tn "\test4"

0x06 总结

  • Windows Server 2016 中计划任务主要有注册表决定
  • 通过注册表修改的计划任务不会立即生效,会在计划任务服务重启后生效
  • 计划任务文件修改后不会影响计划任务执行
  • 修改计划任务文件和修改注册表不会互相同步,也不会单向同步

0x07 往期文章

有态度,不苟同

文章来源: http://mp.weixin.qq.com/s?__biz=MzI5NDg0ODkwMQ==&mid=2247485731&idx=1&sn=d6a2de49d2435ce54907af183b8adf2c&chksm=ed98b4e1344c9d58de038f54c220da098c3c7a83af7e03fc2ce5f7ec4517ddf258c8a6e5ecac&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh