ExtRemoteTyped GetHive( _In_ PWSTR FullKeyPath ) { PHIVE_OBJECT Hive = NULL; ULONG64 HiveAddress = NULL; ULONG HiveRootLength; ULONG KeyPathLength; if (g_Hives.size()) { KeyPathLength = (ULONG)wcslen(FullKeyPath); for (size_t i = 0; i < g_Hives.size(); i++) { HiveRootLength = (ULONG)wcslen(g_Hives[i].HiveRootPath); if (HiveRootLength && (HiveRootLength <= KeyPathLength) && (0 == _wcsnicmp(g_Hives[i].HiveRootPath, FullKeyPath, HiveRootLength))) { Hive = &g_Hives[i]; break; } } if (!Hive) { Hive = &g_Hives[0]; } HiveAddress = Hive->HivePtr; } return ExtRemoteTyped("(nt!_HHIVE *)@$extin", HiveAddress); }
vector<HANDLE_OBJECT> ObOpenObjectDirectory( _In_ ULONG64 InputObject ) /*++ Routine Description: Description. Arguments: InputObject - Return Value: vector<HANDLE_OBJECT>. --*/ { vector<HANDLE_OBJECT> Handles; HANDLE_OBJECT Handle = { 0 }; ExtRemoteTyped Directory; ULONG64 ObjectDir = InputObject; if (!ObjectDir) { ReadPointer(GetExpression("nt!ObpRootDirectoryObject"), &ObjectDir); } Directory = ExtRemoteTyped("(nt!_OBJECT_DIRECTORY *)@$extin", ObjectDir); ObReadObject(ObjectDir, &Handle); for (UINT i = 0; i < 37; i += 1) { ULONG64 Entry = Directory.Field("HashBuckets").ArrayElement(i).GetPointerTo().GetPtr(); if (!Entry) continue; // // ExtRemoteTypedList requires a POINTER to the first entry. Not the offset of the first entry. // ExtRemoteTypedList EntryList(Entry, "nt!_OBJECT_DIRECTORY_ENTRY", "ChainLink"); for (EntryList.StartHead(); EntryList.HasNode(); EntryList.Next()) { HANDLE_OBJECT Handle = {0}; ULONG64 Object = EntryList.GetTypedNode().Field("Object").GetPtr(); ObReadObject(Object, &Handle); Handles.push_back(Handle); } } return Handles; }
bool Walk(WalkResult* result) { if ( !IsValid() ) { return false; } result->reserve(static_cast<size_t>(GetTableCount())); const auto offset = GetTableStart() + GetTableSkipStart(); for ( uint32_t tc = 0; tc < GetTableCount(); tc++ ) { try { result->emplace_back(ExtRemoteTyped(m_type.c_str(), offset + tc * m_type_size, false, m_sym_cache->GetCookieCache(m_type), nullptr)); } catch ( const ExtRemoteException &Ex ) { err << wa::showminus << __FUNCTION__ << ": " << Ex.GetMessage() << endlerr; } } return !result->empty(); }
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; }
BOOLEAN PEFile::InitImage( ) /*++ Routine Description: Description. Arguments: - Return Value: BOOLEAN. --*/ { PIMAGE_DOS_HEADER Header = NULL; PVOID Image = NULL; ULONG BytesRead = 0; ULONG64 BaseImageAddress = m_ImageBase; PIMAGE_NT_HEADERS32 NtHeader32 = NULL; PIMAGE_NT_HEADERS64 NtHeader64 = NULL; PIMAGE_DATA_DIRECTORY DataDirectory = NULL; ExtRemoteTyped BaseImage; BOOLEAN Result = FALSE; ULONG64 ProcessDataOffset = 0ULL; if (m_Image.Initialized) { // g_Ext->Dml("b_Initialized already set to TRUE\n"); Result = TRUE; goto CleanUp; } if (!m_ImageSize) { Header = (PIMAGE_DOS_HEADER)malloc(PAGE_SIZE); if (Header == NULL) goto CleanUp; RtlZeroMemory(Header, PAGE_SIZE); if (g_Ext->m_Data->ReadVirtual(BaseImageAddress, Header, PAGE_SIZE, &BytesRead) != S_OK) { #if VERBOSE_MODE g_Ext->Dml("Error: Can't read 0x%I64x bytes at %I64x.\n", PAGE_SIZE, BaseImageAddress); #endif goto CleanUp; } BaseImage = ExtRemoteTyped("(nt!_IMAGE_DOS_HEADER *)@$extin", BaseImageAddress); if (BaseImage.Field("e_magic").GetUshort() != IMAGE_DOS_SIGNATURE) goto CleanUp; NtHeader32 = (PIMAGE_NT_HEADERS32)((PUCHAR)Header + BaseImage.Field("e_lfanew").GetUlong()); if (NtHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { m_ImageSize = NtHeader32->OptionalHeader.SizeOfImage; } else if (NtHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { NtHeader64 = (PIMAGE_NT_HEADERS64)NtHeader32; NtHeader32 = NULL; m_ImageSize = NtHeader64->OptionalHeader.SizeOfImage;; } else { #if VERBOSE_MODE g_Ext->Dml("Error: Invalid signature.\n"); #endif goto CleanUp; } } Image = malloc(m_ImageSize); if (Image == NULL) goto CleanUp; RtlZeroMemory(Image, (ULONG)m_ImageSize); if (ExtRemoteTypedEx::ReadVirtual(BaseImageAddress, Image, (ULONG)m_ImageSize, &BytesRead) != S_OK) { #if VERBOSE_MODE g_Ext->Dml("Error: Can't read 0x%I64x bytes at %I64x.\n", m_ImageSize, BaseImageAddress); #endif goto CleanUp; } m_Image.Image = (PIMAGE_DOS_HEADER)Image; REF_POINTER(m_Image.Image); m_Image.NtHeader32 = (PIMAGE_NT_HEADERS32)((PUCHAR)Image + m_Image.Image->e_lfanew); NtHeader32 = m_Image.NtHeader32; if (NtHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { m_Image.NtHeader32 = NULL; m_Image.NtHeader64 = (PIMAGE_NT_HEADERS64)((PUCHAR)Image + m_Image.Image->e_lfanew); m_Image.DataDirectory = (PIMAGE_DATA_DIRECTORY)m_Image.NtHeader64->OptionalHeader.DataDirectory; m_Image.Sections = (PIMAGE_SECTION_HEADER)(m_Image.NtHeader64 + 1); m_Image.NumberOfSections = m_Image.NtHeader64->FileHeader.NumberOfSections; } else if (NtHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { m_Image.NtHeader64 = NULL; m_Image.DataDirectory = (PIMAGE_DATA_DIRECTORY)m_Image.NtHeader32->OptionalHeader.DataDirectory; m_Image.Sections = (PIMAGE_SECTION_HEADER)(m_Image.NtHeader32 + 1); m_Image.NumberOfSections = m_Image.NtHeader32->FileHeader.NumberOfSections; } else { goto CleanUp; } #if VERBOSE_MODE g_Ext->Dml("m_Image = %p\n" "m_NtHeader32 = %p\n" "m_DataDirectory = %p\n" "m_Sections = %p\n", m_Image.Image, m_Image.NtHeader32, m_Image.DataDirectory, m_Image.Sections); g_Ext->Dml("m_NumberOfSections = %x\n", m_Image.NumberOfSections); #endif Result = TRUE; CleanUp: if (Header) free(Header); m_Image.Initialized = Result; return Result; }
ExtRemoteTyped GetKeyNode( _In_ PWSTR FullKeyPath ) { ULONG64 CmpMasterHive; ULONG64 CmpRegistryRootObject; ExtRemoteTyped KeyNode; try { ReadPointer(CmpMasterHiveAddress, &CmpMasterHive); ReadPointer(CmpRegistryRootObjectAddress, &CmpRegistryRootObject); ExtRemoteTyped KeyHive("(nt!_HHIVE *)@$extin", CmpMasterHive); ExtRemoteTyped KeyBody("(nt!_CM_KEY_BODY *)@$extin", CmpRegistryRootObject); ExtRemoteTyped KeyControlBlock("(nt!_CM_KEY_CONTROL_BLOCK *)@$extin", KeyBody.Field("KeyControlBlock").GetPtr()); ULONG KeyCell = KeyControlBlock.Field("KeyCell").GetUlong(); KeyNode = ExtRemoteTyped("(nt!_CM_KEY_NODE *)@$extin", RegGetCellPaged(KeyHive, KeyCell)); vector<KEY_NAME> KeysNames = GetKeysNames(FullKeyPath); for (size_t i = 1; i < KeysNames.size(); i++) { BOOL IsFound = FALSE; vector<KEY_NODE> SubKeys = GetSubKeys(KeyHive, KeyNode); for (size_t j = 0; j < SubKeys.size(); j++) { if (0 == _wcsicmp(KeysNames[i].Name, SubKeys[j].Name)) { KeyNode = SubKeys[j].KeyNode; if (KeyNode.Field("Signature").GetUshort() == CM_LINK_NODE_SIGNATURE) { KeyHive = ExtRemoteTyped("(nt!_HHIVE *)@$extin", KeyNode.Field("ChildHiveReference.KeyHive").GetPtr()); KeyCell = KeyNode.Field("ChildHiveReference.KeyCell").GetUlong(); KeyNode = ExtRemoteTyped("(nt!_CM_KEY_NODE *)@$extin", RegGetCellPaged(KeyHive, KeyCell)); } IsFound = TRUE; break; } } if (!IsFound) { KeyNode = ExtRemoteTyped("(nt!_CM_KEY_NODE *)@$extin", NULL); break; } } } catch (...) { } return KeyNode; }
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); }