/* * ucmShowProcessIntegrityLevel * * Purpose: * * Output current integrity level of target application. * */ void ucmShowProcessIntegrityLevel( VOID ) { NTSTATUS status; HANDLE hToken; ULONG LengthNeeded; PTOKEN_MANDATORY_LABEL pTIL = NULL; DWORD dwIntegrityLevel; WCHAR *t = NULL; WCHAR szBuffer[MAX_PATH + 1]; status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &hToken); if (NT_SUCCESS(status)) { status = NtQueryInformationToken(hToken, TokenIntegrityLevel, NULL, 0, &LengthNeeded); if (status == STATUS_BUFFER_TOO_SMALL) { pTIL = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, LengthNeeded); if (pTIL) { status = NtQueryInformationToken(hToken, TokenIntegrityLevel, pTIL, LengthNeeded, &LengthNeeded); if (NT_SUCCESS(status)) { dwIntegrityLevel = *RtlSubAuthoritySid(pTIL->Label.Sid, (DWORD)(UCHAR)(*RtlSubAuthorityCountSid(pTIL->Label.Sid) - 1)); if (dwIntegrityLevel == SECURITY_MANDATORY_LOW_RID) { t = L"Low Process"; } else if (dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID && dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID) { t = L"Medium Process"; } else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID) { t = L"High Integrity Process"; } else if (dwIntegrityLevel >= SECURITY_MANDATORY_SYSTEM_RID) { t = L"System Integrity Process"; } RtlSecureZeroMemory(szBuffer, sizeof(szBuffer)); wsprintf(szBuffer, L"PID=%lu, IntegrityLevel=%ws", GetCurrentProcessId(), t); } LocalFree(pTIL); } } NtClose(hToken); } if (t) MessageBox(GetDesktopWindow(), szBuffer, GetCommandLineW(), MB_ICONINFORMATION); }
BOOLEAN SepServerTestIdentification( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ) { BOOLEAN CompletionStatus = TRUE; ////////////////////////////////////////////////////////////////////////// // // // Identification Use Test // // // ////////////////////////////////////////////////////////////////////////// DbgPrint("Se: Identification Use ... "); SepServerWaitForNextConnect(); SepServerGetNextMessage(); SepServerImpersonateClient(); Status = NtOpenThreadToken( SepServerThread, TOKEN_ALL_ACCESS, TRUE, &ClientToken ); SEASSERT_SUCCESS(Status); SepServerRevertToSelf(); Status = NtQueryInformationToken( ClientToken, TokenStatistics, &ClientTokenStatistics, (ULONG)sizeof(TOKEN_STATISTICS), &IgnoreLength ); SEASSERT_SUCCESS(Status); if ( (ClientTokenStatistics.TokenType == TokenImpersonation) && (ClientTokenStatistics.ImpersonationLevel == SecurityIdentification) ) { DbgPrint(" Succeeded\n"); } else { DbgPrint("* ! FAILED (srvr) ! *\n"); CompletionStatus = FALSE; } SepServerCompleteMessage(); SepServerDropConnection(); // // Appease the compiler Gods.. // if (StaticTest) {;} if (EffectiveOnly) {;} return CompletionStatus; }
BOOL GetTokenInfo( HANDLE Token, TOKEN_INFORMATION_CLASS TokenInformationClass, PPVOID pBuffer) { NTSTATUS Status; ULONG BufferSize; ULONG InfoLength; PVOID Buffer; *pBuffer = NULL; // Prepare for failure Buffer = AllocTokenInfo(Token, TokenInformationClass); if (Buffer == NULL) { return(FALSE); } BufferSize = GetAllocSize(Buffer); Status = NtQueryInformationToken( Token, // Handle TokenInformationClass, // TokenInformationClass Buffer, // TokenInformation BufferSize, // TokenInformationLength &InfoLength // ReturnLength ); if (!NT_SUCCESS(Status)) { #ifdef NTBUILD DbgPrint("SECEDIT: NtQueryInformationToken failed, status = 0x%lx\n", Status); #endif FreeTokenInfo(Buffer); return(FALSE); } if (InfoLength > BufferSize) { #ifdef NTBUILD DbgPrint("SECEDIT: NtQueryInformationToken failed, DataSize > BufferSize"); #endif FreeTokenInfo(Buffer); return(FALSE); } *pBuffer = Buffer; return(TRUE); }
/* TODO: This function should be placed in a better place */ static PSID get_user_sid() { if (cached_sid_initialized) return cached_sid; else { HANDLE token; NTSTATUS status; NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &token); DWORD len; NtQueryInformationToken(token, TokenUser, cached_token_user, sizeof(cached_token_user), &len); TOKEN_USER *token_user = (TOKEN_USER *)cached_token_user; cached_sid = token_user->User.Sid; cached_sid_initialized = 1; NtClose(token); return cached_sid; } }
/* * @implemented */ BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength) { NTSTATUS Status; Status = NtQueryInformationToken(TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength, (PULONG)ReturnLength); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; } return TRUE; }
PVOID AllocTokenInfo( HANDLE Token, TOKEN_INFORMATION_CLASS TokenInformationClass) { NTSTATUS Status; ULONG InfoLength; Status = NtQueryInformationToken( Token, // Handle TokenInformationClass, // TokenInformationClass NULL, // TokenInformation 0, // TokenInformationLength &InfoLength // ReturnLength ); if (Status != STATUS_BUFFER_TOO_SMALL) { #ifdef NTBUILD DbgPrint("SECEDIT: NtQueryInformationToken did NOT return buffer_too_small, status = 0x%lx\n", Status); #endif return(NULL); } return Alloc(InfoLength); }
/* * @unimplemented */ PSID WINAPI GetSiteSidFromToken(IN HANDLE TokenHandle) { PTOKEN_GROUPS RestrictedSids; ULONG RetLen; UINT i; NTSTATUS Status; PSID PSiteSid = NULL; SID_IDENTIFIER_AUTHORITY InternetSiteAuthority = {SECURITY_INTERNETSITE_AUTHORITY}; Status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, NULL, 0, &RetLen); if (Status != STATUS_BUFFER_TOO_SMALL) { SetLastError(RtlNtStatusToDosError(Status)); return NULL; } RestrictedSids = (PTOKEN_GROUPS)RtlAllocateHeap(RtlGetProcessHeap(), 0, RetLen); if (RestrictedSids == NULL) { SetLastError(ERROR_OUTOFMEMORY); return NULL; } Status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, RestrictedSids, RetLen, &RetLen); if (NT_SUCCESS(Status)) { for (i = 0; i < RestrictedSids->GroupCount; i++) { SID* RSSid = RestrictedSids->Groups[i].Sid; if (RtlCompareMemory(&(RSSid->IdentifierAuthority), &InternetSiteAuthority, sizeof(SID_IDENTIFIER_AUTHORITY)) == sizeof(SID_IDENTIFIER_AUTHORITY)) { PSiteSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, RtlLengthSid((RestrictedSids-> Groups[i]).Sid)); if (PSiteSid == NULL) { SetLastError(ERROR_OUTOFMEMORY); } else { RtlCopySid(RtlLengthSid(RestrictedSids->Groups[i].Sid), PSiteSid, RestrictedSids->Groups[i].Sid); } break; } } } else { SetLastError(RtlNtStatusToDosError(Status)); } RtlFreeHeap(RtlGetProcessHeap(), 0, RestrictedSids); return PSiteSid; }
/* * @implemented */ BOOL WINAPI IsTokenRestricted(HANDLE TokenHandle) { ULONG RetLength; PTOKEN_GROUPS lpGroups; NTSTATUS Status; BOOL Ret = FALSE; /* determine the required buffer size and allocate enough memory to read the list of restricted SIDs */ Status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, NULL, 0, &RetLength); if (Status != STATUS_BUFFER_TOO_SMALL) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; } AllocAndReadRestrictedSids: lpGroups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), 0, RetLength); if (lpGroups == NULL) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } /* actually read the list of the restricted SIDs */ Status = NtQueryInformationToken(TokenHandle, TokenRestrictedSids, lpGroups, RetLength, &RetLength); if (NT_SUCCESS(Status)) { Ret = (lpGroups->GroupCount != 0); } else if (Status == STATUS_BUFFER_TOO_SMALL) { /* looks like the token was modified in the meanwhile, let's just try again */ HeapFree(GetProcessHeap(), 0, lpGroups); goto AllocAndReadRestrictedSids; } else { SetLastError(RtlNtStatusToDosError(Status)); } /* free allocated memory */ HeapFree(GetProcessHeap(), 0, lpGroups); return Ret; }
/****************************************************************************** * GetTokenInformation [ADVAPI32.@] * * PARAMS * token [] * tokeninfoclass [] * tokeninfo [] * tokeninfolength [] * retlen [] * */ BOOL WINAPI GetTokenInformation( HANDLE token, TOKEN_INFORMATION_CLASS tokeninfoclass, LPVOID tokeninfo, DWORD tokeninfolength, LPDWORD retlen ) { CallWin32ToNt (NtQueryInformationToken( token, tokeninfoclass, tokeninfo, tokeninfolength, retlen)); }
VOID DisplaySecurityContext( IN HANDLE TokenHandle ) { #define BUFFER_SIZE (2048) NTSTATUS Status; ULONG i; ULONG ReturnLength; TOKEN_STATISTICS ProcessTokenStatistics; GUID AuthenticationId; UCHAR Buffer[BUFFER_SIZE]; PTOKEN_USER UserId; PTOKEN_OWNER DefaultOwner; PTOKEN_PRIMARY_GROUP PrimaryGroup; PTOKEN_GROUPS GroupIds; PTOKEN_PRIVILEGES Privileges; ///////////////////////////////////////////////////////////////////////// // // // Logon ID // // // ///////////////////////////////////////////////////////////////////////// Status = NtQueryInformationToken( TokenHandle, // Handle TokenStatistics, // TokenInformationClass &ProcessTokenStatistics, // TokenInformation sizeof(TOKEN_STATISTICS), // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); AuthenticationId = ProcessTokenStatistics.AuthenticationId; printf(" Logon Session: "); if (RtlEqualGuid(&AuthenticationId, &SystemAuthenticationId )) { printf("(System Logon Session)\n"); } else { PrintGuid( &AuthenticationId ); } ///////////////////////////////////////////////////////////////////////// // // // User Id // // // ///////////////////////////////////////////////////////////////////////// UserId = (PTOKEN_USER)&Buffer[0]; Status = NtQueryInformationToken( TokenHandle, // Handle TokenUser, // TokenInformationClass UserId, // TokenInformation BUFFER_SIZE, // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); printf(" User id: "); DisplayAccountSid( (PISID)UserId->User.Sid ); ///////////////////////////////////////////////////////////////////////// // // // Default Owner // // // ///////////////////////////////////////////////////////////////////////// DefaultOwner = (PTOKEN_OWNER)&Buffer[0]; Status = NtQueryInformationToken( TokenHandle, // Handle TokenOwner, // TokenInformationClass DefaultOwner, // TokenInformation BUFFER_SIZE, // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); printf(" Default Owner: "); DisplayAccountSid( (PISID)DefaultOwner->Owner ); ///////////////////////////////////////////////////////////////////////// // // // Primary Group // // // ///////////////////////////////////////////////////////////////////////// PrimaryGroup = (PTOKEN_PRIMARY_GROUP)&Buffer[0]; Status = NtQueryInformationToken( TokenHandle, // Handle TokenPrimaryGroup, // TokenInformationClass PrimaryGroup, // TokenInformation BUFFER_SIZE, // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); printf(" Primary Group: "); DisplayAccountSid( (PISID)PrimaryGroup->PrimaryGroup ); ///////////////////////////////////////////////////////////////////////// // // // Group Ids // // // ///////////////////////////////////////////////////////////////////////// printf("\n"); GroupIds = (PTOKEN_GROUPS)&Buffer[0]; Status = NtQueryInformationToken( TokenHandle, // Handle TokenGroups, // TokenInformationClass GroupIds, // TokenInformation BUFFER_SIZE, // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); //printf(" Number of groups: %ld\n", GroupIds->GroupCount); printf(" Groups: "); for (i=0; i < GroupIds->GroupCount; i++ ) { //printf(" Group %ld: ", i); DisplayAccountSid( (PISID)GroupIds->Groups[i].Sid ); printf(" "); } ///////////////////////////////////////////////////////////////////////// // // // Privileges // // // ///////////////////////////////////////////////////////////////////////// printf("\n"); Privileges = (PTOKEN_PRIVILEGES)&Buffer[0]; Status = NtQueryInformationToken( TokenHandle, // Handle TokenPrivileges, // TokenInformationClass Privileges, // TokenInformation BUFFER_SIZE, // TokenInformationLength &ReturnLength // ReturnLength ); ASSERT(NT_SUCCESS(Status)); printf(" Privileges: "); if (Privileges->PrivilegeCount > 0) { for (i=0; i < Privileges->PrivilegeCount; i++ ) { DisplayPrivilege( &(Privileges->Privileges[i]) ); } } else { printf("(none assigned)\n"); } return; }
/*++ * @name CsrSetProcessSecurity * * The CsrSetProcessSecurity routine protects access to the CSRSS process * from unauthorized tampering. * * @param None. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks None. * *--*/ NTSTATUS NTAPI CsrSetProcessSecurity(VOID) { NTSTATUS Status; HANDLE hToken, hProcess = NtCurrentProcess(); ULONG Length; PTOKEN_USER TokenInfo = NULL; PSECURITY_DESCRIPTOR ProcSd = NULL; PACL Dacl; PSID UserSid; /* Open our token */ Status = NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken); if (!NT_SUCCESS(Status)) goto Quickie; /* Get the Token User Length */ NtQueryInformationToken(hToken, TokenUser, NULL, 0, &Length); /* Allocate space for it */ TokenInfo = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Length); if (!TokenInfo) { Status = STATUS_NO_MEMORY; goto Quickie; } /* Now query the data */ Status = NtQueryInformationToken(hToken, TokenUser, TokenInfo, Length, &Length); NtClose(hToken); if (!NT_SUCCESS(Status)) goto Quickie; /* Now check the SID Length */ UserSid = TokenInfo->User.Sid; Length = RtlLengthSid(UserSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); /* Allocate a buffer for the Security Descriptor, with SID and DACL */ ProcSd = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, SECURITY_DESCRIPTOR_MIN_LENGTH + Length); if (!ProcSd) { Status = STATUS_NO_MEMORY; goto Quickie; } /* Set the pointer to the DACL */ Dacl = (PACL)((ULONG_PTR)ProcSd + SECURITY_DESCRIPTOR_MIN_LENGTH); /* Now create the SD itself */ Status = RtlCreateSecurityDescriptor(ProcSd, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status); goto Quickie; } /* Create the DACL for it*/ Status = RtlCreateAcl(Dacl, Length, ACL_REVISION2); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status); goto Quickie; } /* Create the ACE */ Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | PROCESS_TERMINATE | PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION | READ_CONTROL, UserSid); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status); goto Quickie; } /* Clear the DACL in the SD */ Status = RtlSetDaclSecurityDescriptor(ProcSd, TRUE, Dacl, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status); goto Quickie; } /* Write the SD into the Process */ Status = NtSetSecurityObject(hProcess, DACL_SECURITY_INFORMATION, ProcSd); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status); goto Quickie; } /* Free the memory and return */ Quickie: if (ProcSd) RtlFreeHeap(CsrHeap, 0, ProcSd); RtlFreeHeap(CsrHeap, 0, TokenInfo); return Status; }
BOOL GetUserSidFromToken(HANDLE hToken, PSID *Sid) { PTOKEN_USER UserBuffer, nsb; PSID pSid = NULL; ULONG Length; NTSTATUS Status; Length = 256; UserBuffer = LocalAlloc(LPTR, Length); if (UserBuffer == NULL) { return FALSE; } Status = NtQueryInformationToken(hToken, TokenUser, (PVOID)UserBuffer, Length, &Length); if (Status == STATUS_BUFFER_TOO_SMALL) { nsb = LocalReAlloc(UserBuffer, Length, LMEM_MOVEABLE); if (nsb == NULL) { LocalFree(UserBuffer); return FALSE; } UserBuffer = nsb; Status = NtQueryInformationToken(hToken, TokenUser, (PVOID)UserBuffer, Length, &Length); } if (!NT_SUCCESS (Status)) { LocalFree(UserBuffer); return FALSE; } Length = RtlLengthSid(UserBuffer->User.Sid); pSid = LocalAlloc(LPTR, Length); if (pSid == NULL) { LocalFree(UserBuffer); return FALSE; } Status = RtlCopySid(Length, pSid, UserBuffer->User.Sid); LocalFree(UserBuffer); if (!NT_SUCCESS (Status)) { LocalFree(pSid); return FALSE; } *Sid = pSid; return TRUE; }
BOOLEAN OpenDotNetPublicControlBlock_V4( _In_ BOOLEAN IsImmersive, _In_ HANDLE ProcessHandle, _In_ HANDLE ProcessId, _Out_ HANDLE* BlockTableHandle, _Out_ PVOID* BlockTableAddress ) { BOOLEAN result = FALSE; PVOID boundaryDescriptorHandle = NULL; HANDLE privateNamespaceHandle = NULL; HANDLE blockTableHandle = NULL; HANDLE tokenHandle = NULL; PSID everyoneSIDHandle = NULL; PVOID blockTableAddress = NULL; LARGE_INTEGER sectionOffset = { 0 }; SIZE_T viewSize = 0; UNICODE_STRING prefixNameUs; UNICODE_STRING sectionNameUs; UNICODE_STRING boundaryNameUs; OBJECT_ATTRIBUTES namespaceObjectAttributes; OBJECT_ATTRIBUTES sectionObjectAttributes; PTOKEN_APPCONTAINER_INFORMATION appContainerInfo = NULL; SID_IDENTIFIER_AUTHORITY SIDWorldAuth = SECURITY_WORLD_SID_AUTHORITY; if (!PhStringRefToUnicodeString(&GenerateBoundaryDescriptorName(ProcessId)->sr, &boundaryNameUs)) goto CleanupExit; if (!(boundaryDescriptorHandle = RtlCreateBoundaryDescriptor(&boundaryNameUs, 0))) goto CleanupExit; if (!NT_SUCCESS(RtlAllocateAndInitializeSid(&SIDWorldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSIDHandle))) goto CleanupExit; if (!NT_SUCCESS(RtlAddSIDToBoundaryDescriptor(&boundaryDescriptorHandle, everyoneSIDHandle))) goto CleanupExit; if (WINDOWS_HAS_IMMERSIVE && IsImmersive) { if (NT_SUCCESS(NtOpenProcessToken(&tokenHandle, TOKEN_QUERY, ProcessHandle))) { ULONG returnLength = 0; if (NtQueryInformationToken( tokenHandle, TokenAppContainerSid, NULL, 0, &returnLength ) != STATUS_BUFFER_TOO_SMALL) { goto CleanupExit; } appContainerInfo = PhAllocate(returnLength); if (!NT_SUCCESS(NtQueryInformationToken( tokenHandle, TokenAppContainerSid, appContainerInfo, returnLength, &returnLength ))) { goto CleanupExit; } if (!NT_SUCCESS(RtlAddSIDToBoundaryDescriptor(&boundaryDescriptorHandle, appContainerInfo->TokenAppContainer))) goto CleanupExit; } } RtlInitUnicodeString(&prefixNameUs, CorSxSReaderPrivateNamespacePrefix); InitializeObjectAttributes( &namespaceObjectAttributes, &prefixNameUs, OBJ_CASE_INSENSITIVE, boundaryDescriptorHandle, NULL ); if (!NT_SUCCESS(NtOpenPrivateNamespace( &privateNamespaceHandle, MAXIMUM_ALLOWED, &namespaceObjectAttributes, boundaryDescriptorHandle ))) { goto CleanupExit; } RtlInitUnicodeString(§ionNameUs, CorSxSVistaPublicIPCBlock); InitializeObjectAttributes( §ionObjectAttributes, §ionNameUs, OBJ_CASE_INSENSITIVE, privateNamespaceHandle, NULL ); if (!NT_SUCCESS(NtOpenSection( &blockTableHandle, SECTION_MAP_READ, §ionObjectAttributes ))) { goto CleanupExit; } if (!NT_SUCCESS(NtMapViewOfSection( blockTableHandle, NtCurrentProcess(), &blockTableAddress, 0, viewSize, §ionOffset, &viewSize, ViewShare, 0, PAGE_READONLY ))) { goto CleanupExit; } *BlockTableHandle = blockTableHandle; *BlockTableAddress = blockTableAddress; result = TRUE; CleanupExit: if (!result) { if (blockTableHandle) { NtClose(blockTableHandle); } if (blockTableAddress) { NtUnmapViewOfSection(NtCurrentProcess(), blockTableAddress); } *BlockTableHandle = NULL; *BlockTableAddress = NULL; } if (tokenHandle) { NtClose(tokenHandle); } if (appContainerInfo) { PhFree(appContainerInfo); } if (privateNamespaceHandle) { NtClose(privateNamespaceHandle); } if (everyoneSIDHandle) { RtlFreeSid(everyoneSIDHandle); } if (boundaryDescriptorHandle) { RtlDeleteBoundaryDescriptor(boundaryDescriptorHandle); } return result; }
ULONG BaseSrvDebugProcess( IN OUT PCSR_API_MSG m, IN OUT PCSR_REPLY_STATUS ReplyStatus ) { NTSTATUS Status; PBASE_DEBUGPROCESS_MSG a = (PBASE_DEBUGPROCESS_MSG)&m->u.ApiMessageData; HANDLE Thread,ProcessHandle,Token; PCSR_PROCESS Process; DWORD ThreadId; PTOKEN_DEFAULT_DACL lpDefaultDacl; TOKEN_DEFAULT_DACL DefaultDacl; ULONG DaclLength; SECURITY_ATTRIBUTES ThreadAttributes; SECURITY_DESCRIPTOR SecurityDescriptor; UNICODE_STRING ModuleNameString_U; PVOID ModuleHandle; STRING ProcedureNameString; PCREATE_REMOTE_THREAD CreateRemoteThreadRoutine; if (a->dwProcessId == -1 && a->AttachCompleteRoutine == NULL) { HANDLE DebugPort; DebugPort = (HANDLE)NULL; Status = NtQueryInformationProcess( NtCurrentProcess(), ProcessDebugPort, (PVOID)&DebugPort, sizeof(DebugPort), NULL ); if ( NT_SUCCESS(Status) && DebugPort ) { return (ULONG)STATUS_ACCESS_DENIED; } return STATUS_SUCCESS; } #if DEVL if (a->dwProcessId != -1) { #endif // DEVL if ( a->AttachCompleteRoutine == NULL ) { Status = CsrLockProcessByClientId((HANDLE)a->dwProcessId,&Process); if ( NT_SUCCESS(Status) ) { ProcessHandle = Process->ProcessHandle; Status = NtOpenProcessToken(ProcessHandle, TOKEN_QUERY, &Token ); if ( !NT_SUCCESS(Status) ) { CsrUnlockProcess(Process); return Status; } lpDefaultDacl = &DefaultDacl; Status = NtQueryInformationToken(Token, TokenDefaultDacl, lpDefaultDacl, sizeof(DefaultDacl), &DaclLength ); if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) { Status = STATUS_ACCESS_DENIED; } else { Status = STATUS_SUCCESS; } if ( Process->DebugUserInterface.UniqueProcess || Process->DebugUserInterface.UniqueThread ) { Status = STATUS_ACCESS_DENIED; } NtClose(Token); CsrUnlockProcess(Process); } return (ULONG)Status; } // // Can't call base, but I know it is there // RtlInitUnicodeString( &ModuleNameString_U, L"kernel32" ); Status = LdrLoadDll( UNICODE_NULL, NULL, &ModuleNameString_U, &ModuleHandle ); if ( !NT_SUCCESS(Status) ) { return (ULONG)Status; } RtlInitString( &ProcedureNameString, "CreateRemoteThread" ); Status = LdrGetProcedureAddress( ModuleHandle, &ProcedureNameString, (ULONG) NULL, (PVOID *) &CreateRemoteThreadRoutine ); if ( !NT_SUCCESS(Status) ) { LdrUnloadDll( ModuleHandle ); return (ULONG)Status; } Status = CsrLockProcessByClientId((HANDLE)a->dwProcessId,&Process); if ( NT_SUCCESS(Status) ) { ProcessHandle = Process->ProcessHandle; Status = NtOpenProcessToken(ProcessHandle, TOKEN_QUERY, &Token ); if (!NT_SUCCESS(Status)) { CsrUnlockProcess(Process); LdrUnloadDll( ModuleHandle ); return (ULONG)Status; } lpDefaultDacl = &DefaultDacl; Status = NtQueryInformationToken(Token, TokenDefaultDacl, lpDefaultDacl, sizeof(DefaultDacl), &DaclLength ); if (!NT_SUCCESS(Status)) { lpDefaultDacl = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), DaclLength); if (lpDefaultDacl) { Status = NtQueryInformationToken(Token, TokenDefaultDacl, lpDefaultDacl, DaclLength, &DaclLength ); } else { Status = STATUS_NO_MEMORY; } NtClose(Token); if (!NT_SUCCESS(Status)) { CsrUnlockProcess(Process); LdrUnloadDll( ModuleHandle ); return (ULONG)Status; } } else { NtClose(Token); } ThreadAttributes.nLength = sizeof(ThreadAttributes); RtlCreateSecurityDescriptor(&SecurityDescriptor,SECURITY_DESCRIPTOR_REVISION1); ThreadAttributes.lpSecurityDescriptor = &SecurityDescriptor; SecurityDescriptor.Control = SE_DACL_PRESENT; SecurityDescriptor.Dacl = lpDefaultDacl->DefaultDacl; ThreadAttributes.bInheritHandle = FALSE; CsrUnlockProcess(Process); } #if DEVL } #endif // DEVL // // Set up the specified user-interface as the debugger of the // target process. Whip through the target process and // suspend all threads. Then Send CreateProcess, LoadModule, and // CreateThread Messages. Finally send the attach complete // exception. // Status = CsrDebugProcess( a->dwProcessId, &a->DebuggerClientId, (PCSR_ATTACH_COMPLETE_ROUTINE)a->AttachCompleteRoutine ); #if DEVL if (a->dwProcessId != -1) { #endif // DEVL if ( NT_SUCCESS(Status) ) { Thread = (PVOID)(CreateRemoteThreadRoutine)(ProcessHandle, &ThreadAttributes, 0L, (LPTHREAD_START_ROUTINE)a->AttachCompleteRoutine, 0, 0, &ThreadId ); LdrUnloadDll( ModuleHandle ); if ( lpDefaultDacl != &DefaultDacl ) { RtlFreeHeap(RtlProcessHeap(), 0,lpDefaultDacl); } if ( !Thread ) { return (ULONG)STATUS_UNSUCCESSFUL; } NtClose(Thread); } #if DEVL } #endif // DEVL return (ULONG) Status; }
/* * supUserIsFullAdmin * * Purpose: * * Tests if the current user is admin with full access token. * */ BOOL supUserIsFullAdmin( VOID ) { BOOL bResult = FALSE, cond = FALSE; HANDLE hToken = NULL; NTSTATUS status; DWORD i, Attributes; ULONG ReturnLength = 0; PTOKEN_GROUPS pTkGroups; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; PSID AdministratorsGroup = NULL; status = NtOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken); if (!NT_SUCCESS(status)) return bResult; do { if (!AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup)) break; status = NtQueryInformationToken(hToken, TokenGroups, NULL, 0, &ReturnLength); if (status != STATUS_BUFFER_TOO_SMALL) break; pTkGroups = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)ReturnLength); if (pTkGroups == NULL) break; status = NtQueryInformationToken(hToken, TokenGroups, pTkGroups, ReturnLength, &ReturnLength); if (NT_SUCCESS(status)) { if (pTkGroups->GroupCount > 0) for (i = 0; i < pTkGroups->GroupCount; i++) { Attributes = pTkGroups->Groups[i].Attributes; if (EqualSid(AdministratorsGroup, pTkGroups->Groups[i].Sid)) if ( (Attributes & SE_GROUP_ENABLED) && (!(Attributes & SE_GROUP_USE_FOR_DENY_ONLY)) ) { bResult = TRUE; break; } } } HeapFree(GetProcessHeap(), 0, pTkGroups); } while (cond); if (AdministratorsGroup != NULL) { FreeSid(AdministratorsGroup); } NtClose(hToken); return bResult; }
/*++ * @name CsrGetProcessLuid * @implemented NT4 * * The CsrGetProcessLuid routine gets the LUID of the given process. * * @param hProcess * Optional handle to the process whose LUID should be returned. * * @param Luid * Pointer to a LUID Pointer which will receive the CSR Process' LUID. * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks If hProcess is not supplied, then the current thread's token will * be used. If that too is missing, then the current process' token * will be used. * *--*/ NTSTATUS NTAPI CsrGetProcessLuid(IN HANDLE hProcess OPTIONAL, OUT PLUID Luid) { HANDLE hToken = NULL; NTSTATUS Status; ULONG Length; PTOKEN_STATISTICS TokenStats; /* Check if we have a handle to a CSR Process */ if (!hProcess) { /* We don't, so try opening the Thread's Token */ Status = NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, FALSE, &hToken); /* Check for success */ if (!NT_SUCCESS(Status)) { /* If we got some other failure, then return and quit */ if (Status != STATUS_NO_TOKEN) return Status; /* We don't have a Thread Token, use a Process Token */ hProcess = NtCurrentProcess(); hToken = NULL; } } /* Check if we have a token by now */ if (!hToken) { /* No token yet, so open the Process Token */ Status = NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken); if (!NT_SUCCESS(Status)) { /* Still no token, return the error */ return Status; } } /* Now get the size we'll need for the Token Information */ Status = NtQueryInformationToken(hToken, TokenStatistics, NULL, 0, &Length); /* Allocate memory for the Token Info */ if (!(TokenStats = RtlAllocateHeap(CsrHeap, 0, Length))) { /* Fail and close the token */ NtClose(hToken); return STATUS_NO_MEMORY; } /* Now query the information */ Status = NtQueryInformationToken(hToken, TokenStatistics, TokenStats, Length, &Length); /* Close the handle */ NtClose(hToken); /* Check for success */ if (NT_SUCCESS(Status)) { /* Return the LUID */ *Luid = TokenStats->AuthenticationId; } /* Free the query information */ RtlFreeHeap(CsrHeap, 0, TokenStats); /* Return the Status */ return Status; }
BOOL GetUserSidStringFromToken(HANDLE hToken, PUNICODE_STRING SidString) { PTOKEN_USER UserBuffer, nsb; ULONG Length; NTSTATUS Status; Length = 256; UserBuffer = LocalAlloc(LPTR, Length); if (UserBuffer == NULL) return FALSE; Status = NtQueryInformationToken(hToken, TokenUser, (PVOID)UserBuffer, Length, &Length); if (Status == STATUS_BUFFER_TOO_SMALL) { nsb = LocalReAlloc(UserBuffer, Length, LMEM_MOVEABLE); if (nsb == NULL) { LocalFree(UserBuffer); return FALSE; } UserBuffer = nsb; Status = NtQueryInformationToken(hToken, TokenUser, (PVOID)UserBuffer, Length, &Length); } if (!NT_SUCCESS (Status)) { LocalFree(UserBuffer); SetLastError(RtlNtStatusToDosError(Status)); return FALSE; } DPRINT("SidLength: %lu\n", RtlLengthSid (UserBuffer->User.Sid)); Status = RtlConvertSidToUnicodeString(SidString, UserBuffer->User.Sid, TRUE); LocalFree(UserBuffer); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; } DPRINT("SidString.Length: %lu\n", SidString->Length); DPRINT("SidString.MaximumLength: %lu\n", SidString->MaximumLength); DPRINT("SidString: '%wZ'\n", SidString); return TRUE; }
SECURITY_STATUS SspGetContextNames( IN PCheaterContext Context ) /*++ Routine Description: This routine obtains the names for a context by opening the token, getting the User ID, and calling LookupAccountNameW on the user id. Arguments: Context - Context to obtain names for Return Value: STATUS_SUCCESS - Call completed successfully SEC_E_INVALID_HANDLE -- Credential/Context Handle is invalid SEC_E_UNSUPPORTED_FUNCTION -- Function code is not supported --*/ { PTOKEN_USER TokenUserInfo = NULL; ULONG TokenUserSize = 0; NTSTATUS Status; WCHAR UserName[UNLEN+1]; ULONG UserNameLength = UNLEN+1; WCHAR DomainName[DNLEN+1]; ULONG DomainNameLength = DNLEN+1; SID_NAME_USE SidUse; LPWSTR ContextNames = NULL; ASSERT(Context->TokenHandle != NULL); // // Get the LogonId from the token. // Status = NtQueryInformationToken( Context->TokenHandle, TokenUser, TokenUserInfo, TokenUserSize, &TokenUserSize ); if ( Status != STATUS_BUFFER_TOO_SMALL ) { goto Cleanup; } TokenUserInfo = LocalAlloc( 0, TokenUserSize ); if ( TokenUserInfo == NULL ) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } Status = NtQueryInformationToken( Context->TokenHandle, TokenUser, TokenUserInfo, TokenUserSize, &TokenUserSize ); if ( !NT_SUCCESS(Status) ) { goto Cleanup; } // // Now that we have the user ID, calling LookupAccountName to translate // it to a SID. // if (!LookupAccountSidW( NULL, // local system TokenUserInfo->User.Sid, UserName, &UserNameLength, DomainName, &DomainNameLength, &SidUse )) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } // // We now have the use & domain name - put them in the context. // ContextNames = LocalAlloc(0, (wcslen(UserName) + wcslen(DomainName) + 2) * sizeof(WCHAR)); if (ContextNames == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } if (DomainName[0] != L'\0') { wcscpy(ContextNames, DomainName); wcscat(ContextNames, L"\\"); } wcscat(ContextNames, UserName); LocalFree(Context->ContextNames); Context->ContextNames = ContextNames; Status = STATUS_SUCCESS; Cleanup: if (TokenUserInfo != NULL) { LocalFree(TokenUserInfo); } return(Status); }
DWORD WINAPI PlayLogonSoundThread( IN LPVOID lpParameter) { BYTE TokenUserBuffer[256]; PTOKEN_USER pTokenUser = (TOKEN_USER*)TokenUserBuffer; ULONG Length; HKEY hKey; WCHAR wszBuffer[MAX_PATH] = {0}; WCHAR wszDest[MAX_PATH]; DWORD dwSize = sizeof(wszBuffer), dwType; SERVICE_STATUS_PROCESS Info; UNICODE_STRING SidString; NTSTATUS Status; ULONG Index = 0; SC_HANDLE hSCManager, hService; // // FIXME: Isn't it possible to *JUST* impersonate the current user // *AND* open its HKCU?? // /* Get SID of current user */ Status = NtQueryInformationToken((HANDLE)lpParameter, TokenUser, TokenUserBuffer, sizeof(TokenUserBuffer), &Length); if (!NT_SUCCESS(Status)) { ERR("NtQueryInformationToken failed: %x!\n", Status); return 0; } /* Convert SID to string */ RtlInitEmptyUnicodeString(&SidString, wszBuffer, sizeof(wszBuffer)); Status = RtlConvertSidToUnicodeString(&SidString, pTokenUser->User.Sid, FALSE); if (!NT_SUCCESS(Status)) { ERR("RtlConvertSidToUnicodeString failed: %x!\n", Status); return 0; } /* Build path to logon sound registry key. Note: We can't use HKCU here, because Winlogon is owned by SYSTEM user */ if (FAILED(StringCbCopyW(wszBuffer + SidString.Length/sizeof(WCHAR), sizeof(wszBuffer) - SidString.Length, L"\\AppEvents\\Schemes\\Apps\\.Default\\WindowsLogon\\.Current"))) { /* SID is too long. Should not happen. */ ERR("StringCbCopyW failed!\n"); return 0; } /* Open registry key and query sound path */ if (RegOpenKeyExW(HKEY_USERS, wszBuffer, 0, KEY_READ, &hKey) != ERROR_SUCCESS) { ERR("RegOpenKeyExW(%ls) failed!\n", wszBuffer); return 0; } if (RegQueryValueExW(hKey, NULL, NULL, &dwType, (LPBYTE)wszBuffer, &dwSize) != ERROR_SUCCESS || (dwType != REG_SZ && dwType != REG_EXPAND_SZ)) { ERR("RegQueryValueExW failed!\n"); RegCloseKey(hKey); return 0; } RegCloseKey(hKey); if (!wszBuffer[0]) { /* No sound has been set */ ERR("No sound has been set\n"); return 0; } /* Expand environment variables */ if (!ExpandEnvironmentStringsW(wszBuffer, wszDest, MAX_PATH)) { ERR("ExpandEnvironmentStringsW failed!\n"); return 0; } /* Open the service manager */ hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (!hSCManager) { ERR("OpenSCManager failed (%x)\n", GetLastError()); return 0; } /* Open the wdmaud service */ hService = OpenServiceW(hSCManager, L"wdmaud", GENERIC_READ); if (!hService) { /* The service is not installed */ TRACE("Failed to open wdmaud service (%x)\n", GetLastError()); CloseServiceHandle(hSCManager); return 0; } /* Wait for wdmaud to start */ do { if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&Info, sizeof(SERVICE_STATUS_PROCESS), &dwSize)) { TRACE("QueryServiceStatusEx failed (%x)\n", GetLastError()); break; } if (Info.dwCurrentState == SERVICE_RUNNING) break; Sleep(1000); } while (Index++ < 20); CloseServiceHandle(hService); CloseServiceHandle(hSCManager); /* If wdmaud is not running exit */ if (Info.dwCurrentState != SERVICE_RUNNING) { WARN("wdmaud has not started!\n"); return 0; } /* Sound subsystem is running. Play logon sound. */ TRACE("Playing logon sound: %ls\n", wszDest); PlaySoundRoutine(wszDest, TRUE, SND_FILENAME); return 0; }
NTSTATUS SspGetTokenUser( HANDLE Token, PTOKEN_USER * pTokenUser ) /*++ RoutineDescription: Gets the TOKEN_USER from an open token Arguments: Token - Handle to a token open for TOKEN_QUERY access Return Value: STATUS_INSUFFICIENT_RESOURCES - not enough memory to complete the function. Errors from NtQueryInformationToken. --*/ { PTOKEN_USER LocalTokenUser = NULL; NTSTATUS Status; ULONG TokenUserSize = 0; // // Query the token user. First pass in NULL to get back the // required size. // Status = NtQueryInformationToken( Token, TokenUser, NULL, 0, &TokenUserSize ); if (Status != STATUS_BUFFER_TOO_SMALL) { ASSERT(Status != STATUS_SUCCESS); return(Status); } // // Now allocate the required ammount of memory and try again. // LocalTokenUser = (PTOKEN_USER) LocalAlloc(0,TokenUserSize); if (LocalTokenUser == NULL) { return(STATUS_INSUFFICIENT_RESOURCES); } Status = NtQueryInformationToken( Token, TokenUser, LocalTokenUser, TokenUserSize, &TokenUserSize ); if (NT_SUCCESS(Status)) { *pTokenUser = LocalTokenUser; } else { LocalFree(LocalTokenUser); } return(Status); }
// Takes ownership on handle (file or registry key). // The handle must be open for WRITE_OWNER access static NTSTATUS NtTakeOwnershipObject(HANDLE ObjectHandle) { SECURITY_DESCRIPTOR sd; PTOKEN_USER pTokenUser = NULL; NTSTATUS Status; HANDLE TokenHandle = NULL; ULONG cbTokenUser = 0; // Open the token of the current process Status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &TokenHandle); if(NT_SUCCESS(Status)) { NtQueryInformationToken(TokenHandle, TokenUser, pTokenUser, cbTokenUser, &cbTokenUser); if(cbTokenUser == 0) { NtClose(TokenHandle); return STATUS_UNSUCCESSFUL; } pTokenUser = (PTOKEN_USER)RtlAllocateHeap(RtlProcessHeap(), 0, cbTokenUser); if(pTokenUser != NULL) { Status = NtQueryInformationToken(TokenHandle, TokenUser, pTokenUser, cbTokenUser, &cbTokenUser); } else { Status = STATUS_NO_MEMORY; } } // Initialize the blank security descriptor if(NT_SUCCESS(Status)) { Status = RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); } // Set the owner to the security descriptor if(NT_SUCCESS(Status)) { Status = RtlSetOwnerSecurityDescriptor(&sd, pTokenUser->User.Sid, FALSE); } // Apply the owner to the object handle if(NT_SUCCESS(Status)) { Status = NtSetSecurityObject(ObjectHandle, OWNER_SECURITY_INFORMATION, &sd); } // Free buffers if(pTokenUser != NULL) RtlFreeHeap(RtlProcessHeap(), 0, pTokenUser); if(TokenHandle != NULL) NtClose(TokenHandle); return Status; }
HANDLE InternalCreateCallbackThread( HANDLE hProcess, DWORD lpfn, DWORD dwData) { LONG BasePriority; HANDLE hThread, hToken; PTOKEN_DEFAULT_DACL lpDaclDefault; TOKEN_DEFAULT_DACL daclDefault; ULONG cbDacl; SECURITY_ATTRIBUTES attrThread; SECURITY_DESCRIPTOR sd; DWORD idThread; NTSTATUS Status; hThread = NULL; Status = NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken); if (!NT_SUCCESS(Status)) { KdPrint(("NtOpenProcessToken failed, status = %x\n", Status)); return NULL; } cbDacl = 0; NtQueryInformationToken(hToken, TokenDefaultDacl, &daclDefault, sizeof(daclDefault), &cbDacl); EnterCrit(); // to synchronize heap lpDaclDefault = (PTOKEN_DEFAULT_DACL)LocalAlloc(LMEM_FIXED, cbDacl); LeaveCrit(); if (lpDaclDefault == NULL) { KdPrint(("LocalAlloc failed for lpDaclDefault")); goto closeexit; } Status = NtQueryInformationToken(hToken, TokenDefaultDacl, lpDaclDefault, cbDacl, &cbDacl); if (!NT_SUCCESS(Status)) { KdPrint(("NtQueryInformationToken failed, status = %x\n", Status)); goto freeexit; } if (!NT_SUCCESS(RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION1))) { UserAssert(FALSE); goto freeexit; } RtlSetDaclSecurityDescriptor(&sd, TRUE, lpDaclDefault->DefaultDacl, TRUE); attrThread.nLength = sizeof(attrThread); attrThread.lpSecurityDescriptor = &sd; attrThread.bInheritHandle = FALSE; GetLastError(); hThread = CreateRemoteThread(hProcess, &attrThread, 0L, (LPTHREAD_START_ROUTINE)lpfn, (LPVOID)dwData, 0, &idThread); if (hThread != NULL) { BasePriority = THREAD_PRIORITY_HIGHEST; NtSetInformationThread(hThread, ThreadBasePriority, &BasePriority, sizeof(LONG)); } freeexit: EnterCrit(); // to synchronize heap LocalFree((HANDLE)lpDaclDefault); LeaveCrit(); closeexit: NtClose(hToken); return hThread; }