NTSTATUS KphUninstall( _In_opt_ PWSTR DeviceName ) { NTSTATUS status = STATUS_SUCCESS; SC_HANDLE scmHandle; SC_HANDLE serviceHandle; if (!DeviceName) DeviceName = KPH_DEVICE_SHORT_NAME; scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (!scmHandle) return PhGetLastWin32ErrorAsNtStatus(); serviceHandle = OpenService(scmHandle, DeviceName, SERVICE_STOP | DELETE); if (serviceHandle) { SERVICE_STATUS serviceStatus; ControlService(serviceHandle, SERVICE_CONTROL_STOP, &serviceStatus); if (!DeleteService(serviceHandle)) status = PhGetLastWin32ErrorAsNtStatus(); CloseServiceHandle(serviceHandle); } else { status = PhGetLastWin32ErrorAsNtStatus(); } CloseServiceHandle(scmHandle); return status; }
static NTSTATUS PhpOpenService( _Out_ PHANDLE Handle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ PVOID Context ) { SC_HANDLE serviceHandle; if (!(serviceHandle = PhOpenService( ((PPH_SERVICE_ITEM)Context)->Name->Buffer, DesiredAccess ))) return PhGetLastWin32ErrorAsNtStatus(); *Handle = serviceHandle; return STATUS_SUCCESS; }
_Check_return_ ULONG KphUninstall( VOID ) { ULONG status = ERROR_SUCCESS; SC_HANDLE scmHandle; SC_HANDLE serviceHandle; scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (!scmHandle) return PhGetLastWin32ErrorAsNtStatus(); serviceHandle = OpenService(scmHandle, L"KProcessHacker2", SERVICE_STOP | DELETE); if (serviceHandle) { SERVICE_STATUS serviceStatus; ControlService(serviceHandle, SERVICE_CONTROL_STOP, &serviceStatus); if (!DeleteService(serviceHandle)) { status = GetLastError(); } CloseServiceHandle(serviceHandle); } else { status = GetLastError(); } CloseServiceHandle(scmHandle); return status; }
NTSTATUS PhCommandModeStart( VOID ) { static PH_COMMAND_LINE_OPTION options[] = { { PH_COMMAND_OPTION_HWND, L"hwnd", MandatoryArgumentType } }; NTSTATUS status; PPH_STRING commandLine; if (!NT_SUCCESS(status = PhGetProcessCommandLine(NtCurrentProcess(), &commandLine))) return status; PhParseCommandLine( &commandLine->sr, options, sizeof(options) / sizeof(PH_COMMAND_LINE_OPTION), PH_COMMAND_LINE_IGNORE_UNKNOWN_OPTIONS, PhpCommandModeOptionCallback, NULL ); PhDereferenceObject(commandLine); if (PhEqualString2(PhStartupParameters.CommandType, L"process", TRUE)) { SIZE_T i; SIZE_T processIdLength; HANDLE processId; HANDLE processHandle; if (!PhStartupParameters.CommandObject) return STATUS_INVALID_PARAMETER; processIdLength = PhStartupParameters.CommandObject->Length / 2; for (i = 0; i < processIdLength; i++) { if (!PhIsDigitCharacter(PhStartupParameters.CommandObject->Buffer[i])) break; } if (i == processIdLength) { ULONG64 processId64; if (!PhStringToInteger64(&PhStartupParameters.CommandObject->sr, 10, &processId64)) return STATUS_INVALID_PARAMETER; processId = (HANDLE)processId64; } else { PVOID processes; PSYSTEM_PROCESS_INFORMATION process; if (!NT_SUCCESS(status = PhEnumProcesses(&processes))) return status; if (!(process = PhFindProcessInformationByImageName(processes, &PhStartupParameters.CommandObject->sr))) { PhFree(processes); return STATUS_NOT_FOUND; } processId = process->UniqueProcessId; PhFree(processes); } if (PhEqualString2(PhStartupParameters.CommandAction, L"terminate", TRUE)) { if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_TERMINATE, processId))) { status = NtTerminateProcess(processHandle, STATUS_SUCCESS); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"suspend", TRUE)) { if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SUSPEND_RESUME, processId))) { status = NtSuspendProcess(processHandle); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"resume", TRUE)) { if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SUSPEND_RESUME, processId))) { status = NtResumeProcess(processHandle); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"priority", TRUE)) { UCHAR priority; if (!PhStartupParameters.CommandValue) return STATUS_INVALID_PARAMETER; if (PhEqualString2(PhStartupParameters.CommandValue, L"idle", TRUE)) priority = PROCESS_PRIORITY_CLASS_IDLE; else if (PhEqualString2(PhStartupParameters.CommandValue, L"normal", TRUE)) priority = PROCESS_PRIORITY_CLASS_NORMAL; else if (PhEqualString2(PhStartupParameters.CommandValue, L"high", TRUE)) priority = PROCESS_PRIORITY_CLASS_HIGH; else if (PhEqualString2(PhStartupParameters.CommandValue, L"realtime", TRUE)) priority = PROCESS_PRIORITY_CLASS_REALTIME; else if (PhEqualString2(PhStartupParameters.CommandValue, L"abovenormal", TRUE)) priority = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL; else if (PhEqualString2(PhStartupParameters.CommandValue, L"belownormal", TRUE)) priority = PROCESS_PRIORITY_CLASS_BELOW_NORMAL; else return STATUS_INVALID_PARAMETER; if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId))) { PROCESS_PRIORITY_CLASS priorityClass; priorityClass.Foreground = FALSE; priorityClass.PriorityClass = priority; status = NtSetInformationProcess(processHandle, ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS)); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"iopriority", TRUE)) { ULONG ioPriority; if (!PhStartupParameters.CommandValue) return STATUS_INVALID_PARAMETER; if (PhEqualString2(PhStartupParameters.CommandValue, L"verylow", TRUE)) ioPriority = 0; else if (PhEqualString2(PhStartupParameters.CommandValue, L"low", TRUE)) ioPriority = 1; else if (PhEqualString2(PhStartupParameters.CommandValue, L"normal", TRUE)) ioPriority = 2; else if (PhEqualString2(PhStartupParameters.CommandValue, L"high", TRUE)) ioPriority = 3; else return STATUS_INVALID_PARAMETER; if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId))) { status = PhSetProcessIoPriority(processHandle, ioPriority); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"pagepriority", TRUE)) { ULONG64 pagePriority64; ULONG pagePriority; if (!PhStartupParameters.CommandValue) return STATUS_INVALID_PARAMETER; PhStringToInteger64(&PhStartupParameters.CommandValue->sr, 10, &pagePriority64); pagePriority = (ULONG)pagePriority64; if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId))) { status = NtSetInformationProcess( processHandle, ProcessPagePriority, &pagePriority, sizeof(ULONG) ); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"injectdll", TRUE)) { if (!PhStartupParameters.CommandValue) return STATUS_INVALID_PARAMETER; if (NT_SUCCESS(status = PhOpenProcessPublic( &processHandle, ProcessQueryAccess | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, processId ))) { LARGE_INTEGER timeout; timeout.QuadPart = -5 * PH_TIMEOUT_SEC; status = PhInjectDllProcess( processHandle, PhStartupParameters.CommandValue->Buffer, &timeout ); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"unloaddll", TRUE)) { if (!PhStartupParameters.CommandValue) return STATUS_INVALID_PARAMETER; if (NT_SUCCESS(status = PhOpenProcessPublic( &processHandle, ProcessQueryAccess | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, processId ))) { PVOID baseAddress; if (NT_SUCCESS(status = PhpGetDllBaseRemote( processHandle, &PhStartupParameters.CommandValue->sr, &baseAddress ))) { LARGE_INTEGER timeout; timeout.QuadPart = -5 * PH_TIMEOUT_SEC; status = PhUnloadDllProcess( processHandle, baseAddress, &timeout ); } NtClose(processHandle); } } } else if (PhEqualString2(PhStartupParameters.CommandType, L"service", TRUE)) { SC_HANDLE serviceHandle; SERVICE_STATUS serviceStatus; if (!PhStartupParameters.CommandObject) return STATUS_INVALID_PARAMETER; if (PhEqualString2(PhStartupParameters.CommandAction, L"start", TRUE)) { if (!(serviceHandle = PhOpenService( PhStartupParameters.CommandObject->Buffer, SERVICE_START ))) return PhGetLastWin32ErrorAsNtStatus(); if (!StartService(serviceHandle, 0, NULL)) status = PhGetLastWin32ErrorAsNtStatus(); CloseServiceHandle(serviceHandle); } else if (PhEqualString2(PhStartupParameters.CommandAction, L"continue", TRUE)) { if (!(serviceHandle = PhOpenService( PhStartupParameters.CommandObject->Buffer, SERVICE_PAUSE_CONTINUE ))) return PhGetLastWin32ErrorAsNtStatus(); if (!ControlService(serviceHandle, SERVICE_CONTROL_CONTINUE, &serviceStatus)) status = PhGetLastWin32ErrorAsNtStatus(); CloseServiceHandle(serviceHandle); } else if (PhEqualString2(PhStartupParameters.CommandAction, L"pause", TRUE)) { if (!(serviceHandle = PhOpenService( PhStartupParameters.CommandObject->Buffer, SERVICE_PAUSE_CONTINUE ))) return PhGetLastWin32ErrorAsNtStatus(); if (!ControlService(serviceHandle, SERVICE_CONTROL_PAUSE, &serviceStatus)) status = PhGetLastWin32ErrorAsNtStatus(); CloseServiceHandle(serviceHandle); } else if (PhEqualString2(PhStartupParameters.CommandAction, L"stop", TRUE)) { if (!(serviceHandle = PhOpenService( PhStartupParameters.CommandObject->Buffer, SERVICE_STOP ))) return PhGetLastWin32ErrorAsNtStatus(); if (!ControlService(serviceHandle, SERVICE_CONTROL_STOP, &serviceStatus)) status = PhGetLastWin32ErrorAsNtStatus(); CloseServiceHandle(serviceHandle); } else if (PhEqualString2(PhStartupParameters.CommandAction, L"delete", TRUE)) { if (!(serviceHandle = PhOpenService( PhStartupParameters.CommandObject->Buffer, DELETE ))) return PhGetLastWin32ErrorAsNtStatus(); if (!DeleteService(serviceHandle)) status = PhGetLastWin32ErrorAsNtStatus(); CloseServiceHandle(serviceHandle); } } else if (PhEqualString2(PhStartupParameters.CommandType, L"thread", TRUE)) { ULONG64 threadId64; HANDLE threadId; HANDLE threadHandle; if (!PhStartupParameters.CommandObject) return STATUS_INVALID_PARAMETER; if (!PhStringToInteger64(&PhStartupParameters.CommandObject->sr, 10, &threadId64)) return STATUS_INVALID_PARAMETER; threadId = (HANDLE)threadId64; if (PhEqualString2(PhStartupParameters.CommandAction, L"terminate", TRUE)) { if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_TERMINATE, threadId))) { status = NtTerminateThread(threadHandle, STATUS_SUCCESS); NtClose(threadHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"suspend", TRUE)) { if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_SUSPEND_RESUME, threadId))) { status = NtSuspendThread(threadHandle, NULL); NtClose(threadHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"resume", TRUE)) { if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_SUSPEND_RESUME, threadId))) { status = NtResumeThread(threadHandle, NULL); NtClose(threadHandle); } } } return status; }
/** * Executes the run-as service. * * \param Parameters The run-as parameters. * * \remarks This function requires administrator-level access. */ NTSTATUS PhExecuteRunAsCommand( _In_ PPH_RUNAS_SERVICE_PARAMETERS Parameters ) { NTSTATUS status; ULONG win32Result; PPH_STRING commandLine; SC_HANDLE scManagerHandle; SC_HANDLE serviceHandle; PPH_STRING portName; UNICODE_STRING portNameUs; ULONG attempts; LARGE_INTEGER interval; if (!(scManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE))) return PhGetLastWin32ErrorAsNtStatus(); commandLine = PhFormatString(L"\"%s\" -ras \"%s\"", PhApplicationFileName->Buffer, Parameters->ServiceName); serviceHandle = CreateService( scManagerHandle, Parameters->ServiceName, Parameters->ServiceName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, commandLine->Buffer, NULL, NULL, NULL, L"LocalSystem", L"" ); win32Result = GetLastError(); PhDereferenceObject(commandLine); CloseServiceHandle(scManagerHandle); if (!serviceHandle) { return NTSTATUS_FROM_WIN32(win32Result); } PhSetDesktopWinStaAccess(); StartService(serviceHandle, 0, NULL); DeleteService(serviceHandle); portName = PhConcatStrings2(L"\\BaseNamedObjects\\", Parameters->ServiceName); PhStringRefToUnicodeString(&portName->sr, &portNameUs); attempts = 10; // Try to connect several times because the server may take // a while to initialize. do { status = PhSvcConnectToServer(&portNameUs, 0); if (NT_SUCCESS(status)) break; interval.QuadPart = -50 * PH_TIMEOUT_MS; NtDelayExecution(FALSE, &interval); } while (--attempts != 0); PhDereferenceObject(portName); if (NT_SUCCESS(status)) { status = PhSvcCallInvokeRunAsService(Parameters); PhSvcDisconnectFromServer(); } if (serviceHandle) CloseServiceHandle(serviceHandle); return status; }
NTSTATUS KphInstallEx( _In_opt_ PWSTR DeviceName, _In_ PWSTR FileName, _In_opt_ PKPH_PARAMETERS Parameters ) { NTSTATUS status = STATUS_SUCCESS; SC_HANDLE scmHandle; SC_HANDLE serviceHandle; if (!DeviceName) DeviceName = KPH_DEVICE_SHORT_NAME; scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (!scmHandle) return PhGetLastWin32ErrorAsNtStatus(); serviceHandle = CreateService( scmHandle, DeviceName, DeviceName, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_SYSTEM_START, SERVICE_ERROR_IGNORE, FileName, NULL, NULL, NULL, NULL, L"" ); if (serviceHandle) { // See KphConnect2Ex for more details. if (Parameters) { status = KphSetParameters(DeviceName, Parameters); if (!NT_SUCCESS(status)) { DeleteService(serviceHandle); goto CreateEnd; } } if (!StartService(serviceHandle, 0, NULL)) status = PhGetLastWin32ErrorAsNtStatus(); CreateEnd: CloseServiceHandle(serviceHandle); } else { status = PhGetLastWin32ErrorAsNtStatus(); } CloseServiceHandle(scmHandle); return status; }