INT_PTR CALLBACK PhpMemoryEditorDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PMEMORY_EDITOR_CONTEXT context; if (uMsg != WM_INITDIALOG) { context = GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PMEMORY_EDITOR_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { NTSTATUS status; if (context->Title) { SetWindowText(hwndDlg, context->Title->Buffer); } else { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(context->ProcessId)) { SetWindowText(hwndDlg, PhaFormatString(L"%s (%u) (0x%Ix - 0x%Ix)", processItem->ProcessName->Buffer, HandleToUlong(context->ProcessId), context->BaseAddress, (ULONG_PTR)context->BaseAddress + context->RegionSize)->Buffer); PhDereferenceObject(processItem); } } PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); if (context->RegionSize > 1024 * 1024 * 1024) // 1 GB { PhShowError(NULL, L"Unable to edit the memory region because it is too large."); return TRUE; } if (!NT_SUCCESS(status = PhOpenProcess( &context->ProcessHandle, PROCESS_VM_READ, context->ProcessId ))) { PhShowStatus(NULL, L"Unable to open the process", status, 0); return TRUE; } context->Buffer = PhAllocatePage(context->RegionSize, NULL); if (!context->Buffer) { PhShowError(NULL, L"Unable to allocate memory for the buffer."); return TRUE; } if (!NT_SUCCESS(status = PhReadVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(PhMainWndHandle, L"Unable to read memory", status, 0); return TRUE; } PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_BYTESPERROW), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_GOTO), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_WRITE), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_REREAD), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 290; rect.bottom = 140; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } context->HexEditHandle = GetDlgItem(hwndDlg, IDC_MEMORY); PhAddLayoutItem(&context->LayoutManager, context->HexEditHandle, NULL, PH_ANCHOR_ALL); HexEdit_SetBuffer(context->HexEditHandle, context->Buffer, (ULONG)context->RegionSize); { PH_RECTANGLE windowRectangle; windowRectangle.Position = PhGetIntegerPairSetting(L"MemEditPosition"); windowRectangle.Size = PhGetScalableIntegerPairSetting(L"MemEditSize", TRUE).Pair; PhAdjustRectangleToWorkingArea(NULL, &windowRectangle); MoveWindow(hwndDlg, windowRectangle.Left, windowRectangle.Top, windowRectangle.Width, windowRectangle.Height, FALSE); // Implement cascading by saving an offsetted rectangle. windowRectangle.Left += 20; windowRectangle.Top += 20; PhSetIntegerPairSetting(L"MemEditPosition", windowRectangle.Position); PhSetScalableIntegerPairSetting2(L"MemEditSize", windowRectangle.Size); } { PWSTR bytesPerRowStrings[7]; ULONG i; ULONG bytesPerRow; for (i = 0; i < sizeof(bytesPerRowStrings) / sizeof(PWSTR); i++) bytesPerRowStrings[i] = PhaFormatString(L"%u bytes per row", 1 << (2 + i))->Buffer; PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_BYTESPERROW), bytesPerRowStrings, sizeof(bytesPerRowStrings) / sizeof(PWSTR)); bytesPerRow = PhGetIntegerSetting(L"MemEditBytesPerRow"); if (bytesPerRow >= 4) { HexEdit_SetBytesPerRow(context->HexEditHandle, bytesPerRow); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_BYTESPERROW), PhaFormatString(L"%u bytes per row", bytesPerRow)->Buffer, FALSE); } } context->LoadCompleted = TRUE; } break; case WM_DESTROY: { if (context->LoadCompleted) { PhSaveWindowPlacementToSetting(L"MemEditPosition", L"MemEditSize", hwndDlg); PhRemoveElementAvlTree(&PhMemoryEditorSet, &context->Links); PhUnregisterDialog(hwndDlg); } RemoveProp(hwndDlg, PhMakeContextAtom()); PhDeleteLayoutManager(&context->LayoutManager); if (context->Buffer) PhFreePage(context->Buffer); if (context->ProcessHandle) NtClose(context->ProcessHandle); PhClearReference(&context->Title); if ((context->Flags & PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION) && context->ProcessId == NtCurrentProcessId()) NtUnmapViewOfSection(NtCurrentProcess(), context->BaseAddress); PhFree(context); } break; case WM_SHOWWINDOW: { SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: DestroyWindow(hwndDlg); break; case IDC_SAVE: { static PH_FILETYPE_FILTER filters[] = { { L"Binary files (*.bin)", L"*.bin" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_PROCESS_ITEM processItem; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); if (!context->Title && (processItem = PhReferenceProcessItem(context->ProcessId))) { PhSetFileDialogFileName(fileDialog, PhaFormatString(L"%s_0x%Ix-0x%Ix.bin", processItem->ProcessName->Buffer, context->BaseAddress, context->RegionSize)->Buffer); PhDereferenceObject(processItem); } else { PhSetFileDialogFileName(fileDialog, L"Memory.bin"); } if (PhShowFileDialog(hwndDlg, fileDialog)) { NTSTATUS status; PPH_STRING fileName; PPH_FILE_STREAM fileStream; fileName = PH_AUTO(PhGetFileDialogFileName(fileDialog)); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { status = PhWriteFileStream(fileStream, context->Buffer, (ULONG)context->RegionSize); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; case IDC_GOTO: { PPH_STRING selectedChoice = NULL; while (PhaChoiceDialog( hwndDlg, L"Go to Offset", L"Enter an offset:", NULL, 0, NULL, PH_CHOICE_DIALOG_USER_CHOICE, &selectedChoice, NULL, L"MemEditGotoChoices" )) { ULONG64 offset; if (selectedChoice->Length == 0) continue; if (PhStringToInteger64(&selectedChoice->sr, 0, &offset)) { if (offset >= context->RegionSize) { PhShowError(hwndDlg, L"The offset is too large."); continue; } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); HexEdit_SetSel(context->HexEditHandle, (LONG)offset, (LONG)offset); break; } } } break; case IDC_WRITE: { NTSTATUS status; if (!context->WriteAccess) { HANDLE processHandle; if (!NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_VM_READ | PROCESS_VM_WRITE, context->ProcessId ))) { PhShowStatus(hwndDlg, L"Unable to open the process", status, 0); break; } if (context->ProcessHandle) NtClose(context->ProcessHandle); context->ProcessHandle = processHandle; context->WriteAccess = TRUE; } if (!NT_SUCCESS(status = PhWriteVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(hwndDlg, L"Unable to write memory", status, 0); } } break; case IDC_REREAD: { NTSTATUS status; if (!NT_SUCCESS(status = PhReadVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(hwndDlg, L"Unable to read memory", status, 0); } InvalidateRect(context->HexEditHandle, NULL, TRUE); } break; case IDC_BYTESPERROW: if (HIWORD(wParam) == CBN_SELCHANGE) { PPH_STRING bytesPerRowString = PhaGetDlgItemText(hwndDlg, IDC_BYTESPERROW); PH_STRINGREF firstPart; PH_STRINGREF secondPart; ULONG64 bytesPerRow64; if (PhSplitStringRefAtChar(&bytesPerRowString->sr, ' ', &firstPart, &secondPart)) { if (PhStringToInteger64(&firstPart, 10, &bytesPerRow64)) { PhSetIntegerSetting(L"MemEditBytesPerRow", (ULONG)bytesPerRow64); HexEdit_SetBytesPerRow(context->HexEditHandle, (ULONG)bytesPerRow64); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); } } } break; } } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_PH_SELECT_OFFSET: { HexEdit_SetEditMode(context->HexEditHandle, EDIT_ASCII); HexEdit_SetSel(context->HexEditHandle, (ULONG)wParam, (ULONG)wParam + (ULONG)lParam); } break; } return FALSE; }
VOID PhSvcHandleConnectionRequest( _In_ PPORT_MESSAGE PortMessage ) { NTSTATUS status; PPHSVC_API_MSG message; PPHSVC_API_MSG64 message64; CLIENT_ID clientId; PPHSVC_CLIENT client; HANDLE portHandle; REMOTE_PORT_VIEW clientView; REMOTE_PORT_VIEW64 clientView64; PREMOTE_PORT_VIEW actualClientView; message = (PPHSVC_API_MSG)PortMessage; message64 = (PPHSVC_API_MSG64)PortMessage; if (PhIsExecutingInWow64()) { clientId.UniqueProcess = (HANDLE)message64->h.ClientId.UniqueProcess; clientId.UniqueThread = (HANDLE)message64->h.ClientId.UniqueThread; } else { PPH_STRING referenceFileName; PPH_STRING remoteFileName; clientId = message->h.ClientId; // Make sure that the remote process is Process Hacker itself and not some other program. referenceFileName = NULL; PhGetProcessImageFileNameByProcessId(NtCurrentProcessId(), &referenceFileName); PH_AUTO(referenceFileName); remoteFileName = NULL; PhGetProcessImageFileNameByProcessId(clientId.UniqueProcess, &remoteFileName); PH_AUTO(remoteFileName); if (!referenceFileName || !remoteFileName || !PhEqualString(referenceFileName, remoteFileName, TRUE)) { NtAcceptConnectPort(&portHandle, NULL, PortMessage, FALSE, NULL, NULL); return; } } client = PhSvcCreateClient(&clientId); if (!client) { NtAcceptConnectPort(&portHandle, NULL, PortMessage, FALSE, NULL, NULL); return; } if (PhIsExecutingInWow64()) { message64->p.ConnectInfo.ServerProcessId = HandleToUlong(NtCurrentProcessId()); clientView64.Length = sizeof(REMOTE_PORT_VIEW64); clientView64.ViewSize = 0; clientView64.ViewBase = 0; actualClientView = (PREMOTE_PORT_VIEW)&clientView64; } else { message->p.ConnectInfo.ServerProcessId = HandleToUlong(NtCurrentProcessId()); clientView.Length = sizeof(REMOTE_PORT_VIEW); clientView.ViewSize = 0; clientView.ViewBase = NULL; actualClientView = &clientView; } status = NtAcceptConnectPort( &portHandle, client, PortMessage, TRUE, NULL, actualClientView ); if (!NT_SUCCESS(status)) { PhDereferenceObject(client); return; } // IMPORTANT: Since Vista, NtCompleteConnectPort does not do anything and simply returns STATUS_SUCCESS. // We will call it anyway (for completeness), but we need to use an event to ensure that other threads don't try // to process requests before we have finished setting up the client object. client->PortHandle = portHandle; if (PhIsExecutingInWow64()) { client->ClientViewBase = (PVOID)clientView64.ViewBase; client->ClientViewLimit = (PCHAR)clientView64.ViewBase + (ULONG)clientView64.ViewSize; } else { client->ClientViewBase = clientView.ViewBase; client->ClientViewLimit = (PCHAR)clientView.ViewBase + clientView.ViewSize; } NtCompleteConnectPort(portHandle); PhSetEvent(&client->ReadyEvent); if (_InterlockedIncrement(&PhSvcApiNumberOfClients) == 1) { NtSetEvent(PhSvcTimeoutCancelEventHandle, NULL); } }
VOID PhShowMemoryEditorDialog( _In_ HWND OwnerWindow, _In_ HANDLE ProcessId, _In_ PVOID BaseAddress, _In_ SIZE_T RegionSize, _In_ ULONG SelectOffset, _In_ ULONG SelectLength, _In_opt_ PPH_STRING Title, _In_ ULONG Flags ) { PMEMORY_EDITOR_CONTEXT context; MEMORY_EDITOR_CONTEXT lookupContext; PPH_AVL_LINKS links; lookupContext.ProcessId = ProcessId; lookupContext.BaseAddress = BaseAddress; lookupContext.RegionSize = RegionSize; links = PhFindElementAvlTree(&PhMemoryEditorSet, &lookupContext.Links); if (!links) { context = PhAllocate(sizeof(MEMORY_EDITOR_CONTEXT)); memset(context, 0, sizeof(MEMORY_EDITOR_CONTEXT)); context->OwnerHandle = OwnerWindow; context->ProcessId = ProcessId; context->BaseAddress = BaseAddress; context->RegionSize = RegionSize; context->SelectOffset = SelectOffset; PhSwapReference(&context->Title, Title); context->Flags = Flags; context->WindowHandle = CreateDialogParam( PhInstanceHandle, MAKEINTRESOURCE(IDD_MEMEDIT), NULL, PhpMemoryEditorDlgProc, (LPARAM)context ); if (!context->LoadCompleted) { DestroyWindow(context->WindowHandle); return; } if (SelectOffset != -1) PostMessage(context->WindowHandle, WM_PH_SELECT_OFFSET, SelectOffset, SelectLength); PhRegisterDialog(context->WindowHandle); PhAddElementAvlTree(&PhMemoryEditorSet, &context->Links); ShowWindow(context->WindowHandle, SW_SHOW); SetForegroundWindow(context->WindowHandle); } else { context = CONTAINING_RECORD(links, MEMORY_EDITOR_CONTEXT, Links); if (IsIconic(context->WindowHandle)) ShowWindow(context->WindowHandle, SW_RESTORE); else SetForegroundWindow(context->WindowHandle); if (SelectOffset != -1) PostMessage(context->WindowHandle, WM_PH_SELECT_OFFSET, SelectOffset, SelectLength); // Just in case. if ((Flags & PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION) && ProcessId == NtCurrentProcessId()) NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); } }
NTSTATUS PhpThreadProviderLoadSymbols( __in PVOID Parameter ) { PPH_THREAD_PROVIDER threadProvider = (PPH_THREAD_PROVIDER)Parameter; PH_THREAD_SYMBOL_LOAD_CONTEXT loadContext; loadContext.ThreadProvider = threadProvider; loadContext.SymbolProvider = threadProvider->SymbolProvider; PhLoadSymbolProviderOptions(threadProvider->SymbolProvider); if (threadProvider->ProcessId != SYSTEM_IDLE_PROCESS_ID) { if ( threadProvider->SymbolProvider->IsRealHandle || threadProvider->ProcessId == SYSTEM_PROCESS_ID ) { loadContext.ProcessId = threadProvider->ProcessId; PhEnumGenericModules( threadProvider->ProcessId, threadProvider->SymbolProvider->ProcessHandle, 0, LoadSymbolsEnumGenericModulesCallback, &loadContext ); } else { // We can't enumerate the process modules. Load // symbols for ntdll.dll and kernel32.dll. loadContext.ProcessId = NtCurrentProcessId(); PhEnumGenericModules( NtCurrentProcessId(), NtCurrentProcess(), 0, LoadBasicSymbolsEnumGenericModulesCallback, &loadContext ); } // Load kernel module symbols as well. if (threadProvider->ProcessId != SYSTEM_PROCESS_ID) { loadContext.ProcessId = SYSTEM_PROCESS_ID; PhEnumGenericModules( SYSTEM_PROCESS_ID, NULL, 0, LoadSymbolsEnumGenericModulesCallback, &loadContext ); } } else { // System Idle Process has one thread for each CPU, // each having a start address at KiIdleLoop. We // need to load symbols for the kernel. PRTL_PROCESS_MODULES kernelModules; if (NT_SUCCESS(PhEnumKernelModules(&kernelModules))) { if (kernelModules->NumberOfModules > 0) { PPH_STRING fileName; PPH_STRING newFileName; fileName = PhCreateStringFromAnsi(kernelModules->Modules[0].FullPathName); newFileName = PhGetFileName(fileName); PhDereferenceObject(fileName); PhLoadModuleSymbolProvider( threadProvider->SymbolProvider, newFileName->Buffer, (ULONG64)kernelModules->Modules[0].ImageBase, kernelModules->Modules[0].ImageSize ); PhDereferenceObject(newFileName); } PhFree(kernelModules); } } // Check if the process has services - we'll need to know before getting service tag/name // information. if (WINDOWS_HAS_SERVICE_TAGS) { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(threadProvider->ProcessId)) { threadProvider->HasServices = processItem->ServiceList && processItem->ServiceList->Count != 0; PhDereferenceObject(processItem); } } PhSetEvent(&threadProvider->SymbolsLoadedEvent); PhDereferenceObject(threadProvider); return STATUS_SUCCESS; }
VOID PhLoadSymbolsThreadProvider( _In_ PPH_THREAD_PROVIDER ThreadProvider ) { PH_THREAD_SYMBOL_LOAD_CONTEXT loadContext; ULONG64 runId; loadContext.ThreadProvider = ThreadProvider; loadContext.SymbolProvider = ThreadProvider->SymbolProvider; PhAcquireQueuedLockExclusive(&ThreadProvider->LoadSymbolsLock); runId = ThreadProvider->RunId; PhLoadSymbolProviderOptions(ThreadProvider->SymbolProvider); if (ThreadProvider->ProcessId != SYSTEM_IDLE_PROCESS_ID) { if (ThreadProvider->SymbolProvider->IsRealHandle || ThreadProvider->ProcessId == SYSTEM_PROCESS_ID) { loadContext.ProcessId = ThreadProvider->ProcessId; PhEnumGenericModules( ThreadProvider->ProcessId, ThreadProvider->SymbolProvider->ProcessHandle, 0, LoadSymbolsEnumGenericModulesCallback, &loadContext ); } else { // We can't enumerate the process modules. Load // symbols for ntdll.dll and kernel32.dll. loadContext.ProcessId = NtCurrentProcessId(); PhEnumGenericModules( NtCurrentProcessId(), NtCurrentProcess(), 0, LoadBasicSymbolsEnumGenericModulesCallback, &loadContext ); } // Load kernel module symbols as well. if (ThreadProvider->ProcessId != SYSTEM_PROCESS_ID) { loadContext.ProcessId = SYSTEM_PROCESS_ID; PhEnumGenericModules( SYSTEM_PROCESS_ID, NULL, 0, LoadSymbolsEnumGenericModulesCallback, &loadContext ); } } else { // System Idle Process has one thread for each CPU, // each having a start address at KiIdleLoop. We // need to load symbols for the kernel. PRTL_PROCESS_MODULES kernelModules; if (NT_SUCCESS(PhEnumKernelModules(&kernelModules))) { if (kernelModules->NumberOfModules > 0) { PPH_STRING fileName; PPH_STRING newFileName; fileName = PhConvertMultiByteToUtf16(kernelModules->Modules[0].FullPathName); newFileName = PhGetFileName(fileName); PhDereferenceObject(fileName); PhLoadModuleSymbolProvider( ThreadProvider->SymbolProvider, newFileName->Buffer, (ULONG64)kernelModules->Modules[0].ImageBase, kernelModules->Modules[0].ImageSize ); PhDereferenceObject(newFileName); } PhFree(kernelModules); } } ThreadProvider->SymbolsLoadedRunId = runId; PhReleaseQueuedLockExclusive(&ThreadProvider->LoadSymbolsLock); }
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."); } } } }