Life has its own fate, and meeting may not be accidental.

0%

C++提权的几种方式(win)(一)

之前在学校的时候打acm用的C++,不过没学过底层的东西。没想到竟然有一天,会拿着C++看算法以外的东西。提到权的那一刻是真爽啊!下面只给了Task Scheduler 2.0的图,其他的图忘记截了= =

常见问题

Q:Task schduler是什么?

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

Q:为什么提的权限要是SYSTEM账户?

A:SYSTEM 用户和使用普通管理员用户对于文件有同样的特权。系统帐户可以由 Windows 下执行的服务和操作系统使用。有很多服务和 Windows 进程须要可以在内部登录(比如在 Windows 安装过程中)而系统帐户就是为该目的设计的;它是内部帐户,不显示在用户管理器,也无法加入到不论什么组,而且不能分配用户权限。可是对于一些服务和进程,我们须要使用系统账户而非管理员账户,由于这些服务和进程要和系统交互,须要内部登录。

在运行计划任务的时候,假设我们使用NT AUTHORITY\SYSTEM 账户,是不须要输入密码的。如果使用了其他管理员账户,我们必须输入密码。一般我们使用系统账户,主要是为了防止管理员改变密码后任务无法运行。


关于计划任务的设定,可以参考这篇文章任务的安全上下文,例如 Administrators 组或 SYSTEM 帐户的成员可以读取、更新、删除和运行任何任务。 “用户”组、LocalService 帐户和 NetworkService 帐户的成员只能读取、更新、删除和运行已创建的任务。


C++ Task Scheduler 2.0提权

注意:客户端需要 Windows Vista 或更高版本。服务器需要 Windows Server 2008 或更高版本。必须要管理员权限才可以运行添加计划任务。

1
#include <windows.h>
2
#include <iostream>
3
#include <stdio.h>
4
#include <comdef.h>
5
#include <wincred.h>
6
#include <taskschd.h>
7
#pragma comment(lib, "taskschd.lib")
8
#pragma comment(lib, "comsupp.lib")
9
#pragma comment(lib, "credui.lib")
10
#pragma warning(disable : 4996)
11
using namespace std;
12
int __cdecl wmain()
13
{
14
15
    // 初始化COM
16
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
17
    if (FAILED(hr))
18
    {
19
20
        printf("\nCoInitializeEx failed: %x", hr);
21
        return 1;
22
    }
23
    // 注册安全性并设置该过程的默认安全性值。
24
    hr = CoInitializeSecurity(
25
        NULL,
26
        -1,
27
        NULL,
28
        NULL,
29
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
30
        RPC_C_IMP_LEVEL_IMPERSONATE,
31
        NULL,
32
        0,
33
        NULL);
34
    LPCWSTR wszTaskName = L"WIND0WS Update"; //设置计划任务名称
35
    //创建ITaskService的实例
36
    ITaskService* pService = NULL;
37
    hr = CoCreateInstance(CLSID_TaskScheduler,
38
        NULL,
39
        CLSCTX_INPROC_SERVER,
40
        IID_ITaskService,
41
        (void**)&pService);
42
    // 链接到任务实例
43
    hr = pService->Connect(_variant_t(), _variant_t(),
44
        _variant_t(), _variant_t());
45
    //     获取指向根任务文件夹的指针。
46
    ITaskFolder* pRootFolder = NULL;
47
    hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder);
48
    //  如果存在相同的任务删除该任务
49
    pRootFolder->DeleteTask(_bstr_t(wszTaskName), 0);
50
    //  创建任务生成器对象以创建任务。
51
    ITaskDefinition* pTask = NULL;
52
    hr = pService->NewTask(0, &pTask);
53
    pService->Release();  //清理Com
54
    // 获取注册信息
55
    IRegistrationInfo* pRegInfo = NULL;
56
    hr = pTask->get_RegistrationInfo(&pRegInfo);
57
    hr = pRegInfo->put_Author((_bstr_t)"Microsoft");                                // 修改你想要改的计划任务创建者
