mirror of
https://github.com/8damon/Blackbird-Platform
synced 2026-06-21 13:41:12 +00:00
354 lines
9.2 KiB
C++
354 lines
9.2 KiB
C++
#include "internal.h"
|
|
|
|
BOOL ControllerInjectionAcquirePrimaryTokenFromProcess(_In_ DWORD ProcessId, _Out_ HANDLE *TokenOut)
|
|
{
|
|
HANDLE processHandle = NULL;
|
|
HANDLE token = NULL;
|
|
HANDLE primaryToken = NULL;
|
|
|
|
if (TokenOut == NULL || ProcessId == 0)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
*TokenOut = NULL;
|
|
processHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, ProcessId);
|
|
if (processHandle == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!OpenProcessToken(processHandle,
|
|
TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_DEFAULT |
|
|
TOKEN_ADJUST_SESSIONID,
|
|
&token))
|
|
{
|
|
DWORD err = GetLastError();
|
|
CloseHandle(processHandle);
|
|
SetLastError(err);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!DuplicateTokenEx(
|
|
token, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID,
|
|
NULL, SecurityImpersonation, TokenPrimary, &primaryToken))
|
|
{
|
|
DWORD err = GetLastError();
|
|
CloseHandle(token);
|
|
CloseHandle(processHandle);
|
|
SetLastError(err);
|
|
return FALSE;
|
|
}
|
|
|
|
CloseHandle(token);
|
|
CloseHandle(processHandle);
|
|
*TokenOut = primaryToken;
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL ControllerInjectionDuplicateWtsUserToken(_In_ DWORD SessionId, _Out_ HANDLE *TokenOut)
|
|
{
|
|
HANDLE userToken = NULL;
|
|
HANDLE primaryToken = NULL;
|
|
|
|
if (TokenOut == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
*TokenOut = NULL;
|
|
if (SessionId == 0 || SessionId == 0xFFFFFFFFu)
|
|
{
|
|
SetLastError(ERROR_NO_TOKEN);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!WTSQueryUserToken(SessionId, &userToken))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!DuplicateTokenEx(userToken,
|
|
TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_DEFAULT |
|
|
TOKEN_ADJUST_SESSIONID,
|
|
NULL, SecurityImpersonation, TokenPrimary, &primaryToken))
|
|
{
|
|
DWORD err = GetLastError();
|
|
CloseHandle(userToken);
|
|
SetLastError(err);
|
|
return FALSE;
|
|
}
|
|
|
|
CloseHandle(userToken);
|
|
*TokenOut = primaryToken;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL ControllerInjectionAcquireActiveInteractiveUserToken(_Out_ HANDLE *TokenOut, _Out_opt_ DWORD *SessionIdOut)
|
|
{
|
|
DWORD consoleSessionId = WTSGetActiveConsoleSessionId();
|
|
WTS_SESSION_INFOW *sessions = NULL;
|
|
DWORD sessionCount = 0;
|
|
DWORD lastErr = ERROR_NO_TOKEN;
|
|
|
|
if (TokenOut == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
*TokenOut = NULL;
|
|
if (SessionIdOut != NULL)
|
|
{
|
|
*SessionIdOut = 0;
|
|
}
|
|
|
|
if (consoleSessionId != 0 && consoleSessionId != 0xFFFFFFFFu)
|
|
{
|
|
if (ControllerInjectionDuplicateWtsUserToken(consoleSessionId, TokenOut))
|
|
{
|
|
if (SessionIdOut != NULL)
|
|
{
|
|
*SessionIdOut = consoleSessionId;
|
|
}
|
|
return TRUE;
|
|
}
|
|
lastErr = GetLastError();
|
|
}
|
|
|
|
if (!WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessions, &sessionCount))
|
|
{
|
|
DWORD err = GetLastError();
|
|
SetLastError(err == ERROR_SUCCESS ? lastErr : err);
|
|
return FALSE;
|
|
}
|
|
|
|
for (DWORD i = 0; i < sessionCount; ++i)
|
|
{
|
|
DWORD sessionId = sessions[i].SessionId;
|
|
if (sessions[i].State != WTSActive || sessionId == 0 || sessionId == consoleSessionId)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (ControllerInjectionDuplicateWtsUserToken(sessionId, TokenOut))
|
|
{
|
|
if (SessionIdOut != NULL)
|
|
{
|
|
*SessionIdOut = sessionId;
|
|
}
|
|
WTSFreeMemory(sessions);
|
|
return TRUE;
|
|
}
|
|
lastErr = GetLastError();
|
|
}
|
|
|
|
WTSFreeMemory(sessions);
|
|
SetLastError(lastErr == ERROR_SUCCESS ? ERROR_NO_TOKEN : lastErr);
|
|
return FALSE;
|
|
}
|
|
|
|
static DWORD ControllerInjectionIntegrityRid(_In_ UINT32 IntegrityLevel)
|
|
{
|
|
switch (IntegrityLevel)
|
|
{
|
|
case BK_LAUNCH_INTEGRITY_UNTRUSTED:
|
|
return SECURITY_MANDATORY_UNTRUSTED_RID;
|
|
case BK_LAUNCH_INTEGRITY_LOW:
|
|
return SECURITY_MANDATORY_LOW_RID;
|
|
case BK_LAUNCH_INTEGRITY_MEDIUM:
|
|
return SECURITY_MANDATORY_MEDIUM_RID;
|
|
case BK_LAUNCH_INTEGRITY_HIGH:
|
|
return SECURITY_MANDATORY_HIGH_RID;
|
|
case BK_LAUNCH_INTEGRITY_SYSTEM:
|
|
return SECURITY_MANDATORY_SYSTEM_RID;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
BOOL ControllerInjectionApplyRequestedIntegrity(_In_ HANDLE TokenHandle, _In_ UINT32 IntegrityLevel)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authority = SECURITY_MANDATORY_LABEL_AUTHORITY;
|
|
PSID integritySid = NULL;
|
|
TOKEN_MANDATORY_LABEL label;
|
|
DWORD integrityRid = ControllerInjectionIntegrityRid(IntegrityLevel);
|
|
BOOL success;
|
|
|
|
if (IntegrityLevel == BK_LAUNCH_INTEGRITY_DEFAULT)
|
|
{
|
|
return TRUE;
|
|
}
|
|
if (TokenHandle == NULL || TokenHandle == INVALID_HANDLE_VALUE || integrityRid == 0)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!AllocateAndInitializeSid(&authority, 1, integrityRid, 0, 0, 0, 0, 0, 0, 0, &integritySid))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
ZeroMemory(&label, sizeof(label));
|
|
label.Label.Attributes = SE_GROUP_INTEGRITY;
|
|
label.Label.Sid = integritySid;
|
|
success = SetTokenInformation(TokenHandle, TokenIntegrityLevel, &label, sizeof(label) + GetLengthSid(integritySid));
|
|
if (!success)
|
|
{
|
|
DWORD err = GetLastError();
|
|
FreeSid(integritySid);
|
|
SetLastError(err);
|
|
return FALSE;
|
|
}
|
|
|
|
FreeSid(integritySid);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL ControllerInjectionEnablePrivilege(_In_z_ PCWSTR PrivilegeName)
|
|
{
|
|
HANDLE token = NULL;
|
|
TOKEN_PRIVILEGES privileges;
|
|
LUID luid;
|
|
DWORD err;
|
|
|
|
if (PrivilegeName == NULL || PrivilegeName[0] == L'\0')
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!LookupPrivilegeValueW(NULL, PrivilegeName, &luid))
|
|
{
|
|
err = GetLastError();
|
|
CloseHandle(token);
|
|
SetLastError(err);
|
|
return FALSE;
|
|
}
|
|
|
|
ZeroMemory(&privileges, sizeof(privileges));
|
|
privileges.PrivilegeCount = 1;
|
|
privileges.Privileges[0].Luid = luid;
|
|
privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
if (!AdjustTokenPrivileges(token, FALSE, &privileges, sizeof(privileges), NULL, NULL))
|
|
{
|
|
err = GetLastError();
|
|
CloseHandle(token);
|
|
SetLastError(err);
|
|
return FALSE;
|
|
}
|
|
|
|
err = GetLastError();
|
|
CloseHandle(token);
|
|
if (err == ERROR_NOT_ALL_ASSIGNED)
|
|
{
|
|
SetLastError(err);
|
|
return FALSE;
|
|
}
|
|
|
|
SetLastError(ERROR_SUCCESS);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL ControllerInjectionQueryPipeClientSession(_In_ HANDLE PipeHandle, _Out_opt_ DWORD *ClientProcessIdOut,
|
|
_Out_ DWORD *SessionIdOut)
|
|
{
|
|
DWORD clientPid = 0;
|
|
DWORD sessionId = 0;
|
|
|
|
if (SessionIdOut == NULL || PipeHandle == NULL || PipeHandle == INVALID_HANDLE_VALUE)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
*SessionIdOut = 0;
|
|
if (ClientProcessIdOut != NULL)
|
|
{
|
|
*ClientProcessIdOut = 0;
|
|
}
|
|
|
|
if (!GetNamedPipeClientSessionId(PipeHandle, &sessionId))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (ClientProcessIdOut != NULL)
|
|
{
|
|
if (GetNamedPipeClientProcessId(PipeHandle, &clientPid))
|
|
{
|
|
*ClientProcessIdOut = clientPid;
|
|
}
|
|
}
|
|
*SessionIdOut = sessionId;
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL ControllerInjectionQueryTokenSession(_In_ HANDLE TokenHandle, _Out_ DWORD *SessionIdOut)
|
|
{
|
|
DWORD sessionId = 0;
|
|
DWORD bytesReturned = 0;
|
|
|
|
if (TokenHandle == NULL || TokenHandle == INVALID_HANDLE_VALUE || SessionIdOut == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!GetTokenInformation(TokenHandle, TokenSessionId, &sessionId, sizeof(sessionId), &bytesReturned))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
*SessionIdOut = sessionId;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL ControllerInjectionEnsureTokenSession(_In_ HANDLE TokenHandle, _In_ DWORD DesiredSessionId,
|
|
_Out_opt_ DWORD *OriginalSessionIdOut, _Out_opt_ DWORD *TokenSessionIdOut)
|
|
{
|
|
DWORD tokenSessionId = 0;
|
|
|
|
if (OriginalSessionIdOut != NULL)
|
|
{
|
|
*OriginalSessionIdOut = 0;
|
|
}
|
|
if (TokenSessionIdOut != NULL)
|
|
{
|
|
*TokenSessionIdOut = 0;
|
|
}
|
|
if (!ControllerInjectionQueryTokenSession(TokenHandle, &tokenSessionId))
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (OriginalSessionIdOut != NULL)
|
|
{
|
|
*OriginalSessionIdOut = tokenSessionId;
|
|
}
|
|
|
|
if (tokenSessionId != DesiredSessionId)
|
|
{
|
|
DWORD desired = DesiredSessionId;
|
|
if (!SetTokenInformation(TokenHandle, TokenSessionId, &desired, sizeof(desired)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
tokenSessionId = desired;
|
|
}
|
|
|
|
if (TokenSessionIdOut != NULL)
|
|
{
|
|
*TokenSessionIdOut = tokenSessionId;
|
|
}
|
|
return TRUE;
|
|
}
|