bool khPresenceMask::GetEstimatedPresence(const khTileAddr &addr) const { assert(addr.level < NumFusionLevels); if (levels[addr.level]) { return levels[addr.level]->GetPresence(addr.row, addr.col); } else if (addr.level >= endLevel) { // reach up to maxLevel (endLevel-1) and check the single tile there khTileAddr maxAddr(addr.MinifiedToLevel(endLevel-1)); return levels[maxAddr.level]->GetPresence(maxAddr.row, maxAddr.col); } else { assert(addr.level < beginLevel); // reach down to beginLevel and traverse all tiles there // stop as soon as we find a hit khLevelCoverage minCoverage(addr.MagnifiedToLevel(beginLevel)); khExtents<uint32> tocheck = khExtents<uint32>::Intersection(minCoverage.extents, levels[beginLevel]->extents); for (uint32 row = tocheck.beginRow(); row < tocheck.endRow(); ++row) { for (uint32 col = tocheck.beginCol(); col < tocheck.endCol(); ++col) { if (levels[beginLevel]->GetPresence(row, col)) { return true; } } } } return false; }
/// <summary> /// Enumerate valid memory regions /// </summary> /// <param name="includeFree">If true - non-allocated regions will be included in list</param> /// <returns>Found regions</returns> std::vector<MEMORY_BASIC_INFORMATION64> Native::EnumRegions( bool includeFree /*= false*/ ) { MEMORY_BASIC_INFORMATION64 mbi = { 0 }; std::vector<MEMORY_BASIC_INFORMATION64> results; for (ptr_t memptr = minAddr(); memptr < maxAddr(); memptr = mbi.BaseAddress + mbi.RegionSize) { auto status = VirtualQueryExT( memptr, &mbi ); if (status == STATUS_INVALID_PARAMETER || status == STATUS_ACCESS_DENIED) break; else if (status != STATUS_SUCCESS) continue; // Filter, if required if (includeFree || mbi.State & (MEM_COMMIT | MEM_RESERVE)) results.emplace_back( mbi ); } return results; }
/// <summary> /// Enum pages containing valid PE headers /// </summary> /// <param name="result">Found modules</param> /// <returns>Sections count</returns> std::vector<ModuleDataPtr> Native::EnumPEHeaders() { MEMORY_BASIC_INFORMATION64 mbi = { 0 }; uint8_t buf[0x1000]; ptr_t lastBase = 0; std::vector<ModuleDataPtr> result; for (ptr_t memptr = minAddr(); memptr < maxAddr(); memptr = mbi.BaseAddress + mbi.RegionSize) { auto status = VirtualQueryExT( memptr, &mbi ); if (status == STATUS_INVALID_PARAMETER || status == STATUS_ACCESS_DENIED || status == STATUS_PROCESS_IS_TERMINATING) break; else if (status != STATUS_SUCCESS) continue; // Filter regions if (mbi.State != MEM_COMMIT || mbi.AllocationProtect == PAGE_NOACCESS || mbi.AllocationProtect & PAGE_GUARD || lastBase == mbi.AllocationBase) { continue; } ModuleData data; IMAGE_DOS_HEADER* phdrDos = reinterpret_cast<PIMAGE_DOS_HEADER>(buf); IMAGE_NT_HEADERS32 *phdrNt32 = nullptr; IMAGE_NT_HEADERS64 *phdrNt64 = nullptr; if (ReadProcessMemoryT( mbi.AllocationBase, buf, 0x1000 ) != STATUS_SUCCESS) continue; phdrNt32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(buf + phdrDos->e_lfanew); phdrNt64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(phdrNt32); if (phdrDos->e_magic != IMAGE_DOS_SIGNATURE || phdrNt32->Signature != IMAGE_NT_SIGNATURE) continue; if (phdrNt32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { data.size = phdrNt32->OptionalHeader.SizeOfImage; data.type = mt_mod32; } else if (phdrNt32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { data.size = phdrNt64->OptionalHeader.SizeOfImage; data.type = mt_mod64; } data.baseAddress = mbi.AllocationBase; data.ldrPtr = 0; data.manual = false; // Try to get section name _UNICODE_STRING_T<DWORD64>* ustr = (decltype(ustr))buf; status = VirtualQueryExT( mbi.AllocationBase, MemorySectionName, ustr, sizeof(buf) ); if (status == STATUS_SUCCESS) { // Hack for x86 OS if (_wowBarrier.x86OS == true) { _UNICODE_STRING_T<DWORD>* ustr32 = reinterpret_cast<_UNICODE_STRING_T<DWORD>*>(ustr); data.fullPath = Utils::ToLower( reinterpret_cast<wchar_t*>((uintptr_t)ustr32->Buffer) ); } else data.fullPath = Utils::ToLower( reinterpret_cast<wchar_t*>((uintptr_t)ustr->Buffer) ); data.name = Utils::StripPath( data.fullPath ); } else { wchar_t name[64] = { 0 }; wsprintfW( name, L"Unknown_0x%I64x", data.baseAddress ); data.fullPath = name; data.name = data.fullPath; } result.emplace_back( std::make_shared<const ModuleData>( data ) ); lastBase = mbi.AllocationBase; } return result; }
/// <summary> /// Enum process section objects /// </summary> /// <param name="result">Found modules</param> /// <returns>Sections count</returns> std::vector<ModuleDataPtr> Native::EnumSections() { MEMORY_BASIC_INFORMATION64 mbi = { 0 }; ptr_t lastBase = 0; std::vector<ModuleDataPtr> result; for (ptr_t memptr = minAddr(); memptr < maxAddr(); memptr = mbi.BaseAddress + mbi.RegionSize) { auto status = VirtualQueryExT( memptr, &mbi ); if (status == STATUS_INVALID_PARAMETER || status == STATUS_ACCESS_DENIED || status == STATUS_PROCESS_IS_TERMINATING) break; else if (status != STATUS_SUCCESS) continue; // Filter non-section regions if (mbi.State != MEM_COMMIT || mbi.Type != SEC_IMAGE || lastBase == mbi.AllocationBase) continue; uint8_t buf[0x1000] = { 0 }; _UNICODE_STRING_T<uint64_t>* ustr = (decltype(ustr))(buf + 0x800); status = VirtualQueryExT( mbi.AllocationBase, MemorySectionName, ustr, sizeof(buf) / 2 ); // Get additional if (NT_SUCCESS( status )) { ModuleData data; IMAGE_DOS_HEADER* phdrDos = reinterpret_cast<PIMAGE_DOS_HEADER>(buf); IMAGE_NT_HEADERS32 *phdrNt32 = nullptr; IMAGE_NT_HEADERS64 *phdrNt64 = nullptr; if (ReadProcessMemoryT( mbi.AllocationBase, buf, 0x800 ) != STATUS_SUCCESS) continue; phdrNt32 = reinterpret_cast<PIMAGE_NT_HEADERS32>(buf + phdrDos->e_lfanew); phdrNt64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(phdrNt32); // If no PE header present if (phdrDos->e_magic != IMAGE_DOS_SIGNATURE || phdrNt32->Signature != IMAGE_NT_SIGNATURE) { // Iterate until region end MEMORY_BASIC_INFORMATION64 mbi2 = { 0 }; for (ptr_t memptr2 = mbi.AllocationBase; memptr2 < maxAddr(); memptr2 = mbi2.BaseAddress + mbi2.RegionSize) if (!NT_SUCCESS( VirtualQueryExT( memptr2, &mbi2 ) ) || mbi2.Type != SEC_IMAGE) { data.size = static_cast<uint32_t>(mbi2.BaseAddress - mbi.AllocationBase); break; } data.type = mt_unknown; } else if( phdrNt32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC ) { data.size = phdrNt32->OptionalHeader.SizeOfImage; data.type = mt_mod32; } else if (phdrNt32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { data.size = phdrNt64->OptionalHeader.SizeOfImage; data.type = mt_mod64; } else continue; // Hack for x86 OS if (_wowBarrier.x86OS == true) { _UNICODE_STRING_T<DWORD>* ustr32 = reinterpret_cast<_UNICODE_STRING_T<DWORD>*>(ustr); data.fullPath = Utils::ToLower( reinterpret_cast<wchar_t*>((uintptr_t)ustr32->Buffer) ); } else data.fullPath = Utils::ToLower( reinterpret_cast<wchar_t*>((uintptr_t)ustr->Buffer) ); data.name = Utils::StripPath( data.fullPath ); data.baseAddress = mbi.AllocationBase; data.ldrPtr = 0; data.manual = false; result.emplace_back( std::make_shared<const ModuleData>( data ) ); } lastBase = mbi.AllocationBase; } return result; }