58
    //  创建计划任务设置
59
    ITaskSettings* pSettings = NULL;
60
    hr = pTask->get_Settings(&pSettings);
61
    //      设置任务的设置值
62
    hr = pSettings->put_StartWhenAvailable(VARIANT_TRUE);
63
    pSettings->Release();
64
    //  ------------------------------------------------------
65
    //  获取取触发器集合以插入登录触发器。
66
    ITriggerCollection* pTriggerCollection = NULL;
67
    hr = pTask->get_Triggers(&pTriggerCollection);
68
    //  添加触发器
69
    ITrigger* pTrigger = NULL;
70
    hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger);   //TASK_TRIGGER_EVENT    事件触发
71
    pTriggerCollection->Release();
72
    ILogonTrigger* pLogonTrigger = NULL;
73
    hr = pTrigger->QueryInterface(
74
        IID_ILogonTrigger, (void**)&pLogonTrigger);
75
    pTrigger->Release();
76
    hr = pLogonTrigger->put_Id(_bstr_t(L"Trigger1"));
77
    /*
78
    //设置指定触发时间 如果不设置 代表任何时间都可以触发
79
    hr = pLogonTrigger->put_StartBoundary( _bstr_t(L"2020-10-30T08:00:00") );
80
    hr = pLogonTrigger->put_EndBoundary( _bstr_t(L"2020-10-30T08:00:00") );
81
    */
82
    /*
83
    //  定义某个用户 登录时触发 注释掉代表所有用户登录后触发
84
    hr = pLogonTrigger->put_UserId( _bstr_t( L"administrator" ) );   //某用户登录后触发 设置某用户
85
    pLogonTrigger->Release();
86
   */
87
    IActionCollection* pActionCollection = NULL;
88
    hr = pTask->get_Actions(&pActionCollection);
89
    IAction* pAction = NULL;
90
    hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction); //触发程序执行:TASK_ACTION_EXEC
91
    IExecAction* pExecAction = NULL;
92
    hr = pAction->QueryInterface(
93
        IID_IExecAction, (void**)&pExecAction);
94
    string cmdName;
95
    cout << "输入文件位置:\n";
96
    cin >> cmdName;
97
    hr = pExecAction->put_Path(_bstr_t(cmdName.c_str()));
98
    pExecAction->Release();
99
    if (FAILED(hr))
100
    {
101
102
        printf(" 无法设置程序执行路径: %x", hr);
103
        pRootFolder->Release();
104
        pTask->Release();
105
        CoUninitialize();
106
        return 1;
107
    }
108
    IRegisteredTask* pRegisteredTask = NULL;
109
    hr = pRootFolder->RegisterTaskDefinition(
110
        _bstr_t(wszTaskName),
111
        pTask,
112
        TASK_CREATE_OR_UPDATE,  // 创建并覆盖现有的计划任务:TASK_CREATE_OR_UPDATE 
113
                                                        //仅更新:TASK_UPDATE
114
                                                        //仅创建:TASK_CREATE
115
                                                        //禁用:TASK_DISABLE
116
        _variant_t(L"system"),  // 启动身份 system 或者administrator 
117
        _variant_t(),
118
        TASK_LOGON_GROUP, //登录技术  组激活:TASK_LOGON_GROUP 用户登录后激活:TASK_LOGON_INTERACTIVE_TOKEN
119
        _variant_t(L""),
120
        &pRegisteredTask);
121
    if (FAILED(hr))
122
    {
123
124
        printf("\n无法保存计划任务 : %x", hr);
125
        pRootFolder->Release();
126
        pTask->Release();
127
        CoUninitialize();
128
        return 1;
129
    }
130
    printf("Success!成功注册计划任务 ");
131
    pRootFolder->Release();
132
    pTask->Release();
133
    pRegisteredTask->Release();
134
    CoUninitialize();
135
    return 0;
136
}

运行后,把绝对路径输入后,成功提权至system,非常的爽

cs

C++ Task Scheduler 1.0写入提权(利用COM组件的 API 编程创建计划任务)

