Skip to content

Commit cfa02fa

Browse files
committed
api: don't auto-elevate
There's no longer a need to do this for every API call. This only exists now for the pnp guid reuse workaround hack. Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent e011ab7 commit cfa02fa

File tree

8 files changed

+69
-161
lines changed

8 files changed

+69
-161
lines changed

api/adapter.c

Lines changed: 13 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -668,18 +668,13 @@ WintunFreeAdapter(_In_ WINTUN_ADAPTER *Adapter)
668668
_Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI
669669
WintunOpenAdapter(_In_z_ const WCHAR *Pool, _In_z_ const WCHAR *Name)
670670
{
671-
if (!ElevateToSystem())
672-
{
673-
LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
674-
return NULL;
675-
}
676671
DWORD LastError;
677672
WINTUN_ADAPTER *Adapter = NULL;
678673
HANDLE Mutex = NamespaceTakePoolMutex(Pool);
679674
if (!Mutex)
680675
{
681676
LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Pool);
682-
goto cleanupToken;
677+
goto cleanup;
683678
}
684679

685680
HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
@@ -759,8 +754,7 @@ _Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI
759754
SetupDiDestroyDeviceInfoList(DevInfo);
760755
cleanupMutex:
761756
NamespaceReleaseMutex(Mutex);
762-
cleanupToken:
763-
RevertToSelf();
757+
cleanup:
764758
SetLastError(LastError);
765759
return Adapter;
766760
}
@@ -1840,11 +1834,6 @@ _Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI WintunCreateAdapter
18401834
_In_opt_ const GUID *RequestedGUID,
18411835
_Out_opt_ BOOL *RebootRequired)
18421836
{
1843-
if (!ElevateToSystem())
1844-
{
1845-
LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
1846-
return NULL;
1847-
}
18481837
BOOL DummyRebootRequired;
18491838
if (!RebootRequired)
18501839
RebootRequired = &DummyRebootRequired;
@@ -1855,12 +1844,11 @@ _Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI WintunCreateAdapter
18551844
{
18561845
Adapter = CreateAdapterViaRundll32(Pool, Name, RequestedGUID, RebootRequired);
18571846
LastError = Adapter ? ERROR_SUCCESS : GetLastError();
1858-
goto cleanupToken;
1847+
goto cleanup;
18591848
}
18601849
Adapter = CreateAdapter(Pool, Name, RequestedGUID, RebootRequired);
18611850
LastError = Adapter ? ERROR_SUCCESS : GetLastError();
1862-
cleanupToken:
1863-
RevertToSelf();
1851+
cleanup:
18641852
return RET_ERROR(Adapter, LastError);
18651853
}
18661854

