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:
parent
d33732ab4b
commit
ed2f5cc225
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
@ -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);
|
||||||
|
43
api/entry.c
43
api/entry.c
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user