注意:Task Scheduler 1.0是在C:\Windows\Tasks目录下生成job文件,如果job文件存在重复会报错,注意及时删除。客户端需要 Windows Vista 或 Windows XP。服务器需要 Windows Server 2008 或 Windows Server 2003。

使用 Task Scheduler 1.0 的几个注意点:

  • 创建计划任务需要管理员权限。
  • 必须确保 Task Scheduler service 正在运行。
  • 通过 COM 组件创建的计划任务,会在C:\windows\Tasks目录下创建一个同名的 JOB 文件。
  • 同时需要为计划任务指定一个唯一的名称,如果指定的名称已被使用,则会导致任务创建失败。
  • 该计划任务无法通过 schtasks 命令查询。
1
#include <windows.h>
2
#include <initguid.h>
3
#include <ole2.h>
4
#include <mstask.h>
5
#include <msterr.h>
6
#include <objidl.h>
7
#include <wchar.h>
8
#include <stdio.h>
9
#pragma warning(disable : 4996)
10
11
void WGetUserName(WCHAR* username, int len)
12
{
13
    // 获取并显示计算机的名称。
14
    char   szName[255];
15
    ULONG   nLen = sizeof(szName);
16
    ::GetUserNameA(szName, &nLen);
17
18
    for (unsigned int i = 0; i < strlen(szName); i++)
19
    {
20
        username[i] = szName[i];
21
    }
22
    username[strlen(szName)] = '\0';
23
    printf("%s", szName);
24
}
25
26
27
28
int main(int argc, char** argv)
29
{
30
    HRESULT hr = S_OK;
31
    ITaskScheduler* pITS;
32
33
    //调用CoInitialize初始化COM库,然后  
34
    //调用CoCreateInstance获取Task Scheduler对象。  
35
    hr = CoInitialize(NULL);
36
    if (SUCCEEDED(hr))
37
    {
38
        hr = CoCreateInstance(CLSID_CTaskScheduler,
39
            NULL,
40
            CLSCTX_INPROC_SERVER,
41
            IID_ITaskScheduler,
42
            (void**)&pITS);
43
        if (FAILED(hr))
44
        {
45
            CoUninitialize();
46
            return 1;
47
        }
48
    }
49
    else
50
    {
51
        return 1;
52
    }
53
54
    /// 获取计算机的用户名
55
    WCHAR username[512];
56
    memset(username, 0, sizeof(username));
57
    WGetUserName(username, sizeof(username));
58
59
    // 调用ITaskScheduler::NewWorkItem创建新任务。  
60
    WCHAR pwszTaskName[512] = L"Test_Task";
61
    ITask* pITask;
62
63
    wcscat(pwszTaskName, username);
64
    hr = pITS->NewWorkItem(pwszTaskName,         // 任务名称
65
        CLSID_CTask,          // 类标识符
66
        IID_ITask,            // 接口标识符
67
        (IUnknown**)&pITask); // 解决的任务
68
    //    接口
69
70
71
    pITS->Release();          // 释放对象
72
    if (FAILED(hr))
73
    {
74
        CoUninitialize();
75
        fprintf(stderr, "Failed calling NewWorkItem, error = 0x%x\n", hr);
76
        return 1;
77
    }
78
79
    //调用ITask::SetApplicationName指定应用程序的名称
80
    //测试任务。
81
    LPCWSTR pwszApplicationName = L"C:\\Windows\\System32\\cmd.exe ";
82
    hr = pITask->SetApplicationName(pwszApplicationName);
83
84
    if (FAILED(hr))
85
    {
86
        wprintf(L"Failed calling ITask::SetApplicationName: ");
87
        wprintf(L"error = 0x%x\n", hr);
88
        pITask->Release();
89
        CoUninitialize();
90
        return 1;
91
    }
92
93
        // set flag仅在登录时设置
94
        hr = pITask->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON);
95
    if (FAILED(hr))
96
    {
97
        wprintf(L"Failed calling ITask::EditWorkItem, ");
98
        wprintf(L"error = 0x%x\n", hr);
99
        CoUninitialize();
100
        return 1;
101
    }
