PPH_STRING UpdateWindowsString( VOID ) { static PH_STRINGREF keyName = PH_STRINGREF_INIT(L"Software\\Microsoft\\Windows NT\\CurrentVersion"); HANDLE keyHandle; PPH_STRING buildLabHeader = NULL; if (NT_SUCCESS(PhOpenKey( &keyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &keyName, 0 ))) { PPH_STRING buildLabString; if (buildLabString = PhQueryRegistryString(keyHandle, L"BuildLabEx")) { buildLabHeader = PhConcatStrings2(L"ProcessHacker-OsBuild: ", buildLabString->Buffer); PhDereferenceObject(buildLabString); } else if (buildLabString = PhQueryRegistryString(keyHandle, L"BuildLab")) { buildLabHeader = PhConcatStrings2(L"ProcessHacker-OsBuild: ", buildLabString->Buffer); PhDereferenceObject(buildLabString); } NtClose(keyHandle); } return buildLabHeader; }
PPH_STRING WepGetWindowTitleForSelector( _In_ PWE_WINDOW_SELECTOR Selector ) { switch (Selector->Type) { case WeWindowSelectorAll: { return PhCreateString(L"Windows - All"); } break; case WeWindowSelectorThread: { return PhFormatString(L"Windows - Thread %lu", HandleToUlong(Selector->Thread.ThreadId)); } break; case WeWindowSelectorProcess: { CLIENT_ID clientId; clientId.UniqueProcess = Selector->Process.ProcessId; clientId.UniqueThread = NULL; return PhConcatStrings2(L"Windows - ", PH_AUTO_T(PH_STRING, PhGetClientIdName(&clientId))->Buffer); } break; case WeWindowSelectorDesktop: { return PhFormatString(L"Windows - Desktop \"%s\"", Selector->Desktop.DesktopName->Buffer); } break; default: return PhCreateString(L"Windows"); } }
static PPH_STRING UpdateVersionString( VOID ) { ULONG majorVersion; ULONG minorVersion; ULONG revisionVersion; PPH_STRING currentVersion = NULL; PPH_STRING versionHeader = NULL; PhGetPhVersionNumbers( &majorVersion, &minorVersion, NULL, &revisionVersion ); currentVersion = PhFormatString( L"%lu.%lu.%lu", majorVersion, minorVersion, revisionVersion ); if (currentVersion) { versionHeader = PhConcatStrings2(L"ProcessHacker-Build: ", currentVersion->Buffer); PhDereferenceObject(currentVersion); } return versionHeader; }
static BOOLEAN NTAPI PhpWalkThreadStackCallback( _In_ PPH_THREAD_STACK_FRAME StackFrame, _In_opt_ PVOID Context ) { PTHREAD_STACK_CONTEXT threadStackContext = (PTHREAD_STACK_CONTEXT)Context; PPH_STRING symbol; PTHREAD_STACK_ITEM item; if (threadStackContext->StopWalk) return FALSE; PhAcquireQueuedLockExclusive(&threadStackContext->StatusLock); PhMoveReference(&threadStackContext->StatusMessage, PhFormatString(L"Processing frame %u...", threadStackContext->NewList->Count)); PhReleaseQueuedLockExclusive(&threadStackContext->StatusLock); PostMessage(threadStackContext->ProgressWindowHandle, WM_PH_STATUS_UPDATE, 0, 0); symbol = PhGetSymbolFromAddress( threadStackContext->SymbolProvider, (ULONG64)StackFrame->PcAddress, NULL, NULL, NULL, NULL ); if (symbol && (StackFrame->Flags & PH_THREAD_STACK_FRAME_I386) && !(StackFrame->Flags & PH_THREAD_STACK_FRAME_FPO_DATA_PRESENT)) { PhMoveReference(&symbol, PhConcatStrings2(symbol->Buffer, L" (No unwind info)")); } item = PhAllocate(sizeof(THREAD_STACK_ITEM)); item->StackFrame = *StackFrame; item->Index = threadStackContext->NewList->Count; if (PhPluginsEnabled) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.Type = PluginThreadStackResolveSymbol; control.UniqueKey = threadStackContext; control.u.ResolveSymbol.StackFrame = StackFrame; control.u.ResolveSymbol.Symbol = symbol; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); symbol = control.u.ResolveSymbol.Symbol; } item->Symbol = symbol; PhAddItemList(threadStackContext->NewList, item); return TRUE; }
BOOLEAN RemoveDirectoryPath(_In_ PWSTR DirPath) { HANDLE findHandle; PPH_STRING findPath; WIN32_FIND_DATA data = { 0 }; findPath = PhConcatStrings2(DirPath, L"\\*"); if ((findHandle = FindFirstFile(findPath->Buffer, &data)) == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { PhDereferenceObject(findPath); return TRUE; } PhDereferenceObject(findPath); return FALSE; } do { if (PhEqualStringZ(data.cFileName, L".", TRUE) || PhEqualStringZ(data.cFileName, L"..", TRUE)) continue; if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { PPH_STRING dirPath = PhConcatStrings(3, DirPath, L"\\", data.cFileName); RemoveDirectoryPath(dirPath->Buffer); PhDereferenceObject(dirPath); } else { PPH_STRING filePath = PhConcatStrings(3, DirPath, L"\\", data.cFileName); if (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { _wchmod(filePath->Buffer, _S_IWRITE); } SetupDeleteDirectoryFile(filePath->Buffer); PhDereferenceObject(filePath); } } while (FindNextFile(findHandle, &data)); FindClose(findHandle); // Delete the parent directory RemoveDirectory(DirPath); PhDereferenceObject(findPath); return TRUE; }
NTSTATUS PhpGetProcessSystemDllInitBlock( _In_ HANDLE ProcessHandle, _Out_ PPS_SYSTEM_DLL_INIT_BLOCK *SystemDllInitBlock ) { NTSTATUS status; PPS_SYSTEM_DLL_INIT_BLOCK ldrInitBlock = NULL; PVOID ldrInitBlockBaseAddress = NULL; PPH_STRING ntdllFileName; ldrInitBlock = PhAllocate(sizeof(PS_SYSTEM_DLL_INIT_BLOCK)); memset(ldrInitBlock, 0, sizeof(PS_SYSTEM_DLL_INIT_BLOCK)); ntdllFileName = PhConcatStrings2(USER_SHARED_DATA->NtSystemRoot, L"\\System32\\ntdll.dll"); status = PhGetProcedureAddressRemote( ProcessHandle, ntdllFileName->Buffer, "LdrSystemDllInitBlock", 0, &ldrInitBlockBaseAddress, NULL ); PhDereferenceObject(ntdllFileName); if (NT_SUCCESS(status) && ldrInitBlockBaseAddress) { status = NtReadVirtualMemory( ProcessHandle, ldrInitBlockBaseAddress, ldrInitBlock, sizeof(PS_SYSTEM_DLL_INIT_BLOCK), NULL ); } if (NT_SUCCESS(status)) { *SystemDllInitBlock = ldrInitBlock; } return status; }
PPH_STRING WepGetWindowTitleForSelector( _In_ PWE_WINDOW_SELECTOR Selector ) { PPH_STRING title; CLIENT_ID clientId; PPH_STRING clientIdName; switch (Selector->Type) { case WeWindowSelectorAll: { return PhCreateString(L"Windows - All"); } break; case WeWindowSelectorThread: { return PhFormatString(L"Windows - Thread %u", (ULONG)Selector->Thread.ThreadId); } break; case WeWindowSelectorProcess: { clientId.UniqueProcess = Selector->Process.ProcessId; clientId.UniqueThread = NULL; clientIdName = PhGetClientIdName(&clientId); title = PhConcatStrings2(L"Windows - ", clientIdName->Buffer); PhDereferenceObject(clientIdName); return title; } break; case WeWindowSelectorDesktop: { return PhFormatString(L"Windows - Desktop \"%s\"", Selector->Desktop.DesktopName->Buffer); } break; default: return PhCreateString(L"Windows"); } }
static VOID WINAPI RunAsServiceMain( _In_ DWORD dwArgc, _In_ LPTSTR *lpszArgv ) { PPH_STRING portName; UNICODE_STRING portNameUs; LARGE_INTEGER timeout; memset(&RunAsServiceStop, 0, sizeof(PHSVC_STOP)); RunAsServiceStatusHandle = RegisterServiceCtrlHandlerEx(RunAsServiceName->Buffer, RunAsServiceHandlerEx, NULL); SetRunAsServiceStatus(SERVICE_RUNNING); portName = PhConcatStrings2(L"\\BaseNamedObjects\\", RunAsServiceName->Buffer); PhStringRefToUnicodeString(&portName->sr, &portNameUs); // Use a shorter timeout value to reduce the time spent running as SYSTEM. timeout.QuadPart = -5 * PH_TIMEOUT_SEC; PhSvcMain(&portNameUs, &timeout, &RunAsServiceStop); SetRunAsServiceStatus(SERVICE_STOPPED); }
VOID NTAPI DotNetEventCallback( _In_ PEVENT_RECORD EventRecord ) { PASMPAGE_QUERY_CONTEXT context = EventRecord->UserContext; PEVENT_HEADER eventHeader = &EventRecord->EventHeader; PEVENT_DESCRIPTOR eventDescriptor = &eventHeader->EventDescriptor; if (UlongToHandle(eventHeader->ProcessId) == context->ProcessId) { // .NET 4.0+ switch (eventDescriptor->Id) { case RuntimeInformationDCStart: { PRuntimeInformationRundown data = EventRecord->UserData; PDNA_NODE node; PPH_STRING startupFlagsString; PPH_STRING startupModeString; // Check for duplicates. if (FindClrNode(context, data->ClrInstanceID)) break; node = AddNode(context); node->Type = DNA_TYPE_CLR; node->u.Clr.ClrInstanceID = data->ClrInstanceID; node->u.Clr.DisplayName = PhFormatString(L"CLR v%u.%u.%u.%u", data->VMMajorVersion, data->VMMinorVersion, data->VMBuildNumber, data->VMQfeNumber); node->StructureText = node->u.Clr.DisplayName->sr; node->IdText = PhFormatString(L"%u", data->ClrInstanceID); startupFlagsString = FlagsToString(data->StartupFlags, StartupFlagsMap, sizeof(StartupFlagsMap)); startupModeString = FlagsToString(data->StartupMode, StartupModeMap, sizeof(StartupModeMap)); if (startupFlagsString->Length != 0 && startupModeString->Length != 0) { node->FlagsText = PhConcatStrings(3, startupFlagsString->Buffer, L", ", startupModeString->Buffer); PhDereferenceObject(startupFlagsString); PhDereferenceObject(startupModeString); } else if (startupFlagsString->Length != 0) { node->FlagsText = startupFlagsString; PhDereferenceObject(startupModeString); } else if (startupModeString->Length != 0) { node->FlagsText = startupModeString; PhDereferenceObject(startupFlagsString); } if (data->CommandLine[0]) node->PathText = PhCreateString(data->CommandLine); PhAddItemList(context->NodeRootList, node); } break; case AppDomainDCStart_V1: { PAppDomainLoadUnloadRundown_V1 data = EventRecord->UserData; SIZE_T appDomainNameLength; USHORT clrInstanceID; PDNA_NODE parentNode; PDNA_NODE node; appDomainNameLength = PhCountStringZ(data->AppDomainName) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)data + FIELD_OFFSET(AppDomainLoadUnloadRundown_V1, AppDomainName) + appDomainNameLength + sizeof(WCHAR) + sizeof(ULONG)); // Find the CLR node to add the AppDomain node to. parentNode = FindClrNode(context, clrInstanceID); if (parentNode) { // Check for duplicates. if (FindAppDomainNode(parentNode, data->AppDomainID)) break; node = AddNode(context); node->Type = DNA_TYPE_APPDOMAIN; node->u.AppDomain.AppDomainID = data->AppDomainID; node->u.AppDomain.DisplayName = PhConcatStrings2(L"AppDomain: ", data->AppDomainName); node->StructureText = node->u.AppDomain.DisplayName->sr; node->IdText = PhFormatString(L"%I64u", data->AppDomainID); node->FlagsText = FlagsToString(data->AppDomainFlags, AppDomainFlagsMap, sizeof(AppDomainFlagsMap)); PhAddItemList(parentNode->Children, node); } } break; case AssemblyDCStart_V1: { PAssemblyLoadUnloadRundown_V1 data = EventRecord->UserData; SIZE_T fullyQualifiedAssemblyNameLength; USHORT clrInstanceID; PDNA_NODE parentNode; PDNA_NODE node; PH_STRINGREF remainingPart; fullyQualifiedAssemblyNameLength = PhCountStringZ(data->FullyQualifiedAssemblyName) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)data + FIELD_OFFSET(AssemblyLoadUnloadRundown_V1, FullyQualifiedAssemblyName) + fullyQualifiedAssemblyNameLength + sizeof(WCHAR)); // Find the AppDomain node to add the Assembly node to. parentNode = FindClrNode(context, clrInstanceID); if (parentNode) parentNode = FindAppDomainNode(parentNode, data->AppDomainID); if (parentNode) { // Check for duplicates. if (FindAssemblyNode(parentNode, data->AssemblyID)) break; node = AddNode(context); node->Type = DNA_TYPE_ASSEMBLY; node->u.Assembly.AssemblyID = data->AssemblyID; node->u.Assembly.FullyQualifiedAssemblyName = PhCreateStringEx(data->FullyQualifiedAssemblyName, fullyQualifiedAssemblyNameLength); // Display only the assembly name, not the whole fully qualified name. if (!PhSplitStringRefAtChar(&node->u.Assembly.FullyQualifiedAssemblyName->sr, ',', &node->StructureText, &remainingPart)) node->StructureText = node->u.Assembly.FullyQualifiedAssemblyName->sr; node->IdText = PhFormatString(L"%I64u", data->AssemblyID); node->FlagsText = FlagsToString(data->AssemblyFlags, AssemblyFlagsMap, sizeof(AssemblyFlagsMap)); PhAddItemList(parentNode->Children, node); } } break; case ModuleDCStart_V1: { PModuleLoadUnloadRundown_V1 data = EventRecord->UserData; PWSTR moduleILPath; SIZE_T moduleILPathLength; PWSTR moduleNativePath; SIZE_T moduleNativePathLength; USHORT clrInstanceID; PDNA_NODE node; moduleILPath = data->ModuleILPath; moduleILPathLength = PhCountStringZ(moduleILPath) * sizeof(WCHAR); moduleNativePath = (PWSTR)((PCHAR)moduleILPath + moduleILPathLength + sizeof(WCHAR)); moduleNativePathLength = PhCountStringZ(moduleNativePath) * sizeof(WCHAR); clrInstanceID = *(PUSHORT)((PCHAR)moduleNativePath + moduleNativePathLength + sizeof(WCHAR)); // Find the Assembly node to set the path on. node = FindClrNode(context, clrInstanceID); if (node) node = FindAssemblyNode2(node, data->AssemblyID); if (node) { PhMoveReference(&node->PathText, PhCreateStringEx(moduleILPath, moduleILPathLength)); if (moduleNativePathLength != 0) PhMoveReference(&node->NativePathText, PhCreateStringEx(moduleNativePath, moduleNativePathLength)); } } break; case DCStartComplete_V1: { if (_InterlockedExchange(&context->TraceHandleActive, 0) == 1) { CloseTrace(context->TraceHandle); } } break; } // .NET 2.0 if (eventDescriptor->Id == 0) { switch (eventDescriptor->Opcode) { case CLR_MODULEDCSTART_OPCODE: { PModuleLoadUnloadRundown_V1 data = EventRecord->UserData; PWSTR moduleILPath; SIZE_T moduleILPathLength; PWSTR moduleNativePath; SIZE_T moduleNativePathLength; PDNA_NODE node; ULONG_PTR indexOfBackslash; ULONG_PTR indexOfLastDot; moduleILPath = data->ModuleILPath; moduleILPathLength = PhCountStringZ(moduleILPath) * sizeof(WCHAR); moduleNativePath = (PWSTR)((PCHAR)moduleILPath + moduleILPathLength + sizeof(WCHAR)); moduleNativePathLength = PhCountStringZ(moduleNativePath) * sizeof(WCHAR); if (context->ClrV2Node && (moduleILPathLength != 0 || moduleNativePathLength != 0)) { node = AddNode(context); node->Type = DNA_TYPE_ASSEMBLY; node->FlagsText = FlagsToString(data->ModuleFlags, ModuleFlagsMap, sizeof(ModuleFlagsMap)); node->PathText = PhCreateStringEx(moduleILPath, moduleILPathLength); if (moduleNativePathLength != 0) node->NativePathText = PhCreateStringEx(moduleNativePath, moduleNativePathLength); // Use the name between the last backslash and the last dot for the structure column text. // (E.g. C:\...\AcmeSoft.BigLib.dll -> AcmeSoft.BigLib) indexOfBackslash = PhFindLastCharInString(node->PathText, 0, '\\'); indexOfLastDot = PhFindLastCharInString(node->PathText, 0, '.'); if (indexOfBackslash != -1) { node->StructureText.Buffer = node->PathText->Buffer + indexOfBackslash + 1; if (indexOfLastDot != -1 && indexOfLastDot > indexOfBackslash) { node->StructureText.Length = (indexOfLastDot - indexOfBackslash - 1) * sizeof(WCHAR); } else { node->StructureText.Length = node->PathText->Length - indexOfBackslash * sizeof(WCHAR) - sizeof(WCHAR); } } else { node->StructureText = node->PathText->sr; } PhAddItemList(context->ClrV2Node->Children, node); } } break; case CLR_METHODDC_DCSTARTCOMPLETE_OPCODE: { if (_InterlockedExchange(&context->TraceHandleActive, 0) == 1) { CloseTrace(context->TraceHandle); } } break; } } } }
VOID PhpProcessStartupParameters( VOID ) { static PH_COMMAND_LINE_OPTION options[] = { { PH_ARG_SETTINGS, L"settings", MandatoryArgumentType }, { PH_ARG_NOSETTINGS, L"nosettings", NoArgumentType }, { PH_ARG_SHOWVISIBLE, L"v", NoArgumentType }, { PH_ARG_SHOWHIDDEN, L"hide", NoArgumentType }, { PH_ARG_COMMANDMODE, L"c", NoArgumentType }, { PH_ARG_COMMANDTYPE, L"ctype", MandatoryArgumentType }, { PH_ARG_COMMANDOBJECT, L"cobject", MandatoryArgumentType }, { PH_ARG_COMMANDACTION, L"caction", MandatoryArgumentType }, { PH_ARG_COMMANDVALUE, L"cvalue", MandatoryArgumentType }, { PH_ARG_RUNASSERVICEMODE, L"ras", MandatoryArgumentType }, { PH_ARG_NOKPH, L"nokph", NoArgumentType }, { PH_ARG_INSTALLKPH, L"installkph", NoArgumentType }, { PH_ARG_UNINSTALLKPH, L"uninstallkph", NoArgumentType }, { PH_ARG_DEBUG, L"debug", NoArgumentType }, { PH_ARG_HWND, L"hwnd", MandatoryArgumentType }, { PH_ARG_POINT, L"point", MandatoryArgumentType }, { PH_ARG_SHOWOPTIONS, L"showoptions", NoArgumentType }, { PH_ARG_PHSVC, L"phsvc", NoArgumentType }, { PH_ARG_NOPLUGINS, L"noplugins", NoArgumentType }, { PH_ARG_NEWINSTANCE, L"newinstance", NoArgumentType }, { PH_ARG_ELEVATE, L"elevate", NoArgumentType }, { PH_ARG_SILENT, L"s", NoArgumentType }, { PH_ARG_HELP, L"help", NoArgumentType }, { PH_ARG_SELECTPID, L"selectpid", MandatoryArgumentType }, { PH_ARG_PRIORITY, L"priority", MandatoryArgumentType }, { PH_ARG_PLUGIN, L"plugin", MandatoryArgumentType }, { PH_ARG_SELECTTAB, L"selecttab", MandatoryArgumentType } }; PH_STRINGREF commandLine; PhUnicodeStringToStringRef(&NtCurrentPeb()->ProcessParameters->CommandLine, &commandLine); memset(&PhStartupParameters, 0, sizeof(PH_STARTUP_PARAMETERS)); if (!PhParseCommandLine( &commandLine, options, sizeof(options) / sizeof(PH_COMMAND_LINE_OPTION), PH_COMMAND_LINE_IGNORE_UNKNOWN_OPTIONS | PH_COMMAND_LINE_IGNORE_FIRST_PART, PhpCommandLineOptionCallback, NULL ) || PhStartupParameters.Help) { PhShowInformation( NULL, L"Command line options:\n\n" L"-c\n" L"-ctype command-type\n" L"-cobject command-object\n" L"-caction command-action\n" L"-cvalue command-value\n" L"-debug\n" L"-elevate\n" L"-help\n" L"-hide\n" L"-installkph\n" L"-newinstance\n" L"-nokph\n" L"-noplugins\n" L"-nosettings\n" L"-plugin pluginname:value\n" L"-priority r|h|n|l\n" L"-s\n" L"-selectpid pid-to-select\n" L"-selecttab name-of-tab-to-select\n" L"-settings filename\n" L"-uninstallkph\n" L"-v\n" ); if (PhStartupParameters.Help) RtlExitUserProcess(STATUS_SUCCESS); } if (PhStartupParameters.InstallKph) { NTSTATUS status; PPH_STRING kprocesshackerFileName; KPH_PARAMETERS parameters; kprocesshackerFileName = PhConcatStrings2(PhApplicationDirectory->Buffer, L"\\kprocesshacker.sys"); parameters.SecurityLevel = KphSecurityNone; parameters.CreateDynamicConfiguration = TRUE; status = KphInstallEx(L"KProcessHacker2", kprocesshackerFileName->Buffer, ¶meters); if (!NT_SUCCESS(status) && !PhStartupParameters.Silent) PhShowStatus(NULL, L"Unable to install KProcessHacker", status, 0); RtlExitUserProcess(status); } if (PhStartupParameters.UninstallKph) { NTSTATUS status; status = KphUninstall(L"KProcessHacker2"); if (!NT_SUCCESS(status) && !PhStartupParameters.Silent) PhShowStatus(NULL, L"Unable to uninstall KProcessHacker", status, 0); RtlExitUserProcess(status); } if (PhStartupParameters.Elevate && !PhElevated) { PhShellProcessHacker( NULL, NULL, SW_SHOW, PH_SHELL_EXECUTE_ADMIN, PH_SHELL_APP_PROPAGATE_PARAMETERS | PH_SHELL_APP_PROPAGATE_PARAMETERS_FORCE_SETTINGS, 0, NULL ); RtlExitUserProcess(STATUS_SUCCESS); } if (PhStartupParameters.Debug) { // The symbol provider won't work if this is chosen. PhShowDebugConsole(); } }
INT_PTR CALLBACK DotNetAsmPageDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PASMPAGE_CONTEXT context; if (PhPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { context = propPageContext->Context; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { PPH_STRING settings; HWND tnHandle; context = PhAllocate(sizeof(ASMPAGE_CONTEXT)); memset(context, 0, sizeof(ASMPAGE_CONTEXT)); propPageContext->Context = context; context->WindowHandle = hwndDlg; context->ProcessItem = processItem; context->ClrVersions = 0; PhGetProcessIsDotNetEx(processItem->ProcessId, NULL, 0, NULL, &context->ClrVersions); tnHandle = GetDlgItem(hwndDlg, IDC_LIST); context->TnHandle = tnHandle; TreeNew_SetCallback(tnHandle, DotNetAsmTreeNewCallback, context); TreeNew_SetExtendedFlags(tnHandle, TN_FLAG_ITEM_DRAG_SELECT, TN_FLAG_ITEM_DRAG_SELECT); PhSetControlTheme(tnHandle, L"explorer"); SendMessage(TreeNew_GetTooltips(tnHandle), TTM_SETMAXTIPWIDTH, 0, MAXSHORT); PhAddTreeNewColumn(tnHandle, DNATNC_STRUCTURE, TRUE, L"Structure", 240, PH_ALIGN_LEFT, -2, 0); PhAddTreeNewColumn(tnHandle, DNATNC_ID, TRUE, L"ID", 50, PH_ALIGN_RIGHT, 0, DT_RIGHT); PhAddTreeNewColumn(tnHandle, DNATNC_FLAGS, TRUE, L"Flags", 120, PH_ALIGN_LEFT, 1, 0); PhAddTreeNewColumn(tnHandle, DNATNC_PATH, TRUE, L"Path", 600, PH_ALIGN_LEFT, 2, 0); // don't use path ellipsis - the user already has the base file name PhAddTreeNewColumn(tnHandle, DNATNC_NATIVEPATH, TRUE, L"Native image path", 600, PH_ALIGN_LEFT, 3, 0); settings = PhGetStringSetting(SETTING_NAME_ASM_TREE_LIST_COLUMNS); PhCmLoadSettings(tnHandle, &settings->sr); PhDereferenceObject(settings); PhSwapReference(&context->TnErrorMessage, PhCreateString(L"Loading .NET assemblies...")); TreeNew_SetEmptyText(tnHandle, &context->TnErrorMessage->sr, 0); if ( !IsProcessSuspended(processItem->ProcessId) || PhShowMessage(hwndDlg, MB_ICONWARNING | MB_YESNO, L".NET assembly enumeration may not work properly because the process is currently suspended. Do you want to continue?") == IDYES ) { CreateDotNetTraceQueryThread( hwndDlg, context->ClrVersions, processItem->ProcessId ); } else { PhSwapReference(&context->TnErrorMessage, PhCreateString(L"Unable to start the event tracing session because the process is suspended.") ); TreeNew_SetEmptyText(tnHandle, &context->TnErrorMessage->sr, 0); InvalidateRect(tnHandle, NULL, FALSE); } } break; case WM_DESTROY: { PPH_STRING settings; ULONG i; settings = PhCmSaveSettings(context->TnHandle); PhSetStringSetting2(SETTING_NAME_ASM_TREE_LIST_COLUMNS, &settings->sr); PhDereferenceObject(settings); if (context->NodeList) { for (i = 0; i < context->NodeList->Count; i++) DestroyNode(context->NodeList->Items[i]); PhDereferenceObject(context->NodeList); } if (context->NodeRootList) PhDereferenceObject(context->NodeRootList); PhClearReference(&context->TnErrorMessage); PhFree(context); PhPropPageDlgProcDestroy(hwndDlg); } break; case WM_SHOWWINDOW: { PPH_LAYOUT_ITEM dialogItem; if (dialogItem = PhBeginPropPageLayout(hwndDlg, propPageContext)) { PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_LIST), dialogItem, PH_ANCHOR_ALL); PhEndPropPageLayout(hwndDlg, propPageContext); } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case ID_COPY: { PPH_STRING text; text = PhGetTreeNewText(context->TnHandle, 0); PhSetClipboardString(context->TnHandle, &text->sr); PhDereferenceObject(text); } break; } } break; case UPDATE_MSG: { ULONG result = (ULONG)wParam; PASMPAGE_QUERY_CONTEXT queryContext = (PASMPAGE_QUERY_CONTEXT)lParam; if (result == 0) { PhSwapReference(&context->NodeList, queryContext->NodeList); PhSwapReference(&context->NodeRootList, queryContext->NodeRootList); DestroyDotNetTraceQuery(queryContext); TreeNew_NodesStructured(context->TnHandle); } else { PhSwapReference(&context->TnErrorMessage, PhConcatStrings2(L"Unable to start the event tracing session: ", PhGetStringOrDefault(PhGetWin32Message(result), L"Unknown error")) ); TreeNew_SetEmptyText(context->TnHandle, &context->TnErrorMessage->sr, 0); InvalidateRect(context->TnHandle, NULL, FALSE); } } break; } return FALSE; }
static BOOLEAN PhpRunTerminatorTest( _In_ HWND WindowHandle, _In_ INT Index ) { NTSTATUS status; PTEST_ITEM testItem; PPH_PROCESS_ITEM processItem; HWND lvHandle; PVOID processes; BOOLEAN success = FALSE; LARGE_INTEGER interval; processItem = (PPH_PROCESS_ITEM)GetProp(WindowHandle, L"ProcessItem"); lvHandle = GetDlgItem(WindowHandle, IDC_TERMINATOR_LIST); if (!PhGetListViewItemParam( lvHandle, Index, &testItem )) return FALSE; if (WSTR_EQUAL(testItem->Id, L"TT4")) { if (!PhShowConfirmMessage( WindowHandle, L"run", L"the TT4 test", L"The TT4 test may cause the system to crash.", TRUE )) return FALSE; } status = testItem->TestProc(processItem->ProcessId); interval.QuadPart = -1000 * PH_TIMEOUT_MS; NtDelayExecution(FALSE, &interval); if (status == STATUS_NOT_SUPPORTED) { PPH_STRING concat; concat = PhConcatStrings2(L"(Not available) ", testItem->Description); PhSetListViewSubItem(lvHandle, Index, 1, concat->Buffer); PhDereferenceObject(concat); } if (!NT_SUCCESS(PhEnumProcesses(&processes))) return FALSE; // Check if the process exists. if (!PhFindProcessInformation(processes, processItem->ProcessId)) { PhSetListViewItemImageIndex(lvHandle, Index, TICK_INDEX); SetDlgItemText(WindowHandle, IDC_TERMINATOR_TEXT, L"The process was terminated."); success = TRUE; } else { PhSetListViewItemImageIndex(lvHandle, Index, CROSS_INDEX); } PhFree(processes); UpdateWindow(WindowHandle); return success; }
BOOLEAN NvGpuDriverIsWHQL(VOID) { BOOLEAN nvGpuDriverIsWHQL = FALSE; HANDLE keyHandle = NULL; HANDLE keyServiceHandle = NULL; PWSTR deviceInterfaceList = NULL; ULONG deviceInterfaceListLength = 0; PWSTR deviceInterface; PPH_STRING keyPath = NULL; PPH_STRING matchingDeviceIdString; PPH_STRING keyServicePath; NvAPI_LongString nvNameAnsiString = ""; if (!NvAPI_GetDisplayDriverRegistryPath) goto CleanupExit; if (NvAPI_GetDisplayDriverRegistryPath(NvGpuDisplayHandleList->Items[0], nvNameAnsiString) != NVAPI_OK) goto CleanupExit; keyPath = PhConvertMultiByteToUtf16(nvNameAnsiString); if (!NT_SUCCESS(PhOpenKey( &keyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &keyPath->sr, 0 ))) { goto CleanupExit; } matchingDeviceIdString = PhQueryRegistryString(keyHandle, L"MatchingDeviceId"); //keySettingsPath = PhConcatStrings2(keyPath->Buffer, L"\\VolatileSettings"); //if (NT_SUCCESS(PhOpenKey( // &keySettingsHandle, // KEY_READ, // PH_KEY_LOCAL_MACHINE, // &keySettingsPath->sr, // 0 // ))) //{ // GUID settingsKey = GUID_DEVINTERFACE_DISPLAY_ADAPTER; // PPH_STRING guidString = PhFormatGuid(&settingsKey); // // ULONG dwType = REG_BINARY; // LONG length = DOS_MAX_PATH_LENGTH; // // if (RegQueryValueEx( // keySettingsHandle, // guidString->Buffer, // 0, // &dwType, // (PBYTE)displayInstancePath, // &length // ) != ERROR_SUCCESS) // { // //__leave; // } // // NtClose(keySettingsHandle); // PhDereferenceObject(guidString); //} if (CM_Get_Device_Interface_List_Size( &deviceInterfaceListLength, (PGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT ) != CR_SUCCESS) { return FALSE; } deviceInterfaceList = PhAllocate(deviceInterfaceListLength * sizeof(WCHAR)); memset(deviceInterfaceList, 0, deviceInterfaceListLength * sizeof(WCHAR)); if (CM_Get_Device_Interface_List( (PGUID)&GUID_DEVINTERFACE_DISPLAY_ADAPTER, NULL, deviceInterfaceList, deviceInterfaceListLength, CM_GET_DEVICE_INTERFACE_LIST_PRESENT ) != CR_SUCCESS) { PhFree(deviceInterfaceList); return FALSE; } for (deviceInterface = deviceInterfaceList; *deviceInterface; deviceInterface += PhCountStringZ(deviceInterface) + 1) { CONFIGRET result; PPH_STRING string; ULONG bufferSize; DEVPROPTYPE devicePropertyType; DEVINST deviceInstanceHandle; ULONG deviceInstanceIdLength = MAX_DEVICE_ID_LEN; WCHAR deviceInstanceId[MAX_DEVICE_ID_LEN]; if (CM_Get_Device_Interface_Property( deviceInterface, &DEVPKEY_Device_InstanceId, &devicePropertyType, (PBYTE)deviceInstanceId, &deviceInstanceIdLength, 0 ) != CR_SUCCESS) { continue; } if (CM_Locate_DevNode(&deviceInstanceHandle, deviceInstanceId, CM_LOCATE_DEVNODE_NORMAL)!= CR_SUCCESS) continue; bufferSize = 0x40; string = PhCreateStringEx(NULL, bufferSize); if ((result = CM_Get_DevNode_Property( deviceInstanceHandle, &DEVPKEY_Device_MatchingDeviceId, &devicePropertyType, (PBYTE)string->Buffer, &bufferSize, 0 )) != CR_SUCCESS) { PhDereferenceObject(string); string = PhCreateStringEx(NULL, bufferSize); result = CM_Get_DevNode_Property( deviceInstanceHandle, &DEVPKEY_Device_MatchingDeviceId, &devicePropertyType, (PBYTE)string->Buffer, &bufferSize, 0 ); } if (result != CR_SUCCESS) { PhDereferenceObject(string); continue; } PhTrimToNullTerminatorString(string); if (!PhEqualString(string, matchingDeviceIdString, TRUE)) { PhDereferenceObject(string); continue; } bufferSize = 0x40; PhDereferenceObject(string); string = PhCreateStringEx(NULL, bufferSize); if ((result = CM_Get_DevNode_Property( deviceInstanceHandle, &DEVPKEY_Device_Service, &devicePropertyType, (PBYTE)string->Buffer, &bufferSize, 0 )) != CR_SUCCESS) { PhDereferenceObject(string); string = PhCreateStringEx(NULL, bufferSize); result = CM_Get_DevNode_Property( deviceInstanceHandle, &DEVPKEY_Device_Service, &devicePropertyType, (PBYTE)string->Buffer, &bufferSize, 0 ); } if (result != CR_SUCCESS) { PhDereferenceObject(string); continue; } keyServicePath = PhConcatStrings2(L"System\\CurrentControlSet\\Services\\", string->Buffer); if (NT_SUCCESS(PhOpenKey( &keyServiceHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &keyServicePath->sr, 0 ))) { PPH_STRING driverNtPathString; PPH_STRING driverDosPathString = NULL; if (driverNtPathString = PhQueryRegistryString(keyServiceHandle, L"ImagePath")) { driverDosPathString = PhGetFileName(driverNtPathString); PhDereferenceObject(driverNtPathString); } if (driverDosPathString) { PPH_STRING fileSignerName = NULL; //PH_MAPPED_IMAGE fileMappedImage; // //if (NT_SUCCESS(PhLoadMappedImage(driverDosPathString->Buffer, NULL, TRUE, &fileMappedImage))) //{ // LARGE_INTEGER time; // SYSTEMTIME systemTime; // PPH_STRING string; // // RtlSecondsSince1970ToTime(fileMappedImage.NtHeaders->FileHeader.TimeDateStamp, &time); // PhLargeIntegerToLocalSystemTime(&systemTime, &time); // // string = PhFormatDateTime(&systemTime); // //SetDlgItemText(hwndDlg, IDC_TIMESTAMP, string->Buffer); // PhDereferenceObject(string); // // PhUnloadMappedImage(&fileMappedImage); //} if (PhVerifyFile(driverDosPathString->Buffer, &fileSignerName) == VrTrusted) { //if (PhEqualString2(fileSignerName, L"Microsoft Windows Hardware Compatibility Publisher", TRUE)) nvGpuDriverIsWHQL = TRUE; } if (fileSignerName) PhDereferenceObject(fileSignerName); PhDereferenceObject(driverDosPathString); } NtClose(keyServiceHandle); } } CleanupExit: if (keyHandle) { NtClose(keyHandle); } if (deviceInterfaceList) { PhFree(deviceInterfaceList); } if (keyPath) { PhDereferenceObject(keyPath); } return nvGpuDriverIsWHQL; }
PSTR VirusTotalSendHttpRequest( _In_ PPH_BYTES JsonArray ) { HANDLE fileHandle = INVALID_HANDLE_VALUE; HINTERNET httpSessionHandle = NULL; HINTERNET connectHandle = NULL; HINTERNET requestHandle = NULL; PSTR subRequestBuffer = NULL; PPH_STRING phVersion = NULL; PPH_STRING userAgent = NULL; PPH_STRING urlString = NULL; phVersion = PhGetPhVersion(); userAgent = PhConcatStrings2(L"ProcessHacker_", phVersion->Buffer); if (!(httpSessionHandle = WinHttpOpen( userAgent->Buffer, WindowsVersion >= WINDOWS_8_1 ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 ))) { goto CleanupExit; } if (WindowsVersion >= WINDOWS_8_1) { WinHttpSetOption( httpSessionHandle, WINHTTP_OPTION_DECOMPRESSION, &(ULONG){ WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE }, sizeof(ULONG) ); } if (!(connectHandle = WinHttpConnect( httpSessionHandle, L"www.virustotal.com", INTERNET_DEFAULT_HTTPS_PORT, 0 ))) { goto CleanupExit; } PPH_BYTES resourceString = VirusTotalGetCachedDbHash(); urlString = PhFormatString( L"%s%s%s%s%S", L"/partners", L"/sysinternals", L"/file-reports", L"?apikey=", resourceString->Buffer ); PhClearReference(&resourceString); if (!(requestHandle = WinHttpOpenRequest( connectHandle, L"POST", PhGetString(urlString), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE ))) { PhClearReference(&urlString); goto CleanupExit; } PhClearReference(&urlString); if (!WinHttpAddRequestHeaders(requestHandle, L"Content-Type: application/json", -1L, 0)) { goto CleanupExit; } if (!WinHttpSendRequest( requestHandle, WINHTTP_NO_ADDITIONAL_HEADERS, 0, JsonArray->Buffer, (ULONG)JsonArray->Length, (ULONG)JsonArray->Length, 0 )) { goto CleanupExit; } if (WinHttpReceiveResponse(requestHandle, NULL)) { BYTE buffer[PAGE_SIZE]; ULONG allocatedLength; ULONG dataLength; ULONG returnLength; allocatedLength = sizeof(buffer); subRequestBuffer = PhAllocate(allocatedLength); dataLength = 0; while (WinHttpReadData(requestHandle, buffer, PAGE_SIZE, &returnLength)) { if (returnLength == 0) break; if (allocatedLength < dataLength + returnLength) { allocatedLength *= 2; subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength); } memcpy(subRequestBuffer + dataLength, buffer, returnLength); dataLength += returnLength; } if (allocatedLength < dataLength + 1) { allocatedLength++; subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength); } // Ensure that the buffer is null-terminated. subRequestBuffer[dataLength] = 0; } CleanupExit: if (requestHandle) WinHttpCloseHandle(requestHandle); if (connectHandle) WinHttpCloseHandle(connectHandle); if (httpSessionHandle) WinHttpCloseHandle(httpSessionHandle); if (JsonArray) PhDereferenceObject(JsonArray); return subRequestBuffer; }
PPH_STRING FormatFilterEntry( _In_ PFILTER_ENTRY Entry ) { return PhConcatStrings2(Entry->Type == FilterInclude ? L"[Include] " : L"[Exclude] ", Entry->Filter->Buffer); }
PVIRUSTOTAL_API_RESPONSE VirusTotalRequestIpAddressReport( _In_ PPH_STRING IpAddress ) { PVIRUSTOTAL_API_RESPONSE result = NULL; PPH_BYTES jsonString = NULL; PPH_HTTP_CONTEXT httpContext = NULL; PPH_STRING versionString = NULL; PPH_STRING userAgentString = NULL; PPH_STRING urlPathString = NULL; PVOID jsonRootObject = NULL; versionString = PhGetPhVersion(); userAgentString = PhConcatStrings2(L"ProcessHacker_", versionString->Buffer); if (!PhHttpSocketCreate( &httpContext, PhGetString(userAgentString) )) { goto CleanupExit; } if (!PhHttpSocketConnect( httpContext, L"www.virustotal.com", PH_HTTP_DEFAULT_HTTPS_PORT )) { goto CleanupExit; } { PPH_BYTES resourceString = VirusTotalGetCachedDbHash(); urlPathString = PhFormatString( L"%s%s%s%s%s%S%s%s", L"/vtapi", L"/v2", L"/ip-address", L"/report", L"?\x0061\x0070\x0069\x006B\x0065\x0079=", resourceString->Buffer, L"&ip=", IpAddress->Buffer ); PhClearReference(&resourceString); } if (!PhHttpSocketBeginRequest( httpContext, L"POST", PhGetString(urlPathString), PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE )) { goto CleanupExit; } if (!PhHttpSocketAddRequestHeaders(httpContext, L"Content-Type: application/json", 0)) goto CleanupExit; if (!PhHttpSocketSendRequest(httpContext, NULL, 0)) goto CleanupExit; if (!PhHttpSocketEndRequest(httpContext)) goto CleanupExit; if (!(jsonString = PhHttpSocketDownloadString(httpContext, FALSE))) goto CleanupExit; if (!(jsonRootObject = PhCreateJsonParser(jsonString->Buffer))) goto CleanupExit; result = PhAllocate(sizeof(VIRUSTOTAL_API_RESPONSE)); memset(result, 0, sizeof(VIRUSTOTAL_API_RESPONSE)); //result->ResponseCode = PhGetJsonValueAsLong64(jsonRootObject, "response_code"); //result->StatusMessage = PhGetJsonValueAsString(jsonRootObject, "verbose_msg"); //result->PermaLink = PhGetJsonValueAsString(jsonRootObject, "permalink"); //result->ScanId = PhGetJsonValueAsString(jsonRootObject, "scan_id"); CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); if (jsonRootObject) PhFreeJsonParser(jsonRootObject); PhClearReference(&jsonString); PhClearReference(&versionString); PhClearReference(&userAgentString); return result; }
PPH_BYTES VirusTotalSendHttpRequest( _In_ PPH_BYTES JsonArray ) { PPH_BYTES subRequestBuffer = NULL; PPH_HTTP_CONTEXT httpContext = NULL; PPH_STRING versionString = NULL; PPH_STRING userAgentString = NULL; PPH_STRING urlPathString = NULL; versionString = PhGetPhVersion(); userAgentString = PhConcatStrings2(L"ProcessHacker_", versionString->Buffer); if (!PhHttpSocketCreate(&httpContext, PhGetString(userAgentString))) goto CleanupExit; if (!PhHttpSocketConnect(httpContext, L"www.virustotal.com", PH_HTTP_DEFAULT_HTTPS_PORT)) goto CleanupExit; { PPH_BYTES resourceString = VirusTotalGetCachedDbHash(); urlPathString = PhFormatString( L"%s%s%s%s%S", L"/partners", L"/sysinternals", L"/file-reports", L"?\x0061\x0070\x0069\x006B\x0065\x0079=", resourceString->Buffer ); PhClearReference(&resourceString); } if (!PhHttpSocketBeginRequest( httpContext, L"POST", urlPathString->Buffer, PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE )) { goto CleanupExit; } if (!PhHttpSocketAddRequestHeaders(httpContext, L"Content-Type: application/json", 0)) goto CleanupExit; if (!PhHttpSocketSendRequest(httpContext, JsonArray->Buffer, (ULONG)JsonArray->Length)) goto CleanupExit; if (!PhHttpSocketEndRequest(httpContext)) goto CleanupExit; if (!(subRequestBuffer = PhHttpSocketDownloadString(httpContext, FALSE))) goto CleanupExit; CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); PhClearReference(&urlPathString); PhClearReference(&versionString); PhClearReference(&userAgentString); if (JsonArray) PhDereferenceObject(JsonArray); return subRequestBuffer; }
static BOOL QueryXmlData( VOID ) { PCHAR data = NULL; BOOL isSuccess = FALSE; HINTERNET netInitialize = NULL, netConnection = NULL, netRequest = NULL; mxml_node_t *xmlDoc = NULL, *xmlNodeVer = NULL, *xmlNodeRelDate = NULL, *xmlNodeSize = NULL, *xmlNodeHash = NULL; // Create a user agent string. PPH_STRING phVersion = PhGetPhVersion(); PPH_STRING userAgent = PhConcatStrings2(L"PH Updater v", phVersion->Buffer); __try { // Initialize the wininet library. if (!(netInitialize = InternetOpen( userAgent->Buffer, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ))) { LogEvent(NULL, PhFormatString(L"Updater: (InitializeConnection) InternetOpen failed (%d)", GetLastError())); __leave; } // Connect to the server. if (!(netConnection = InternetConnect( netInitialize, UPDATE_URL, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 ))) { LogEvent(NULL, PhFormatString(L"Updater: (InitializeConnection) InternetConnect failed (%d)", GetLastError())); __leave; } // Open the HTTP request. if (!(netRequest = HttpOpenRequest( netConnection, L"GET", UPDATE_FILE, NULL, NULL, NULL, // wj32: do NOT cache --------------------------- Old - "Always cache the update xml, it can be cleared by deleting IE history, we configured the file to cache locally for two days." INTERNET_FLAG_RELOAD, 0 ))) { LogEvent(NULL, PhFormatString(L"Updater: (InitializeConnection) HttpOpenRequest failed (%d)", GetLastError())); __leave; } // Send the HTTP request. if (!HttpSendRequest(netRequest, NULL, 0, NULL, 0)) { LogEvent(NULL, PhFormatString(L"HttpSendRequest failed (%d)", GetLastError())); __leave; } // Read the resulting xml into our buffer. if (!ReadRequestString(netRequest, &data, NULL)) { // We don't need to log this. __leave; } // Load our XML. xmlDoc = mxmlLoadString(NULL, data, QueryXmlDataCallback); // Check our XML. if (xmlDoc == NULL || xmlDoc->type != MXML_ELEMENT) { LogEvent(NULL, PhCreateString(L"Updater: (WorkerThreadStart) mxmlLoadString failed.")); __leave; } // Find the ver node. xmlNodeVer = mxmlFindElement(xmlDoc, xmlDoc, "ver", NULL, NULL, MXML_DESCEND); // Find the reldate node. xmlNodeRelDate = mxmlFindElement(xmlDoc, xmlDoc, "reldate", NULL, NULL, MXML_DESCEND); // Find the size node. xmlNodeSize = mxmlFindElement(xmlDoc, xmlDoc, "size", NULL, NULL, MXML_DESCEND); // Find the hash node. xmlNodeHash = mxmlFindElement(xmlDoc, xmlDoc, "sha1", NULL, NULL, MXML_DESCEND); // Format strings into unicode PPH_STRING's UpdateData.Version = PhGetOpaqueXmlNodeText(xmlNodeVer); UpdateData.RelDate = PhGetOpaqueXmlNodeText(xmlNodeRelDate); UpdateData.Size = PhGetOpaqueXmlNodeText(xmlNodeSize); UpdateData.Hash = PhGetOpaqueXmlNodeText(xmlNodeHash); // parse and check string //if (!ParseVersionString(XmlData->Version->Buffer, &XmlData->MajorVersion, &XmlData->MinorVersion)) // __leave; if (!PhIsNullOrEmptyString(UpdateData.Version)) { PH_STRINGREF sr, majorPart, minorPart; ULONG64 majorInteger = 0, minorInteger = 0; PhInitializeStringRef(&sr, UpdateData.Version->Buffer); if (PhSplitStringRefAtChar(&sr, '.', &majorPart, &minorPart)) { PhStringToInteger64(&majorPart, 10, &majorInteger); PhStringToInteger64(&minorPart, 10, &minorInteger); UpdateData.MajorVersion = (ULONG)majorInteger; UpdateData.MinorVersion = (ULONG)minorInteger; isSuccess = TRUE; } } } __finally { if (xmlDoc) { mxmlDelete(xmlDoc); xmlDoc = NULL; } if (netInitialize) { InternetCloseHandle(netInitialize); netInitialize = NULL; } if (netConnection) { InternetCloseHandle(netConnection); netConnection = NULL; } if (netRequest) { InternetCloseHandle(netRequest); netRequest = NULL; } if (userAgent) { PhDereferenceObject(userAgent); userAgent = NULL; } if (phVersion) { PhDereferenceObject(phVersion); phVersion = NULL; } } return isSuccess; }
PVIRUSTOTAL_FILE_REPORT_RESULT VirusTotalSendHttpFileReportRequest( _In_ PPH_STRING FileHash ) { NTSTATUS status = STATUS_SUCCESS; HANDLE fileHandle = INVALID_HANDLE_VALUE; HINTERNET httpSessionHandle = NULL; HINTERNET connectHandle = NULL; HINTERNET requestHandle = NULL; PSTR subRequestBuffer = NULL; PPH_STRING phVersion = NULL; PPH_STRING userAgent = NULL; PPH_STRING urlString = NULL; phVersion = PhGetPhVersion(); userAgent = PhConcatStrings2(L"ProcessHacker_", phVersion->Buffer); if (!(httpSessionHandle = WinHttpOpen( userAgent->Buffer, WindowsVersion >= WINDOWS_8_1 ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 ))) { goto CleanupExit; } if (WindowsVersion >= WINDOWS_8_1) { WinHttpSetOption( httpSessionHandle, WINHTTP_OPTION_DECOMPRESSION, &(ULONG){ WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE }, sizeof(ULONG) ); } if (!(connectHandle = WinHttpConnect( httpSessionHandle, L"www.virustotal.com", INTERNET_DEFAULT_HTTPS_PORT, 0 ))) { goto CleanupExit; } PPH_BYTES resourceString = VirusTotalGetCachedDbHash(); urlString = PhFormatString( L"%s%s%s%s%S%s%s", L"/vtapi", L"/v2", L"/file", L"/report", L"?apikey=", resourceString->Buffer, L"&resource=", PhGetString(FileHash) ); PhClearReference(&resourceString); if (!(requestHandle = WinHttpOpenRequest( connectHandle, L"POST", PhGetString(urlString), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE ))) { goto CleanupExit; } if (!WinHttpAddRequestHeaders(requestHandle, L"Content-Type: application/json", -1L, 0)) goto CleanupExit; if (!WinHttpSendRequest( requestHandle, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0 )) { goto CleanupExit; } if (WinHttpReceiveResponse(requestHandle, NULL)) { BYTE buffer[PAGE_SIZE]; ULONG allocatedLength; ULONG dataLength; ULONG returnLength; allocatedLength = sizeof(buffer); subRequestBuffer = PhAllocate(allocatedLength); dataLength = 0; while (WinHttpReadData(requestHandle, buffer, PAGE_SIZE, &returnLength)) { if (returnLength == 0) break; if (allocatedLength < dataLength + returnLength) { allocatedLength *= 2; subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength); } memcpy(subRequestBuffer + dataLength, buffer, returnLength); dataLength += returnLength; } if (allocatedLength < dataLength + 1) { allocatedLength++; subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength); } subRequestBuffer[dataLength] = 0; } CleanupExit: PhClearReference(&urlString); if (requestHandle) WinHttpCloseHandle(requestHandle); if (connectHandle) WinHttpCloseHandle(connectHandle); if (httpSessionHandle) WinHttpCloseHandle(httpSessionHandle); PVOID jsonRootObject; //PVOID jsonScanObject; PVIRUSTOTAL_FILE_REPORT_RESULT result; if (!(jsonRootObject = CreateJsonParser(subRequestBuffer))) goto CleanupExit; if (!GetJsonValueAsUlong(jsonRootObject, "response_code")) goto CleanupExit; result = PhAllocate(sizeof(VIRUSTOTAL_FILE_REPORT_RESULT)); memset(result, 0, sizeof(VIRUSTOTAL_FILE_REPORT_RESULT)); result->Total = PhFormatUInt64(GetJsonValueAsUlong(jsonRootObject, "total"), FALSE); result->Positives = PhFormatUInt64(GetJsonValueAsUlong(jsonRootObject, "positives"), FALSE); result->Resource = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "resource")); result->ScanId = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "scan_id")); result->Md5 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "md5")); result->Sha1 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "sha1")); result->Sha256 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "sha256")); result->ScanDate = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "scan_date")); result->Permalink = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "permalink")); result->StatusMessage = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "verbose_msg")); //if (jsonScanObject = JsonGetObject(jsonRootObject, "scans")) //{ // PPH_LIST jsonArrayList; // // if (jsonArrayList = JsonGetObjectArrayList(jsonScanObject)) // { // result->ScanResults = PhCreateList(jsonArrayList->Count); // // for (ULONG i = 0; i < jsonArrayList->Count; i++) // { // PJSON_ARRAY_LIST_OBJECT object = jsonArrayList->Items[i]; // //BOOLEAN detected = GetJsonValueAsBool(object->Entry, "detected") == TRUE; // //PSTR version = GetJsonValueAsString(object->Entry, "version"); // //PSTR result = GetJsonValueAsString(object->Entry, "result"); // //PSTR update = GetJsonValueAsString(object->Entry, "update"); // // PhFree(object); // } // // PhDereferenceObject(jsonArrayList); // } //} return result; }
PPH_STRING FiFormatFileName( _In_ PPH_STRING FileName ) { if (!FiArgNative) { PPH_STRING fileName; PPH_STRING fullPath; UNICODE_STRING fileNameUs; // Get the full path first so we can detect long file names. fullPath = PhGetFullPath(FileName->Buffer, NULL); if (fullPath) { if (fullPath->Length / 2 > MAX_PATH) { wprintf(L"Warning: Detected long file name \"%s\".\n", fullPath->Buffer); fileName = PhConcatStrings2(L"\\??\\", fullPath->Buffer); PhDereferenceObject(fullPath); return fileName; } PhDereferenceObject(fullPath); } if (RtlDosPathNameToNtPathName_U( FileName->Buffer, &fileNameUs, NULL, NULL )) { fileName = PhCreateStringFromUnicodeString(&fileNameUs); RtlFreeHeap(RtlProcessHeap(), 0, fileNameUs.Buffer); return fileName; } else { wprintf(L"Warning: Unable to convert the file name \"%s\" to a NT file name.\n", FileName->Buffer); // Fallback method. return PhConcatStrings2(L"\\??\\", FileName->Buffer); } } else { // Some limited conversions are applied for convenience. if (FileName->Length >= 2 * 2 && iswalpha(FileName->Buffer[0]) && FileName->Buffer[1] == ':') { return PhConcatStrings2(L"\\??\\", FileName->Buffer); } else if (FileName->Buffer[0] != '\\') { return PhFormatString( L"\\??\\%s%s", NtCurrentPeb()->ProcessParameters->CurrentDirectory.DosPath.Buffer, FileName->Buffer ); } else { return PhReferenceObject(FileName); } } }
static NTSTATUS DownloadUpdateThreadStart( __in PVOID Parameter ) { PPH_STRING downloadUrlPath = NULL; HANDLE tempFileHandle = NULL; HINTERNET hInitialize = NULL, hConnection = NULL, hRequest = NULL; NTSTATUS status = STATUS_UNSUCCESSFUL; HWND hwndDlg = (HWND)Parameter; Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), FALSE); SetDlgItemText(hwndDlg, IDC_STATUS, L"Initializing"); // Reset the progress state on Vista and above. if (WindowsVersion > WINDOWS_XP) SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_NORMAL, 0L); if (!ConnectionAvailable()) return status; __try { // Get temp dir. WCHAR tempPathString[MAX_PATH]; DWORD tempPathLength = GetTempPath(MAX_PATH, tempPathString); if (tempPathLength == 0 || tempPathLength > MAX_PATH) { LogEvent(hwndDlg, PhFormatString(L"CreateFile failed (%d)", GetLastError())); __leave; } // create the download path string. downloadUrlPath = PhFormatString( L"/projects/processhacker/files/processhacker2/processhacker-%u.%u-setup.exe/download?use_mirror=autoselect", /* ?use_mirror=waix" */ UpdateData.MajorVersion, UpdateData.MinorVersion ); // Append the tempath to our string: %TEMP%processhacker-%u.%u-setup.exe // Example: C:\\Users\\dmex\\AppData\\Temp\\processhacker-2.10-setup.exe SetupFilePath = PhFormatString( L"%sprocesshacker-%u.%u-setup.exe", tempPathString, UpdateData.MajorVersion, UpdateData.MinorVersion ); // Create output file status = PhCreateFileWin32( &tempFileHandle, SetupFilePath->Buffer, FILE_GENERIC_READ | FILE_GENERIC_WRITE, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_TEMPORARY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) { LogEvent(hwndDlg, PhFormatString(L"PhCreateFileWin32 failed (%s)", ((PPH_STRING)PHA_DEREFERENCE(PhGetNtMessage(status)))->Buffer)); __leave; } { // Create a user agent string. PPH_STRING phVersion = PhGetPhVersion(); PPH_STRING userAgent = PhConcatStrings2(L"PH Updater v", phVersion->Buffer); // Initialize the wininet library. if (!(hInitialize = InternetOpen( userAgent->Buffer, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ))) { LogEvent(hwndDlg, PhFormatString(L"Updater: (InitializeConnection) InternetOpen failed (%d)", GetLastError())); PhDereferenceObject(userAgent); PhDereferenceObject(phVersion); __leave; } PhDereferenceObject(userAgent); PhDereferenceObject(phVersion); } // Connect to the server. if (!(hConnection = InternetConnect( hInitialize, L"sourceforge.net", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0))) { LogEvent(hwndDlg, PhFormatString(L"InternetConnect failed (%d)", GetLastError())); __leave; } // Open the HTTP request. if (!(hRequest = HttpOpenRequest( hConnection, NULL, downloadUrlPath->Buffer, NULL, NULL, NULL, INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RESYNCHRONIZE, 0 ))) { LogEvent(hwndDlg, PhFormatString(L"HttpOpenRequest failed (%d)", GetLastError())); __leave; } SetDlgItemText(hwndDlg, IDC_STATUS, L"Connecting"); // Send the HTTP request. if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)) { LogEvent(hwndDlg, PhFormatString(L"HttpSendRequest failed (%d)", GetLastError())); // Enable the 'Retry' button. Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE); SetDlgItemText(hwndDlg, IDC_DOWNLOAD, L"Retry"); // Reset the state and let user retry the download. PhUpdaterState = Download; } else { BYTE hashBuffer[20]; DWORD contentLengthSize = sizeof(DWORD); PH_HASH_CONTEXT hashContext; // Initialize hash algorithm. PhInitializeHash(&hashContext, Sha1HashAlgorithm); if (!HttpQueryInfoW(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &contentLength, &contentLengthSize, 0)) { // No content length...impossible to calculate % complete... // we can read the data, BUT in this instance Sourceforge always returns the content length // so instead we'll exit here instead of downloading the file. LogEvent(hwndDlg, PhFormatString(L"HttpQueryInfo failed (%d)", GetLastError())); __leave; } else { BYTE buffer[PAGE_SIZE]; DWORD bytesRead = 0, startTick = 0; IO_STATUS_BLOCK isb; // Zero the buffer. ZeroMemory(buffer, PAGE_SIZE); // Reset the counters. bytesDownloaded = 0, timeTransferred = 0, LastUpdateTime = 0; IsUpdating = FALSE; // Start the clock. startTick = GetTickCount(); timeTransferred = startTick; // Download the data. while (InternetReadFile(hRequest, buffer, PAGE_SIZE, &bytesRead)) { // If we get zero bytes, the file was uploaded or there was an error. if (bytesRead == 0) break; // If window closed and thread handle was closed, just dispose and exit. // (This also skips error checking/prompts and updating the disposed UI) if (!DownloadThreadHandle) __leave; // Update the hash of bytes we downloaded. PhUpdateHash(&hashContext, buffer, bytesRead); // Write the downloaded bytes to disk. status = NtWriteFile( tempFileHandle, NULL, NULL, NULL, &isb, buffer, bytesRead, NULL, NULL ); if (!NT_SUCCESS(status)) { PPH_STRING message = PhGetNtMessage(status); LogEvent(hwndDlg, PhFormatString(L"NtWriteFile failed (%s)", message->Buffer)); PhDereferenceObject(message); break; } // Check dwBytesRead are the same dwBytesWritten length returned by WriteFile. if (bytesRead != isb.Information) { PPH_STRING message = PhGetNtMessage(status); LogEvent(hwndDlg, PhFormatString(L"NtWriteFile failed (%s)", message->Buffer)); PhDereferenceObject(message); break; } // Update our total bytes downloaded PhAcquireQueuedLockExclusive(&Lock); bytesDownloaded += (DWORD)isb.Information; PhReleaseQueuedLockExclusive(&Lock); AsyncUpdate(); } // Check if we downloaded the entire file. assert(bytesDownloaded == contentLength); // Compute our hash result. if (PhFinalHash(&hashContext, &hashBuffer, 20, NULL)) { // Allocate our hash string, hex the final hash result in our hashBuffer. PPH_STRING hexString = PhBufferToHexString(hashBuffer, 20); if (PhEqualString(hexString, UpdateData.Hash, TRUE)) { // If PH is not elevated, set the UAC shield for the install button as the setup requires elevation. if (!PhElevated) SendMessage(GetDlgItem(hwndDlg, IDC_DOWNLOAD), BCM_SETSHIELD, 0, TRUE); // Set the download result, don't include hash status since it succeeded. //SetDlgItemText(hwndDlg, IDC_STATUS, L"Download Complete"); // Set button text for next action Button_SetText(GetDlgItem(hwndDlg, IDC_DOWNLOAD), L"Install"); // Enable the Install button Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE); // Hash succeeded, set state as ready to install. PhUpdaterState = Install; } else { if (WindowsVersion > WINDOWS_XP) SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_ERROR, 0L); SetDlgItemText(hwndDlg, IDC_STATUS, L"Download complete, SHA1 Hash failed."); // Set button text for next action Button_SetText(GetDlgItem(hwndDlg, IDC_DOWNLOAD), L"Retry"); // Enable the Install button Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE); // Hash failed, reset state to downloading so user can redownload the file. PhUpdaterState = Download; } PhDereferenceObject(hexString); } else { //SetDlgItemText(hwndDlg, IDC_STATUS, L"PhFinalHash failed"); // Show fancy Red progressbar if hash failed on Vista and above. if (WindowsVersion > WINDOWS_XP) SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_ERROR, 0L); } } } status = STATUS_SUCCESS; } __finally { if (hInitialize) { InternetCloseHandle(hInitialize); hInitialize = NULL; } if (hConnection) { InternetCloseHandle(hConnection); hConnection = NULL; } if (hRequest) { InternetCloseHandle(hRequest); hRequest = NULL; } if (tempFileHandle) { NtClose(tempFileHandle); tempFileHandle = NULL; } if (downloadUrlPath) { PhDereferenceObject(downloadUrlPath); downloadUrlPath = NULL; } } 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; }
PVIRUSTOTAL_FILE_REPORT VirusTotalRequestFileReport( _In_ PPH_STRING FileHash ) { PVIRUSTOTAL_FILE_REPORT result = NULL; PPH_BYTES jsonString = NULL; PPH_HTTP_CONTEXT httpContext = NULL; PPH_STRING versionString = NULL; PPH_STRING userAgentString = NULL; PPH_STRING urlPathString = NULL; PVOID jsonRootObject = NULL; PVOID jsonScanObject; versionString = PhGetPhVersion(); userAgentString = PhConcatStrings2(L"ProcessHacker_", versionString->Buffer); if (!PhHttpSocketCreate( &httpContext, PhGetString(userAgentString) )) { goto CleanupExit; } if (!PhHttpSocketConnect( httpContext, L"www.virustotal.com", PH_HTTP_DEFAULT_HTTPS_PORT )) { goto CleanupExit; } { PPH_BYTES resourceString = VirusTotalGetCachedDbHash(); urlPathString = PhFormatString( L"%s%s%s%s%s%S%s%s", L"/vtapi", L"/v2", L"/file", L"/report", L"?\x0061\x0070\x0069\x006B\x0065\x0079=", resourceString->Buffer, L"&resource=", FileHash->Buffer ); PhClearReference(&resourceString); } if (!PhHttpSocketBeginRequest( httpContext, L"POST", PhGetString(urlPathString), PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE )) { goto CleanupExit; } if (!PhHttpSocketAddRequestHeaders(httpContext, L"Content-Type: application/json", 0)) goto CleanupExit; if (!PhHttpSocketSendRequest(httpContext, NULL, 0)) goto CleanupExit; if (!PhHttpSocketEndRequest(httpContext)) goto CleanupExit; if (!(jsonString = PhHttpSocketDownloadString(httpContext, FALSE))) goto CleanupExit; if (!(jsonRootObject = PhCreateJsonParser(jsonString->Buffer))) goto CleanupExit; result = PhAllocate(sizeof(VIRUSTOTAL_FILE_REPORT)); memset(result, 0, sizeof(VIRUSTOTAL_FILE_REPORT)); result->ResponseCode = PhGetJsonValueAsLong64(jsonRootObject, "response_code"); result->StatusMessage = PhGetJsonValueAsString(jsonRootObject, "verbose_msg"); result->PermaLink = PhGetJsonValueAsString(jsonRootObject, "permalink"); result->ScanDate = PhGetJsonValueAsString(jsonRootObject, "scan_date"); result->ScanId = PhGetJsonValueAsString(jsonRootObject, "scan_id"); result->Total = PhFormatUInt64(PhGetJsonValueAsLong64(jsonRootObject, "total"), FALSE); result->Positives = PhFormatUInt64(PhGetJsonValueAsLong64(jsonRootObject, "positives"), FALSE); //result->Md5 = PhGetJsonValueAsString(jsonRootObject, "md5"); //result->Sha1 = PhGetJsonValueAsString(jsonRootObject, "sha1"); //result->Sha256 = PhGetJsonValueAsString(jsonRootObject, "sha256"); if (jsonScanObject = PhGetJsonObject(jsonRootObject, "scans")) { PPH_LIST jsonArrayList; if (jsonArrayList = PhGetJsonObjectAsArrayList(jsonScanObject)) { result->ScanResults = PhCreateList(jsonArrayList->Count); for (ULONG i = 0; i < jsonArrayList->Count; i++) { PVIRUSTOTAL_FILE_REPORT_RESULT entry; PJSON_ARRAY_LIST_OBJECT object = jsonArrayList->Items[i]; entry = PhAllocate(sizeof(VIRUSTOTAL_FILE_REPORT_RESULT)); memset(entry, 0, sizeof(VIRUSTOTAL_FILE_REPORT_RESULT)); entry->Vendor = PhConvertUtf8ToUtf16(object->Key); entry->Detected = PhGetJsonObjectBool(object->Entry, "detected"); entry->EngineVersion = PhGetJsonValueAsString(object->Entry, "version"); entry->DetectionName = PhGetJsonValueAsString(object->Entry, "result"); entry->DatabaseDate = PhGetJsonValueAsString(object->Entry, "update"); PhAddItemList(result->ScanResults, entry); PhFree(object); } PhDereferenceObject(jsonArrayList); } } CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); if (jsonRootObject) PhFreeJsonParser(jsonRootObject); PhClearReference(&jsonString); PhClearReference(&versionString); PhClearReference(&userAgentString); return result; }
/** * Starts a program as another user. * * \param hWnd A handle to the parent window. * \param Program The command line of the program to start. * \param UserName The user to start the program as. The user * name should be specified as: domain\\name. This parameter * can be NULL if \a ProcessIdWithToken is specified. * \param Password The password for the specified user. If there * is no password, specify an empty string. This parameter * can be NULL if \a ProcessIdWithToken is specified. * \param LogonType The logon type for the specified user. This * parameter can be 0 if \a ProcessIdWithToken is specified. * \param ProcessIdWithToken The ID of a process from which * to duplicate the token. * \param SessionId The ID of the session to run the program * under. * \param DesktopName The window station and desktop to run the * program under. * \param UseLinkedToken Uses the linked token if possible. * * \retval STATUS_CANCELLED The user cancelled the operation. * * \remarks This function will cause another instance of * Process Hacker to be executed if the current security context * does not have sufficient system access. This is done * through a UAC elevation prompt. */ NTSTATUS PhExecuteRunAsCommand2( _In_ HWND hWnd, _In_ PWSTR Program, _In_opt_ PWSTR UserName, _In_opt_ PWSTR Password, _In_opt_ ULONG LogonType, _In_opt_ HANDLE ProcessIdWithToken, _In_ ULONG SessionId, _In_ PWSTR DesktopName, _In_ BOOLEAN UseLinkedToken ) { NTSTATUS status = STATUS_SUCCESS; PH_RUNAS_SERVICE_PARAMETERS parameters; WCHAR serviceName[32]; PPH_STRING portName; UNICODE_STRING portNameUs; memset(¶meters, 0, sizeof(PH_RUNAS_SERVICE_PARAMETERS)); parameters.ProcessId = HandleToUlong(ProcessIdWithToken); parameters.UserName = UserName; parameters.Password = Password; parameters.LogonType = LogonType; parameters.SessionId = SessionId; parameters.CommandLine = Program; parameters.DesktopName = DesktopName; parameters.UseLinkedToken = UseLinkedToken; // Try to use an existing instance of the service if possible. if (RunAsOldServiceName[0] != 0) { PhAcquireQueuedLockExclusive(&RunAsOldServiceLock); portName = PhConcatStrings2(L"\\BaseNamedObjects\\", RunAsOldServiceName); PhStringRefToUnicodeString(&portName->sr, &portNameUs); if (NT_SUCCESS(PhSvcConnectToServer(&portNameUs, 0))) { parameters.ServiceName = RunAsOldServiceName; status = PhSvcCallInvokeRunAsService(¶meters); PhSvcDisconnectFromServer(); PhDereferenceObject(portName); PhReleaseQueuedLockExclusive(&RunAsOldServiceLock); return status; } PhDereferenceObject(portName); PhReleaseQueuedLockExclusive(&RunAsOldServiceLock); } // An existing instance was not available. Proceed normally. memcpy(serviceName, L"ProcessHacker", 13 * sizeof(WCHAR)); PhGenerateRandomAlphaString(&serviceName[13], 16); PhAcquireQueuedLockExclusive(&RunAsOldServiceLock); memcpy(RunAsOldServiceName, serviceName, sizeof(serviceName)); PhReleaseQueuedLockExclusive(&RunAsOldServiceLock); parameters.ServiceName = serviceName; if (PhGetOwnTokenAttributes().Elevated) { status = PhExecuteRunAsCommand(¶meters); } else { if (PhUiConnectToPhSvc(hWnd, FALSE)) { status = PhSvcCallExecuteRunAsCommand(¶meters); PhUiDisconnectFromPhSvc(); } else { status = STATUS_CANCELLED; } } return status; }
VOID StatusBarUpdate( _In_ BOOLEAN ResetMaxWidths ) { static ULONG64 lastTickCount = 0; ULONG count; ULONG i; HDC hdc; BOOLEAN resetMaxWidths = FALSE; PPH_STRING text[MAX_STATUSBAR_ITEMS]; ULONG widths[MAX_STATUSBAR_ITEMS]; if (ProcessesUpdatedCount < 2) return; if (ResetMaxWidths) resetMaxWidths = TRUE; if (!StatusBarItemList || StatusBarItemList->Count == 0) { // The status bar doesn't cope well with 0 parts. widths[0] = -1; SendMessage(StatusBarHandle, SB_SETPARTS, 1, (LPARAM)widths); SendMessage(StatusBarHandle, SB_SETTEXT, 0, (LPARAM)L""); return; } hdc = GetDC(StatusBarHandle); SelectObject(hdc, (HFONT)SendMessage(StatusBarHandle, WM_GETFONT, 0, 0)); // Reset max. widths for Max. CPU Process and Max. I/O Process parts once in a while. { LARGE_INTEGER tickCount; PhQuerySystemTime(&tickCount); if (tickCount.QuadPart - lastTickCount >= 10 * PH_TICKS_PER_SEC) { resetMaxWidths = TRUE; lastTickCount = tickCount.QuadPart; } } count = 0; for (i = 0; i < StatusBarItemList->Count; i++) { SIZE size; ULONG width; PSTATUSBAR_ITEM statusItem; statusItem = StatusBarItemList->Items[i]; switch (statusItem->Id) { case ID_STATUS_CPUUSAGE: { text[count] = PhFormatString( L"CPU Usage: %.2f%%", (SystemStatistics.CpuKernelUsage + SystemStatistics.CpuUserUsage) * 100 ); } break; case ID_STATUS_COMMITCHARGE: { ULONG commitUsage = SystemStatistics.Performance->CommittedPages; FLOAT commitFraction = (FLOAT)commitUsage / SystemStatistics.Performance->CommitLimit * 100; text[count] = PhFormatString( L"Commit Charge: %s (%.2f%%)", PhaFormatSize(UInt32x32To64(commitUsage, PAGE_SIZE), -1)->Buffer, commitFraction ); } break; case ID_STATUS_PHYSICALMEMORY: { ULONG physicalUsage = PhSystemBasicInformation.NumberOfPhysicalPages - SystemStatistics.Performance->AvailablePages; FLOAT physicalFraction = (FLOAT)physicalUsage / PhSystemBasicInformation.NumberOfPhysicalPages * 100; text[count] = PhFormatString( L"Physical Memory: %s (%.2f%%)", PhaFormatSize(UInt32x32To64(physicalUsage, PAGE_SIZE), -1)->Buffer, physicalFraction ); } break; case ID_STATUS_FREEMEMORY: { ULONG physicalFree = SystemStatistics.Performance->AvailablePages; FLOAT physicalFreeFraction = (FLOAT)physicalFree / PhSystemBasicInformation.NumberOfPhysicalPages * 100; text[count] = PhFormatString( L"Free Memory: %s (%.2f%%)", PhaFormatSize(UInt32x32To64(physicalFree, PAGE_SIZE), -1)->Buffer, physicalFreeFraction ); } break; case ID_STATUS_NUMBEROFPROCESSES: { text[count] = PhConcatStrings2( L"Processes: ", PhaFormatUInt64(SystemStatistics.NumberOfProcesses, TRUE)->Buffer ); } break; case ID_STATUS_NUMBEROFTHREADS: { text[count] = PhConcatStrings2( L"Threads: ", PhaFormatUInt64(SystemStatistics.NumberOfThreads, TRUE)->Buffer ); } break; case ID_STATUS_NUMBEROFHANDLES: { text[count] = PhConcatStrings2( L"Handles: ", PhaFormatUInt64(SystemStatistics.NumberOfHandles, TRUE)->Buffer ); } break; case ID_STATUS_IO_RO: { text[count] = PhConcatStrings2( L"I/O R+O: ", PhaFormatSize(SystemStatistics.IoReadDelta.Delta + SystemStatistics.IoOtherDelta.Delta, -1)->Buffer ); } break; case ID_STATUS_IO_W: { text[count] = PhConcatStrings2( L"I/O W: ", PhaFormatSize(SystemStatistics.IoWriteDelta.Delta, -1)->Buffer ); } break; case ID_STATUS_MAX_CPU_PROCESS: { PPH_PROCESS_ITEM processItem; if (SystemStatistics.MaxCpuProcessId && (processItem = PhReferenceProcessItem(SystemStatistics.MaxCpuProcessId))) { if (!PH_IS_FAKE_PROCESS_ID(processItem->ProcessId)) { text[count] = PhFormatString( L"%s (%lu): %.2f%%", processItem->ProcessName->Buffer, HandleToUlong(processItem->ProcessId), processItem->CpuUsage * 100 ); } else { text[count] = PhFormatString( L"%s: %.2f%%", processItem->ProcessName->Buffer, processItem->CpuUsage * 100 ); } PhDereferenceObject(processItem); } else { text[count] = PhCreateString(L"-"); } } break; case ID_STATUS_MAX_IO_PROCESS: { PPH_PROCESS_ITEM processItem; if (SystemStatistics.MaxIoProcessId && (processItem = PhReferenceProcessItem(SystemStatistics.MaxIoProcessId))) { if (!PH_IS_FAKE_PROCESS_ID(processItem->ProcessId)) { text[count] = PhFormatString( L"%s (%lu): %s", processItem->ProcessName->Buffer, HandleToUlong(processItem->ProcessId), PhaFormatSize(processItem->IoReadDelta.Delta + processItem->IoWriteDelta.Delta + processItem->IoOtherDelta.Delta, -1)->Buffer ); } else { text[count] = PhFormatString( L"%s: %s", processItem->ProcessName->Buffer, PhaFormatSize(processItem->IoReadDelta.Delta + processItem->IoWriteDelta.Delta + processItem->IoOtherDelta.Delta, -1)->Buffer ); } PhDereferenceObject(processItem); } else { text[count] = PhCreateString(L"-"); } } break; case ID_STATUS_NUMBEROFVISIBLEITEMS: { HWND tnHandle = NULL; tnHandle = GetCurrentTreeNewHandle(); if (tnHandle) { ULONG visibleCount = 0; visibleCount = TreeNew_GetFlatNodeCount(tnHandle); text[count] = PhFormatString( L"Visible: %lu", visibleCount ); } else { text[count] = PhCreateString( L"Visible: N/A" ); } } break; case ID_STATUS_NUMBEROFSELECTEDITEMS: { HWND tnHandle = NULL; tnHandle = GetCurrentTreeNewHandle(); if (tnHandle) { ULONG visibleCount = 0; ULONG selectedCount = 0; visibleCount = TreeNew_GetFlatNodeCount(tnHandle); for (ULONG i = 0; i < visibleCount; i++) { if (TreeNew_GetFlatNode(tnHandle, i)->Selected) selectedCount++; } text[count] = PhFormatString( L"Selected: %lu", selectedCount ); } else { text[count] = PhCreateString( L"Selected: N/A" ); } } break; case ID_STATUS_INTERVALSTATUS: { ULONG interval; interval = PhGetIntegerSetting(L"UpdateInterval"); if (UpdateAutomatically) { switch (interval) { case 500: text[count] = PhCreateString(L"Interval: Fast"); break; case 1000: text[count] = PhCreateString(L"Interval: Normal"); break; case 2000: text[count] = PhCreateString(L"Interval: Below Normal"); break; case 5000: text[count] = PhCreateString(L"Interval: Slow"); break; case 10000: text[count] = PhCreateString(L"Interval: Very Slow"); break; } } else { text[count] = PhCreateString(L"Interval: Paused"); } } break; } if (resetMaxWidths) StatusBarMaxWidths[count] = 0; if (!GetTextExtentPoint32(hdc, text[count]->Buffer, (ULONG)text[count]->Length / sizeof(WCHAR), &size)) size.cx = 200; if (count != 0) widths[count] = widths[count - 1]; else widths[count] = 0; width = size.cx + 10; if (width <= StatusBarMaxWidths[count]) { width = StatusBarMaxWidths[count]; } else { StatusBarMaxWidths[count] = width; } widths[count] += width; count++; } ReleaseDC(StatusBarHandle, hdc); SendMessage(StatusBarHandle, SB_SETPARTS, count, (LPARAM)widths); for (i = 0; i < count; i++) { SendMessage(StatusBarHandle, SB_SETTEXT, i, (LPARAM)text[i]->Buffer); PhDereferenceObject(text[i]); } }
VOID PhShowHandleObjectProperties1( _In_ HWND hWnd, _In_ PPH_HANDLE_ITEM_INFO Info ) { if (PhIsNullOrEmptyString(Info->TypeName)) return; if (PhEqualString2(Info->TypeName, L"File", TRUE) || PhEqualString2(Info->TypeName, L"DLL", TRUE) || PhEqualString2(Info->TypeName, L"Mapped file", TRUE) || PhEqualString2(Info->TypeName, L"Mapped image", TRUE)) { if (Info->BestObjectName) { PhShellExecuteUserString( PhMainWndHandle, L"FileBrowseExecutable", Info->BestObjectName->Buffer, FALSE, L"Make sure the Explorer executable file is present." ); } else PhShowError(hWnd, L"Unable to open file location because the object is unnamed."); } else if (PhEqualString2(Info->TypeName, L"Key", TRUE)) { if (Info->BestObjectName) PhShellOpenKey2(hWnd, Info->BestObjectName); else PhShowError(hWnd, L"Unable to open key because the object is unnamed."); } else if (PhEqualString2(Info->TypeName, L"Process", TRUE)) { HANDLE processHandle; HANDLE processId; PPH_PROCESS_ITEM targetProcessItem; processId = NULL; if (KphIsConnected()) { if (NT_SUCCESS(PhOpenProcess( &processHandle, PROCESS_QUERY_LIMITED_INFORMATION, Info->ProcessId ))) { PROCESS_BASIC_INFORMATION basicInfo; if (NT_SUCCESS(KphQueryInformationObject( processHandle, Info->Handle, KphObjectProcessBasicInformation, &basicInfo, sizeof(PROCESS_BASIC_INFORMATION), NULL ))) { processId = basicInfo.UniqueProcessId; } NtClose(processHandle); } } else { HANDLE handle; PROCESS_BASIC_INFORMATION basicInfo; if (NT_SUCCESS(PhpDuplicateHandleFromProcessItem( &handle, PROCESS_QUERY_LIMITED_INFORMATION, Info->ProcessId, Info->Handle ))) { if (NT_SUCCESS(PhGetProcessBasicInformation(handle, &basicInfo))) processId = basicInfo.UniqueProcessId; NtClose(handle); } } if (processId) { targetProcessItem = PhReferenceProcessItem(processId); if (targetProcessItem) { ProcessHacker_ShowProcessProperties(PhMainWndHandle, targetProcessItem); PhDereferenceObject(targetProcessItem); } else { PhShowError(hWnd, L"The process does not exist."); } } } else if (PhEqualString2(Info->TypeName, L"Section", TRUE)) { NTSTATUS status; HANDLE handle = NULL; BOOLEAN readOnly = FALSE; if (!NT_SUCCESS(status = PhpDuplicateHandleFromProcessItem( &handle, SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE, Info->ProcessId, Info->Handle ))) { status = PhpDuplicateHandleFromProcessItem( &handle, SECTION_QUERY | SECTION_MAP_READ, Info->ProcessId, Info->Handle ); readOnly = TRUE; } if (handle) { PPH_STRING sectionName = NULL; SECTION_BASIC_INFORMATION basicInfo; SIZE_T viewSize = PH_MAX_SECTION_EDIT_SIZE; PVOID viewBase = NULL; BOOLEAN tooBig = FALSE; PhGetHandleInformation(NtCurrentProcess(), handle, ULONG_MAX, NULL, NULL, NULL, §ionName); if (NT_SUCCESS(status = PhGetSectionBasicInformation(handle, &basicInfo))) { if (basicInfo.MaximumSize.QuadPart <= PH_MAX_SECTION_EDIT_SIZE) viewSize = (SIZE_T)basicInfo.MaximumSize.QuadPart; else tooBig = TRUE; status = NtMapViewOfSection( handle, NtCurrentProcess(), &viewBase, 0, 0, NULL, &viewSize, ViewShare, 0, readOnly ? PAGE_READONLY : PAGE_READWRITE ); if (status == STATUS_SECTION_PROTECTION && !readOnly) { status = NtMapViewOfSection( handle, NtCurrentProcess(), &viewBase, 0, 0, NULL, &viewSize, ViewShare, 0, PAGE_READONLY ); } if (NT_SUCCESS(status)) { PPH_SHOW_MEMORY_EDITOR showMemoryEditor = PhAllocate(sizeof(PH_SHOW_MEMORY_EDITOR)); if (tooBig) PhShowWarning(hWnd, L"The section size is greater than 32 MB. Only the first 32 MB will be available for editing."); memset(showMemoryEditor, 0, sizeof(PH_SHOW_MEMORY_EDITOR)); showMemoryEditor->ProcessId = NtCurrentProcessId(); showMemoryEditor->BaseAddress = viewBase; showMemoryEditor->RegionSize = viewSize; showMemoryEditor->SelectOffset = ULONG_MAX; showMemoryEditor->SelectLength = 0; showMemoryEditor->Title = sectionName ? PhConcatStrings2(L"Section - ", sectionName->Buffer) : PhCreateString(L"Section"); showMemoryEditor->Flags = PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION; ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor); } else { PhShowStatus(hWnd, L"Unable to map a view of the section.", status, 0); } } PhClearReference(§ionName); NtClose(handle); } if (!NT_SUCCESS(status)) { PhShowStatus(hWnd, L"Unable to query the section.", status, 0); } } else if (PhEqualString2(Info->TypeName, L"Thread", TRUE)) { HANDLE processHandle; CLIENT_ID clientId; PPH_PROCESS_ITEM targetProcessItem; PPH_PROCESS_PROPCONTEXT propContext; clientId.UniqueProcess = NULL; clientId.UniqueThread = NULL; if (KphIsConnected()) { if (NT_SUCCESS(PhOpenProcess( &processHandle, PROCESS_QUERY_LIMITED_INFORMATION, Info->ProcessId ))) { THREAD_BASIC_INFORMATION basicInfo; if (NT_SUCCESS(KphQueryInformationObject( processHandle, Info->Handle, KphObjectThreadBasicInformation, &basicInfo, sizeof(THREAD_BASIC_INFORMATION), NULL ))) { clientId = basicInfo.ClientId; } NtClose(processHandle); } } else { HANDLE handle; THREAD_BASIC_INFORMATION basicInfo; if (NT_SUCCESS(PhpDuplicateHandleFromProcessItem( &handle, THREAD_QUERY_LIMITED_INFORMATION, Info->ProcessId, Info->Handle ))) { if (NT_SUCCESS(PhGetThreadBasicInformation(handle, &basicInfo))) clientId = basicInfo.ClientId; NtClose(handle); } } if (clientId.UniqueProcess) { targetProcessItem = PhReferenceProcessItem(clientId.UniqueProcess); if (targetProcessItem) { propContext = PhCreateProcessPropContext(NULL, targetProcessItem); PhDereferenceObject(targetProcessItem); PhSetSelectThreadIdProcessPropContext(propContext, clientId.UniqueThread); ProcessHacker_Invoke(PhMainWndHandle, PhpShowProcessPropContext, propContext); } else { PhShowError(hWnd, L"The process does not exist."); } } } }