StoreManager::StoreManager( ) /*++ Routine Description: Description. Arguments: - Return Value: None. --*/ { m_SmLogCtxOffset = GetFieldOffset("nt!_SM_GLOBALS", "StoreMgr.Log"); m_SmcCacheMgrOffset = GetFieldOffset("nt!_SM_GLOBALS", "CacheMgr"); if (!m_SmLogCtxOffset || !m_SmcCacheMgrOffset) { g_Ext->Dml("Error: Can't retrieve Store and Cache offsets.\n"); } m_SmGlobalsAddress = 0; if (g_Ext->m_Control->IsPointer64Bit() == S_OK) { m_SmpLogBufferSize = sizeof(SMP_LOG_BUFFER64); m_SmLogEntrySize = sizeof(SM_LOG_ENTRY64); } else { m_SmpLogBufferSize = sizeof(SMP_LOG_BUFFER32); m_SmLogEntrySize = sizeof(SM_LOG_ENTRY32); } g_Ext->m_Symbols->GetOffsetByName("nt!SmGlobals", &m_SmGlobalsAddress); }
void WDbgArk::InitCallbackCommands() { uint32_t timer_routine_offset = 0; if ( GetFieldOffset("nt!_IO_TIMER", "TimerRoutine", reinterpret_cast<PULONG>(&timer_routine_offset)) != 0 ) warn << wa::showqmark << __FUNCTION__ << ": GetFieldOffset failed with nt!_IO_TIMER.TimerRoutine" << endlwarn; uint32_t le_size = GetTypeSize("nt!_LIST_ENTRY"); m_system_cb_commands = { { { "image", { "nt!PspLoadImageNotifyRoutineCount", "nt!PspLoadImageNotifyRoutine", 0, 0, 0 } }, { "process", { "nt!PspCreateProcessNotifyRoutineCount", "nt!PspCreateProcessNotifyRoutine", 0, 0, 0 } }, { "thread", { "nt!PspCreateThreadNotifyRoutineCount", "nt!PspCreateThreadNotifyRoutine", 0, 0, 0 } }, { "registry", { "nt!CmpCallBackCount", "nt!CmpCallBackVector", GetCmCallbackItemFunctionOffset(), 0, 0 } }, { "bugcheck", { "", "nt!KeBugCheckCallbackListHead", le_size, 0, 0 } }, { "bugcheckreason", { "", "nt!KeBugCheckReasonCallbackListHead", le_size, 0, 0 } }, { "bugcheckaddpages", { "", "nt!KeBugCheckAddPagesCallbackListHead", le_size, 0, 0 } }, { "bugcheckaddremovepages", { "", "nt!KeBugCheckAddRemovePagesCallbackListHead", le_size, 0, 0 } }, { "powersetting", { "", "nt!PopRegisteredPowerSettingCallbacks", GetPowerCallbackItemFunctionOffset(), 0, 0 } }, { "kdppower", { "", "nt!KdpPowerListHead", le_size, 0, 0 } }, { "callbackdir", {} }, { "shutdown", { "", "nt!IopNotifyShutdownQueueHead", 0, 0, 0 } }, { "shutdownlast", { "", "nt!IopNotifyLastChanceShutdownQueueHead", 0, 0, 0 } }, { "drvreinit", { "", "nt!IopDriverReinitializeQueueHead", le_size + m_PtrSize, 0, 0 } }, { "bootdrvreinit", { "", "nt!IopBootDriverReinitializeQueueHead", le_size + m_PtrSize, 0, 0 } }, { "fschange", { "", "nt!IopFsNotifyChangeQueueHead", le_size + m_PtrSize, 0, 0 } }, { "nmi", { "", "nt!KiNmiCallbackListHead", m_PtrSize, 0, 0 } }, { "logonsessionroutine", { "", "nt!SeFileSystemNotifyRoutinesHead", m_PtrSize, 0, 0 } }, { "prioritycallback", { "nt!IopUpdatePriorityCallbackRoutineCount", "nt!IopUpdatePriorityCallbackRoutine", 0, 0, 0 } }, { "pnp", {} }, { "lego", { "", "nt!PspLegoNotifyRoutine", 0, 0, 0 } }, { "debugprint", { "", "nt!RtlpDebugPrintCallbackList", le_size, 0, 0 } }, { "alpcplog", { "", "nt!AlpcpLogCallbackListHead", le_size, 0, 0 } }, { "empcb", { "", "nt!EmpCallbackListHead", GetTypeSize("nt!_GUID"), 0, 0 } }, { "ioperf", { "", "nt!IopPerfIoTrackingListHead", le_size, 0, 0 } }, { "dbgklkmd", { "", "nt!DbgkLkmdCallbackArray", 0, 0, 0 } }, { "ioptimer", { "", "nt!IopTimerQueueHead", timer_routine_offset, 0, 0 } } } }; for ( auto &cb_pair : m_system_cb_commands ) { uint64_t offset_count = 0ULL; uint64_t offset_head = 0ULL; if ( !cb_pair.second.list_count_name.empty() ) { if ( m_sym_cache->GetSymbolOffset(cb_pair.second.list_count_name, true, &offset_count) ) cb_pair.second.list_count_address = offset_count; } if ( !cb_pair.second.list_head_name.empty() ) { if ( m_sym_cache->GetSymbolOffset(cb_pair.second.list_head_name, true, &offset_head) ) cb_pair.second.list_head_address = offset_head; } } }
std::vector<ModuleInfo> GetLoadedModules() { std::vector<ModuleInfo> info; ULONG cb; ULONG64 pebAddress = GetPebAddress(); if (IsTarget64()) { ULONG64 ldr; if (GetFieldValue(pebAddress, "ntdll!_PEB", "Ldr", ldr) != 0) { dprintf("read Ldr failed\n"); goto ERROR_EXIT; } ULONG offset; if (GetFieldOffset("ntdll!_PEB_LDR_DATA", "InMemoryOrderModuleList", &offset) != 0) { dprintf("GetFieldOffset(_PEB_LDR_DATA::InMemoryOrderModuleList) failed\n"); goto ERROR_EXIT; } ULONG64 headAddress = ldr + offset; LIST_ENTRY64 inMemoryOrderModuleList; if (GetFieldValue(ldr, "ntdll!_PEB_LDR_DATA", "InMemoryOrderModuleList", inMemoryOrderModuleList) != 0) { dprintf("read InMemoryOrderModuleList failed\n"); goto ERROR_EXIT; } LIST_ENTRY64 entry = inMemoryOrderModuleList; while (entry.Flink != headAddress) { ModuleInfo moduleInfo; ULONG64 address = entry.Flink; if (!READMEMORY(address, entry)) { dprintf("read entry at %p failed\n", address); goto ERROR_EXIT; } // LDR_DATA_TABLE_ENTRY at address - sizeof(entry) ULONG64 dllBase, sizeOfImage; if (GetFieldValue(address - sizeof(entry), "ntdll!_LDR_DATA_TABLE_ENTRY", "DllBase", dllBase) != 0) { dprintf("read DllBase around %p failed\n", address - sizeof(entry)); goto ERROR_EXIT; } moduleInfo.DllBase = dllBase; if (GetFieldValue(address - sizeof(entry), "ntdll!_LDR_DATA_TABLE_ENTRY", "SizeOfImage", sizeOfImage) != 0) { dprintf("read SizeOfImage around %p failed\n", address - sizeof(entry)); goto ERROR_EXIT; } moduleInfo.SizeOfImage = sizeOfImage; // UNICODE_STRING struct { USHORT Length; USHORT MaximumLength; ULONG64 Buffer; } fullDllName; if (GetFieldValue(address - sizeof(entry), "ntdll!_LDR_DATA_TABLE_ENTRY", "FullDllName", fullDllName) != 0) { dprintf("read FullDllName around %p failed\n", address - sizeof(entry)); goto ERROR_EXIT; } std::vector<wchar_t> unicode; unicode.resize(fullDllName.Length / sizeof(wchar_t)); if (!ReadMemory(fullDllName.Buffer, &unicode[0], fullDllName.Length, &cb) || cb != fullDllName.Length) { dprintf("read unicode at %p %d failed\n", fullDllName.Buffer, (int)fullDllName.Length); goto ERROR_EXIT; } int written = WideCharToMultiByte(CP_ACP, 0, &unicode[0], fullDllName.Length / sizeof(wchar_t), moduleInfo.FullDllName, sizeof(moduleInfo.FullDllName), NULL, NULL); if (written < 0 || written >= sizeof(moduleInfo.FullDllName)) { dprintf("WideCharToMultiByte returns %d\n", written); goto ERROR_EXIT; } moduleInfo.FullDllName[written] = '\0'; info.push_back(moduleInfo); } return info; } else { ULONG32 ldr; if (!READMEMORY(pebAddress + 0xc, ldr)) { dprintf("read Ldr failed\n"); goto ERROR_EXIT; } ULONG64 headAddress = ldr + 0x14; LIST_ENTRY32 inMemoryOrderModuleList; if (!READMEMORY(headAddress, inMemoryOrderModuleList)) { dprintf("read InMemoryOrderModuleList failed\n"); goto ERROR_EXIT; } LIST_ENTRY32 entry = inMemoryOrderModuleList; while (entry.Flink != headAddress) { ModuleInfo moduleInfo; ULONG64 address = entry.Flink; if (!READMEMORY(address, entry)) { dprintf("read entry at %p failed\n", address); goto ERROR_EXIT; } // LDR_DATA_TABLE_ENTRY at address - sizeof(entry) ULONG32 dllBase, sizeOfImage; if (!READMEMORY(address - sizeof(entry) + 0x18, dllBase)) { dprintf("read DllBase at %p failed\n", address - sizeof(entry) + 0x18); goto ERROR_EXIT; } moduleInfo.DllBase = dllBase; if (!READMEMORY(address - sizeof(entry) + 0x20, sizeOfImage)) { dprintf("read SizeOfImage at %p failed\n", address - sizeof(entry) + 0x20); goto ERROR_EXIT; } moduleInfo.SizeOfImage = sizeOfImage; // UNICODE_STRING struct { USHORT Length; USHORT MaximumLength; ULONG32 Buffer; } fullDllName; if (!READMEMORY(address - sizeof(entry) + 0x24, fullDllName)) { dprintf("read FullDllName at %p failed\n", address - sizeof(entry) + 0x24); goto ERROR_EXIT; } std::vector<wchar_t> unicode; unicode.resize(fullDllName.Length / sizeof(wchar_t)); if (!ReadMemory(fullDllName.Buffer, &unicode[0], fullDllName.Length, &cb) || cb != fullDllName.Length) { dprintf("read unicode at %p %d failed\n", (ULONG64)fullDllName.Buffer, (int)fullDllName.Length); goto ERROR_EXIT; } int written = WideCharToMultiByte(CP_ACP, 0, &unicode[0], fullDllName.Length / sizeof(wchar_t), moduleInfo.FullDllName, sizeof(moduleInfo.FullDllName), NULL, NULL); if (written < 0 || written >= sizeof(moduleInfo.FullDllName)) { dprintf("WideCharToMultiByte returns %d\n", written); goto ERROR_EXIT; } moduleInfo.FullDllName[written] = '\0'; info.push_back(moduleInfo); } return info; } ERROR_EXIT: info.clear(); return info; }
BOOLEAN ObReadObject( _In_ ULONG64 Object, _Out_ PHANDLE_OBJECT HandleObj ) /*++ Routine Description: Description. Arguments: Object - HandleObj - Return Value: BOOLEAN. --*/ { BOOLEAN Result = FALSE; LPWSTR ObjName = NULL; ULONG BodyOffset = 0; GetFieldOffset("nt!_OBJECT_HEADER", "Body", &BodyOffset); WCHAR TypeStr[64] = { 0 }; if ((!Object) || (!IsValid(Object))) return FALSE; if (!ObTypeInit) { ObjTypeTable = ExtRemoteTyped("(nt!_OBJECT_TYPE **)@$extin", GetExpression("nt!ObTypeIndexTable")); ObTypeInit = TRUE; } ULONG64 ObjHeaderAddr = Object - BodyOffset; if (!IsValid(ObjHeaderAddr)) return FALSE; ExtRemoteTyped ObjHeader("(nt!_OBJECT_HEADER *)@$extin", ObjHeaderAddr); HandleObj->ObjectPtr = Object; // ObjHeader.Field("Body").GetPointerTo().GetPtr(); if (ObjHeader.HasField("TypeIndex")) { HandleObj->ObjectTypeIndex = ObjHeader.Field("TypeIndex").GetChar(); if ((HandleObj->ObjectTypeIndex <= 1) || (HandleObj->ObjectTypeIndex >= 45)) return FALSE; ExtRemoteTypedEx::GetUnicodeString(ObjTypeTable.ArrayElement(HandleObj->ObjectTypeIndex).Field("Name"), TypeStr, sizeof(TypeStr)); wcscpy_s(HandleObj->Type, TypeStr); } else { if (!IsValid(ObjHeader.Field("Type").GetPtr())) goto CleanUp; ExtRemoteTypedEx::GetUnicodeString(ObjHeader.Field("Type").Field("Name"), TypeStr, sizeof(TypeStr)); wcscpy_s(HandleObj->Type, TypeStr); } if (_wcsicmp(TypeStr, L"File") == 0) { ExtRemoteTyped FileObject("(nt!_FILE_OBJECT *)@$extin", HandleObj->ObjectPtr); ObjName = ExtRemoteTypedEx::GetUnicodeString2(FileObject.Field("FileName")); } else if (_wcsicmp(TypeStr, L"Driver") == 0) { ExtRemoteTyped DrvObject("(nt!_DRIVER_OBJECT *)@$extin", HandleObj->ObjectPtr); ObjName = ExtRemoteTypedEx::GetUnicodeString2(DrvObject.Field("DriverName")); } else if (_wcsicmp(TypeStr, L"Process") == 0) { ExtRemoteTyped ProcessObj("(nt!_EPROCESS *)@$extin", HandleObj->ObjectPtr); ObjName = ExtRemoteTypedEx::GetUnicodeString2(ProcessObj.Field("ImageFileName")); } else if (_wcsicmp(TypeStr, L"ALPC Port") == 0) { // dt nt!_ALPC_PORT } else if (_wcsicmp(TypeStr, L"EtwRegistration") == 0) { // dt nt!_ETW_? } else if (_wcsicmp(TypeStr, L"Thread") == 0) { // dt nt!_ETHREAD } else if (_wcsicmp(TypeStr, L"Event") == 0) { // dt nt!_KTHREAD } else if (_wcsicmp(TypeStr, L"Key") == 0) { ExtRemoteTyped KeyObject("(nt!_CM_KEY_BODY *)@$extin", HandleObj->ObjectPtr); HandleObj->ObjectKcb = KeyObject.Field("KeyControlBlock").GetPtr(); ObjName = RegGetKeyName(KeyObject.Field("KeyControlBlock")); // dt nt!_CM_KEY_BODY -> nt!_CM_KEY_CONTROL_BLOCK } else { ULONG Offset = 0; UCHAR InfoMask = 0; if (ObjHeader.HasField("InfoMask")) { InfoMask = ObjHeader.Field("InfoMask").GetUchar(); if (InfoMask & OBP_NAME_INFO_BIT) { if (InfoMask & OBP_CREATOR_INFO_BIT) Offset += GetTypeSize("nt!_OBJECT_HEADER_CREATOR_INFO"); Offset += GetTypeSize("nt!_OBJECT_HEADER_NAME_INFO"); } } else { Offset = ObjHeader.Field("NameInfoOffset").GetUchar(); } if (Offset) { ExtRemoteTyped ObjNameInfo("(nt!_OBJECT_HEADER_NAME_INFO *)@$extin", ObjHeaderAddr - Offset); ObjName = ExtRemoteTypedEx::GetUnicodeString2(ObjNameInfo.Field("Name")); } } if (ObjName) { wcscpy_s(HandleObj->Name, ObjName); free(ObjName); ObjName = NULL; } Result = TRUE; CleanUp: return Result; }
size_t GetFieldRuntimeOffset() const { return GetFieldOffset() - m_state.fields_debug_bytes; }
BOOLEAN ObReadObject( _In_ ULONG64 Object, _Out_ PHANDLE_OBJECT HandleObj ) /*++ Routine Description: Description. Arguments: Object - HandleObj - Return Value: BOOLEAN. --*/ { BOOLEAN Result = FALSE; PWSTR ObjectName = NULL; WCHAR TypeStr[64] = {0}; ULONG BodyOffset = 0; GetFieldOffset("nt!_OBJECT_HEADER", "Body", &BodyOffset); try { ZeroMemory(HandleObj, sizeof(HANDLE_OBJECT)); if ((!Object) || (!IsValid(Object))) return FALSE; if (!ObTypeInit) { ObjTypeTable = ExtRemoteTyped("(nt!_OBJECT_TYPE **)@$extin", ObTypeIndexTableAddress); ObTypeInit = TRUE; } ULONG64 ObjHeaderAddr = Object - BodyOffset; if (!IsValid(ObjHeaderAddr)) return FALSE; ExtRemoteTyped ObjHeader("(nt!_OBJECT_HEADER *)@$extin", ObjHeaderAddr); HandleObj->ObjectPtr = Object; // ObjHeader.Field("Body").GetPointerTo().GetPtr(); if (ObjHeader.HasField("TypeIndex")) { BYTE HeaderCookie; HandleObj->ObjectTypeIndex = ObjHeader.Field("TypeIndex").GetUchar(); if (g_Ext->m_Data->ReadVirtual(ObHeaderCookieAddress, &HeaderCookie, sizeof(HeaderCookie), NULL) == S_OK) { HandleObj->ObjectTypeIndex = (((ObjHeaderAddr >> 8) & 0xff) ^ HandleObj->ObjectTypeIndex) ^ HeaderCookie; } ExtRemoteTypedEx::GetUnicodeString(ObjTypeTable.ArrayElement(HandleObj->ObjectTypeIndex).Field("Name"), TypeStr, sizeof(TypeStr)); StringCchCopyW(HandleObj->Type, _countof(HandleObj->Type), TypeStr); }