@@ -1869,11 +1857,6 @@ _Return_type_success_(return != FALSE) BOOL WINAPI WintunDeleteAdapter(
18691857
_In_ BOOL ForceCloseSessions,
18701858
_Out_opt_ BOOL *RebootRequired)
18711859
{
1872-
if (!ElevateToSystem())
1873-
{
1874-
LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
1875-
return FALSE;
1876-
}
18771860
BOOL DummyRebootRequired;
18781861
if (!RebootRequired)
18791862
RebootRequired = &DummyRebootRequired;
@@ -1883,14 +1866,14 @@ _Return_type_success_(return != FALSE) BOOL WINAPI WintunDeleteAdapter(
18831866
{
18841867
LastError =
18851868
DeleteAdapterViaRundll32(Adapter, ForceCloseSessions, RebootRequired) ? ERROR_SUCCESS : GetLastError();
1886-
goto cleanupToken;
1869+
goto cleanup;
18871870
}
18881871

18891872
HANDLE Mutex = NamespaceTakePoolMutex(Adapter->Pool);
18901873
if (!Mutex)
18911874
{
18921875
LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Adapter->Pool);
1893-
goto cleanupToken;
1876+
goto cleanup;
18941877
}
18951878

18961879
HDEVINFO DevInfo;
@@ -1930,8 +1913,7 @@ _Return_type_success_(return != FALSE) BOOL WINAPI WintunDeleteAdapter(
19301913
SetupDiDestroyDeviceInfoList(DevInfo);
19311914
cleanupMutex:
19321915
NamespaceReleaseMutex(Mutex);
1933-
cleanupToken:
1934-
RevertToSelf();
1916+
cleanup:
19351917
return RET_ERROR(TRUE, LastError);
19361918
}
19371919

@@ -1990,12 +1972,6 @@ static _Return_type_success_(return != FALSE) BOOL
19901972
_Return_type_success_(return != FALSE) BOOL WINAPI
19911973
WintunDeletePoolDriver(_In_z_ const WCHAR *Pool, _Out_opt_ BOOL *RebootRequired)
19921974
{
1993-
if (!ElevateToSystem())
1994-
{
1995-
LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
1996-
return FALSE;
1997-
}
1998-
19991975
BOOL DummyRebootRequired;
20001976
if (!RebootRequired)
20011977
RebootRequired = &DummyRebootRequired;
@@ -2005,20 +1981,20 @@ _Return_type_success_(return != FALSE) BOOL WINAPI
20051981
if (MAYBE_WOW64 && NativeMachine != IMAGE_FILE_PROCESS)
20061982
{
20071983
LastError = DeletePoolDriverViaRundll32(Pool, RebootRequired) ? ERROR_SUCCESS : GetLastError();
2008-
goto cleanupToken;
1984+
goto cleanup;
20091985
}
20101986

20111987
if (!DeleteAllOurAdapters(Pool, RebootRequired))
20121988
{
20131989
LastError = GetLastError();
2014-
goto cleanupToken;
1990+
goto cleanup;
20151991
}
20161992

20171993
HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex();
20181994
if (!DriverInstallationLock)
20191995
{
20201996
LastError = LOG(WINTUN_LOG_ERR, L"Failed to take driver installation mutex");
2021-
goto cleanupToken;
1997+
goto cleanup;
20221998
}
20231999
HDEVINFO DeviceInfoSet = SetupDiGetClassDevsW(&GUID_DEVCLASS_NET, NULL, NULL, 0);
20242000
if (!DeviceInfoSet)
@@ -2060,25 +2036,19 @@ _Return_type_success_(return != FALSE) BOOL WINAPI
20602036
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
20612037
cleanupDriverInstallationLock:
20622038
NamespaceReleaseMutex(DriverInstallationLock);
2063-
cleanupToken:
2064-
RevertToSelf();
2039+
cleanup:
20652040
return RET_ERROR(TRUE, LastError);
20662041
}
20672042

20682043
_Return_type_success_(return != FALSE) BOOL WINAPI
20692044
WintunEnumAdapters(_In_z_ const WCHAR *Pool, _In_ WINTUN_ENUM_CALLBACK Func, _In_ LPARAM Param)
20702045
{
2071-
if (!ElevateToSystem())
2072-
{
2073-
LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
2074-
return FALSE;
2075-
}
20762046
DWORD LastError = ERROR_SUCCESS;
20772047
HANDLE Mutex = NamespaceTakePoolMutex(Pool);
20782048
if (!Mutex)
20792049
{
20802050
LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Pool);
2081-
goto cleanupToken;
2051+
goto cleanup;
20822052
}
20832053
HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
20842054
if (DevInfo == INVALID_HANDLE_VALUE)
@@ -2112,7 +2082,6 @@ _Return_type_success_(return != FALSE) BOOL WINAPI
21122082
SetupDiDestroyDeviceInfoList(DevInfo);
21132083
cleanupMutex:
21142084
NamespaceReleaseMutex(Mutex);
2115-
cleanupToken:
2116-
RevertToSelf();
2085+
cleanup:
21172086
return RET_ERROR(TRUE, LastError);
21182087
}

api/elevate.c

Lines changed: 7 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@
99
#include <Windows.h>
1010
#include <TlHelp32.h>
1111

12-
_Return_type_success_(return != FALSE) BOOL ElevateToSystem(void)
12+
static _Return_type_success_(return != FALSE) BOOL ElevateToSystem(void)
1313
{
1414
HANDLE CurrentProcessToken, ThreadToken, ProcessSnapshot, WinlogonProcess, WinlogonToken, DuplicatedToken;
1515
PROCESSENTRY32W ProcessEntry = { .dwSize = sizeof(PROCESSENTRY32W) };
1616
BOOL Ret;
1717
DWORD LastError = ERROR_SUCCESS;
1818
TOKEN_PRIVILEGES Privileges = { .PrivilegeCount = 1, .Privileges = { { .Attributes = SE_PRIVILEGE_ENABLED } } };
19-
CHAR LocalSystemSid[0x400];
19+
CHAR LocalSystemSid[MAX_SID_SIZE];
2020
DWORD RequiredBytes = sizeof(LocalSystemSid);
2121
struct
2222
{
2323
TOKEN_USER MaybeLocalSystem;
24-
CHAR LargeEnoughForLocalSystem[0x400];
24+
CHAR LargeEnoughForLocalSystem[MAX_SID_SIZE];
2525
} TokenUserBuffer;
2626

2727
Ret = CreateWellKnownSid(WinLocalSystemSid, NULL, &LocalSystemSid, &RequiredBytes);
@@ -46,7 +46,7 @@ _Return_type_success_(return != FALSE) BOOL ElevateToSystem(void)
4646
goto cleanup;
4747
}
4848
if (EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid))
49-
return TRUE;
49+
return ImpersonateSelf(SecurityImpersonation);
5050
Ret = LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &Privileges.Privileges[0].Luid);
5151
if (!Ret)
5252
{
@@ -122,81 +122,6 @@ _Return_type_success_(return != FALSE) BOOL ElevateToSystem(void)
122122
return FALSE;
123123
}
124124

