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 <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2021-06-24 12:12:13 +02:00
parent d33732ab4b
commit ed2f5cc225
8 changed files with 69 additions and 161 deletions

View File

@ -668,18 +668,13 @@ WintunFreeAdapter(_In_ WINTUN_ADAPTER *Adapter)
_Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI _Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI
WintunOpenAdapter(_In_z_ const WCHAR *Pool, _In_z_ const WCHAR *Name) WintunOpenAdapter(_In_z_ const WCHAR *Pool, _In_z_ const WCHAR *Name)
{ {
if (!ElevateToSystem())
{
LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
return NULL;
}
DWORD LastError; DWORD LastError;
WINTUN_ADAPTER *Adapter = NULL; WINTUN_ADAPTER *Adapter = NULL;
HANDLE Mutex = NamespaceTakePoolMutex(Pool); HANDLE Mutex = NamespaceTakePoolMutex(Pool);
if (!Mutex) if (!Mutex)
{ {
LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Pool); LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Pool);
goto cleanupToken; goto cleanup;
} }
HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL); HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
@ -759,8 +754,7 @@ cleanupDevInfo:
SetupDiDestroyDeviceInfoList(DevInfo); SetupDiDestroyDeviceInfoList(DevInfo);
cleanupMutex: cleanupMutex:
NamespaceReleaseMutex(Mutex); NamespaceReleaseMutex(Mutex);
cleanupToken: cleanup:
RevertToSelf();
SetLastError(LastError); SetLastError(LastError);
return Adapter; return Adapter;
} }
@ -1840,11 +1834,6 @@ _Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI WintunCreateAdapter
_In_opt_ const GUID *RequestedGUID, _In_opt_ const GUID *RequestedGUID,
_Out_opt_ BOOL *RebootRequired) _Out_opt_ BOOL *RebootRequired)
{ {
if (!ElevateToSystem())
{
LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
return NULL;
}
BOOL DummyRebootRequired; BOOL DummyRebootRequired;
if (!RebootRequired) if (!RebootRequired)
RebootRequired = &DummyRebootRequired; RebootRequired = &DummyRebootRequired;
@ -1855,12 +1844,11 @@ _Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI WintunCreateAdapter
{ {
Adapter = CreateAdapterViaRundll32(Pool, Name, RequestedGUID, RebootRequired); Adapter = CreateAdapterViaRundll32(Pool, Name, RequestedGUID, RebootRequired);
LastError = Adapter ? ERROR_SUCCESS : GetLastError(); LastError = Adapter ? ERROR_SUCCESS : GetLastError();
goto cleanupToken; goto cleanup;
} }
Adapter = CreateAdapter(Pool, Name, RequestedGUID, RebootRequired); Adapter = CreateAdapter(Pool, Name, RequestedGUID, RebootRequired);
LastError = Adapter ? ERROR_SUCCESS : GetLastError(); LastError = Adapter ? ERROR_SUCCESS : GetLastError();
cleanupToken: cleanup:
RevertToSelf();
return RET_ERROR(Adapter, LastError); return RET_ERROR(Adapter, LastError);
} }
@ -1869,11 +1857,6 @@ _Return_type_success_(return != FALSE) BOOL WINAPI WintunDeleteAdapter(
_In_ BOOL ForceCloseSessions, _In_ BOOL ForceCloseSessions,
_Out_opt_ BOOL *RebootRequired) _Out_opt_ BOOL *RebootRequired)
{ {
if (!ElevateToSystem())
{
LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
return FALSE;
}
BOOL DummyRebootRequired; BOOL DummyRebootRequired;
if (!RebootRequired) if (!RebootRequired)
RebootRequired = &DummyRebootRequired; RebootRequired = &DummyRebootRequired;
@ -1883,14 +1866,14 @@ _Return_type_success_(return != FALSE) BOOL WINAPI WintunDeleteAdapter(
{ {
LastError = LastError =
DeleteAdapterViaRundll32(Adapter, ForceCloseSessions, RebootRequired) ? ERROR_SUCCESS : GetLastError(); DeleteAdapterViaRundll32(Adapter, ForceCloseSessions, RebootRequired) ? ERROR_SUCCESS : GetLastError();
goto cleanupToken; goto cleanup;
} }
HANDLE Mutex = NamespaceTakePoolMutex(Adapter->Pool); HANDLE Mutex = NamespaceTakePoolMutex(Adapter->Pool);
if (!Mutex) if (!Mutex)
{ {
LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Adapter->Pool); LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Adapter->Pool);
goto cleanupToken; goto cleanup;
} }
HDEVINFO DevInfo; HDEVINFO DevInfo;
@ -1930,8 +1913,7 @@ cleanupDevInfo:
SetupDiDestroyDeviceInfoList(DevInfo); SetupDiDestroyDeviceInfoList(DevInfo);
cleanupMutex: cleanupMutex:
NamespaceReleaseMutex(Mutex); NamespaceReleaseMutex(Mutex);
cleanupToken: cleanup:
RevertToSelf();
return RET_ERROR(TRUE, LastError); return RET_ERROR(TRUE, LastError);
} }
@ -1990,12 +1972,6 @@ cleanupMutex:
_Return_type_success_(return != FALSE) BOOL WINAPI _Return_type_success_(return != FALSE) BOOL WINAPI
WintunDeletePoolDriver(_In_z_ const WCHAR *Pool, _Out_opt_ BOOL *RebootRequired) WintunDeletePoolDriver(_In_z_ const WCHAR *Pool, _Out_opt_ BOOL *RebootRequired)
{ {
if (!ElevateToSystem())
{
LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
return FALSE;
}
BOOL DummyRebootRequired; BOOL DummyRebootRequired;
if (!RebootRequired) if (!RebootRequired)
RebootRequired = &DummyRebootRequired; RebootRequired = &DummyRebootRequired;
@ -2005,20 +1981,20 @@ _Return_type_success_(return != FALSE) BOOL WINAPI
if (MAYBE_WOW64 && NativeMachine != IMAGE_FILE_PROCESS) if (MAYBE_WOW64 && NativeMachine != IMAGE_FILE_PROCESS)
{ {
LastError = DeletePoolDriverViaRundll32(Pool, RebootRequired) ? ERROR_SUCCESS : GetLastError(); LastError = DeletePoolDriverViaRundll32(Pool, RebootRequired) ? ERROR_SUCCESS : GetLastError();
goto cleanupToken; goto cleanup;
} }
if (!DeleteAllOurAdapters(Pool, RebootRequired)) if (!DeleteAllOurAdapters(Pool, RebootRequired))
{ {
LastError = GetLastError(); LastError = GetLastError();
goto cleanupToken; goto cleanup;
} }
HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex(); HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex();
if (!DriverInstallationLock) if (!DriverInstallationLock)
{ {
LastError = LOG(WINTUN_LOG_ERR, L"Failed to take driver installation mutex"); LastError = LOG(WINTUN_LOG_ERR, L"Failed to take driver installation mutex");
goto cleanupToken; goto cleanup;
} }
HDEVINFO DeviceInfoSet = SetupDiGetClassDevsW(&GUID_DEVCLASS_NET, NULL, NULL, 0); HDEVINFO DeviceInfoSet = SetupDiGetClassDevsW(&GUID_DEVCLASS_NET, NULL, NULL, 0);
if (!DeviceInfoSet) if (!DeviceInfoSet)
@ -2060,25 +2036,19 @@ cleanupDeviceInfoSet:
SetupDiDestroyDeviceInfoList(DeviceInfoSet); SetupDiDestroyDeviceInfoList(DeviceInfoSet);
cleanupDriverInstallationLock: cleanupDriverInstallationLock:
NamespaceReleaseMutex(DriverInstallationLock); NamespaceReleaseMutex(DriverInstallationLock);
cleanupToken: cleanup:
RevertToSelf();
return RET_ERROR(TRUE, LastError); return RET_ERROR(TRUE, LastError);
} }
_Return_type_success_(return != FALSE) BOOL WINAPI _Return_type_success_(return != FALSE) BOOL WINAPI
WintunEnumAdapters(_In_z_ const WCHAR *Pool, _In_ WINTUN_ENUM_CALLBACK Func, _In_ LPARAM Param) WintunEnumAdapters(_In_z_ const WCHAR *Pool, _In_ WINTUN_ENUM_CALLBACK Func, _In_ LPARAM Param)
{ {
if (!ElevateToSystem())
{
LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
return FALSE;
}
DWORD LastError = ERROR_SUCCESS; DWORD LastError = ERROR_SUCCESS;
HANDLE Mutex = NamespaceTakePoolMutex(Pool); HANDLE Mutex = NamespaceTakePoolMutex(Pool);
if (!Mutex) if (!Mutex)
{ {
LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Pool); LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Pool);
goto cleanupToken; goto cleanup;
} }
HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL); HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
if (DevInfo == INVALID_HANDLE_VALUE) if (DevInfo == INVALID_HANDLE_VALUE)
@ -2112,7 +2082,6 @@ _Return_type_success_(return != FALSE) BOOL WINAPI
SetupDiDestroyDeviceInfoList(DevInfo); SetupDiDestroyDeviceInfoList(DevInfo);
cleanupMutex: cleanupMutex:
NamespaceReleaseMutex(Mutex); NamespaceReleaseMutex(Mutex);
cleanupToken: cleanup:
RevertToSelf();
return RET_ERROR(TRUE, LastError); return RET_ERROR(TRUE, LastError);
} }

