From 768f7c78465fb93936e5ca50a0ca712664fe54e7 Mon Sep 17 00:00:00 2001 From: kat Date: Sun, 6 Jul 2025 15:05:01 -0400 Subject: KernelCache rewrite --- view/kernelcache/api/kernelcache.cpp | 373 ++++++++++++++++++----------------- 1 file changed, 187 insertions(+), 186 deletions(-) (limited to 'view/kernelcache/api/kernelcache.cpp') diff --git a/view/kernelcache/api/kernelcache.cpp b/view/kernelcache/api/kernelcache.cpp index 7a650660..30f40656 100644 --- a/view/kernelcache/api/kernelcache.cpp +++ b/view/kernelcache/api/kernelcache.cpp @@ -4,191 +4,192 @@ #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(const std::string& installName) - { - return BNKCViewLoadImageWithInstallName(m_object, installName.c_str()); - } - - bool KernelCache::LoadImageContainingAddress(uint64_t addr) - { - return BNKCViewLoadImageContainingAddress(m_object, addr); - } - - std::vector KernelCache::GetAvailableImages() +using namespace BinaryNinja; +using namespace KernelCacheAPI; + +BNKernelCacheImage ImageToApi(CacheImage image) +{ + BNKernelCacheImage apiImage {}; + apiImage.name = BNAllocString(image.name.c_str()); + apiImage.headerFileAddress = image.headerFileAddress; + apiImage.headerVirtualAddress = image.headerVirtualAddress; + return apiImage; +} + +CacheImage ImageFromApi(BNKernelCacheImage image) +{ + CacheImage apiImage {}; + apiImage.name = image.name; + apiImage.headerVirtualAddress = image.headerVirtualAddress; + apiImage.headerFileAddress = image.headerFileAddress; + return apiImage; +} + +CacheSymbol SymbolFromApi(BNKernelCacheSymbol apiSymbol) +{ + CacheSymbol symbol; + symbol.name = apiSymbol.name; + symbol.address = apiSymbol.address; + symbol.type = apiSymbol.symbolType; + return symbol; +} + +std::pair> CacheSymbol::DemangledName(BinaryView &view) const +{ + QualifiedName qname; + Ref outType = nullptr; + std::string shortName = name; + if (DemangleGeneric(view.GetDefaultArchitecture(), name, outType, qname, &view, true)) + shortName = qname.GetString(); + return {shortName, outType}; +} + +Ref CacheSymbol::GetBNSymbol(BinaryView &view) const +{ + auto [shortName, _] = DemangledName(view); + return new Symbol(type, shortName, shortName, name, address, nullptr); +} + +std::string KernelCacheAPI::GetSymbolTypeAsString(const BNSymbolType &type) +{ + // NOTE: We currently only use the function and data symbol for cache symbols. + // update this if that changes. + switch (type) { - 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; + case FunctionSymbol: + return "Function"; + case DataSymbol: + return "Data"; + default: + return "Unknown"; } - - bool KernelCache::IsImageLoaded(const uint64_t address) const - { - return BNKCViewIsImageLoaded(m_object, address); - } - - 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(const std::string& name) - { - char* outputStr = BNKCViewGetImageHeaderForName(m_object, name.c_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 +} + +KernelCacheController::KernelCacheController(BNKernelCacheController *controller) +{ + m_object = controller; +} + +KCRef KernelCacheController::GetController(BinaryView &view) +{ + BNKernelCacheController *controller = BNGetKernelCacheController(view.GetObject()); + if (controller == nullptr) + return nullptr; + return new KernelCacheController(controller); +} + +bool KernelCacheController::ApplyImage(BinaryView &view, const CacheImage &image) +{ + auto apiImage = ImageToApi(image); + bool result = BNKernelCacheControllerApplyImage(m_object, view.GetObject(), &apiImage); + BNKernelCacheFreeImage(apiImage); + return result; +} + +bool KernelCacheController::IsImageLoaded(const CacheImage &image) const +{ + auto apiImage = ImageToApi(image); + bool result = BNKernelCacheControllerIsImageLoaded(m_object, &apiImage); + BNKernelCacheFreeImage(apiImage); + return result; +} + +std::optional KernelCacheController::GetImageAt(uint64_t address) const +{ + BNKernelCacheImage apiImage; + if (!BNKernelCacheControllerGetImageAt(m_object, address, &apiImage)) + return std::nullopt; + CacheImage image = ImageFromApi(apiImage); + BNKernelCacheFreeImage(apiImage); + return image; +} + +std::optional KernelCacheController::GetImageContaining(uint64_t address) const +{ + BNKernelCacheImage apiImage; + if (!BNKernelCacheControllerGetImageContaining(m_object, address, &apiImage)) + return std::nullopt; + CacheImage image = ImageFromApi(apiImage); + BNKernelCacheFreeImage(apiImage); + return image; +} + +std::optional KernelCacheController::GetImageWithName(const std::string &name) const +{ + BNKernelCacheImage apiImage; + if (!BNKernelCacheControllerGetImageWithName(m_object, name.c_str(), &apiImage)) + return std::nullopt; + CacheImage image = ImageFromApi(apiImage); + BNKernelCacheFreeImage(apiImage); + return image; +} + +std::vector KernelCacheController::GetImageDependencies(const CacheImage &image) const +{ + size_t count; + BNKernelCacheImage apiImage = ImageToApi(image); + char **dependencies = BNKernelCacheControllerGetImageDependencies(m_object, &apiImage, &count); + BNKernelCacheFreeImage(apiImage); + std::vector result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + result.emplace_back(dependencies[i]); + BNFreeStringList(dependencies, count); + return result; +} + +std::optional KernelCacheController::GetSymbolAt(uint64_t address) const +{ + BNKernelCacheSymbol apiSymbol; + if (!BNKernelCacheControllerGetSymbolAt(m_object, address, &apiSymbol)) + return std::nullopt; + CacheSymbol symbol = SymbolFromApi(apiSymbol); + BNKernelCacheFreeSymbol(apiSymbol); + return symbol; +} + +std::optional KernelCacheController::GetSymbolWithName(const std::string &name) const +{ + BNKernelCacheSymbol apiSymbol; + if (!BNKernelCacheControllerGetSymbolWithName(m_object, name.c_str(), &apiSymbol)) + return std::nullopt; + CacheSymbol symbol = SymbolFromApi(apiSymbol); + BNKernelCacheFreeSymbol(apiSymbol); + return symbol; +} + +std::vector KernelCacheController::GetImages() const +{ + size_t count; + BNKernelCacheImage *images = BNKernelCacheControllerGetImages(m_object, &count); + std::vector result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + result.emplace_back(ImageFromApi(images[i])); + BNKernelCacheFreeImageList(images, count); + return result; +} + +std::vector KernelCacheController::GetLoadedImages() const +{ + size_t count; + BNKernelCacheImage *images = BNKernelCacheControllerGetLoadedImages(m_object, &count); + std::vector result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + result.emplace_back(ImageFromApi(images[i])); + BNKernelCacheFreeImageList(images, count); + return result; +} + +std::vector KernelCacheController::GetSymbols() const +{ + size_t count; + BNKernelCacheSymbol *symbols = BNKernelCacheControllerGetSymbols(m_object, &count); + std::vector result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + result.emplace_back(SymbolFromApi(symbols[i])); + BNKernelCacheFreeSymbolList(symbols, count); + return result; +} -- cgit v1.3.1