Good in study, attitude and health

渗透基础——Windows下计划任务的使用

0x00 前言


在渗透测试中,尤其是域渗透,常常会用到Windows系统的计划任务,一是用于远程启动程序,二是用于程序的自启动

那么,计划任务具体有哪些使用技巧呢?是否对权限有要求?一定需要管理员权限才能运行吗?

0x01 简介


本文将要介绍以下内容:

  • 命令行实现
  • c++实现
  • 不同权限下创建计划任务的区别
  • COM组件ITaskService能否提权运行
  • 命令行开启和关闭计划任务
  • 日志位置

0x02 简介


官方说明文档:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa446802(v=vs.85).aspx

需要开启服务Task Scheduler

可在以下情况触发:

  • When a specific system event occurs.
  • At a specific time.
  • At a specific time on a daily schedule.
  • At a specific time on a weekly schedule.
  • At a specific time on a monthly schedule.
  • At a specific time on a monthly day-of-week schedule.
  • When the computer enters an idle state.
  • When the task is registered.
  • When the system is booted.
  • When a user logs on.
  • When a Terminal Server session changes state.

计划任务创建后,会在C:\Windows\System32\Tasks保存XML格式的配置文件

0x03 计划任务的配置方式


1、界面操作

执行taskschd.msc,如下图

Alt text

选中Task Scheduler Library ,右键 -> Create Task...

弹出界面,逐个配置即可,如下图

Alt text

2、命令行配置

(1) at 命令

(管理员权限)

eg:

at 23:53 notepad.exe

默认以system权限启动,适用于Win7

从Win8开始不再支持at命令,所以不过多介绍

(2) schtasks命令

支持Win7-Win10

1.每天固定时间,以普通权限启动notepad.exe

命令如下:

schtasks /Create /TN TestService1 /SC DAILY /ST 01:02 /TR notepad.exe

C:\Windows\System32\Tasks产生新文件TestService1,内容如下:

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2018-05-23T17:21:00</Date>
    <Author>a</Author>
  </RegistrationInfo>
  <Triggers>
    <CalendarTrigger>
      <StartBoundary>2018-05-23T01:02:00</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <Duration>PT10M</Duration>
      <WaitTimeout>PT1H</WaitTimeout>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>notepad.exe</Command>
    </Exec>
  </Actions>
  <Principals>
    <Principal id="Author">
      <UserId>WIN-R7MM90ERBMD\a</UserId>
      <LogonType>InteractiveToken</LogonType>
      <RunLevel>LeastPrivilege</RunLevel>
    </Principal>
  </Principals>
</Task>

值得注意的是<RunLevel>LeastPrivilege</RunLevel>,代表权限为普通用户

2.每天固定时间,以system权限启动notepad.exe

命令如下(管理员权限):

schtasks /Create /TN TestService2 /SC DAILY /ST 01:02 /TR notepad.exe /RL HIGHEST

C:\Windows\System32\Tasks产生新文件TestService2,内容如下:

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2018-05-23T17:23:23</Date>
    <Author>a</Author>
  </RegistrationInfo>
  <Triggers>
    <CalendarTrigger>
      <StartBoundary>2018-05-23T01:02:00</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <RunLevel>HighestAvailable</RunLevel>
      <UserId>WIN-R7MM90ERBMD\a</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>
      <Duration>PT10M</Duration>
      <WaitTimeout>PT1H</WaitTimeout>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>notepad.exe</Command>
    </Exec>
  </Actions>
</Task>

值得注意的是<RunLevel>HighestAvailable</RunLevel>,代表权限为最高,一般为System权限

3.每天固定时间,以system权限启动notepad.exe,通过导入xml文件的方式

以文件TestService2作为模板,修改启动时间,保存为1.xml,内容如下:

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2018-05-23T17:23:23</Date>
    <Author>a</Author>
  </RegistrationInfo>
  <Triggers>
    <CalendarTrigger>
      <StartBoundary>2018-05-23T01:03:00</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <RunLevel>HighestAvailable</RunLevel>
      <UserId>WIN-R7MM90ERBMD\a</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>
      <Duration>PT10M</Duration>
      <WaitTimeout>PT1H</WaitTimeout>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>notepad.exe</Command>
    </Exec>
  </Actions>
</Task>

通过xml文件导入配置,建立计划任务,以system权限启动,命令如下(管理员权限):

schtasks /create /xml c:\test\1.xml /tn TestService3

注:

如果是一个新的系统,修改<Author><Date><StartBoundary><UserId><Command>即可

4.每天固定时间,以普通权限启动notepad.exe,通过导入xml文件的方式

修改1.xml:

<RunLevel>HighestAvailable</RunLevel>改为<RunLevel>LeastPrivilege</RunLevel>即可

导入配置的命令如下:

schtasks /create /xml c:\test\1.xml /tn TestService4

补充:schtasks的其他命令用法

查看服务状态:

schtasks /Query /TN TestService1

删除服务:

schtasks /Delete /TN TestService1 /F

注:

服务执行成功后不会自动删除

0x04 编写程序实现


官方文档:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa383614(v=vs.85).aspx

c++定时启动程序的实现实例:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa383624(v=vs.85).aspx

程序实现了在特定时间启动notepad.exe

通过分析源码,发现是调用了COM组件ITaskService

