-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimpersonate.cpp
157 lines (118 loc) · 3.62 KB
/
impersonate.cpp
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
#include "stdafx.h"
_NT_BEGIN
#include "impersonate.h"
extern const SECURITY_QUALITY_OF_SERVICE sqos = {
sizeof (sqos), SecurityImpersonation, SECURITY_DYNAMIC_TRACKING, FALSE
};
extern const OBJECT_ATTRIBUTES oa_sqos = { sizeof(oa_sqos), 0, 0, 0, 0, const_cast<SECURITY_QUALITY_OF_SERVICE*>(&sqos) };
extern const TOKEN_PRIVILEGES tp_Debug = { 1, { { { SE_DEBUG_PRIVILEGE }, SE_PRIVILEGE_ENABLED } } };
extern const TOKEN_PRIVILEGES tp_Permanent = { 1, { { { SE_CREATE_PERMANENT_PRIVILEGE }, SE_PRIVILEGE_ENABLED } } };
extern const TOKEN_PRIVILEGES tp_TCB = { 1, { { { SE_TCB_PRIVILEGE }, SE_PRIVILEGE_ENABLED } } };
NTSTATUS GetToken(PVOID buf, const TOKEN_PRIVILEGES* RequiredSet)
{
NTSTATUS status;
union {
PVOID pv;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};
pv = buf;
ULONG NextEntryOffset = 0;
do
{
pb += NextEntryOffset;
HANDLE hProcess, hToken, hNewToken;
CLIENT_ID ClientId = { pspi->UniqueProcessId };
if (ClientId.UniqueProcess)
{
if (0 <= NtOpenProcess(&hProcess, PROCESS_QUERY_LIMITED_INFORMATION,
const_cast<POBJECT_ATTRIBUTES>(&oa_sqos), &ClientId))
{
status = NtOpenProcessToken(hProcess, TOKEN_DUPLICATE, &hToken);
NtClose(hProcess);
if (0 <= status)
{
status = NtDuplicateToken(hToken, TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE,
const_cast<POBJECT_ATTRIBUTES>(&oa_sqos), FALSE, TokenImpersonation, &hNewToken);
NtClose(hToken);
if (0 <= status)
{
status = NtAdjustPrivilegesToken(hNewToken, FALSE, const_cast<PTOKEN_PRIVILEGES>(RequiredSet), 0, 0, 0);
if (STATUS_SUCCESS == status)
{
status = NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &hNewToken, sizeof(hNewToken));
}
NtClose(hNewToken);
if (STATUS_SUCCESS == status)
{
return STATUS_SUCCESS;
}
}
}
}
}
} while (NextEntryOffset = pspi->NextEntryOffset);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS WINAPI AdjustPrivileges(_In_ const TOKEN_PRIVILEGES* ptp)
{
NTSTATUS status;
HANDLE hToken, hNewToken;
if (0 <= (status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_DUPLICATE, &hToken)))
{
status = NtDuplicateToken(hToken, TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE,
const_cast<OBJECT_ATTRIBUTES*>(&oa_sqos), FALSE, TokenImpersonation, &hNewToken);
NtClose(hToken);
if (0 <= status)
{
if (STATUS_SUCCESS == (status = NtAdjustPrivilegesToken(hNewToken, FALSE,
const_cast<PTOKEN_PRIVILEGES>(ptp), 0, 0, 0)))
{
status = NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &hNewToken, sizeof(hNewToken));
}
NtClose(hNewToken);
}
}
return status;
}
NTSTATUS WINAPI ImpersonateToken(_In_ const TOKEN_PRIVILEGES* RequiredSet)
{
NTSTATUS status = AdjustPrivileges(&tp_Debug);
ULONG cb = 0x40000;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (PBYTE buf = new BYTE[cb += PAGE_SIZE])
{
if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
status = GetToken(buf, RequiredSet);
if (status == STATUS_INFO_LENGTH_MISMATCH)
{
status = STATUS_UNSUCCESSFUL;
}
}
delete [] buf;
}
} while(status == STATUS_INFO_LENGTH_MISMATCH);
return status;
}
AutoImpesonate::~AutoImpesonate()
{
if (bRevert) NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &hOriginalToken, sizeof(hOriginalToken));
if (hOriginalToken)
{
NtClose(hOriginalToken);
}
}
AutoImpesonate::AutoImpesonate()
{
switch (NtOpenThreadToken(NtCurrentThread(), TOKEN_IMPERSONATE, TRUE, &(hOriginalToken = 0)))
{
case STATUS_NO_TOKEN:
case STATUS_SUCCESS:
bRevert = TRUE;
break;
}
}
_NT_END