102
103
    // 仅为登录设置用户名
104
    hr = pITask->SetAccountInformation(L"Administrator", NULL); //L"NT AUTHORITY\\SYSTEM"; 
105
    if (FAILED(hr))
106
    {
107
        wprintf(L"Failed calling ITask::SetApplicationName: ");
108
        wprintf(L"error = 0x%x\n", hr);
109
        pITask->Release();
110
        CoUninitialize();
111
        return 1;
112
    }
113
114
    // 调用ITask::CreateTrigger来创建一个新的触发器。
115
    ITaskTrigger* pITaskTrigger;
116
    WORD piNewTrigger;
117
    hr = pITask->CreateTrigger(&piNewTrigger,
118
        &pITaskTrigger);
119
    if (FAILED(hr))
120
    {
121
        wprintf(L"Failed calling ITask::CreatTrigger: ");
122
        wprintf(L"error = 0x%x\n", hr);
123
        pITask->Release();
124
        CoUninitialize();
125
        return 1;
126
    }
127
128
    //定义TASK_TRIGGER结构。注意,wBeginDay,
129
    //wBeginMonth和wBeginYear必须设置为一个有效的
130
    //分别为日、月、年。
131
    TASK_TRIGGER pTrigger;
132
    ZeroMemory(&pTrigger, sizeof(TASK_TRIGGER));
133
134
    // 添加代码设置触发器结构?
135
    pTrigger.cbTriggerSize = sizeof(TASK_TRIGGER);
136
    pTrigger.wBeginDay = 20;                  // 必需的
137
    pTrigger.wBeginMonth = 1;                // 必需的
138
    pTrigger.wBeginYear = 1997;              // 必需的
139
    pTrigger.wStartHour = 10;
140
    pTrigger.wStartMinute = 10;
141
    pTrigger.MinutesDuration = 600;
142
    pTrigger.TriggerType = TASK_EVENT_TRIGGER_AT_SYSTEMSTART;   //TASK_EVENT_TRIGGER_AT_SYSTEMSTART   
143
    pTrigger.Type.Daily.DaysInterval = 1;
144
145
    // 调用ITaskTrigger::SetTrigger来设置触发条件。  
146
    hr = pITaskTrigger->SetTrigger(&pTrigger);
147
    if (FAILED(hr))
148
    {
149
        wprintf(L"Failed calling ITaskTrigger::SetTrigger: ");
150
        wprintf(L"error = 0x%x\n", hr);
151
        pITask->Release();
152
        pITaskTrigger->Release();
153
        CoUninitialize();
154
        return 1;
155
    }
156
157
    // 调用IPersistFile::Save将触发器保存到磁盘。  
158
    IPersistFile* pIPersistFile;
159
    hr = pITask->QueryInterface(IID_IPersistFile,
160
        (void**)&pIPersistFile);
161
    hr = pIPersistFile->Save(NULL,
162
        TRUE);
163
164
    if (FAILED(hr))
165
    {
166
        wprintf(L"Failed calling IPersistFile::Save: ");
167
        wprintf(L"error = 0x%x\n", hr);
168
        pITask->Release();
169
        pITaskTrigger->Release();
170
        pIPersistFile->Release();
171
        CoUninitialize();
172
        return 1;
173
    }
174
175
    wprintf(L"The trigger was created and IPersistFile::Save was \n");
176
    wprintf(L"called to save the new trigger to disk.\n");
177
178
    // 释放资源。
179
    pITask->Release();
180
    pITaskTrigger->Release();
181
    pIPersistFile->Release();
182
    CoUninitialize();
183
    printf("Created task.\n");
184
    return 0;
185
}

运行后生成job文件

生成的job文件

参考文章

关于计划任务的探究

Task Scheduler 2.0的相关操作

任务计划程序 2.0 接口

计划任务中使用NT AUTHORITY\SYSTEM用户和普通管理员用户有什么差别

Tasks

VC++创建计划任务的若干方式