于是产生了一个新问题,能否通过COM组件ITaskService越权执行?

答案是不能,原因如下:

首先,在c代码中能够找到CLSID_TaskScheduler对应的GUID,位于taskschd.h文件中

如下图

Alt text

GUID为"0f87369f-a4e5-4cfc-bd3e-73e6154572dd"

查看注册表信息,路径为HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{0f87369f-a4e5-4cfc-bd3e-73e6154572dd}

信息如下图

Alt text

未发现注册表项Elevation,也就是说这个COM组件ITaskService不支持使用COM Elevation Moniker提升权限

那么,能否通过添加注册表项Elevation实现COM组件提升权限呢?

答案也是不可以,测试如下:

修改注册表HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{0f87369f-a4e5-4cfc-bd3e-73e6154572dd},需要TrustedInstaller权限

关于如何获得TrustedInstaller权限可参考文章《渗透技巧——Token窃取与利用》

接下来添加注册表项Elevation,值为1

测试1:

添加LocalizedString,值为C:\Windows\system32\taskschd.dll

如下图

Alt text

修改官方的实例代码,添加使用COM Elevation Moniker提升权限的代码,关键代码如下:

  HWND    hwnd = GetConsoleWindow();
  BIND_OPTS3  bo;
  WCHAR   wszCLSID[50];
  WCHAR   wszMonikerName[300];
  StringFromGUID2( CLSID_TaskScheduler,wszCLSID,sizeof(wszCLSID)/sizeof(wszCLSID[0])); 
  hr = StringCchPrintf(wszMonikerName,sizeof(wszMonikerName)/sizeof(wszMonikerName[0]),L"Elevation:Administrator!new:%s", wszCLSID);
  memset(&bo, 0, sizeof(bo));
  bo.cbStruct     = sizeof(bo);
  bo.hwnd       = hwnd;
  bo.dwClassContext = CLSCTX_LOCAL_SERVER;
  hr =  CoGetObject(wszMonikerName, &bo, IID_PPV_ARGS(&pService));

程序报错,而且没有弹出需要提升权限的UAC对话框,对其跟踪调试,如下图

Alt text

提示(ERROR_INVALID_DATA) : 数据无效

通过IDA静态分析taskschd.dll,查看Function

没有发现提升权限的函数(关键词Elevated、Admin)

测试2:

接下来尝试将LocalizedString修改为其他可用的路径

LocalizedString设置为@%SystemRoot%\system32\shell32.dll,-50176(COM组件IFileOperation的值)

执行过程弹出需要提升权限的UAC对话框,接下来报错,如下图

Alt text

提示REGDB_E_CLASSNOTREG Class not registered

表示这个组件不支持ITaskService::Connect

和预期的一样,shell32.dll不包含函数ITaskService::Connect

综上,不能简单的通过修改注册表就能使一个普通的COM组件支持权限提升

接下来介绍一下C++代码在实现上的细节

1、添加计划任务,定时以普通权限执行程序

直接参考示例代码即可,地址如下:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa383624(v=vs.85).aspx

修改源代码的启动时间,去掉结束时间

2、添加计划任务,定时以system权限执行程序

需要管理员权限

上面的代码直接以管理员权限运行是不可以的,这是因为并没有指定以最高权限启动

如下图

Alt text

需要修改源代码,添加指定以HIGHEST权限启动

关键代码如下:

    //  ------------------------------------------------------
    //  Create the principal for the task - these credentials
    //  are overwritten with the credentials passed to RegisterTaskDefinition
    IPrincipal *pPrincipal = NULL;
    hr = pTask->get_Principal( &pPrincipal );
    if( FAILED(hr) )
    {
        printf("\nCannot get principal pointer: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }
    
    //  Set up principal logon type to interactive logon
    hr = pPrincipal->put_LogonType( TASK_LOGON_INTERACTIVE_TOKEN );
//    pPrincipal->Release();
    if( FAILED(hr) )
    {
        printf("\nCannot put principal info: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    } 

  //
  hr = pPrincipal->put_RunLevel( TASK_RUNLEVEL_HIGHEST );
  pPrincipal->Release();
    if( FAILED(hr) )
    {
        printf("\nCannot put principal info: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
  }

当然,以普通权限启动会提示权限不够,如下图

Alt text

0x05 TaskScheduler日志


日志类别: Microsoft-Windows-TaskScheduler

保存位置: C:\Windows\System32\winevt\Logs

TaskScheduler日志功能默认关闭

开启方法:

注册表位置:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Channels\Microsoft-Windows-TaskScheduler/Operational

键Enabled设为1(默认为0)

cmd命令如下:

REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Channels\Microsoft-Windows-TaskScheduler/Operational" /v Enabled /t REG_DWORD /d 1 /f

统计日志列表,查询所有日志信息,包含时间,数目:

wevtutil gli Microsoft-Windows-TaskScheduler/Operational

查看日志内容:

wevtutil qe Microsoft-Windows-TaskScheduler/Operational

删除该类日志所有内容:

wevtutil cl Microsoft-Windows-TaskScheduler/Operational

删除单条日志:

该部分放在之后的文章进行详细介绍

0x06 小结


本文介绍了计划任务的常用内容,包括多种创建计划任务的方法,不同权限创建计划任务的区别,经测试得出了一个结论,COM组件ITaskService无法提权运行


LEAVE A REPLY