View File

@ -9,19 +9,19 @@
#include <Windows.h> #include <Windows.h>
#include <TlHelp32.h> #include <TlHelp32.h>
_Return_type_success_(return != FALSE) BOOL ElevateToSystem(void) static _Return_type_success_(return != FALSE) BOOL ElevateToSystem(void)
{ {
HANDLE CurrentProcessToken, ThreadToken, ProcessSnapshot, WinlogonProcess, WinlogonToken, DuplicatedToken; HANDLE CurrentProcessToken, ThreadToken, ProcessSnapshot, WinlogonProcess, WinlogonToken, DuplicatedToken;
PROCESSENTRY32W ProcessEntry = { .dwSize = sizeof(PROCESSENTRY32W) }; PROCESSENTRY32W ProcessEntry = { .dwSize = sizeof(PROCESSENTRY32W) };
BOOL Ret; BOOL Ret;
DWORD LastError = ERROR_SUCCESS; DWORD LastError = ERROR_SUCCESS;
TOKEN_PRIVILEGES Privileges = { .PrivilegeCount = 1, .Privileges = { { .Attributes = SE_PRIVILEGE_ENABLED } } }; TOKEN_PRIVILEGES Privileges = { .PrivilegeCount = 1, .Privileges = { { .Attributes = SE_PRIVILEGE_ENABLED } } };
CHAR LocalSystemSid[0x400]; CHAR LocalSystemSid[MAX_SID_SIZE];
DWORD RequiredBytes = sizeof(LocalSystemSid); DWORD RequiredBytes = sizeof(LocalSystemSid);
struct struct
{ {
TOKEN_USER MaybeLocalSystem; TOKEN_USER MaybeLocalSystem;
CHAR LargeEnoughForLocalSystem[0x400]; CHAR LargeEnoughForLocalSystem[MAX_SID_SIZE];
} TokenUserBuffer; } TokenUserBuffer;
Ret = CreateWellKnownSid(WinLocalSystemSid, NULL, &LocalSystemSid, &RequiredBytes); Ret = CreateWellKnownSid(WinLocalSystemSid, NULL, &LocalSystemSid, &RequiredBytes);
@ -46,7 +46,7 @@ _Return_type_success_(return != FALSE) BOOL ElevateToSystem(void)
goto cleanup; goto cleanup;
} }
if (EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid)) if (EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid))
return TRUE; return ImpersonateSelf(SecurityImpersonation);
Ret = LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &Privileges.Privileges[0].Luid); Ret = LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &Privileges.Privileges[0].Luid);
if (!Ret) if (!Ret)
{ {
@ -122,81 +122,6 @@ cleanup:
return FALSE; return FALSE;
} }
_Return_type_success_(return != NULL) HANDLE GetPrimarySystemTokenFromThread(void)
{
HANDLE CurrentToken, DuplicatedToken;
BOOL Ret;
DWORD LastError;
TOKEN_PRIVILEGES Privileges = { .PrivilegeCount = 1, .Privileges = { { .Attributes = SE_PRIVILEGE_ENABLED } } };
CHAR LocalSystemSid[0x400];
DWORD RequiredBytes = sizeof(LocalSystemSid);
struct
{
TOKEN_USER MaybeLocalSystem;
CHAR LargeEnoughForLocalSystem[0x400];
} TokenUserBuffer;
Ret = CreateWellKnownSid(WinLocalSystemSid, NULL, &LocalSystemSid, &RequiredBytes);
if (!Ret)
{
LastError = LOG_LAST_ERROR(L"Failed to create SID");
return NULL;
}
Ret = OpenThreadToken(
GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_DUPLICATE, FALSE, &CurrentToken);
if (!Ret && GetLastError() == ERROR_NO_TOKEN)
Ret = OpenProcessToken(
GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_DUPLICATE, &CurrentToken);
if (!Ret)
{
LastError = LOG_LAST_ERROR(L"Failed to open token");
return NULL;
}
Ret = GetTokenInformation(CurrentToken, TokenUser, &TokenUserBuffer, sizeof(TokenUserBuffer), &RequiredBytes);
if (!Ret)
{
LastError = LOG_LAST_ERROR(L"Failed to get token information");
goto cleanup;
}
if (!EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid))
{
LOG(WINTUN_LOG_ERR, L"Not SYSTEM");
LastError = ERROR_ACCESS_DENIED;
goto cleanup;
}
Ret = LookupPrivilegeValueW(NULL, SE_ASSIGNPRIMARYTOKEN_NAME, &Privileges.Privileges[0].Luid);
if (!Ret)
{
LastError = LOG_LAST_ERROR(L"Failed to lookup privilege value");
goto cleanup;
}
Ret = AdjustTokenPrivileges(CurrentToken, FALSE, &Privileges, 0, NULL, NULL);
if (!Ret)
{
LastError = LOG_LAST_ERROR(L"Failed to adjust token privileges");
goto cleanup;
}
Ret = DuplicateTokenEx(
CurrentToken,
TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY,
NULL,
SecurityImpersonation,
TokenPrimary,
&DuplicatedToken);
if (!Ret)
{
LastError = LOG_LAST_ERROR(L"Failed to duplicate token");
goto cleanup;
}
CloseHandle(CurrentToken);
return DuplicatedToken;
cleanup:
CloseHandle(CurrentToken);
SetLastError(LastError);
return NULL;
}
_Return_type_success_(return != FALSE) BOOL ImpersonateService(_In_z_ WCHAR *ServiceName, _In_ HANDLE *OriginalToken) _Return_type_success_(return != FALSE) BOOL ImpersonateService(_In_z_ WCHAR *ServiceName, _In_ HANDLE *OriginalToken)
{ {
HANDLE ThreadToken, ServiceProcess, ServiceToken, DuplicatedToken; HANDLE ThreadToken, ServiceProcess, ServiceToken, DuplicatedToken;
@ -212,20 +137,14 @@ _Return_type_success_(return != FALSE) BOOL ImpersonateService(_In_z_ WCHAR *Ser
GetLastError() != ERROR_NO_TOKEN) GetLastError() != ERROR_NO_TOKEN)
return FALSE; return FALSE;
if (!ElevateToSystem())
goto cleanup;
if (!LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &Privileges.Privileges[0].Luid)) if (!LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &Privileges.Privileges[0].Luid))
{ {
LastError = LOG_LAST_ERROR(L"Failed to lookup privilege value"); LastError = LOG_LAST_ERROR(L"Failed to lookup privilege value");
goto cleanup; goto cleanup;
} }
if (!*OriginalToken)
{
RevertToSelf();
if (!ImpersonateSelf(SecurityImpersonation))
{
LastError = LOG_LAST_ERROR(L"Failed to impersonate self");
goto cleanup;
}
}
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &ThreadToken)) if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &ThreadToken))
{ {
LastError = LOG_LAST_ERROR(L"Failed to open thread token"); LastError = LOG_LAST_ERROR(L"Failed to open thread token");

View File

@ -7,10 +7,6 @@
#include <Windows.h> #include <Windows.h>
_Return_type_success_(return != FALSE) BOOL ElevateToSystem(void);
_Return_type_success_(return != NULL) HANDLE GetPrimarySystemTokenFromThread(void);
_Return_type_success_(return != FALSE) BOOL ImpersonateService(_In_z_ WCHAR *ServiceName, _In_ HANDLE *OriginalToken); _Return_type_success_(return != FALSE) BOOL ImpersonateService(_In_z_ WCHAR *ServiceName, _In_ HANDLE *OriginalToken);
_Return_type_success_(return != FALSE) BOOL RestoreToken(_In_ HANDLE OriginalToken); _Return_type_success_(return != FALSE) BOOL RestoreToken(_In_ HANDLE OriginalToken);

View File

@ -21,6 +21,7 @@
HINSTANCE ResourceModule; HINSTANCE ResourceModule;
HANDLE ModuleHeap; HANDLE ModuleHeap;
SECURITY_ATTRIBUTES SecurityAttributes = { .nLength = sizeof(SECURITY_ATTRIBUTES) }; SECURITY_ATTRIBUTES SecurityAttributes = { .nLength = sizeof(SECURITY_ATTRIBUTES) };
BOOL IsLocalSystem;
static FARPROC WINAPI static FARPROC WINAPI
DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli) DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli)
@ -35,6 +36,41 @@ DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli)
const PfnDliHook __pfnDliNotifyHook2 = DelayedLoadLibraryHook; const PfnDliHook __pfnDliNotifyHook2 = DelayedLoadLibraryHook;
static BOOL
InitializeSecurityObjects(void)
{
BYTE LocalSystemSid[MAX_SID_SIZE];
DWORD RequiredBytes = sizeof(LocalSystemSid);
HANDLE CurrentProcessToken;
struct
{
TOKEN_USER MaybeLocalSystem;
CHAR LargeEnoughForLocalSystem[MAX_SID_SIZE];
} TokenUserBuffer;
BOOL Ret = FALSE;
if (!CreateWellKnownSid(WinLocalSystemSid, NULL, LocalSystemSid, &RequiredBytes))
return FALSE;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &CurrentProcessToken))
return FALSE;
if (!GetTokenInformation(CurrentProcessToken, TokenUser, &TokenUserBuffer, sizeof(TokenUserBuffer), &RequiredBytes))
goto cleanupProcessToken;
IsLocalSystem = EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid);
Ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(
IsLocalSystem ? L"O:SYD:P(A;;GA;;;SY)(A;;GA;;;BA)S:(ML;;NWNRNX;;;HI)"
: L"O:BAD:P(A;;GA;;;SY)(A;;GA;;;BA)S:(ML;;NWNRNX;;;HI)",
SDDL_REVISION_1,
&SecurityAttributes.lpSecurityDescriptor,
NULL);
cleanupProcessToken:
CloseHandle(CurrentProcessToken);
return Ret;
}
BOOL APIENTRY BOOL APIENTRY
DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved) DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
{ {
@ -47,8 +83,11 @@ DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
ModuleHeap = HeapCreate(0, 0, 0); ModuleHeap = HeapCreate(0, 0, 0);
if (!ModuleHeap) if (!ModuleHeap)
return FALSE; return FALSE;
ConvertStringSecurityDescriptorToSecurityDescriptorW( if (!InitializeSecurityObjects())
L"O:SYD:P(A;;GA;;;SY)", SDDL_REVISION_1, &SecurityAttributes.lpSecurityDescriptor, NULL); {
HeapDestroy(ModuleHeap);
return FALSE;
}
AdapterInit(); AdapterInit();
NamespaceInit(); NamespaceInit();
break; break;

View File

@ -29,3 +29,4 @@
extern HINSTANCE ResourceModule; extern HINSTANCE ResourceModule;
extern HANDLE ModuleHeap; extern HANDLE ModuleHeap;
extern SECURITY_ATTRIBUTES SecurityAttributes; extern SECURITY_ATTRIBUTES SecurityAttributes;
extern BOOL IsLocalSystem;

View File

@ -59,8 +59,8 @@ static _Return_type_success_(return != FALSE) BOOL NamespaceRuntimeInit(void)
} }
BYTE Sid[MAX_SID_SIZE]; BYTE Sid[MAX_SID_SIZE];
DWORD SidSize = MAX_SID_SIZE; DWORD SidSize = sizeof(Sid);
if (!CreateWellKnownSid(WinLocalSystemSid, NULL, Sid, &SidSize)) if (!CreateWellKnownSid(IsLocalSystem ? WinLocalSystemSid : WinBuiltinAdministratorsSid, NULL, Sid, &SidSize))
{ {
LastError = LOG_LAST_ERROR(L"Failed to create SID"); LastError = LOG_LAST_ERROR(L"Failed to create SID");
goto cleanupBCryptCloseAlgorithmProvider; goto cleanupBCryptCloseAlgorithmProvider;

View File

@ -176,23 +176,15 @@ static _Return_type_success_(return != FALSE) BOOL ExecuteRunDll32(
.hStdOutput = StreamWStdout, .hStdOutput = StreamWStdout,
.hStdError = StreamWStderr }; .hStdError = StreamWStderr };
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
HANDLE ProcessToken = GetPrimarySystemTokenFromThread(); if (!CreateProcessW(RunDll32Path, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
if (!ProcessToken)
{
LastError = LOG(WINTUN_LOG_ERR, L"Failed to get primary system token from thread");
goto cleanupThreads;
}
if (!CreateProcessAsUserW(ProcessToken, RunDll32Path, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{ {
LastError = LOG_LAST_ERROR(L"Failed to create process: %s", CommandLine); LastError = LOG_LAST_ERROR(L"Failed to create process: %s", CommandLine);
goto cleanupToken; goto cleanupThreads;
} }
LastError = ERROR_SUCCESS; LastError = ERROR_SUCCESS;
WaitForSingleObject(pi.hProcess, INFINITE); WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
cleanupToken:
CloseHandle(ProcessToken);
cleanupThreads: cleanupThreads:
if (ThreadStderr) if (ThreadStderr)
{ {

View File

@ -77,7 +77,7 @@ _Return_type_success_(return != NULL) TUN_SESSION *WINAPI
if (!Session) if (!Session)
{ {
LastError = GetLastError(); LastError = GetLastError();
goto out; goto cleanup;
} }
const ULONG RingSize = TUN_RING_SIZE(Capacity); const ULONG RingSize = TUN_RING_SIZE(Capacity);
BYTE *AllocatedRegion = VirtualAlloc(0, (size_t)RingSize * 2, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); BYTE *AllocatedRegion = VirtualAlloc(0, (size_t)RingSize * 2, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
@ -86,18 +86,13 @@ _Return_type_success_(return != NULL) TUN_SESSION *WINAPI
LastError = LOG_LAST_ERROR(L"Failed to allocate ring memory (requested size: 0x%zx)", (size_t)RingSize * 2); LastError = LOG_LAST_ERROR(L"Failed to allocate ring memory (requested size: 0x%zx)", (size_t)RingSize * 2);
goto cleanupRings; goto cleanupRings;
} }
if (!ElevateToSystem())
{
LastError = LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
goto cleanupAllocatedRegion;
}
Session->Descriptor.Send.RingSize = RingSize; Session->Descriptor.Send.RingSize = RingSize;
Session->Descriptor.Send.Ring = (TUN_RING *)AllocatedRegion; Session->Descriptor.Send.Ring = (TUN_RING *)AllocatedRegion;
Session->Descriptor.Send.TailMoved = CreateEventW(&SecurityAttributes, FALSE, FALSE, NULL); Session->Descriptor.Send.TailMoved = CreateEventW(&SecurityAttributes, FALSE, FALSE, NULL);
if (!Session->Descriptor.Send.TailMoved) if (!Session->Descriptor.Send.TailMoved)
{ {
LastError = LOG_LAST_ERROR(L"Failed to create send event"); LastError = LOG_LAST_ERROR(L"Failed to create send event");
goto cleanupToken; goto cleanupAllocatedRegion;
} }
Session->Descriptor.Receive.RingSize = RingSize; Session->Descriptor.Receive.RingSize = RingSize;
@ -129,7 +124,6 @@ _Return_type_success_(return != NULL) TUN_SESSION *WINAPI
LastError = LOG_LAST_ERROR(L"Failed to register rings"); LastError = LOG_LAST_ERROR(L"Failed to register rings");
goto cleanupHandle; goto cleanupHandle;
} }
RevertToSelf();
Session->Capacity = Capacity; Session->Capacity = Capacity;
(void)InitializeCriticalSectionAndSpinCount(&Session->Receive.Lock, LOCK_SPIN_COUNT); (void)InitializeCriticalSectionAndSpinCount(&Session->Receive.Lock, LOCK_SPIN_COUNT);
(void)InitializeCriticalSectionAndSpinCount(&Session->Send.Lock, LOCK_SPIN_COUNT); (void)InitializeCriticalSectionAndSpinCount(&Session->Send.Lock, LOCK_SPIN_COUNT);
@ -140,13 +134,11 @@ cleanupReceiveTailMoved:
CloseHandle(Session->Descriptor.Receive.TailMoved); CloseHandle(Session->Descriptor.Receive.TailMoved);
cleanupSendTailMoved: cleanupSendTailMoved:
CloseHandle(Session->Descriptor.Send.TailMoved); CloseHandle(Session->Descriptor.Send.TailMoved);
cleanupToken:
RevertToSelf();
cleanupAllocatedRegion: cleanupAllocatedRegion:
VirtualFree(AllocatedRegion, 0, MEM_RELEASE); VirtualFree(AllocatedRegion, 0, MEM_RELEASE);
cleanupRings: cleanupRings:
Free(Session); Free(Session);
out: cleanup:
SetLastError(LastError); SetLastError(LastError);
return NULL; return NULL;
} }