PPH_STRING PhpGetThreadBasicStartAddress( __in PPH_THREAD_PROVIDER ThreadProvider, __in ULONG64 Address, __out PPH_SYMBOL_RESOLVE_LEVEL ResolveLevel ) { ULONG64 modBase; PPH_STRING fileName = NULL; PPH_STRING baseName = NULL; PPH_STRING symbol; modBase = PhGetModuleFromAddress( ThreadProvider->SymbolProvider, Address, &fileName ); if (fileName == NULL) { *ResolveLevel = PhsrlAddress; symbol = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2); PhPrintPointer(symbol->Buffer, (PVOID)Address); PhTrimToNullTerminatorString(symbol); } else { PH_FORMAT format[3]; baseName = PhGetBaseName(fileName); *ResolveLevel = PhsrlModule; PhInitFormatSR(&format[0], baseName->sr); PhInitFormatS(&format[1], L"+0x"); PhInitFormatIX(&format[2], (ULONG_PTR)(Address - modBase)); symbol = PhFormat(format, 3, baseName->Length + 6 + 32); } if (fileName) PhDereferenceObject(fileName); if (baseName) PhDereferenceObject(baseName); return symbol; }
VOID PhpHandlePluginLoadError( _In_ PPH_STRING FileName, _In_opt_ PPH_STRING ErrorMessage ) { PPH_STRING baseName; baseName = PhGetBaseName(FileName); if (PhShowMessage( NULL, MB_ICONERROR | MB_YESNO, L"Unable to load %s: %s\nDo you want to disable the plugin?", baseName->Buffer, PhGetStringOrDefault(ErrorMessage, L"An unknown error occurred.") ) == IDYES) { PhSetPluginDisabled(&baseName->sr, TRUE); } PhDereferenceObject(baseName); }
static PPH_STRING EtpGetBasicSymbol( _In_ PPH_SYMBOL_PROVIDER SymbolProvider, _In_ ULONG64 Address ) { ULONG64 modBase; PPH_STRING fileName = NULL; PPH_STRING baseName = NULL; PPH_STRING symbol; modBase = PhGetModuleFromAddress(SymbolProvider, Address, &fileName); if (!fileName) { symbol = PhCreateStringEx(NULL, PH_PTR_STR_LEN * 2); PhPrintPointer(symbol->Buffer, (PVOID)Address); PhTrimToNullTerminatorString(symbol); } else { PH_FORMAT format[3]; baseName = PhGetBaseName(fileName); PhInitFormatSR(&format[0], baseName->sr); PhInitFormatS(&format[1], L"+0x"); PhInitFormatIX(&format[2], (ULONG_PTR)(Address - modBase)); symbol = PhFormat(format, 3, baseName->Length + 6 + 32); } if (fileName) PhDereferenceObject(fileName); if (baseName) PhDereferenceObject(baseName); return symbol; }
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; }
/** * Loads plugins from the default plugins directory. */ VOID PhLoadPlugins( VOID ) { HANDLE pluginsDirectoryHandle; PPH_STRING pluginsDirectory; pluginsDirectory = PhGetStringSetting(L"PluginsDirectory"); if (RtlDetermineDosPathNameType_U(pluginsDirectory->Buffer) == RtlPathTypeRelative) { // Not absolute. Make sure it is. PluginsDirectory = PhConcatStrings(4, PhApplicationDirectory->Buffer, L"\\", pluginsDirectory->Buffer, L"\\"); PhDereferenceObject(pluginsDirectory); } else { PluginsDirectory = pluginsDirectory; } if (NT_SUCCESS(PhCreateFileWin32( &pluginsDirectoryHandle, PluginsDirectory->Buffer, FILE_GENERIC_READ, 0, FILE_SHARE_READ, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { UNICODE_STRING pattern = RTL_CONSTANT_STRING(L"*.dll"); PhEnumDirectoryFile(pluginsDirectoryHandle, &pattern, EnumPluginsDirectoryCallback, NULL); NtClose(pluginsDirectoryHandle); } // Handle load errors. // In certain startup modes we want to ignore all plugin load errors. if (LoadErrors && LoadErrors->Count != 0 && !PhStartupParameters.PhSvc) { PH_STRING_BUILDER sb; ULONG i; PPHP_PLUGIN_LOAD_ERROR loadError; PPH_STRING baseName; PhInitializeStringBuilder(&sb, 100); PhAppendStringBuilder2(&sb, L"Unable to load the following plugin(s):\n\n"); for (i = 0; i < LoadErrors->Count; i++) { loadError = LoadErrors->Items[i]; baseName = PhGetBaseName(loadError->FileName); PhAppendFormatStringBuilder(&sb, L"%s: %s\n", baseName->Buffer, PhGetStringOrDefault(loadError->ErrorMessage, L"An unknown error occurred.")); PhDereferenceObject(baseName); } PhAppendStringBuilder2(&sb, L"\nDo you want to disable the above plugin(s)?"); if (PhShowMessage( NULL, MB_ICONERROR | MB_YESNO, sb.String->Buffer ) == IDYES) { ULONG i; for (i = 0; i < LoadErrors->Count; i++) { loadError = LoadErrors->Items[i]; baseName = PhGetBaseName(loadError->FileName); PhSetPluginDisabled(&baseName->sr, TRUE); PhDereferenceObject(baseName); } } PhDeleteStringBuilder(&sb); } // When we loaded settings before, we didn't know about plugin settings, so they // went into the ignored settings list. Now that they've had a chance to add // settings, we should scan the ignored settings list and move the settings to // the right places. if (PhSettingsFileName) PhConvertIgnoredSettings(); PhpExecuteCallbackForAllPlugins(PluginCallbackLoad, TRUE); }
static PPH_PROCESS_ITEM PhpCreateProcessItemForHiddenProcess( _In_ PPH_HIDDEN_PROCESS_ENTRY Entry ) { NTSTATUS status; PPH_PROCESS_ITEM processItem; PPH_PROCESS_ITEM idleProcessItem; HANDLE processHandle; PROCESS_BASIC_INFORMATION basicInfo; KERNEL_USER_TIMES times; PROCESS_PRIORITY_CLASS priorityClass; ULONG handleCount; HANDLE processHandle2; if (Entry->Type == NormalProcess) { processItem = PhReferenceProcessItem(Entry->ProcessId); if (processItem) return processItem; } processItem = PhCreateProcessItem(Entry->ProcessId); // Mark the process as terminated if necessary. if (Entry->Type == TerminatedProcess) processItem->State |= PH_PROCESS_ITEM_REMOVED; // We need a process record. Just use the record of System Idle Process. if (idleProcessItem = PhReferenceProcessItem(SYSTEM_IDLE_PROCESS_ID)) { processItem->Record = idleProcessItem->Record; PhReferenceProcessRecord(processItem->Record); } else { PhDereferenceObject(processItem); return NULL; } // Set up the file name and process name. PhSwapReference(&processItem->FileName, Entry->FileName); if (processItem->FileName) { processItem->ProcessName = PhGetBaseName(processItem->FileName); } else { processItem->ProcessName = PhCreateString(L"Unknown"); } if (ProcessesMethod == BruteForceScanMethod) { status = PhOpenProcess( &processHandle, ProcessQueryAccess, Entry->ProcessId ); } else { status = PhOpenProcessByCsrHandles( &processHandle, ProcessQueryAccess, Entry->ProcessId ); } if (NT_SUCCESS(status)) { // Basic information and not-so-dynamic information processItem->QueryHandle = processHandle; if (NT_SUCCESS(PhGetProcessBasicInformation(processHandle, &basicInfo))) { processItem->ParentProcessId = basicInfo.InheritedFromUniqueProcessId; processItem->BasePriority = basicInfo.BasePriority; } PhGetProcessSessionId(processHandle, &processItem->SessionId); PhPrintUInt32(processItem->ParentProcessIdString, HandleToUlong(processItem->ParentProcessId)); PhPrintUInt32(processItem->SessionIdString, processItem->SessionId); if (NT_SUCCESS(PhGetProcessTimes(processHandle, ×))) { processItem->CreateTime = times.CreateTime; processItem->KernelTime = times.KernelTime; processItem->UserTime = times.UserTime; } // TODO: Token information? if (NT_SUCCESS(NtQueryInformationProcess( processHandle, ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS), NULL ))) { processItem->PriorityClass = priorityClass.PriorityClass; } if (NT_SUCCESS(NtQueryInformationProcess( processHandle, ProcessHandleCount, &handleCount, sizeof(ULONG), NULL ))) { processItem->NumberOfHandles = handleCount; } } // Stage 1 // Some copy and paste magic here... if (processItem->FileName) { // Small icon, large icon. ExtractIconEx( processItem->FileName->Buffer, 0, &processItem->LargeIcon, &processItem->SmallIcon, 1 ); // Version info. PhInitializeImageVersionInfo(&processItem->VersionInfo, processItem->FileName->Buffer); } // Use the default EXE icon if we didn't get the file's icon. { if (!processItem->SmallIcon || !processItem->LargeIcon) { if (processItem->SmallIcon) { DestroyIcon(processItem->SmallIcon); processItem->SmallIcon = NULL; } else if (processItem->LargeIcon) { DestroyIcon(processItem->LargeIcon); processItem->LargeIcon = NULL; } PhGetStockApplicationIcon(&processItem->SmallIcon, &processItem->LargeIcon); processItem->SmallIcon = DuplicateIcon(NULL, processItem->SmallIcon); processItem->LargeIcon = DuplicateIcon(NULL, processItem->LargeIcon); } } // POSIX, command line status = PhOpenProcess( &processHandle2, ProcessQueryAccess | PROCESS_VM_READ, Entry->ProcessId ); if (NT_SUCCESS(status)) { BOOLEAN isPosix = FALSE; PPH_STRING commandLine; ULONG i; status = PhGetProcessIsPosix(processHandle2, &isPosix); processItem->IsPosix = isPosix; if (!NT_SUCCESS(status) || !isPosix) { status = PhGetProcessCommandLine(processHandle2, &commandLine); if (NT_SUCCESS(status)) { // Some command lines (e.g. from taskeng.exe) have nulls in them. // Since Windows can't display them, we'll replace them with // spaces. for (i = 0; i < (ULONG)commandLine->Length / 2; i++) { if (commandLine->Buffer[i] == 0) commandLine->Buffer[i] = ' '; } } } else { // Get the POSIX command line. status = PhGetProcessPosixCommandLine(processHandle2, &commandLine); } if (NT_SUCCESS(status)) { processItem->CommandLine = commandLine; } NtClose(processHandle2); } // TODO: Other stage 1 tasks. PhSetEvent(&processItem->Stage1Event); return processItem; }
static VOID DbgProcessLogMessageEntry( _Inout_ PPH_DBGEVENTS_CONTEXT Context, _In_ BOOLEAN GlobalEvents ) { NTSTATUS status; PDBWIN_PAGE_BUFFER debugMessageBuffer; PDEBUG_LOG_ENTRY entry = NULL; HANDLE processHandle = NULL; PPH_STRING fileName = NULL; HICON icon = NULL; debugMessageBuffer = GlobalEvents ? Context->GlobalDebugBuffer : Context->LocalDebugBuffer; entry = PhAllocate(sizeof(DEBUG_LOG_ENTRY)); memset(entry, 0, sizeof(DEBUG_LOG_ENTRY)); PhQuerySystemTime(&entry->Time); entry->ProcessId = UlongToHandle(debugMessageBuffer->ProcessId); entry->Message = PhConvertMultiByteToUtf16(debugMessageBuffer->Buffer); if (WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID) { status = PhGetProcessImageFileNameByProcessId(entry->ProcessId, &fileName); } else { if (NT_SUCCESS(status = PhOpenProcess(&processHandle, ProcessQueryAccess, entry->ProcessId))) { status = PhGetProcessImageFileName(processHandle, &fileName); NtClose(processHandle); } } if (!NT_SUCCESS(status)) fileName = PhGetKernelFileName(); PhSwapReference2(&fileName, PhGetFileName(fileName)); icon = PhGetFileShellIcon(PhGetString(fileName), L".exe", TRUE); if (icon) { entry->ImageIndex = ImageList_AddIcon(Context->ListViewImageList, icon); DestroyIcon(icon); } entry->FilePath = fileName; entry->ProcessName = PhGetBaseName(fileName); // Drop event if it matches a filter for (ULONG i = 0; i < Context->ExcludeList->Count; i++) { PDBG_FILTER_TYPE filterEntry = Context->ExcludeList->Items[i]; if (filterEntry->Type == FilterByName) { if (PhEqualString(filterEntry->ProcessName, entry->ProcessName, TRUE)) { DbgFreeLogEntry(entry); return; } } else if (filterEntry->Type == FilterByPid) { if (filterEntry->ProcessId == entry->ProcessId) { DbgFreeLogEntry(entry); return; } } } DbgAddLogEntry(Context, entry); }