NTSTATUS NTAPI SmpTerminate(IN PULONG_PTR Parameters, IN ULONG ParameterMask, IN ULONG ParameterCount) { NTSTATUS Status; BOOLEAN Old; ULONG Response; /* Give the shutdown privilege to the thread */ if (RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, TRUE, &Old) == STATUS_NO_TOKEN) { /* Thread doesn't have a token, give it to the entire process */ RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old); } /* Take down the process/machine with a hard error */ Status = NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, ParameterCount, ParameterMask, Parameters, OptionShutdownSystem, &Response); /* Terminate the process if the hard error didn't already */ return NtTerminateProcess(NtCurrentProcess(), Status); }
static DWORD ScmUnloadDriver(PSERVICE lpService) { NTSTATUS Status = STATUS_SUCCESS; BOOLEAN WasPrivilegeEnabled = FALSE; PWSTR pszDriverPath; UNICODE_STRING DriverPath; DWORD dwError; /* Build the driver path */ /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */ pszDriverPath = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (52 + wcslen(lpService->lpServiceName) + 1) * sizeof(WCHAR)); if (pszDriverPath == NULL) return ERROR_NOT_ENOUGH_MEMORY; wcscpy(pszDriverPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); wcscat(pszDriverPath, lpService->lpServiceName); RtlInitUnicodeString(&DriverPath, pszDriverPath); DPRINT(" Path: %wZ\n", &DriverPath); /* Acquire driver-unloading privilege */ Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, TRUE, FALSE, &WasPrivilegeEnabled); if (!NT_SUCCESS(Status)) { /* We encountered a failure, exit properly */ DPRINT1("SERVICES: Cannot acquire driver-unloading privilege, Status = 0x%08lx\n", Status); dwError = RtlNtStatusToDosError(Status); goto done; } Status = NtUnloadDriver(&DriverPath); if (Status == STATUS_INVALID_DEVICE_REQUEST) dwError = ERROR_INVALID_SERVICE_CONTROL; else dwError = RtlNtStatusToDosError(Status); /* Release driver-unloading privilege */ RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, WasPrivilegeEnabled, FALSE, &WasPrivilegeEnabled); done: HeapFree(GetProcessHeap(), 0, pszDriverPath); return dwError; }
/* Code taken and adapted from base/system/services/driver.c */ static DWORD ScmLoadDriver(LPCWSTR lpServiceName) { NTSTATUS Status = STATUS_SUCCESS; BOOLEAN WasPrivilegeEnabled = FALSE; PWSTR pszDriverPath; UNICODE_STRING DriverPath; /* Build the driver path */ /* 52 = wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */ pszDriverPath = ConsoleAllocHeap(HEAP_ZERO_MEMORY, (52 + wcslen(lpServiceName) + 1) * sizeof(WCHAR)); if (pszDriverPath == NULL) return ERROR_NOT_ENOUGH_MEMORY; wcscpy(pszDriverPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); wcscat(pszDriverPath, lpServiceName); RtlInitUnicodeString(&DriverPath, pszDriverPath); DPRINT(" Path: %wZ\n", &DriverPath); /* Acquire driver-loading privilege */ Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, TRUE, FALSE, &WasPrivilegeEnabled); if (!NT_SUCCESS(Status)) { /* We encountered a failure, exit properly */ DPRINT1("CONSRV: Cannot acquire driver-loading privilege, Status = 0x%08lx\n", Status); goto done; } Status = NtLoadDriver(&DriverPath); /* Release driver-loading privilege */ RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, WasPrivilegeEnabled, FALSE, &WasPrivilegeEnabled); done: ConsoleFreeHeap(pszDriverPath); return RtlNtStatusToDosError(Status); }
static BOOL StartUserShell( IN OUT PWLSESSION Session) { LPVOID lpEnvironment = NULL; BOOLEAN Old; BOOL ret; /* Create environment block for the user */ if (!CreateEnvironmentBlock(&lpEnvironment, Session->UserToken, TRUE)) { WARN("WL: CreateEnvironmentBlock() failed\n"); return FALSE; } /* Get privilege */ /* FIXME: who should do it? winlogon or gina? */ /* FIXME: reverting to lower privileges after creating user shell? */ RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &Old); ret = Session->Gina.Functions.WlxActivateUserShell( Session->Gina.Context, L"Default", NULL, /* FIXME */ lpEnvironment); DestroyEnvironmentBlock(lpEnvironment); return ret; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Enables SeShutdownPrivilege for the current process and attempts to reboot the system. // VOID Reboot(VOID) { BOOL OldValue; if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, (PBOOLEAN)&OldValue))) ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0); }
NTSTATUS kuhl_m_privilege_simple(ULONG privId) { ULONG previousState; NTSTATUS status; status = RtlAdjustPrivilege(privId, TRUE, FALSE, &previousState); if(NT_SUCCESS(status)) kprintf(L"Privilege \'%u\' OK\n", privId); else PRINT_ERROR(L"RtlAdjustPrivilege (%u) %08x\n", privId, status); return status; }
/** * @brief Enables a user privilege for the current process. * @param[in] luid the identifier of the requested privilege, * ntndk.h file contains definitions of various privileges. * @return Zero for success, negative value otherwise. * @par Example: * @code * winx_enable_privilege(SE_SHUTDOWN_PRIVILEGE); * @endcode */ int winx_enable_privilege(unsigned long luid) { NTSTATUS status; SIZE_T WasEnabled; /* boolean value receiving the previous state */ status = RtlAdjustPrivilege((SIZE_T)luid, TRUE, FALSE, &WasEnabled); if(!NT_SUCCESS(status)){ strace(status,"cannot enable privilege %x",(UINT)luid); return (-1); } return 0; }
/* * SfuElevatePriv * * Purpose: * * Attempt to elevate current thread privileges by impersonating lsass thread token and adding privilegs next. * */ BOOL SfuElevatePriv( VOID ) { BOOLEAN WasEnabled; BOOL cond = FALSE, bResult = FALSE; NTSTATUS status; PSYSTEM_PROCESSES_INFORMATION ProcessList = NULL, pList; UNICODE_STRING uLookupProcess; ULONG i; do { status = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &WasEnabled); if (!NT_SUCCESS(status)) break; ProcessList = SfuGetSystemInfo(SystemProcessInformation); if (ProcessList == NULL) break; RtlInitUnicodeString(&uLookupProcess, L"lsass.exe"); pList = ProcessList; for (;;) { if (RtlEqualUnicodeString(&uLookupProcess, &pList->ImageName, TRUE)) { for (i = 0; i < pList->ThreadCount; i++) { bResult = SfuAdjustCurrentThreadPriv(&pList->Threads[i].ClientId); if (bResult) break; } break; } if (pList->NextEntryDelta == 0) { break; } pList = (PSYSTEM_PROCESSES_INFORMATION)(((LPBYTE)pList) + pList->NextEntryDelta); } } while (cond); if (ProcessList != NULL) RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, ProcessList); return bResult; }
/*++ * @name CsrSetToShutdownPriority * * The CsrSetToShutdownPriority routine sets the current NT Process' * priority to the boosted priority for CSR Processes doing shutdown. * Additonally, it acquires the Shutdown Privilege required for shutdown. * * @param None. * * @return None. * * @remarks The "Shutdown" Priority corresponds to the Normal Foreground * Priority (9) plus a boost of 6. * *--*/ VOID NTAPI CsrSetToShutdownPriority(VOID) { KPRIORITY BasePriority = (8 + 1) + 6; BOOLEAN Old; /* Get the shutdown privilege */ if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old))) { /* Set the Priority */ NtSetInformationProcess(NtCurrentProcess(), ProcessBasePriority, &BasePriority, sizeof(BasePriority)); } }
ForceInline Void main2(Int argc, WChar **argv) { NTSTATUS Status; WCHAR *pExePath, szDllPath[MAX_NTPATH], FullExePath[MAX_NTPATH]; STARTUPINFOW si; PROCESS_INFORMATION pi; if (argc == 1) return; RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, (PBOOLEAN)&Status); while (--argc) { pExePath = findextw(*++argv); if (CHAR_UPPER4W(*(PULONG64)pExePath) == CHAR_UPPER4W(TAG4W('.LNK'))) { if (FAILED(GetPathFromLinkFile(*argv, FullExePath, countof(FullExePath)))) { pExePath = *argv; } else { pExePath = FullExePath; } } else { pExePath = *argv; } RtlGetFullPathName_U(pExePath, sizeof(szDllPath), szDllPath, NULL); rmnamew(szDllPath); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); Status = CreateProcessInternalW( NULL, pExePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, *szDllPath == 0 ? NULL : szDllPath, &si, &pi, NULL); if (!Status) { PrintConsoleW(L"CreateProcess() failed.\n"); continue; } Status = InjectSelfToRemoteProcess(pi.hProcess, pi.hThread); if (!NT_SUCCESS(Status)) { // PrintError(GetLastError()); NtTerminateProcess(pi.hProcess, 0); } NtClose(pi.hProcess); NtClose(pi.hThread); } }
BOOL ApplyGlobalFlagChanges( BOOL fInit, HWND hDlg ) { BOOLEAN Enabled; NTSTATUS Status; SYSTEM_FLAGS_INFORMATION SystemInformation; int iBit; if (fInit) { Status = NtQuerySystemInformation(SystemFlagsInformation, &SystemInformation, sizeof(SystemInformation), NULL); if (!NT_SUCCESS(Status)) { CHAR Buffer[128]; sprintf(Buffer, "NtQuerySystemInformation failed (%08lx)\n", Status); MessageBox(NULL,Buffer,TEXT("Horrible Disaster"),MB_OK); ExitProcess(0); } else { for (iBit = 0; iBit < 32; iBit++) { CheckDlgButton(hDlg, GLOBAL_FLAG_ID + iBit, (SystemInformation.Flags & (1 << iBit))); } } } else { SystemInformation.Flags = 0; for (iBit = 0; iBit < 32; iBit++) { if (IsDlgButtonChecked(hDlg, GLOBAL_FLAG_ID + iBit)) { SystemInformation.Flags |= (1 << iBit); } } // // Attempt to enable the load driver privilege to // allow setting the DPC behavior. // RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &Enabled); Status = NtSetSystemInformation(SystemFlagsInformation, &SystemInformation, sizeof(SystemInformation)); RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, Enabled, FALSE, &Enabled); if (!NT_SUCCESS(Status)) { CHAR Buffer[128]; sprintf(Buffer, "SetSystemInformationFailed (%08lx)\nYou probably do not have debug privileges", Status); MessageBox(NULL,Buffer,TEXT("Oops"),MB_OK); } if (GlobalFlagUpdateRegistry.NewValue) { HKEY Key; LONG Result; DWORD Disposition; // // Update the Value in the registry // if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager"), 0L, NULL, 0L, KEY_SET_VALUE, NULL, &Key, &Disposition) != ERROR_SUCCESS) { CHAR Buffer[128]; sprintf(Buffer, "RegCreateKey for NtGlobalFlag failed (%d)\nYou probably are Not Authorized.", GetLastError()); MessageBox(NULL,Buffer,TEXT("Oops"),MB_OK); return(TRUE); } RegSetValueEx(Key, "GlobalFlag", 0, REG_DWORD, (LPBYTE)&SystemInformation.Flags, sizeof(SystemInformation.Flags)); SendMessage(GetParent(hDlg), PSM_REBOOTSYSTEM, 0, 0); } } return(TRUE); }
NTSTATUS HandleShutdown( IN OUT PWLSESSION Session, IN DWORD wlxAction) { PLOGOFF_SHUTDOWN_DATA LSData; HANDLE hThread; DWORD exitCode; BOOLEAN Old; // SwitchDesktop(Session->WinlogonDesktop); DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_REACTOSISSHUTTINGDOWN); /* Prepare data for shutdown thread */ LSData = HeapAlloc(GetProcessHeap(), 0, sizeof(LOGOFF_SHUTDOWN_DATA)); if (!LSData) { ERR("Failed to allocate mem for thread data\n"); return STATUS_NO_MEMORY; } if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_POWER_OFF) LSData->Flags = EWX_POWEROFF; else if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT) LSData->Flags = EWX_REBOOT; else LSData->Flags = EWX_SHUTDOWN; LSData->Session = Session; // FIXME: We may need to specify this flag to really force application kill // (we are shutting down ReactOS, not just logging off so no hangs, etc... // should be allowed). // LSData->Flags |= EWX_FORCE; /* Run shutdown thread */ hThread = CreateThread(NULL, 0, LogoffShutdownThread, (LPVOID)LSData, 0, NULL); if (!hThread) { ERR("Unable to create shutdown thread, error %lu\n", GetLastError()); HeapFree(GetProcessHeap(), 0, LSData); return STATUS_UNSUCCESSFUL; } WaitForSingleObject(hThread, INFINITE); HeapFree(GetProcessHeap(), 0, LSData); if (!GetExitCodeThread(hThread, &exitCode)) { ERR("Unable to get exit code of shutdown thread (error %lu)\n", GetLastError()); CloseHandle(hThread); return STATUS_UNSUCCESSFUL; } CloseHandle(hThread); if (exitCode == 0) { ERR("Shutdown thread returned failure\n"); return STATUS_UNSUCCESSFUL; } CallNotificationDlls(Session, ShutdownHandler); /* Destroy SAS window */ UninitializeSAS(Session); /* Now we can shut down NT */ ERR("Shutting down NT...\n"); RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old); if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT) { NtShutdownSystem(ShutdownReboot); } else { if (FALSE) { /* FIXME - only show this dialog if it's a shutdown and the computer doesn't support APM */ DialogBox(hAppInstance, MAKEINTRESOURCE(IDD_SHUTDOWNCOMPUTER), GetDesktopWindow(), ShutdownComputerWindowProc); } NtShutdownSystem(ShutdownNoReboot); } RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, Old, FALSE, &Old); return STATUS_SUCCESS; }
ForceInline VOID main2(Int argc, WChar **argv) { NTSTATUS Status; WCHAR *pExePath, szDllPath[MAX_NTPATH], FullExePath[MAX_NTPATH]; STARTUPINFOW si; PROCESS_INFORMATION pi; #if 0 PVOID buf; // CNtFileDisk file; UNICODE_STRING str; // file.Open((FIELD_BASE(FindLdrModuleByName(NULL)->InLoadOrderModuleList.Flink, LDR_MODULE, InLoadOrderModuleList))->FullDllName.Buffer); // buf = AllocateMemory(file.GetSize32()); // file.Read(buf); // file.Close(); RTL_CONST_STRING(str, L"OllyDbg.exe"); LoadDllFromMemory(GetNtdllHandle(), -1, &str, NULL, LMD_MAPPED_DLL); PrintConsoleW( L"%s handle = %08X\n" L"%s.NtSetEvent = %08X\n", str.Buffer, GetModuleHandleW(str.Buffer), str.Buffer, Nt_GetProcAddress(GetModuleHandleW(str.Buffer), "NtSetEvent") ); getch(); FreeMemory(buf); return; #endif #if 1 if (argc == 1) return; RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, (PBOOLEAN)&Status); while (--argc) { pExePath = findextw(*++argv); if (CHAR_UPPER4W(*(PULONG64)pExePath) == CHAR_UPPER4W(TAG4W('.LNK'))) { if (FAILED(GetPathFromLinkFile(*argv, FullExePath, countof(FullExePath)))) { pExePath = *argv; } else { pExePath = FullExePath; } } else { pExePath = *argv; } RtlGetFullPathName_U(pExePath, sizeof(szDllPath), szDllPath, NULL); #if 0 Status = FakeCreateProcess(szDllPath, NULL); if (!NT_SUCCESS(Status)) #else rmnamew(szDllPath); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); Status = CreateProcessInternalW( NULL, pExePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, *szDllPath == 0 ? NULL : szDllPath, &si, &pi, NULL); if (!Status) #endif { PrintConsoleW(L"%s: CreateProcess() failed\n", pExePath); continue; } ULONG Length; UNICODE_STRING DllFullPath; Length = Nt_GetExeDirectory(szDllPath, countof(szDllPath)); CopyStruct(szDllPath + Length, L"XP3Viewer.dll", sizeof(L"XP3Viewer.dll")); DllFullPath.Buffer = szDllPath; DllFullPath.Length = (USHORT)(Length + CONST_STRLEN(L"XP3Viewer.dll")); DllFullPath.Length *= sizeof(WCHAR); DllFullPath.MaximumLength = DllFullPath.Length; Status = InjectDllToRemoteProcess(pi.hProcess, pi.hThread, &DllFullPath, FALSE); if (!NT_SUCCESS(Status)) { // PrintError(GetLastError()); NtTerminateProcess(pi.hProcess, 0); } NtClose(pi.hProcess); NtClose(pi.hThread); } #endif }
BOOL ApplyDpcChanges( BOOL fInit, HWND hDlg ) { SYSTEM_DPC_BEHAVIOR_INFORMATION DpcBehavior; BOOLEAN Enabled; NTSTATUS Status; if (fInit) { Status = NtQuerySystemInformation(SystemDpcBehaviorInformation, &DpcBehavior, sizeof(DpcBehavior), NULL); if (!NT_SUCCESS(Status)) { CHAR Buffer[128]; sprintf(Buffer, "NtQuerySystemInformation failed (%08lx)\n" "You probably need a newer build.\n" "Use information from the registry?", Status); if (MessageBox(NULL,Buffer,TEXT("Horrible Disaster"),MB_YESNO) == IDYES) { return(FALSE); } else { ExitProcess(0); } } else { MaximumDpcQueueDepth.CurrentValue = DpcBehavior.DpcQueueDepth; MinimumDpcRate.CurrentValue = DpcBehavior.MinimumDpcRate; AdjustDpcThreshold.CurrentValue = DpcBehavior.AdjustDpcThreshold; IdealDpcRate.CurrentValue = DpcBehavior.IdealDpcRate; } } else { DpcBehavior.DpcQueueDepth = MaximumDpcQueueDepth.NewValue; DpcBehavior.MinimumDpcRate = MinimumDpcRate.NewValue; DpcBehavior.AdjustDpcThreshold = AdjustDpcThreshold.NewValue; DpcBehavior.IdealDpcRate = IdealDpcRate.NewValue; // // Attempt to enable the load driver privilege to // allow setting the DPC behavior. // RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, TRUE, FALSE, &Enabled); Status = NtSetSystemInformation(SystemDpcBehaviorInformation, &DpcBehavior, sizeof(DpcBehavior)); RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, Enabled, FALSE, &Enabled); if (!NT_SUCCESS(Status)) { CHAR Buffer[128]; sprintf(Buffer, "NtSetSystemInformation failed, status %08lx", Status); MessageBox(NULL,Buffer,TEXT("Oops"),MB_OK); return(FALSE); } if (DpcUpdateRegistry.NewValue) { // // Let the common routine update the values in the registry // return(FALSE); } } return(TRUE); }
NTSTATUS LsapAdtInitializeCrashOnFail( VOID ) /*++ Routine Description: Reads the registry to see if the user has told us to crash if an audit fails. Arguments: None. Return Value: STATUS_SUCCESS --*/ { HANDLE KeyHandle; NTSTATUS Status; NTSTATUS TmpStatus; OBJECT_ATTRIBUTES Obja; ULONG ResultLength; UNICODE_STRING KeyName; UNICODE_STRING ValueName; CHAR KeyInfo[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(BOOLEAN)]; PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo; // // Check the value of the CrashOnAudit key. // RtlInitUnicodeString( &KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Lsa"); InitializeObjectAttributes( &Obja, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtOpenKey( &KeyHandle, KEY_QUERY_VALUE | KEY_SET_VALUE, &Obja ); if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { LsapCrashOnAuditFail = FALSE; return( STATUS_SUCCESS ); } RtlInitUnicodeString( &ValueName, CRASH_ON_AUDIT_FAIL_VALUE ); Status = NtQueryValueKey( KeyHandle, &ValueName, KeyValuePartialInformation, KeyInfo, sizeof(KeyInfo), &ResultLength ); TmpStatus = NtClose(KeyHandle); ASSERT(NT_SUCCESS(TmpStatus)); // // If it's not found, don't enable CrashOnFail. // if (!NT_SUCCESS( Status )) { LsapCrashOnAuditFail = FALSE; } else { // // Check the value of the CrashOnFail value. If it is 1, we // crash on audit fail. If it is two, we only allow admins to // logon. // pKeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo; if (*(pKeyInfo->Data) == LSAP_CRASH_ON_AUDIT_FAIL) { LsapCrashOnAuditFail = TRUE; } else if (*(pKeyInfo->Data) == LSAP_ALLOW_ADIMIN_LOGONS_ONLY) { LsapAllowAdminLogonsOnly = TRUE; } } if ( LsapCrashOnAuditFail ) { BOOLEAN WasEnabled; Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &WasEnabled ); // // This had better work. // ASSERT(NT_SUCCESS(Status)); return( Status ); } return( STATUS_SUCCESS ); }
//-------------------------------------------------------------------------- // Read/write a model specific register using the driver provided by WinDbg. // The following requirements are imposed by this code: // - debugger module should be run with admin privileges // - System must be loaded with /debug switch (use bcdedit.exe to turn it on) // - Windbg local kernel debugging should be used at least once // This code is based on a sample kindly provided by Alex Ionescu. int win32_debmod_t::kldbgdrv_access_msr(SYSDBG_MSR *msr, bool write) { NTSTATUS code; IO_STATUS_BLOCK IoStatusBlock; if ( DriverHandle == NULL ) { // // Acquire 'load driver' privilege // BOOLEAN Old; code = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, TRUE, FALSE, &Old); if ( FAILED(code) ) { dwarning("AUTOHIDE NONE\n" "Failed to acquire 'load driver' privilege, please run as admin!\n" "Error: %s\n", winerr(code)); return code; } // // And need this for the driver to accept our commands // Additionally, system must be booted in /DEBUG mode // code = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &Old); if ( FAILED(code) ) { dwarning("AUTOHIDE NONE\n" "Failed to acquire 'debug' privilege, is system booted in /debug mode?\n" "Error: %s\n", winerr(code)); return code; } // // Now load the driver // code = NtLoadDriver(&DriverPath); if ( FAILED(code) && code != STATUS_IMAGE_ALREADY_LOADED ) { dwarning("AUTOHIDE NONE\n" "Failed to load 'kldbgdrv', please use local kernel debugging at least once!\n" "Error: %s\n", winerr(code)); return code; } // // Open a handle to it // OBJECT_ATTRIBUTES ObjectAttributes; InitializeObjectAttributes(&ObjectAttributes, &DriverName, OBJ_CASE_INSENSITIVE, NULL, NULL); code = NtCreateFile(&DriverHandle, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_CREATE, FILE_NON_DIRECTORY_FILE, NULL, 0); if ( FAILED(code) ) { dwarning("AUTOHIDE NONE\n" "Failed to open 'kldbgdrv'\n" "Error: %s\n", winerr(code)); return code; } } // // Package the input parameters into the private structure // KLDD_DATA_DEBUG_CONTROL KldDebugCommand; KldDebugCommand.Command = write ? SysDbgWriteMsr : SysDbgReadMsr; KldDebugCommand.InputBuffer = msr; KldDebugCommand.InputBufferLength = sizeof(*msr); // // Send the request -- output isn't packaged, just specify directly the buffer // code = NtDeviceIoControlFile(DriverHandle, NULL, NULL, NULL, &IoStatusBlock, KLDD_CODE_DEBUG_CONTROL, &KldDebugCommand, sizeof(KldDebugCommand), msr, sizeof(*msr)); if ( FAILED(code) ) { dwarning("AUTOHIDE NONE\n" "Failed to access model specific register, is system booted in /debug mode?\n" "Error: %s\n", winerr(code)); return code; } // all ok! return code; }
NTSTATUS openProcByName(PHANDLE pProcess, PUNICODE_STRING pProcName, BOOLEAN useDebugPrivilege) { SYSTEM_PROCESS_INFORMATION procInfo; OBJECT_ATTRIBUTES procAttr; OBJECT_BASIC_INFORMATION processHandleInfo; CLIENT_ID cid; BOOLEAN oldValue; HANDLE pid; NTSTATUS status = STATUS_CACHE_PAGE_LOCKED; ULONG procListSize = 0; ULONGLONG memSize = 0; ULONG obQueryLen = 0; PVOID pProcListHead = NULL; PSYSTEM_PROCESS_INFORMATION pProcEntry = NULL; do { if (!pProcName || !pProcess) { status = STATUS_INVALID_PARAMETER; break; } *pProcess = NULL; ///Since we specify a buffer size of 0 the buffer must overflow for sure even if there was running a ///single process only. If we don't receive the dedicated error, something other has gone wrong ///and we cannot rely on the return length. status = NtQuerySystemInformation(SystemProcessInformation, &procInfo, procListSize, &procListSize); if (STATUS_INFO_LENGTH_MISMATCH != status) break; memSize = PAGE_ROUND_UP(procListSize) + PAGE_SIZE; ///We better allocate one page extra ///since between our "test" call and the real call below ///additional processes might be started. (race condition) status = NtAllocateVirtualMemory(INVALID_HANDLE_VALUE, &pProcListHead, 0, &memSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (status) { pProcListHead = NULL; break; } ///By now, we have allocated a buffer large enough for the complete process list, ///even if some new processes have been started in the mean time. ///Hence, the next call is entirely expected to succeed. procListSize = (ULONG)memSize; status = NtQuerySystemInformation(SystemProcessInformation, pProcListHead, procListSize, &procListSize); if (status) break; pid = NULL; pProcEntry = pProcListHead; ///The list of all system processes is a so called singly linked list. while (pProcEntry->NextEntryOffset) { ///If NextEntryOffset member is NULL, we have reached the list end (tail). pProcEntry = (PSYSTEM_PROCESS_INFORMATION)((PUCHAR)pProcEntry + pProcEntry->NextEntryOffset); //DebugPrint2A("PID: %d, %wZ", pProcEntry->UniqueProcessId, pProcEntry->ImageName); if (0 == RtlCompareUnicodeString(pProcName, &pProcEntry->ImageName, TRUE)) { pid = pProcEntry->UniqueProcessId; break; } } if (!pid) { status = STATUS_OBJECT_NAME_NOT_FOUND; break; } if (useDebugPrivilege) { status = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &oldValue); if (status){ ///Since we're for some reason supposed to use the SeDebugPrivilege, useDebugPrivilege = FALSE; break; ///we fail deliberately if we can't enable it. } } InitializeObjectAttributes(&procAttr, NULL, 0, NULL, NULL); cid.UniqueThread = (HANDLE)0; cid.UniqueProcess = pid; ///Opening a process for full access might be less suspicious than opening with our real intentions. status = NtOpenProcess(pProcess, PROCESS_ALL_ACCESS, &procAttr, &cid); if (status) { ///Most likely STATUS_ACCESS_DENIED if ///either we didn't specify the useDebugPrivilege flag when opening a cross session process ///or if we tried to open an elevated process while running non-elevated ///or if the process being opened is a so-called "Protected Process". ///In x64 windows, HIPS or AV drivers have the possibility to legally ///receive a notification if a process is about to open a handle to another process. ///In those ObCallback routines they cannot completely deny the opening. ///However, they are able to modify the access masks, so a handle supposed for VM operations still ///will be lacking the PROCESS_VM_XXX rights, for example. If we therefore query the handle rights ///we can still return an appropriate error if wasn't granted the rights we want ///And are not going to fail at first when performing our process operations. *pProcess = NULL; break; } status = NtQueryObject(*pProcess, ObjectBasicInformation, &processHandleInfo, sizeof(OBJECT_BASIC_INFORMATION), &obQueryLen); if (status) ///Not sure if this call ever will fail... break; ///Maybe, HIPS just wanted to deny PROCESS_TERMINATE/PROCESS_SUSPEND right? ///If so, we don't care. We're only interested in VM rights. if (MIN_VM_ACCESS_MASK & ~processHandleInfo.GrantedAccess) { status = STATUS_UNSUCCESSFUL; break; } } while (status); if (status && pProcess) { if (*pProcess) { NtClose(*pProcess); *pProcess = NULL; } } if (pProcListHead) { memSize = 0; NtFreeVirtualMemory(INVALID_HANDLE_VALUE, &pProcListHead, &memSize, MEM_RELEASE); ///We don't need the list anymore. } if (useDebugPrivilege) RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, oldValue, FALSE, &oldValue); ///We don't need the privilege anymore. return status; }
BOOL GetPrivilege(ULONG Priviliage) { BOOL bRet = FALSE; NTSTATUS St; BOOLEAN bEnable; bRet = NT_SUCCESS(RtlAdjustPrivilege(Priviliage,TRUE,FALSE,&bEnable)) || NT_SUCCESS(RtlAdjustPrivilege(Priviliage,TRUE,TRUE,&bEnable)); if (!bRet) { PSYSTEM_PROCESSES_INFORMATION Processes = (PSYSTEM_PROCESSES_INFORMATION)GetSystemInformation(SystemProcessInformation); if (Processes) { UNICODE_STRING ProcessName = RTL_CONSTANT_STRING(L"services.exe"); for (PSYSTEM_PROCESSES_INFORMATION Proc=Processes; ; *(ULONG*)&Proc += Proc->NextEntryDelta) { if (RtlEqualUnicodeString(&Proc->ProcessName,&ProcessName,TRUE)) { HANDLE hThread; OBJECT_ATTRIBUTES ObjAttr; InitializeObjectAttributes(&ObjAttr,NULL,0,0,0); St = NtOpenThread(&hThread,THREAD_DIRECT_IMPERSONATION,&ObjAttr,&Proc->Threads[0].ClientId); if (NT_SUCCESS(St)) { SECURITY_QUALITY_OF_SERVICE SecurityQos = {0}; SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); SecurityQos.ImpersonationLevel = SecurityImpersonation; SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; St = NtImpersonateThread(NtCurrentThread(),hThread,&SecurityQos); if (NT_SUCCESS(St)) { St = RtlAdjustPrivilege(Priviliage,TRUE,TRUE,&bEnable); bRet = NT_SUCCESS(St); if (!bRet) { DbgPrint(__FUNCTION__"(): RtlAdjustPrivilege failed with status %x\n",St); } } else { DbgPrint(__FUNCTION__"(): NtImpersonateThread failed with status %x\n",St); } NtClose(hThread); } else { DbgPrint(__FUNCTION__"(): NtOpenThread failed with status %x\n",St); } break; } if (!Proc->NextEntryDelta) break; } free(Processes); } } return bRet; }
int WINAPI WinMain( IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd) { #if 0 LSA_STRING ProcessName, PackageName; HANDLE LsaHandle; LSA_OPERATIONAL_MODE Mode; BOOLEAN Old; ULONG AuthenticationPackage; NTSTATUS Status; #endif ULONG HardErrorResponse; MSG Msg; UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(nShowCmd); hAppInstance = hInstance; /* Make us critical */ RtlSetProcessIsCritical(TRUE, NULL, FALSE); RtlSetThreadIsCritical(TRUE, NULL, FALSE); if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE)) { ERR("WL: Could not register logon process\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } WLSession = (PWLSESSION)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION)); if (!WLSession) { ERR("WL: Could not allocate memory for winlogon instance\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } ZeroMemory(WLSession, sizeof(WLSESSION)); WLSession->DialogTimeout = 120; /* 2 minutes */ /* Initialize the dialog tracking list */ InitDialogListHead(); if (!CreateWindowStationAndDesktops(WLSession)) { ERR("WL: Could not create window station and desktops\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } LockWorkstation(WLSession); /* Load default keyboard layouts */ if (!InitKeyboardLayouts()) { ERR("WL: Could not preload keyboard layouts\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } if (!StartRpcServer()) { ERR("WL: Could not start the RPC server\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } if (!StartServicesManager()) { ERR("WL: Could not start services.exe\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } if (!StartLsass()) { ERR("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError()); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } /* Wait for the LSA server */ WaitForLsass(); /* Init Notifications */ InitNotifications(); /* Load and initialize gina */ if (!GinaInit(WLSession)) { ERR("WL: Failed to initialize Gina\n"); // FIXME: Retrieve the real name of the GINA DLL we were trying to load. // It is known only inside the GinaInit function... DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_GINALOADFAILED), GetDesktopWindow(), GinaLoadFailedWindowProc, (LPARAM)L"msgina.dll"); HandleShutdown(WLSession, WLX_SAS_ACTION_SHUTDOWN_REBOOT); ExitProcess(1); } DisplayStatusMessage(WLSession, WLSession->WinlogonDesktop, IDS_REACTOSISSTARTINGUP); #if 0 /* Connect to NetLogon service (lsass.exe) */ /* Real winlogon uses "Winlogon" */ RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"Winlogon"); Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode); if (Status == STATUS_PORT_CONNECTION_REFUSED) { /* Add the 'SeTcbPrivilege' privilege and try again */ Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, TRUE, &Old); if (!NT_SUCCESS(Status)) { ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status)); return 1; } Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode); } if (!NT_SUCCESS(Status)) { ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status)); return 1; } RtlInitUnicodeString((PUNICODE_STRING)&PackageName, MICROSOFT_KERBEROS_NAME_W); Status = LsaLookupAuthenticationPackage(LsaHandle, &PackageName, &AuthenticationPackage); if (!NT_SUCCESS(Status)) { ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status)); LsaDeregisterLogonProcess(LsaHandle); return 1; } #endif CallNotificationDlls(WLSession, StartupHandler); /* Create a hidden window to get SAS notifications */ if (!InitializeSAS(WLSession)) { ERR("WL: Failed to initialize SAS\n"); ExitProcess(2); } // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS); // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS); /* Display logged out screen */ WLSession->LogonState = STATE_INIT; RemoveStatusMessage(WLSession); /* Check for pending setup */ if (GetSetupType() != 0) { /* Run setup and reboot when done */ TRACE("WL: Setup mode detected\n"); RunSetup(); } else { PostMessageW(WLSession->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_CTRL_ALT_DEL, 0); } (void)LoadLibraryW(L"sfc_os.dll"); /* Tell kernel that CurrentControlSet is good (needed * to support Last good known configuration boot) */ NtInitializeRegistry(CM_BOOT_FLAG_ACCEPTED | 1); /* Message loop for the SAS window */ while (GetMessageW(&Msg, WLSession->SASWindow, 0, 0)) { TranslateMessage(&Msg); DispatchMessageW(&Msg); } CleanupNotifications(); /* We never go there */ return 0; }