125-
_Return_type_success_(return != NULL) HANDLE GetPrimarySystemTokenFromThread(void)
126-
{
127-
HANDLE CurrentToken, DuplicatedToken;
128-
BOOL Ret;
129-
DWORD LastError;
130-
TOKEN_PRIVILEGES Privileges = { .PrivilegeCount = 1, .Privileges = { { .Attributes = SE_PRIVILEGE_ENABLED } } };
131-
CHAR LocalSystemSid[0x400];
132-
DWORD RequiredBytes = sizeof(LocalSystemSid);
133-
struct
134-
{
135-
TOKEN_USER MaybeLocalSystem;
136-
CHAR LargeEnoughForLocalSystem[0x400];
137-
} TokenUserBuffer;
138-
139-
Ret = CreateWellKnownSid(WinLocalSystemSid, NULL, &LocalSystemSid, &RequiredBytes);
140-
if (!Ret)
141-
{
142-
LastError = LOG_LAST_ERROR(L"Failed to create SID");
143-
return NULL;
144-
}
145-
Ret = OpenThreadToken(
146-
GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_DUPLICATE, FALSE, &CurrentToken);
147-
if (!Ret && GetLastError() == ERROR_NO_TOKEN)
148-
Ret = OpenProcessToken(
149-
GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_DUPLICATE, &CurrentToken);
150-
if (!Ret)
151-
{
152-
LastError = LOG_LAST_ERROR(L"Failed to open token");
153-
return NULL;
154-
}
155-
Ret = GetTokenInformation(CurrentToken, TokenUser, &TokenUserBuffer, sizeof(TokenUserBuffer), &RequiredBytes);
156-
if (!Ret)
157-
{
158-
LastError = LOG_LAST_ERROR(L"Failed to get token information");
159-
goto cleanup;
160-
}
161-
if (!EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid))
162-
{
163-
LOG(WINTUN_LOG_ERR, L"Not SYSTEM");
164-
LastError = ERROR_ACCESS_DENIED;
165-
goto cleanup;
166-
}
167-
Ret = LookupPrivilegeValueW(NULL, SE_ASSIGNPRIMARYTOKEN_NAME, &Privileges.Privileges[0].Luid);
168-
if (!Ret)
169-
{
170-
LastError = LOG_LAST_ERROR(L"Failed to lookup privilege value");
171-
goto cleanup;
172-
}
173-
Ret = AdjustTokenPrivileges(CurrentToken, FALSE, &Privileges, 0, NULL, NULL);
174-
if (!Ret)
175-
{
176-
LastError = LOG_LAST_ERROR(L"Failed to adjust token privileges");
177-
goto cleanup;
178-
}
179-
Ret = DuplicateTokenEx(
180-
CurrentToken,
181-
TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY,
182-
NULL,
183-
SecurityImpersonation,
184-
TokenPrimary,
185-
&DuplicatedToken);
186-
if (!Ret)
187-
{
188-
LastError = LOG_LAST_ERROR(L"Failed to duplicate token");
189-
goto cleanup;
190-
}
191-
CloseHandle(CurrentToken);
192-
return DuplicatedToken;
193-
194-
cleanup:
195-
CloseHandle(CurrentToken);
196-
SetLastError(LastError);
197-
return NULL;
198-
}
199-
200125
_Return_type_success_(return != FALSE) BOOL ImpersonateService(_In_z_ WCHAR *ServiceName, _In_ HANDLE *OriginalToken)
201126
{
202127
HANDLE ThreadToken, ServiceProcess, ServiceToken, DuplicatedToken;
@@ -212,20 +137,14 @@ _Return_type_success_(return != FALSE) BOOL ImpersonateService(_In_z_ WCHAR *Ser
212137
GetLastError() != ERROR_NO_TOKEN)
213138
return FALSE;
214139

140+
if (!ElevateToSystem())
141+
goto cleanup;
142+
215143
if (!LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &Privileges.Privileges[0].Luid))
216144
{
217145
LastError = LOG_LAST_ERROR(L"Failed to lookup privilege value");
218146
goto cleanup;
219147
}
220-
if (!*OriginalToken)
221-
{
222-
RevertToSelf();
223-
if (!ImpersonateSelf(SecurityImpersonation))
224-
{
225-
LastError = LOG_LAST_ERROR(L"Failed to impersonate self");
226-
goto cleanup;
227-
}
228-
}
229148
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &ThreadToken))
230149
{
231150
LastError = LOG_LAST_ERROR(L"Failed to open thread token");

api/elevate.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77

88
#include <Windows.h>
99

10-
_Return_type_success_(return != FALSE) BOOL ElevateToSystem(void);
11-
12-
_Return_type_success_(return != NULL) HANDLE GetPrimarySystemTokenFromThread(void);
13-
1410
_Return_type_success_(return != FALSE) BOOL ImpersonateService(_In_z_ WCHAR *ServiceName, _In_ HANDLE *OriginalToken);
1511

1612
_Return_type_success_(return != FALSE) BOOL RestoreToken(_In_ HANDLE OriginalToken);

api/entry.c

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
HINSTANCE ResourceModule;
2222
HANDLE ModuleHeap;
2323
SECURITY_ATTRIBUTES SecurityAttributes = { .nLength = sizeof(SECURITY_ATTRIBUTES) };
24+
BOOL IsLocalSystem;
2425

2526
static FARPROC WINAPI
2627
DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli)
@@ -35,6 +36,41 @@ DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli)
3536

