diff options
| author | kat <kat@vector35.com> | 2025-01-21 08:26:03 -0500 |
|---|---|---|
| committer | kat <kat@vector35.com> | 2025-01-27 13:45:54 -0500 |
| commit | af7715d0e86352ca78badc2272a4cb79cf5aef6a (patch) | |
| tree | c9514d182c9ac4c5d82a811031b448447fcb5b94 /view/sharedcache/core | |
| parent | 37f4ee46a40eee23cd039ae8329c9157a86aff65 (diff) | |
Port sharedcache view to MemoryRegions, removing the need for the fake Raw view workaround
Diffstat (limited to 'view/sharedcache/core')
| -rw-r--r-- | view/sharedcache/core/DSCView.cpp | 93 | ||||
| -rw-r--r-- | view/sharedcache/core/DSCView.h | 25 | ||||
| -rw-r--r-- | view/sharedcache/core/SharedCache.cpp | 75 |
3 files changed, 31 insertions, 162 deletions
diff --git a/view/sharedcache/core/DSCView.cpp b/view/sharedcache/core/DSCView.cpp index 459a37bc..f1528095 100644 --- a/view/sharedcache/core/DSCView.cpp +++ b/view/sharedcache/core/DSCView.cpp @@ -18,59 +18,6 @@ using namespace BinaryNinja; -/* - * DSCRawView is a "fake" parent view that the child view actually fills with data on init. - * - * This is the 'magic' that makes this sort of horrible "serialize the file headers and then refill the parent view" - * work. - * - * This throws errors on deser due to undo actions, but it still works. - * */ -DSCRawView::DSCRawView(const std::string& typeName, BinaryView* data, bool parseOnly) : - BinaryView(typeName, data->GetFile(), data) -{ - // This is going to load _only_ the dyld header of the loaded file. - // This written region will be immediately overwritten on image loading by SharedCache.cpp - GetFile()->SetFilename(data->GetFile()->GetOriginalFilename()); - uint32_t size; - GetParentView()->Read(&size, 16, 4); - size += 8; - AddAutoSegment(0, size, 0, size, SegmentReadable); - GetParentView()->WriteBuffer(0, GetParentView()->ReadBuffer(0, size)); -} - -bool DSCRawView::Init() -{ - return true; -} - -DSCRawViewType::DSCRawViewType() : BinaryViewType("DSCRaw", "DSCRaw") {} - -BinaryNinja::Ref<BinaryNinja::BinaryView> DSCRawViewType::Create(BinaryView* data) -{ - return new DSCRawView("DSCRaw", data, false); -} - -BinaryNinja::Ref<BinaryNinja::BinaryView> DSCRawViewType::Parse(BinaryView* data) -{ - return new DSCRawView("DSCRaw", data, true); -} - -bool DSCRawViewType::IsTypeValidForData(BinaryNinja::BinaryView* data) -{ - // Always return false here. - // This view pretty much exists to keep a bunch of internal core logic happy as it expects certain things - // from our view's parent that we need to control, and cannot control on a standard raw view. - - // IIRC an example of this was the need to add more data past the end of the original file. - - // in ios16 caches, the primary file can be like 100kb while a standard image will easily break 1MB - - // I actually should check if the stuff related to non-file-backed-segments changes the need for this, - // but at the time it was created (2022) it was necessary. - return false; -} - DSCView::DSCView(const std::string& typeName, BinaryView* data, bool parseOnly) : BinaryView(typeName, data->GetFile(), data), m_parseOnly(parseOnly) @@ -92,12 +39,14 @@ enum DSCPlatform { bool DSCView::Init() { + std::string os; + std::string arch; + uint32_t platform; GetParentView()->Read(&platform, 0xd8, 4); char magic[17]; GetParentView()->Read(&magic, 0, 16); magic[16] = 0; - std::string os; if (platform == DSCPlatformMacOS) { os = "mac"; @@ -111,21 +60,24 @@ bool DSCView::Init() LogError("Unknown platform: %d", platform); return false; } + if (std::string(magic) == "dyld_v1 arm64" || std::string(magic) == "dyld_v1 arm64e") { - SetDefaultPlatform(Platform::GetByName(os + "-aarch64")); - SetDefaultArchitecture(Architecture::GetByName("aarch64")); + arch = "aarch64"; } else if (std::string(magic) == "dyld_v1 x86_64") { - SetDefaultPlatform(Platform::GetByName(os + "-x86_64")); - SetDefaultArchitecture(Architecture::GetByName("x86_64")); + arch = "x86_64"; } else { LogError("Unknown magic: %s", magic); return false; } + + SetDefaultPlatform(Platform::GetByName(os + "-" + arch)); + SetDefaultArchitecture(Architecture::GetByName(arch)); + QualifiedNameAndType headerType; std::string err; @@ -631,9 +583,9 @@ bool DSCView::Init() DefineType(filesetEntryCommandTypeId, filesetEntryCommandName, filesetEntryCommandType); std::vector<SharedCacheCore::MemoryRegion> regionsMappedIntoMemory; - if (auto meta = GetParentView()->GetParentView()->QueryMetadata(SharedCacheCore::SharedCacheMetadataTag)) + if (auto meta = GetParentView()->QueryMetadata(SharedCacheCore::SharedCacheMetadataTag)) { - std::string data = GetParentView()->GetParentView()->GetStringMetadata(SharedCacheCore::SharedCacheMetadataTag); + std::string data = GetParentView()->GetStringMetadata(SharedCacheCore::SharedCacheMetadataTag); std::stringstream ss; ss.str(data); rapidjson::Document result(rapidjson::kObjectType); @@ -683,14 +635,6 @@ bool DSCView::Init() exportInfos.push_back({obj1["key"].GetUint64(), innerVec}); } - // We need to re-map data located in the Raw (parent parent) viewtype to the DSCRaw (parent) viewtype. - for (auto region : regionsMappedIntoMemory) - { - GetParentView()->AddUserSegment( - region.rawViewOffsetIfLoaded, region.size, region.rawViewOffsetIfLoaded, region.size, region.flags); - GetParentView()->WriteBuffer( - region.rawViewOffsetIfLoaded, GetParentView()->GetParentView()->ReadBuffer(region.rawViewOffsetIfLoaded, region.size)); - } BeginBulkModifySymbols(); for (const auto & [imageBaseAddr, exportList] : exportInfos) @@ -727,14 +671,14 @@ bool DSCView::Init() // first uint64_t in that struct is the base address of the primary // double gpv here because DSCRaw explicitly stops at the start of this mapping table uint64_t basePointer = 0; - GetParentView()->GetParentView()->Read(&basePointer, 16, 4); + GetParentView()->Read(&basePointer, 16, 4); if (basePointer == 0) { LogError("Failed to read base pointer"); return false; } uint64_t primaryBase = 0; - GetParentView()->GetParentView()->Read(&primaryBase, basePointer, 8); + GetParentView()->Read(&primaryBase, basePointer, 8); if (primaryBase == 0) { LogError("Failed to read primary base at 0x%llx", basePointer); @@ -755,12 +699,13 @@ bool DSCView::Init() } -DSCViewType::DSCViewType() : BinaryViewType(VIEW_NAME, VIEW_NAME) {} +DSCViewType::DSCViewType() : BinaryViewType(VIEW_NAME, VIEW_NAME) +{ +} BinaryNinja::Ref<BinaryNinja::BinaryView> DSCViewType::Create(BinaryNinja::BinaryView* data) { - Ref<BinaryView> rawViewRef = new DSCRawView("DSCRawView", data, false); - return new DSCView(VIEW_NAME, rawViewRef, false); + return new DSCView(VIEW_NAME, data, false); } @@ -858,7 +803,7 @@ Ref<Settings> DSCViewType::GetLoadSettingsForData(BinaryView* data) BinaryNinja::Ref<BinaryNinja::BinaryView> DSCViewType::Parse(BinaryNinja::BinaryView* data) { - return new DSCView(VIEW_NAME, new DSCRawView("DSCRawView", data, true), true); + return new DSCView(VIEW_NAME, data, true); } bool DSCViewType::IsTypeValidForData(BinaryNinja::BinaryView* data) diff --git a/view/sharedcache/core/DSCView.h b/view/sharedcache/core/DSCView.h index 1b891e36..bde2f7c2 100644 --- a/view/sharedcache/core/DSCView.h +++ b/view/sharedcache/core/DSCView.h @@ -7,31 +7,6 @@ #include <binaryninjaapi.h> -class DSCRawView : public BinaryNinja::BinaryView { - std::string m_filename; -public: - - DSCRawView(const std::string &typeName, BinaryView *data, bool parseOnly = false); - - bool Init() override; -}; - - -class DSCRawViewType : public BinaryNinja::BinaryViewType { - -public: - BinaryNinja::Ref<BinaryNinja::BinaryView> Create(BinaryNinja::BinaryView* data) override; - BinaryNinja::Ref<BinaryNinja::BinaryView> Parse(BinaryNinja::BinaryView* data) override; - bool IsTypeValidForData(BinaryNinja::BinaryView *data) override; - - bool IsDeprecated() override { return false; } - - BinaryNinja::Ref<BinaryNinja::Settings> GetLoadSettingsForData(BinaryNinja::BinaryView *data) override { return nullptr; } - -public: - DSCRawViewType(); -}; - class DSCView : public BinaryNinja::BinaryView { bool m_parseOnly; diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp index 0eb52c6a..9e43ce0b 100644 --- a/view/sharedcache/core/SharedCache.cpp +++ b/view/sharedcache/core/SharedCache.cpp @@ -1252,7 +1252,7 @@ void SharedCache::ParseAndApplySlideInfoForFile(std::shared_ptr<MMappedFileAcces cursor += sizeof(uint16_t); if (delta == DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE) continue; - + delta = delta/sizeof(uint64_t); // initial offset is byte based uint64_t loc = mapping.mappingInfo.fileOffset + (pageSize * i); do @@ -1307,7 +1307,7 @@ void SharedCache::ParseAndApplySlideInfoForFile(std::shared_ptr<MMappedFileAcces cursor += sizeof(uint16_t); if (delta == DYLD_CACHE_SLIDE_V5_PAGE_ATTR_NO_REBASE) continue; - + delta = delta/sizeof(uint64_t); // initial offset is byte based uint64_t loc = mapping.mappingInfo.fileOffset + (pageSize * i); do @@ -1585,22 +1585,11 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) ParseAndApplySlideInfoForFile(targetFile); auto reader = VMReader(vm); auto buff = reader.ReadBuffer(stubIsland.start, stubIsland.size); - auto rawViewEnd = m_dscView->GetParentView()->GetEnd(); - - auto name = stubIsland.prettyName; - m_dscView->GetParentView()->GetParentView()->WriteBuffer( - m_dscView->GetParentView()->GetParentView()->GetEnd(), buff); - m_dscView->GetParentView()->AddAutoSegment(rawViewEnd, stubIsland.size, rawViewEnd, stubIsland.size, - SegmentReadable | SegmentExecutable); - m_dscView->AddUserSegment(stubIsland.start, stubIsland.size, rawViewEnd, stubIsland.size, - SegmentReadable | SegmentExecutable); - m_dscView->AddUserSection(name, stubIsland.start, stubIsland.size, ReadOnlyCodeSectionSemantics); - m_dscView->WriteBuffer(stubIsland.start, buff); + m_dscView->GetMemoryMap()->AddDataMemoryRegion(stubIsland.prettyName, stubIsland.start, buff, SegmentReadable | SegmentExecutable); + m_dscView->AddUserSection(stubIsland.prettyName, stubIsland.start, stubIsland.size, ReadOnlyCodeSectionSemantics); stubIsland.loaded = true; - stubIsland.rawViewOffsetIfLoaded = rawViewEnd; - MutableState().regionsMappedIntoMemory.push_back(stubIsland); SaveToDSCView(); @@ -1625,20 +1614,10 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) ParseAndApplySlideInfoForFile(targetFile); auto reader = VMReader(vm); auto buff = reader.ReadBuffer(dyldData.start, dyldData.size); - auto rawViewEnd = m_dscView->GetParentView()->GetEnd(); - - auto name = dyldData.prettyName; - m_dscView->GetParentView()->GetParentView()->WriteBuffer( - m_dscView->GetParentView()->GetParentView()->GetEnd(), buff); - m_dscView->GetParentView()->WriteBuffer(rawViewEnd, buff); - m_dscView->GetParentView()->AddAutoSegment(rawViewEnd, dyldData.size, rawViewEnd, dyldData.size, - SegmentReadable); - m_dscView->AddUserSegment(dyldData.start, dyldData.size, rawViewEnd, dyldData.size, SegmentReadable); - m_dscView->AddUserSection(name, dyldData.start, dyldData.size, ReadOnlyDataSectionSemantics); - m_dscView->WriteBuffer(dyldData.start, buff); + m_dscView->GetMemoryMap()->AddDataMemoryRegion(dyldData.prettyName, dyldData.start, buff, SegmentReadable); + m_dscView->AddUserSection(dyldData.prettyName, dyldData.start, dyldData.size, ReadOnlyDataSectionSemantics); dyldData.loaded = true; - dyldData.rawViewOffsetIfLoaded = rawViewEnd; MutableState().regionsMappedIntoMemory.push_back(dyldData); @@ -1664,19 +1643,10 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) ParseAndApplySlideInfoForFile(targetFile); auto reader = VMReader(vm); auto buff = reader.ReadBuffer(region.start, region.size); - auto rawViewEnd = m_dscView->GetParentView()->GetEnd(); - - auto name = region.prettyName; - m_dscView->GetParentView()->GetParentView()->WriteBuffer( - m_dscView->GetParentView()->GetParentView()->GetEnd(), buff); - m_dscView->GetParentView()->WriteBuffer(rawViewEnd, buff); - m_dscView->GetParentView()->AddAutoSegment(rawViewEnd, region.size, rawViewEnd, region.size, region.flags); - m_dscView->AddUserSegment(region.start, region.size, rawViewEnd, region.size, region.flags); - m_dscView->AddUserSection(name, region.start, region.size, region.flags & SegmentDenyExecute ? ReadOnlyDataSectionSemantics : ReadOnlyCodeSectionSemantics); - m_dscView->WriteBuffer(region.start, buff); + m_dscView->GetMemoryMap()->AddDataMemoryRegion(region.prettyName, region.start, buff, region.flags); + m_dscView->AddUserSection(region.prettyName, region.start, region.size, region.flags & SegmentDenyExecute ? ReadOnlyDataSectionSemantics : ReadOnlyCodeSectionSemantics); region.loaded = true; - region.rawViewOffsetIfLoaded = rawViewEnd; MutableState().regionsMappedIntoMemory.push_back(region); @@ -1694,7 +1664,6 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) } auto id = m_dscView->BeginUndoActions(); - auto rawViewEnd = m_dscView->GetParentView()->GetEnd(); auto reader = VMReader(vm); m_logger->LogDebug("Partial loading image %s", targetHeader.installName.c_str()); @@ -1702,17 +1671,9 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) auto targetFile = vm->MappingAtAddress(targetSegment->start).first.fileAccessor->lock(); ParseAndApplySlideInfoForFile(targetFile); auto buff = reader.ReadBuffer(targetSegment->start, targetSegment->size); - m_dscView->GetParentView()->GetParentView()->WriteBuffer( - m_dscView->GetParentView()->GetParentView()->GetEnd(), buff); - m_dscView->GetParentView()->WriteBuffer(rawViewEnd, buff); - m_dscView->GetParentView()->AddAutoSegment( - rawViewEnd, targetSegment->size, rawViewEnd, targetSegment->size, SegmentReadable); - m_dscView->AddUserSegment( - targetSegment->start, targetSegment->size, rawViewEnd, targetSegment->size, targetSegment->flags); - m_dscView->WriteBuffer(targetSegment->start, buff); + m_dscView->GetMemoryMap()->AddDataMemoryRegion(targetSegment->prettyName, targetSegment->start, buff, targetSegment->flags); targetSegment->loaded = true; - targetSegment->rawViewOffsetIfLoaded = rawViewEnd; MutableState().regionsMappedIntoMemory.push_back(*targetSegment); @@ -1793,7 +1754,7 @@ void SharedCache::ProcessAllObjCSections() { if (!region.loaded) continue; - + // Don't repeat the same images multiple times auto header = HeaderForAddress(region.start); if (!header) @@ -1860,20 +1821,12 @@ bool SharedCache::LoadImageWithInstallName(std::string installName, bool skipObj auto targetFile = vm->MappingAtAddress(region.start).first.fileAccessor->lock(); ParseAndApplySlideInfoForFile(targetFile); - auto rawViewEnd = m_dscView->GetParentView()->GetEnd(); - auto buff = reader.ReadBuffer(region.start, region.size); - m_dscView->GetParentView()->GetParentView()->WriteBuffer(rawViewEnd, buff); - m_dscView->GetParentView()->WriteBuffer(rawViewEnd, buff); region.loaded = true; - region.rawViewOffsetIfLoaded = rawViewEnd; MutableState().regionsMappedIntoMemory.push_back(region); - - m_dscView->GetParentView()->AddAutoSegment(rawViewEnd, region.size, rawViewEnd, region.size, region.flags); - m_dscView->AddUserSegment(region.start, region.size, rawViewEnd, region.size, region.flags); - m_dscView->WriteBuffer(region.start, buff); + m_dscView->GetMemoryMap()->AddDataMemoryRegion(region.prettyName, region.start, buff, region.flags); regionsToLoad.push_back(®ion); } @@ -3032,7 +2985,7 @@ bool SharedCache::SaveToDSCView() { auto data = AsMetadata(); m_dscView->StoreMetadata(SharedCacheMetadataTag, data); - m_dscView->GetParentView()->GetParentView()->StoreMetadata(SharedCacheMetadataTag, data); + m_dscView->GetParentView()->StoreMetadata(SharedCacheMetadataTag, data); // By moving our state the to cache we can avoid creating a copy in the case // that no further mutations are made to `this`. If we're not done being mutated, @@ -3413,19 +3366,15 @@ extern "C" } [[maybe_unused]] DSCViewType* g_dscViewType; -[[maybe_unused]] DSCRawViewType* g_dscRawViewType; void InitDSCViewType() { MMappedFileAccessor::InitialVMSetup(); std::atexit(VMShutdown); - static DSCRawViewType rawType; - BinaryViewType::Register(&rawType); static DSCViewType type; BinaryViewType::Register(&type); g_dscViewType = &type; - g_dscRawViewType = &rawType; } namespace SharedCacheCore { |
