/** * Locates a plugin instance structure. * * \param Name The name of the plugin. * * \return A plugin instance structure, or NULL if the plugin was not found. */ PPH_PLUGIN PhFindPlugin2( _In_ PPH_STRINGREF Name ) { PPH_AVL_LINKS links; PH_PLUGIN lookupPlugin; lookupPlugin.Name = *Name; links = PhFindElementAvlTree(&PhPluginsByName, &lookupPlugin.Links); if (links) return CONTAINING_RECORD(links, PH_PLUGIN, Links); else return NULL; }
BOOLEAN PhLoadModuleSymbolProvider( _In_ PPH_SYMBOL_PROVIDER SymbolProvider, _In_ PWSTR FileName, _In_ ULONG64 BaseAddress, _In_ ULONG Size ) { PPH_ANSI_STRING fileName; ULONG64 baseAddress; if (!SymLoadModule64_I) return FALSE; #ifdef PH_SYMBOL_PROVIDER_DELAY_INIT PhpRegisterSymbolProvider(SymbolProvider); #endif fileName = PhCreateAnsiStringFromUnicode(FileName); if (!fileName) return FALSE; PH_LOCK_SYMBOLS(); baseAddress = SymLoadModule64_I( SymbolProvider->ProcessHandle, NULL, fileName->Buffer, NULL, BaseAddress, Size ); PH_UNLOCK_SYMBOLS(); PhDereferenceObject(fileName); // Add the module to the list, even if we couldn't load // symbols for the module. { PPH_SYMBOL_MODULE symbolModule = NULL; PPH_AVL_LINKS existingLinks; PH_SYMBOL_MODULE lookupSymbolModule; lookupSymbolModule.BaseAddress = BaseAddress; PhAcquireQueuedLockExclusive(&SymbolProvider->ModulesListLock); // Check for duplicates. existingLinks = PhFindElementAvlTree(&SymbolProvider->ModulesSet, &lookupSymbolModule.Links); if (!existingLinks) { symbolModule = PhAllocate(sizeof(PH_SYMBOL_MODULE)); symbolModule->BaseAddress = BaseAddress; symbolModule->Size = Size; symbolModule->FileName = PhGetFullPath(FileName, &symbolModule->BaseNameIndex); existingLinks = PhAddElementAvlTree(&SymbolProvider->ModulesSet, &symbolModule->Links); assert(!existingLinks); InsertTailList(&SymbolProvider->ModulesListHead, &symbolModule->ListEntry); } PhReleaseQueuedLockExclusive(&SymbolProvider->ModulesListLock); } if (!baseAddress) { if (GetLastError() != ERROR_SUCCESS) return FALSE; else return TRUE; } return TRUE; }
PPH_STRING PhGetSymbolFromAddress( _In_ PPH_SYMBOL_PROVIDER SymbolProvider, _In_ ULONG64 Address, _Out_opt_ PPH_SYMBOL_RESOLVE_LEVEL ResolveLevel, _Out_opt_ PPH_STRING *FileName, _Out_opt_ PPH_STRING *SymbolName, _Out_opt_ PULONG64 Displacement ) { PSYMBOL_INFOW symbolInfo; ULONG nameLength; PPH_STRING symbol = NULL; PH_SYMBOL_RESOLVE_LEVEL resolveLevel; ULONG64 displacement; PPH_STRING modFileName = NULL; PPH_STRING modBaseName = NULL; ULONG64 modBase; PPH_STRING symbolName = NULL; if (!SymFromAddrW_I && !SymFromAddr_I) return NULL; if (Address == 0) { if (ResolveLevel) *ResolveLevel = PhsrlInvalid; if (FileName) *FileName = NULL; if (SymbolName) *SymbolName = NULL; if (Displacement) *Displacement = 0; return NULL; } #ifdef PH_SYMBOL_PROVIDER_DELAY_INIT PhpRegisterSymbolProvider(SymbolProvider); #endif symbolInfo = PhAllocate(FIELD_OFFSET(SYMBOL_INFOW, Name) + PH_MAX_SYMBOL_NAME_LEN * 2); memset(symbolInfo, 0, sizeof(SYMBOL_INFOW)); symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFOW); symbolInfo->MaxNameLen = PH_MAX_SYMBOL_NAME_LEN; // Get the symbol name. PH_LOCK_SYMBOLS(); // Note that we don't care whether this call // succeeds or not, based on the assumption that // it will not write to the symbolInfo structure // if it fails. We've already zeroed the structure, // so we can deal with it. if (SymFromAddrW_I) { SymFromAddrW_I( SymbolProvider->ProcessHandle, Address, &displacement, symbolInfo ); nameLength = symbolInfo->NameLen; if (nameLength + 1 > PH_MAX_SYMBOL_NAME_LEN) { PhFree(symbolInfo); symbolInfo = PhAllocate(FIELD_OFFSET(SYMBOL_INFOW, Name) + nameLength * 2 + 2); memset(symbolInfo, 0, sizeof(SYMBOL_INFOW)); symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFOW); symbolInfo->MaxNameLen = nameLength + 1; SymFromAddrW_I( SymbolProvider->ProcessHandle, Address, &displacement, symbolInfo ); } } else if (SymFromAddr_I) { PSYMBOL_INFO symbolInfoA; symbolInfoA = PhAllocate(FIELD_OFFSET(SYMBOL_INFO, Name) + PH_MAX_SYMBOL_NAME_LEN); memset(symbolInfoA, 0, sizeof(SYMBOL_INFO)); symbolInfoA->SizeOfStruct = sizeof(SYMBOL_INFO); symbolInfoA->MaxNameLen = PH_MAX_SYMBOL_NAME_LEN; SymFromAddr_I( SymbolProvider->ProcessHandle, Address, &displacement, symbolInfoA ); nameLength = symbolInfoA->NameLen; if (nameLength + 1 > PH_MAX_SYMBOL_NAME_LEN) { PhFree(symbolInfoA); symbolInfoA = PhAllocate(FIELD_OFFSET(SYMBOL_INFO, Name) + nameLength + 1); memset(symbolInfoA, 0, sizeof(SYMBOL_INFO)); symbolInfoA->SizeOfStruct = sizeof(SYMBOL_INFO); symbolInfoA->MaxNameLen = nameLength + 1; SymFromAddr_I( SymbolProvider->ProcessHandle, Address, &displacement, symbolInfoA ); // Also reallocate the Unicode-based buffer. PhFree(symbolInfo); symbolInfo = PhAllocate(FIELD_OFFSET(SYMBOL_INFOW, Name) + nameLength * 2 + 2); memset(symbolInfo, 0, sizeof(SYMBOL_INFOW)); symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFOW); symbolInfo->MaxNameLen = nameLength + 1; } PhpSymbolInfoAnsiToUnicode(symbolInfo, symbolInfoA); PhFree(symbolInfoA); } PH_UNLOCK_SYMBOLS(); // Find the module name. if (symbolInfo->ModBase == 0) { modBase = PhGetModuleFromAddress( SymbolProvider, Address, &modFileName ); } else { PH_SYMBOL_MODULE lookupSymbolModule; PPH_AVL_LINKS existingLinks; PPH_SYMBOL_MODULE symbolModule; lookupSymbolModule.BaseAddress = symbolInfo->ModBase; PhAcquireQueuedLockShared(&SymbolProvider->ModulesListLock); existingLinks = PhFindElementAvlTree(&SymbolProvider->ModulesSet, &lookupSymbolModule.Links); if (existingLinks) { symbolModule = CONTAINING_RECORD(existingLinks, PH_SYMBOL_MODULE, Links); modFileName = symbolModule->FileName; PhReferenceObject(modFileName); } PhReleaseQueuedLockShared(&SymbolProvider->ModulesListLock); } // If we don't have a module name, return an address. if (!modFileName) { resolveLevel = PhsrlAddress; symbol = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2); PhPrintPointer(symbol->Buffer, (PVOID)Address); PhTrimToNullTerminatorString(symbol); goto CleanupExit; } modBaseName = PhGetBaseName(modFileName); // If we have a module name but not a symbol name, // return the module plus an offset: module+offset. if (symbolInfo->NameLen == 0) { PH_FORMAT format[3]; resolveLevel = PhsrlModule; PhInitFormatSR(&format[0], modBaseName->sr); PhInitFormatS(&format[1], L"+0x"); PhInitFormatIX(&format[2], (ULONG_PTR)(Address - modBase)); symbol = PhFormat(format, 3, modBaseName->Length + 6 + 32); goto CleanupExit; } // If we have everything, return the full symbol // name: module!symbol+offset. symbolName = PhCreateStringEx( symbolInfo->Name, symbolInfo->NameLen * 2 ); resolveLevel = PhsrlFunction; if (displacement == 0) { PH_FORMAT format[3]; PhInitFormatSR(&format[0], modBaseName->sr); PhInitFormatC(&format[1], '!'); PhInitFormatSR(&format[2], symbolName->sr); symbol = PhFormat(format, 3, modBaseName->Length + 2 + symbolName->Length); } else { PH_FORMAT format[5]; PhInitFormatSR(&format[0], modBaseName->sr); PhInitFormatC(&format[1], '!'); PhInitFormatSR(&format[2], symbolName->sr); PhInitFormatS(&format[3], L"+0x"); PhInitFormatIX(&format[4], (ULONG_PTR)displacement); symbol = PhFormat(format, 5, modBaseName->Length + 2 + symbolName->Length + 6 + 32); } CleanupExit: if (ResolveLevel) *ResolveLevel = resolveLevel; if (FileName) { *FileName = modFileName; if (modFileName) PhReferenceObject(modFileName); } if (SymbolName) { *SymbolName = symbolName; if (symbolName) PhReferenceObject(symbolName); } if (Displacement) *Displacement = displacement; if (modFileName) PhDereferenceObject(modFileName); if (modBaseName) PhDereferenceObject(modBaseName); if (symbolName) PhDereferenceObject(symbolName); PhFree(symbolInfo); return symbol; }
VOID PhShowMemoryEditorDialog( _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->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); } 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); } }