3637
const PfnDliHook __pfnDliNotifyHook2 = DelayedLoadLibraryHook;
3738

39+
static BOOL
40+
InitializeSecurityObjects(void)
41+
{
42+
BYTE LocalSystemSid[MAX_SID_SIZE];
43+
DWORD RequiredBytes = sizeof(LocalSystemSid);
44+
HANDLE CurrentProcessToken;
45+
struct
46+
{
47+
TOKEN_USER MaybeLocalSystem;
48+
CHAR LargeEnoughForLocalSystem[MAX_SID_SIZE];
49+
} TokenUserBuffer;
50+
BOOL Ret = FALSE;
51+
52+
if (!CreateWellKnownSid(WinLocalSystemSid, NULL, LocalSystemSid, &RequiredBytes))
53+
return FALSE;
54+
55+
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &CurrentProcessToken))
56+
return FALSE;
57+
58+
if (!GetTokenInformation(CurrentProcessToken, TokenUser, &TokenUserBuffer, sizeof(TokenUserBuffer), &RequiredBytes))
59+
goto cleanupProcessToken;
60+
61+
IsLocalSystem = EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid);
62+
Ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(
63+
IsLocalSystem ? L"O:SYD:P(A;;GA;;;SY)(A;;GA;;;BA)S:(ML;;NWNRNX;;;HI)"
64+
: L"O:BAD:P(A;;GA;;;SY)(A;;GA;;;BA)S:(ML;;NWNRNX;;;HI)",
65+
SDDL_REVISION_1,
66+
&SecurityAttributes.lpSecurityDescriptor,
67+
NULL);
68+
69+
cleanupProcessToken:
70+
CloseHandle(CurrentProcessToken);
71+
return Ret;
72+
}
73+
3874
BOOL APIENTRY
3975
DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
4076
{
@@ -47,8 +83,11 @@ DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
4783
ModuleHeap = HeapCreate(0, 0, 0);
4884
if (!ModuleHeap)
4985
return FALSE;
50-
ConvertStringSecurityDescriptorToSecurityDescriptorW(
51-
L"O:SYD:P(A;;GA;;;SY)", SDDL_REVISION_1, &SecurityAttributes.lpSecurityDescriptor, NULL);
86+
if (!InitializeSecurityObjects())
87+
{
88+
HeapDestroy(ModuleHeap);
89+
return FALSE;
90+
}
5291
AdapterInit();
5392
NamespaceInit();
5493
break;

api/entry.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@
2929
extern HINSTANCE ResourceModule;
3030
extern HANDLE ModuleHeap;
3131
extern SECURITY_ATTRIBUTES SecurityAttributes;
32+
extern BOOL IsLocalSystem;

api/namespace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ static _Return_type_success_(return != FALSE) BOOL NamespaceRuntimeInit(void)
5959
}
6060

6161
BYTE Sid[MAX_SID_SIZE];
62-
DWORD SidSize = MAX_SID_SIZE;
63-
if (!CreateWellKnownSid(WinLocalSystemSid, NULL, Sid, &SidSize))
62+
DWORD SidSize = sizeof(Sid);
63+
if (!CreateWellKnownSid(IsLocalSystem ? WinLocalSystemSid : WinBuiltinAdministratorsSid, NULL, Sid, &SidSize))
6464
{
6565
LastError = LOG_LAST_ERROR(L"Failed to create SID");
6666
goto cleanupBCryptCloseAlgorithmProvider;

0 commit comments

Comments
 (0)