From 7f3f394c8bb50c987a5237bc74aa503486571058 Mon Sep 17 00:00:00 2001 From: kat Date: Wed, 19 Mar 2025 09:12:52 -0400 Subject: Add iOS/macOS MH_FILESET KernelCache View and loader. This loader is inspired by/based on our dyld_shared_cache loader, following the same design language. It targets primarily the latest kernels, but should support any with the MH_FILESET format. It allows you to decide which images you would like to map in (the kernel itself included), resulting in targeted analysis when you may only need to load a singular image. It also supports dropping in compressed KernelCaches, directly from the ipsw. This is an early solution and we have many more changes and improvements planned. We look forward to your feedback --- view/kernelcache/api/kernelcache.cpp | 191 +++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 view/kernelcache/api/kernelcache.cpp (limited to 'view/kernelcache/api/kernelcache.cpp') diff --git a/view/kernelcache/api/kernelcache.cpp b/view/kernelcache/api/kernelcache.cpp new file mode 100644 index 00000000..6cca9033 --- /dev/null +++ b/view/kernelcache/api/kernelcache.cpp @@ -0,0 +1,191 @@ +// +// Created by kat on 5/21/23. +// + +#include "kernelcacheapi.h" + +namespace KernelCacheAPI { + + KernelCache::KernelCache(Ref view) { + m_object = BNGetKernelCache(view->GetObject()); + } + + BNKCViewLoadProgress KernelCache::GetLoadProgress(Ref view) + { + return BNKCViewGetLoadProgress(view->GetFile()->GetSessionId()); + } + + uint64_t KernelCache::FastGetImageCount(Ref view) + { + return BNKCViewFastGetImageCount(view->GetObject()); + } + + bool KernelCache::LoadImageWithInstallName(std::string installName) + { + char* str = BNAllocString(installName.c_str()); + return BNKCViewLoadImageWithInstallName(m_object, str); + } + + bool KernelCache::LoadImageContainingAddress(uint64_t addr) + { + return BNKCViewLoadImageContainingAddress(m_object, addr); + } + + std::vector KernelCache::GetAvailableImages() + { + size_t count; + char** value = BNKCViewGetInstallNames(m_object, &count); + if (value == nullptr) + { + return {}; + } + + std::vector result; + for (size_t i = 0; i < count; i++) + { + result.push_back(value[i]); + } + + BNFreeStringList(value, count); + return result; + } + + std::vector KernelCache::GetImages() + { + size_t count; + BNKCImage* value = BNKCViewGetAllImages(m_object, &count); + if (value == nullptr) + { + return {}; + } + + std::vector result; + for (size_t i = 0; i < count; i++) + { + KCImage img; + img.name = value[i].name; + img.headerFileAddress = value[i].headerFileAddress; + for (size_t j = 0; j < value[i].mappingCount; j++) + { + KCImageMemoryMapping mapping; + mapping.name = value[i].mappings[j].name; + mapping.vmAddress = value[i].mappings[j].vmAddress; + mapping.rawViewOffset = value[i].mappings[j].rawViewOffset; + mapping.size = value[i].mappings[j].size; + mapping.loaded = value[i].mappings[j].loaded; + img.mappings.push_back(mapping); + } + result.push_back(img); + } + + BNKCViewFreeAllImages(value, count); + return result; + } + + std::vector KernelCache::GetLoadedImages() + { + size_t count; + auto images = BNKCViewGetLoadedImages(m_object, &count); + if (images == nullptr) + { + return {}; + } + std::vector result; + for (size_t i = 0; i < count; i++) + { + KCImage img; + img.name = images[i].name; + img.headerFileAddress = images[i].headerFileAddress; + for (size_t j = 0; j < images[i].mappingCount; j++) + { + KCImageMemoryMapping mapping; + mapping.name = images[i].mappings[j].name; + mapping.vmAddress = images[i].mappings[j].vmAddress; + mapping.rawViewOffset = images[i].mappings[j].rawViewOffset; + mapping.size = images[i].mappings[j].size; + mapping.loaded = images[i].mappings[j].loaded; + img.mappings.push_back(mapping); + } + result.push_back(img); + } + BNKCViewFreeAllImages(images, count); + + return result; + } + + std::vector KernelCache::LoadAllSymbolsAndWait() + { + size_t count; + BNKCSymbolRep* value = BNKCViewLoadAllSymbolsAndWait(m_object, &count); + if (value == nullptr) + { + return {}; + } + + std::vector result; + for (size_t i = 0; i < count; i++) + { + KCSymbol sym; + sym.address = value[i].address; + sym.name = value[i].name; + sym.image = value[i].image; + result.push_back(sym); + } + + BNKCViewFreeSymbols(value, count); + return result; + } + + std::string KernelCache::GetNameForAddress(uint64_t address) + { + char* name = BNKCViewGetNameForAddress(m_object, address); + if (name == nullptr) + return {}; + std::string result = name; + BNFreeString(name); + return result; + } + + std::string KernelCache::GetImageNameForAddress(uint64_t address) + { + char* name = BNKCViewGetImageNameForAddress(m_object, address); + if (name == nullptr) + return {}; + std::string result = name; + BNFreeString(name); + return result; + } + + std::optional KernelCache::GetMachOHeaderForImage(std::string name) + { + char* str = BNAllocString(name.c_str()); + char* outputStr = BNKCViewGetImageHeaderForName(m_object, str); + if (outputStr == nullptr) + return {}; + std::string output = outputStr; + BNFreeString(outputStr); + if (output.empty()) + return {}; + KernelCacheMachOHeader header = KernelCacheMachOHeader::LoadFromString(output); + return header; + } + + std::optional KernelCache::GetMachOHeaderForAddress(uint64_t address) + { + char* outputStr = BNKCViewGetImageHeaderForAddress(m_object, address); + if (outputStr == nullptr) + return {}; + std::string output = outputStr; + BNFreeString(outputStr); + if (output.empty()) + return {}; + KernelCacheMachOHeader header = KernelCacheMachOHeader::LoadFromString(output); + return header; + } + + BNKCViewState KernelCache::GetState() + { + return BNKCViewGetState(m_object); + } + +} // namespace KernelCacheAPI -- cgit v1.3.1