summaryrefslogtreecommitdiff
path: root/view/kernelcache/api
diff options
context:
space:
mode:
authorkat <kat@vector35.com>2025-07-06 15:05:01 -0400
committerkat <kat@vector35.com>2025-07-07 07:37:23 -0400
commit768f7c78465fb93936e5ca50a0ca712664fe54e7 (patch)
tree78c73e0022d6006882e365a257595a5b55a37432 /view/kernelcache/api
parent8f3e251c42169fb4fe8db9403d900571434d88ff (diff)
KernelCache rewrite
Diffstat (limited to 'view/kernelcache/api')
-rw-r--r--view/kernelcache/api/kernelcache.cpp335
-rw-r--r--view/kernelcache/api/kernelcacheapi.h467
-rw-r--r--view/kernelcache/api/kernelcachecore.h149
-rw-r--r--view/kernelcache/api/python/kernelcache.py283
-rw-r--r--view/kernelcache/api/python/kernelcache_enums.py42
5 files changed, 663 insertions, 613 deletions
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 {
+using namespace BinaryNinja;
+using namespace KernelCacheAPI;
- KernelCache::KernelCache(Ref<BinaryView> view) {
- m_object = BNGetKernelCache(view->GetObject());
- }
+BNKernelCacheImage ImageToApi(CacheImage image)
+{
+ BNKernelCacheImage apiImage {};
+ apiImage.name = BNAllocString(image.name.c_str());
+ apiImage.headerFileAddress = image.headerFileAddress;
+ apiImage.headerVirtualAddress = image.headerVirtualAddress;
+ return apiImage;
+}
- BNKCViewLoadProgress KernelCache::GetLoadProgress(Ref<BinaryView> view)
- {
- return BNKCViewGetLoadProgress(view->GetFile()->GetSessionId());
- }
+CacheImage ImageFromApi(BNKernelCacheImage image)
+{
+ CacheImage apiImage {};
+ apiImage.name = image.name;
+ apiImage.headerVirtualAddress = image.headerVirtualAddress;
+ apiImage.headerFileAddress = image.headerFileAddress;
+ return apiImage;
+}
- uint64_t KernelCache::FastGetImageCount(Ref<BinaryView> view)
- {
- return BNKCViewFastGetImageCount(view->GetObject());
- }
+CacheSymbol SymbolFromApi(BNKernelCacheSymbol apiSymbol)
+{
+ CacheSymbol symbol;
+ symbol.name = apiSymbol.name;
+ symbol.address = apiSymbol.address;
+ symbol.type = apiSymbol.symbolType;
+ return symbol;
+}
- bool KernelCache::LoadImageWithInstallName(const std::string& installName)
- {
- return BNKCViewLoadImageWithInstallName(m_object, installName.c_str());
- }
+std::pair<std::string, Ref<Type>> CacheSymbol::DemangledName(BinaryView &view) const
+{
+ QualifiedName qname;
+ Ref<Type> outType = nullptr;
+ std::string shortName = name;
+ if (DemangleGeneric(view.GetDefaultArchitecture(), name, outType, qname, &view, true))
+ shortName = qname.GetString();
+ return {shortName, outType};
+}
- bool KernelCache::LoadImageContainingAddress(uint64_t addr)
- {
- return BNKCViewLoadImageContainingAddress(m_object, addr);
- }
+Ref<Symbol> CacheSymbol::GetBNSymbol(BinaryView &view) const
+{
+ auto [shortName, _] = DemangledName(view);
+ return new Symbol(type, shortName, shortName, name, address, nullptr);
+}
- std::vector<std::string> KernelCache::GetAvailableImages()
+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<std::string> 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);
- }
+KernelCacheController::KernelCacheController(BNKernelCacheController *controller)
+{
+ m_object = controller;
+}
- std::vector<KCImage> KernelCache::GetImages()
- {
- size_t count;
- BNKCImage* value = BNKCViewGetAllImages(m_object, &count);
- if (value == nullptr)
- {
- return {};
- }
+KCRef<KernelCacheController> KernelCacheController::GetController(BinaryView &view)
+{
+ BNKernelCacheController *controller = BNGetKernelCacheController(view.GetObject());
+ if (controller == nullptr)
+ return nullptr;
+ return new KernelCacheController(controller);
+}
- std::vector<KCImage> 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);
- }
+bool KernelCacheController::ApplyImage(BinaryView &view, const CacheImage &image)
+{
+ auto apiImage = ImageToApi(image);
+ bool result = BNKernelCacheControllerApplyImage(m_object, view.GetObject(), &apiImage);
+ BNKernelCacheFreeImage(apiImage);
+ return result;
+}
- BNKCViewFreeAllImages(value, count);
- return result;
- }
+bool KernelCacheController::IsImageLoaded(const CacheImage &image) const
+{
+ auto apiImage = ImageToApi(image);
+ bool result = BNKernelCacheControllerIsImageLoaded(m_object, &apiImage);
+ BNKernelCacheFreeImage(apiImage);
+ return result;
+}
- std::vector<KCImage> KernelCache::GetLoadedImages()
- {
- size_t count;
- auto images = BNKCViewGetLoadedImages(m_object, &count);
- if (images == nullptr)
- {
- return {};
- }
- std::vector<KCImage> 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);
+std::optional<CacheImage> 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;
+}
- return result;
- }
+std::optional<CacheImage> 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::vector<KCSymbol> KernelCache::LoadAllSymbolsAndWait()
- {
- size_t count;
- BNKCSymbolRep* value = BNKCViewLoadAllSymbolsAndWait(m_object, &count);
- if (value == nullptr)
- {
- return {};
- }
+std::optional<CacheImage> 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<KCSymbol> 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);
- }
+std::vector<std::string> KernelCacheController::GetImageDependencies(const CacheImage &image) const
+{
+ size_t count;
+ BNKernelCacheImage apiImage = ImageToApi(image);
+ char **dependencies = BNKernelCacheControllerGetImageDependencies(m_object, &apiImage, &count);
+ BNKernelCacheFreeImage(apiImage);
+ std::vector<std::string> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(dependencies[i]);
+ BNFreeStringList(dependencies, count);
+ return result;
+}
- BNKCViewFreeSymbols(value, count);
- return result;
- }
+std::optional<CacheSymbol> 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::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::optional<CacheSymbol> 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::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::vector<CacheImage> KernelCacheController::GetImages() const
+{
+ size_t count;
+ BNKernelCacheImage *images = BNKernelCacheControllerGetImages(m_object, &count);
+ std::vector<CacheImage> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(ImageFromApi(images[i]));
+ BNKernelCacheFreeImageList(images, count);
+ return result;
+}
- std::optional<KernelCacheMachOHeader> 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<KernelCacheMachOHeader> 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);
- }
+std::vector<CacheImage> KernelCacheController::GetLoadedImages() const
+{
+ size_t count;
+ BNKernelCacheImage *images = BNKernelCacheControllerGetLoadedImages(m_object, &count);
+ std::vector<CacheImage> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(ImageFromApi(images[i]));
+ BNKernelCacheFreeImageList(images, count);
+ return result;
+}
-} // namespace KernelCacheAPI
+std::vector<CacheSymbol> KernelCacheController::GetSymbols() const
+{
+ size_t count;
+ BNKernelCacheSymbol *symbols = BNKernelCacheControllerGetSymbols(m_object, &count);
+ std::vector<CacheSymbol> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(SymbolFromApi(symbols[i]));
+ BNKernelCacheFreeSymbolList(symbols, count);
+ return result;
+}
diff --git a/view/kernelcache/api/kernelcacheapi.h b/view/kernelcache/api/kernelcacheapi.h
index 35c53d78..aceb30a5 100644
--- a/view/kernelcache/api/kernelcacheapi.h
+++ b/view/kernelcache/api/kernelcacheapi.h
@@ -1,274 +1,311 @@
#pragma once
#include <binaryninjaapi.h>
-#include "../core/MetadataSerializable.hpp"
-#include "../api/view/macho/machoview.h"
#include "kernelcachecore.h"
-using namespace BinaryNinja;
+template<class T>
+class KCRefCountObject {
+ void AddRefInternal() { m_refs.fetch_add(1); }
-namespace KernelCacheAPI {
- template<class T>
- class KCRefCountObject {
- void AddRefInternal() { m_refs.fetch_add(1); }
+ void ReleaseInternal() {
+ if (m_refs.fetch_sub(1) == 1)
+ delete this;
+ }
- void ReleaseInternal() {
- if (m_refs.fetch_sub(1) == 1)
- delete this;
- }
+public:
+ std::atomic<int> m_refs;
+ T *m_object;
- public:
- std::atomic<int> m_refs;
- T *m_object;
+ KCRefCountObject() : m_refs(0), m_object(nullptr) {}
+
+ virtual ~KCRefCountObject() = default;
+
+ T *GetObject() const { return m_object; }
+
+ static T *GetObject(KCRefCountObject *obj) {
+ if (!obj)
+ return nullptr;
+ return obj->GetObject();
+ }
- KCRefCountObject() : m_refs(0), m_object(nullptr) {}
+ void AddRef() { AddRefInternal(); }
- virtual ~KCRefCountObject() {}
+ void Release() { ReleaseInternal(); }
- T *GetObject() const { return m_object; }
+ void AddRefForRegistration() { AddRefInternal(); }
+};
- static T *GetObject(KCRefCountObject *obj) {
- if (!obj)
- return nullptr;
- return obj->GetObject();
+
+template<class T, T *(*AddObjectReference)(T *), void (*FreeObjectReference)(T *)>
+class KCCoreRefCountObject {
+ void AddRefInternal() { m_refs.fetch_add(1); }
+
+ void ReleaseInternal() {
+ if (m_refs.fetch_sub(1) == 1) {
+ if (!m_registeredRef)
+ delete this;
}
+ }
- void AddRef() { AddRefInternal(); }
+public:
+ std::atomic<int> m_refs;
+ bool m_registeredRef = false;
+ T *m_object;
- void Release() { ReleaseInternal(); }
+ KCCoreRefCountObject() : m_refs(0), m_object(nullptr) {}
- void AddRefForRegistration() { AddRefInternal(); }
- };
+ virtual ~KCCoreRefCountObject() = default;
+ T *GetObject() const { return m_object; }
- template<class T, T *(*AddObjectReference)(T *), void (*FreeObjectReference)(T *)>
- class KCCoreRefCountObject {
- void AddRefInternal() { m_refs.fetch_add(1); }
+ static T *GetObject(KCCoreRefCountObject *obj) {
+ if (!obj)
+ return nullptr;
+ return obj->GetObject();
+ }
- void ReleaseInternal() {
- if (m_refs.fetch_sub(1) == 1) {
- if (!m_registeredRef)
- delete this;
- }
- }
+ void AddRef() {
+ if (m_object && (m_refs != 0))
+ AddObjectReference(m_object);
+ AddRefInternal();
+ }
- public:
- std::atomic<int> m_refs;
- bool m_registeredRef = false;
- T *m_object;
+ void Release() {
+ if (m_object)
+ FreeObjectReference(m_object);
+ ReleaseInternal();
+ }
+
+ void AddRefForRegistration() { m_registeredRef = true; }
- KCCoreRefCountObject() : m_refs(0), m_object(nullptr) {}
+ void ReleaseForRegistration() {
+ m_object = nullptr;
+ m_registeredRef = false;
+ if (m_refs == 0)
+ delete this;
+ }
+};
- virtual ~KCCoreRefCountObject() {}
+template <class T>
+class KCRef
+{
+ T* m_obj;
+#ifdef BN_REF_COUNT_DEBUG
+ void* m_assignmentTrace = nullptr;
+#endif
- T *GetObject() const { return m_object; }
+public:
+ KCRef() : m_obj(NULL) {}
- static T *GetObject(KCCoreRefCountObject *obj) {
- if (!obj)
- return nullptr;
- return obj->GetObject();
+ KCRef(T* obj) : m_obj(obj)
+ {
+ if (m_obj)
+ {
+ m_obj->AddRef();
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
}
+ }
- void AddRef() {
- if (m_object && (m_refs != 0))
- AddObjectReference(m_object);
- AddRefInternal();
+ KCRef(const KCRef<T>& obj) : m_obj(obj.m_obj)
+ {
+ if (m_obj)
+ {
+ m_obj->AddRef();
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
}
+ }
- void Release() {
- if (m_object)
- FreeObjectReference(m_object);
- ReleaseInternal();
+ KCRef(KCRef<T>&& other) : m_obj(other.m_obj)
+ {
+ other.m_obj = 0;
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = other.m_assignmentTrace;
+#endif
+ }
+
+ ~KCRef()
+ {
+ if (m_obj)
+ {
+ m_obj->Release();
+#ifdef BN_REF_COUNT_DEBUG
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+#endif
}
+ }
- void AddRefForRegistration() { m_registeredRef = true; }
+ KCRef<T>& operator=(const BinaryNinja::Ref<T>& obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ if (m_obj)
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+ if (obj.m_obj)
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
+ T* oldObj = m_obj;
+ m_obj = obj.m_obj;
+ if (m_obj)
+ m_obj->AddRef();
+ if (oldObj)
+ oldObj->Release();
+ return *this;
+ }
- void ReleaseForRegistration() {
- m_object = nullptr;
- m_registeredRef = false;
- if (m_refs == 0)
- delete this;
+ KCRef<T>& operator=(KCRef<T>&& other)
+ {
+ if (m_obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+#endif
+ m_obj->Release();
}
- };
+ m_obj = other.m_obj;
+ other.m_obj = 0;
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = other.m_assignmentTrace;
+#endif
+ return *this;
+ }
- struct KCMemoryRegion {
- uint64_t vmAddress;
- uint64_t size;
- std::string prettyName;
- };
+ KCRef<T>& operator=(T* obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ if (m_obj)
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+ if (obj)
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
+ T* oldObj = m_obj;
+ m_obj = obj;
+ if (m_obj)
+ m_obj->AddRef();
+ if (oldObj)
+ oldObj->Release();
+ return *this;
+ }
- struct BackingCacheMapping {
- uint64_t vmAddress;
- uint64_t size;
- uint64_t fileOffset;
- };
+ operator T*() const
+ {
+ return m_obj;
+ }
- struct BackingCache {
- std::string path;
- bool isPrimary;
- std::vector<BackingCacheMapping> mappings;
- };
+ T* operator->() const
+ {
+ return m_obj;
+ }
- struct KCImageMemoryMapping {
- std::string name;
- uint64_t vmAddress;
- uint64_t size;
- bool loaded;
- uint64_t rawViewOffset;
- };
+ T& operator*() const
+ {
+ return *m_obj;
+ }
- struct KCImage {
- std::string name;
- uint64_t headerFileAddress;
- std::vector<KCImageMemoryMapping> mappings;
- };
+ bool operator!() const
+ {
+ return m_obj == NULL;
+ }
- struct KCSymbol {
- uint64_t address;
- std::string name;
- std::string image;
- };
+ bool operator==(const T* obj) const
+ {
+ return T::GetObject(m_obj) == T::GetObject(obj);
+ }
- using namespace BinaryNinja;
- struct KernelCacheMachOHeader : public KernelCacheCore::MetadataSerializable<KernelCacheMachOHeader> {
- uint64_t textBase = 0;
- uint64_t loadCommandOffset = 0;
- mach_header_64 ident;
- std::string identifierPrefix;
- std::string installName;
+ bool operator==(const KCRef<T>& obj) const
+ {
+ return T::GetObject(m_obj) == T::GetObject(obj.m_obj);
+ }
- std::vector<std::pair<uint64_t, bool>> entryPoints;
- std::vector<uint64_t> m_entryPoints; //list of entrypoints
+ bool operator!=(const T* obj) const
+ {
+ return T::GetObject(m_obj) != T::GetObject(obj);
+ }
- symtab_command symtab;
- dysymtab_command dysymtab;
- dyld_info_command dyldInfo;
- routines_command_64 routines64;
- function_starts_command functionStarts;
- std::vector<section_64> moduleInitSections;
- linkedit_data_command exportTrie;
- linkedit_data_command chainedFixups {};
+ bool operator!=(const KCRef<T>& obj) const
+ {
+ return T::GetObject(m_obj) != T::GetObject(obj.m_obj);
+ }
- uint64_t relocationBase;
- // Section and program headers, internally use 64-bit form as it is a superset of 32-bit
- std::vector<segment_command_64> segments; //only three types of sections __TEXT, __DATA, __IMPORT
- segment_command_64 linkeditSegment;
- std::vector<section_64> sections;
- std::vector<std::string> sectionNames;
+ bool operator<(const T* obj) const
+ {
+ return T::GetObject(m_obj) < T::GetObject(obj);
+ }
- std::vector<section_64> symbolStubSections;
- std::vector<section_64> symbolPointerSections;
+ bool operator<(const KCRef<T>& obj) const
+ {
+ return T::GetObject(m_obj) < T::GetObject(obj.m_obj);
+ }
- std::vector<std::string> dylibs;
+ T* GetPtr() const
+ {
+ return m_obj;
+ }
+};
- build_version_command buildVersion;
- std::vector<build_tool_version> buildToolVersions;
- bool dysymPresent = false;
- bool dyldInfoPresent = false;
- bool exportTriePresent = false;
- bool chainedFixupsPresent = false;
- bool routinesPresent = false;
- bool functionStartsPresent = false;
- bool relocatable = false;
- void Store(KernelCacheCore::SerializationContext& context) const {
- MSS(textBase);
- MSS(loadCommandOffset);
- MSS_SUBCLASS(ident);
- MSS(identifierPrefix);
- MSS(installName);
- MSS(entryPoints);
- MSS(m_entryPoints);
- MSS_SUBCLASS(symtab);
- MSS_SUBCLASS(dysymtab);
- MSS_SUBCLASS(dyldInfo);
- MSS_SUBCLASS(routines64);
- MSS_SUBCLASS(functionStarts);
- MSS_SUBCLASS(moduleInitSections);
- MSS_SUBCLASS(exportTrie);
- MSS_SUBCLASS(chainedFixups);
- MSS(relocationBase);
- MSS_SUBCLASS(segments);
- MSS_SUBCLASS(linkeditSegment);
- MSS_SUBCLASS(sections);
- MSS(sectionNames);
- MSS_SUBCLASS(symbolStubSections);
- MSS_SUBCLASS(symbolPointerSections);
- MSS(dylibs);
- MSS_SUBCLASS(buildVersion);
- MSS_SUBCLASS(buildToolVersions);
- MSS(dysymPresent);
- MSS(dyldInfoPresent);
- MSS(exportTriePresent);
- MSS(chainedFixupsPresent);
- MSS(routinesPresent);
- MSS(functionStartsPresent);
- MSS(relocatable);
- }
+namespace KernelCacheAPI {
+ struct CacheMappingInfo
+ {
+ uint64_t vmAddress;
+ uint64_t size;
+ uint64_t fileOffset;
+ };
- static KernelCacheMachOHeader Load(KernelCacheCore::DeserializationContext& context) {
- KernelCacheMachOHeader header;
- header.MSL(textBase);
- header.MSL(loadCommandOffset);
- header.MSL(ident);
- header.MSL(identifierPrefix);
- header.MSL(installName);
- header.MSL(entryPoints);
- header.MSL(m_entryPoints);
- header.MSL(symtab);
- header.MSL(dysymtab);
- header.MSL(dyldInfo);
- header.MSL(routines64);
- header.MSL(functionStarts);
- header.MSL(moduleInitSections);
- header.MSL(exportTrie);
- header.MSL(chainedFixups);
- header.MSL(relocationBase);
- header.MSL(segments);
- header.MSL(linkeditSegment);
- header.MSL(sections);
- header.MSL(sectionNames);
- header.MSL(symbolStubSections);
- header.MSL(symbolPointerSections);
- header.MSL(dylibs);
- header.MSL(buildVersion);
- header.MSL(buildToolVersions);
- header.MSL(dysymPresent);
- header.MSL(dyldInfoPresent);
- header.MSL(exportTriePresent);
- header.MSL(chainedFixupsPresent);
- header.MSL(routinesPresent);
- header.MSL(functionStartsPresent);
- header.MSL(relocatable);
- return header;
- }
+ struct CacheImage
+ {
+ uint64_t headerFileAddress;
+ uint64_t headerVirtualAddress;
+ std::string name;
};
+ struct CacheEntry
+ {
+ std::string path;
+ std::string name;
+ BNKernelCacheEntryType entryType;
+ std::vector<CacheMappingInfo> mappings;
+ };
- class KernelCache : public KCCoreRefCountObject<BNKernelCache, BNNewKernelCacheReference, BNFreeKernelCacheReference> {
- public:
- KernelCache(Ref<BinaryView> view);
+ struct CacheSymbol
+ {
+ BNSymbolType type;
+ uint64_t address;
+ std::string name;
+
+ std::pair<std::string, BinaryNinja::Ref<BinaryNinja::Type>> DemangledName(BinaryNinja::BinaryView &view) const;
+ BinaryNinja::Ref<BinaryNinja::Symbol> GetBNSymbol(BinaryNinja::BinaryView& view) const;
+ };
+
+ std::string GetSymbolTypeAsString(const BNSymbolType& type);
- BNKCViewState GetState();
- static BNKCViewLoadProgress GetLoadProgress(Ref<BinaryView> view);
- static uint64_t FastGetImageCount(Ref<BinaryView> view);
+ class KernelCacheController : public KCCoreRefCountObject<BNKernelCacheController, BNNewKernelCacheControllerReference, BNFreeKernelCacheControllerReference> {
+ public:
+ explicit KernelCacheController(BNKernelCacheController* controller);
+ static KCRef<KernelCacheController> GetController(BinaryNinja::BinaryView& view);
- bool LoadImageWithInstallName(const std::string& installName);
- bool LoadImageContainingAddress(uint64_t addr);
- std::vector<std::string> GetAvailableImages();
+ // Attempt to load the given image into the view.
+ //
+ // It is the callers responsibility to run linear sweep and update analysis, as you might want to add
+ // multiple images at a time.
+ bool ApplyImage(BinaryNinja::BinaryView& view, const CacheImage& image);
- bool IsImageLoaded(const uint64_t address) const;
+ bool IsImageLoaded(const CacheImage& image) const;
- std::vector<KCSymbol> LoadAllSymbolsAndWait();
+ std::optional<CacheImage> GetImageAt(uint64_t address) const;
+ std::optional<CacheImage> GetImageContaining(uint64_t address) const;
+ std::optional<CacheImage> GetImageWithName(const std::string& name) const;
- std::string GetNameForAddress(uint64_t address);
- std::string GetImageNameForAddress(uint64_t address);
+ std::vector<std::string> GetImageDependencies(const CacheImage& image) const;
- std::vector<KCImage> GetImages();
- std::vector<KCImage> GetLoadedImages();
+ std::optional<CacheSymbol> GetSymbolAt(uint64_t address) const;
+ std::optional<CacheSymbol> GetSymbolWithName(const std::string& name) const;
- std::optional<KernelCacheMachOHeader> GetMachOHeaderForImage(const std::string& name);
- std::optional<KernelCacheMachOHeader> GetMachOHeaderForAddress(uint64_t address);
+ std::vector<CacheImage> GetImages() const;
+ std::vector<CacheImage> GetLoadedImages() const;
+ std::vector<CacheSymbol> GetSymbols() const;
};
-} \ No newline at end of file
+}
diff --git a/view/kernelcache/api/kernelcachecore.h b/view/kernelcache/api/kernelcachecore.h
index 2f158131..02451a3e 100644
--- a/view/kernelcache/api/kernelcachecore.h
+++ b/view/kernelcache/api/kernelcachecore.h
@@ -28,6 +28,34 @@ extern "C"
#endif // _MSC_VER
#endif // __GNUC__C
+
+// binaryninjacore.h is not included so we must duplicate enum types here.
+#ifdef BN_TYPE_PARSER
+typedef enum BNSegmentFlag
+{
+ SegmentExecutable = 1,
+ SegmentWritable = 2,
+ SegmentReadable = 4,
+ SegmentContainsData = 8,
+ SegmentContainsCode = 0x10,
+ SegmentDenyWrite = 0x20,
+ SegmentDenyExecute = 0x40
+} BNSegmentFlag;
+
+typedef enum BNSymbolType
+{
+ FunctionSymbol = 0,
+ ImportAddressSymbol = 1,
+ ImportedFunctionSymbol = 2,
+ DataSymbol = 3,
+ ImportedDataSymbol = 4,
+ ExternalSymbol = 5,
+ LibraryFunctionSymbol = 6,
+ SymbolicFunctionSymbol = 7,
+ LocalLabelSymbol = 8,
+} BNSymbolType;
+#endif
+
#define CORE_ALLOCATED_STRUCT(T)
#define CORE_ALLOCATED_CLASS(T) \
@@ -35,101 +63,80 @@ extern "C"
CORE_ALLOCATED_STRUCT(T) \
private:
-#define DECLARE_KERNELCACHE_API_OBJECT_INTERNAL(handle, cls, ns) \
- namespace ns { class cls; } struct handle { ns::cls* object; }
-
-#define DECLARE_KERNELCACHE_API_OBJECT(handle, cls) DECLARE_KERNELCACHE_API_OBJECT_INTERNAL(handle, cls, KernelCacheCore)
-
-#define IMPLEMENT_KERNELCACHE_API_OBJECT(handle) \
- CORE_ALLOCATED_CLASS(handle) \
- private: \
- handle m_apiObject; \
- public: \
- typedef handle* APIHandle; \
- handle* GetAPIObject() { return &m_apiObject; } \
- private:
-#define INIT_KERNELCACHE_API_OBJECT() \
- m_apiObject.object = this;
+ typedef struct BNBinaryView BNBinaryView;
+ typedef struct BNKernelCacheController BNKernelCacheController;
- typedef enum BNKCViewState {
- Unloaded,
- Loaded,
- LoadedWithImages,
- } BNKCViewState;
+ typedef enum BNKernelCacheEntryType {
+ KernelCacheEntryTypePrimary,
+ KernelCacheEntryTypeSecondary,
+ KernelCacheEntryTypeSymbols,
+ KernelCacheEntryTypeDyldData,
+ KernelCacheEntryTypeStub,
+ } BNKernelCacheEntryType;
- typedef enum BNKCViewLoadProgress {
- LoadProgressNotStarted,
- LoadProgressLoadingCaches,
- LoadProgressLoadingImages,
- LoadProgressFinished,
- } BNKCViewLoadProgress;
+ typedef enum BNKernelCacheRegionType {
+ KernelCacheRegionTypeImage,
+ KernelCacheRegionTypeStubIsland,
+ KernelCacheRegionTypeDyldData,
+ KernelCacheRegionTypeNonImage,
+ } BNKernelCacheRegionType;
- typedef struct BNBinaryView BNBinaryView;
- typedef struct BNKernelCache BNKernelCache;
+ typedef struct BNKernelCacheImage {
+ char* name;
+ uint64_t headerVirtualAddress;
+ uint64_t headerFileAddress;
+ } BNKernelCacheImage;
- typedef struct BNKCImageMemoryMapping {
+ typedef struct BNKernelCacheRegion {
+ BNKernelCacheRegionType regionType;
char* name;
uint64_t vmAddress;
uint64_t size;
- bool loaded;
- uint64_t rawViewOffset;
- } BNKCImageMemoryMapping;
-
- typedef struct BNKCImage {
- char* name;
- uint64_t headerFileAddress;
- BNKCImageMemoryMapping* mappings;
- size_t mappingCount;
- } BNKCImage;
+ // NOTE: If not associated with an image this will be zero.
+ uint64_t imageStart;
+ BNSegmentFlag flags;
+ } BNKernelCacheRegion;
- typedef struct BNKCMappedMemoryRegion {
+ typedef struct BNKernelCacheMappingInfo {
uint64_t vmAddress;
uint64_t size;
- char* name;
- } BNKCMappedMemoryRegion;
+ uint64_t fileOffset;
+ } BNKernelCacheMappingInfo;
- typedef struct BNKCMemoryUsageInfo {
- uint64_t sharedCacheRefs;
- uint64_t mmapRefs;
- } BNKCMemoryUsageInfo;
-
- typedef struct BNKCSymbolRep {
+ typedef struct BNKernelCacheSymbol {
+ BNSymbolType symbolType;
uint64_t address;
char* name;
- char* image;
- } BNKCSymbolRep;
-
- KERNELCACHE_FFI_API BNKernelCache* BNGetKernelCache(BNBinaryView* data);
+ } BNKernelCacheSymbol;
- KERNELCACHE_FFI_API BNKernelCache* BNNewKernelCacheReference(BNKernelCache* cache);
- KERNELCACHE_FFI_API void BNFreeKernelCacheReference(BNKernelCache* cache);
+ KERNELCACHE_FFI_API BNKernelCacheController* BNGetKernelCacheController(BNBinaryView* data);
- KERNELCACHE_FFI_API char** BNKCViewGetInstallNames(BNKernelCache* cache, size_t* count);
+ KERNELCACHE_FFI_API BNKernelCacheController* BNNewKernelCacheControllerReference(BNKernelCacheController* controller);
+ KERNELCACHE_FFI_API void BNFreeKernelCacheControllerReference(BNKernelCacheController* controller);
- KERNELCACHE_FFI_API bool BNKCViewLoadImageWithInstallName(BNKernelCache* cache, const char* name);
- KERNELCACHE_FFI_API bool BNKCViewLoadImageContainingAddress(BNKernelCache* cache, uint64_t address);
+ KERNELCACHE_FFI_API bool BNKernelCacheControllerApplyImage(BNKernelCacheController* controller, BNBinaryView* view, BNKernelCacheImage* image);
- KERNELCACHE_FFI_API bool BNKCViewIsImageLoaded(BNKernelCache* cache, uint64_t address);
+ KERNELCACHE_FFI_API bool BNKernelCacheControllerIsImageLoaded(BNKernelCacheController* controller, BNKernelCacheImage* image);
- KERNELCACHE_FFI_API char* BNKCViewGetNameForAddress(BNKernelCache* cache, uint64_t address);
- KERNELCACHE_FFI_API char* BNKCViewGetImageNameForAddress(BNKernelCache* cache, uint64_t address);
+ KERNELCACHE_FFI_API bool BNKernelCacheControllerGetImageAt(BNKernelCacheController* controller, uint64_t address, BNKernelCacheImage* image);
+ KERNELCACHE_FFI_API bool BNKernelCacheControllerGetImageContaining(BNKernelCacheController* controller, uint64_t address, BNKernelCacheImage* image);
+ KERNELCACHE_FFI_API bool BNKernelCacheControllerGetImageWithName(BNKernelCacheController* controller, const char* name, BNKernelCacheImage* image);
- KERNELCACHE_FFI_API BNKCViewState BNKCViewGetState(BNKernelCache* cache);
- KERNELCACHE_FFI_API BNKCViewLoadProgress BNKCViewGetLoadProgress(uint64_t sessionID);
- KERNELCACHE_FFI_API uint64_t BNKCViewFastGetImageCount(BNBinaryView* view);
+ KERNELCACHE_FFI_API char** BNKernelCacheControllerGetImageDependencies(BNKernelCacheController* controller, BNKernelCacheImage* image, size_t* count);
- KERNELCACHE_FFI_API BNKCSymbolRep* BNKCViewLoadAllSymbolsAndWait(BNKernelCache* cache, size_t* count);
- KERNELCACHE_FFI_API void BNKCViewFreeSymbols(BNKCSymbolRep* symbols, size_t count);
+ KERNELCACHE_FFI_API BNKernelCacheImage* BNKernelCacheControllerGetImages(BNKernelCacheController* controller, size_t* count);
+ KERNELCACHE_FFI_API BNKernelCacheImage* BNKernelCacheControllerGetLoadedImages(BNKernelCacheController* controller, size_t* count);
- KERNELCACHE_FFI_API BNKCImage* BNKCViewGetAllImages(BNKernelCache* cache, size_t* count);
- KERNELCACHE_FFI_API void BNKCViewFreeAllImages(BNKCImage* images, size_t count);
+ KERNELCACHE_FFI_API void BNKernelCacheFreeImage(BNKernelCacheImage image);
+ KERNELCACHE_FFI_API void BNKernelCacheFreeImageList(BNKernelCacheImage* images, size_t count);
- KERNELCACHE_FFI_API BNKCImage* BNKCViewGetLoadedImages(BNKernelCache* cache, size_t* count);
- KERNELCACHE_FFI_API void BNKCViewFreeLoadedImages(BNKCImage* images, size_t count);
+ KERNELCACHE_FFI_API bool BNKernelCacheControllerGetSymbolAt(BNKernelCacheController* controller, uint64_t address, BNKernelCacheSymbol* symbol);
+ KERNELCACHE_FFI_API bool BNKernelCacheControllerGetSymbolWithName(BNKernelCacheController* controller, const char* name, BNKernelCacheSymbol* symbol);
- KERNELCACHE_FFI_API char* BNKCViewGetImageHeaderForAddress(BNKernelCache* cache, uint64_t address);
- KERNELCACHE_FFI_API char* BNKCViewGetImageHeaderForName(BNKernelCache* cache, const char* name);
+ KERNELCACHE_FFI_API BNKernelCacheSymbol* BNKernelCacheControllerGetSymbols(BNKernelCacheController* controller, size_t* count);
+ KERNELCACHE_FFI_API void BNKernelCacheFreeSymbol(BNKernelCacheSymbol symbol);
+ KERNELCACHE_FFI_API void BNKernelCacheFreeSymbolList(BNKernelCacheSymbol* symbols, size_t count);
#ifdef __cplusplus
}
#endif
diff --git a/view/kernelcache/api/python/kernelcache.py b/view/kernelcache/api/python/kernelcache.py
index 9425ef9c..25360213 100644
--- a/view/kernelcache/api/python/kernelcache.py
+++ b/view/kernelcache/api/python/kernelcache.py
@@ -1,229 +1,210 @@
-import os
import ctypes
import dataclasses
-import traceback
+from typing import Optional
import binaryninja
+from binaryninja import BinaryView
from binaryninja._binaryninjacore import BNFreeStringList, BNAllocString, BNFreeString
from . import _kernelcachecore as kccore
from .kernelcache_enums import *
-
@dataclasses.dataclass
-class KCImageMemoryMapping:
+class CacheImage:
name: str
- vmAddress: int
- rawViewOffset: int
- size: int
+ header_virtual_address: int
+ header_file_address: int
def __str__(self):
return repr(self)
def __repr__(self):
- return (f"<KCImageMemoryMapping '{self.name}' {self.vmAddress:x}+{self.size:x} "
- f"raw<{self.rawViewOffset:x}>>")
-
+ return f"<CacheImage '{self.name}': 0x{self.header_virtual_address:x} (@0x{self.header_file_address:x})>"
@dataclasses.dataclass
-class KCImage:
+class CacheSymbol:
+ symbol_type: kccore.SymbolTypeEnum
+ address: int
name: str
- headerFileAddress: int
- mappings: list[KCImageMemoryMapping]
def __str__(self):
return repr(self)
def __repr__(self):
- return f"<KCImage {self.name} @ {self.headerFileAddress:x}>"
+ return f"<CacheSymbol '{self.name}': 0x{self.address:x}>"
+def image_from_api(image: kccore.BNKernelCacheImage) -> CacheImage:
+ return CacheImage(
+ name=image.name,
+ header_file_address=image.headerFileAddress,
+ header_virtual_address=image.headerVirtualAddress
+ )
-@dataclasses.dataclass
-class KCSymbol:
- name: str
- image: str
- address: int
+def image_to_api(image: CacheImage) -> kccore.BNKernelCacheImage:
+ return kccore.BNKernelCacheImage(
+ _name=BNAllocString(image.name),
+ headerFileAddress=image.header_file_address,
+ headerVirtualAddress=image.header_virtual_address,
+ )
- def __str__(self):
- return repr(self)
+def symbol_from_api(symbol: kccore.BNKernelCacheSymbol) -> CacheSymbol:
+ return CacheSymbol(
+ symbol_type=symbol.symbolType,
+ address=symbol.address,
+ name=symbol.name
+ )
- def __repr__(self):
- return f"<KCSymbol {self.name} @ {self.address:x} ({self.image})>"
+def symbol_to_api(symbol: CacheSymbol) -> kccore.BNKernelCacheSymbol:
+ return kccore.BNKernelCacheSymbol(
+ symbolType=symbol.symbol_type,
+ address=symbol.address,
+ _name=BNAllocString(symbol.name)
+ )
+class KernelCacheController:
+ def __init__(self, view: BinaryView):
+ """
+ Retrieve the shared cache controller for a given view.
+ Call `is_valid` to check if the controller is valid.
+ """
+ self.handle = kccore.BNGetKernelCacheController(view.handle)
-@dataclasses.dataclass
-class KernelCacheMachOHeader:
- header: str
+ def __del__(self):
+ if self.handle is not None:
+ kccore.BNFreeKernelCacheControllerReference(self.handle)
- @classmethod
- def LoadFromString(cls, s: str):
- return cls(header=s)
+ def __str__(self):
+ return repr(self)
def __repr__(self):
- return f"<KernelCacheMachOHeader {self.header!r}>"
+ return f"<KernelCacheController: {len(self.images)} images>"
+ def is_valid(self) -> bool:
+ return self.handle is not None
-class KernelCache:
- def __init__(self, view):
- # Create a KernelCache object from a BinaryView.
- self.handle = kccore.BNGetKernelCache(view.handle)
+ def apply_image(self, view: BinaryView, image: CacheImage) -> bool:
+ api_image: kccore.BNKernelCacheImage = image_to_api(image)
+ result = kccore.BNKernelCacheControllerApplyImage(self.handle, view.handle, api_image)
+ kccore.BNKernelCacheFreeImage(api_image)
+ return result
- @staticmethod
- def get_load_progress(view) -> int:
- """
- Returns the current load progress.
- Note: In the C++ FFI this function takes the BinaryView's file session ID.
- """
- return KCViewLoadProgress(kccore.BNKCViewGetLoadProgress(view.file.session_id))
+ def is_image_loaded(self, image: CacheImage) -> bool:
+ api_image: kccore.BNKernelCacheImage = image_to_api(image)
+ result = kccore.BNKernelCacheControllerIsImageLoaded(self.handle, api_image)
+ kccore.BNKernelCacheFreeImage(api_image)
+ return result
- @staticmethod
- def fast_get_image_count(view) -> int:
- """
- Quickly returns the number of images in the kernel cache.
- """
- return kccore.BNKCViewFastGetImageCount(view.handle)
+ def get_image_at(self, address: int) -> Optional[CacheImage]:
+ api_image = kccore.BNKernelCacheImage()
+ if not kccore.BNKernelCacheControllerGetImageAt(self.handle, address, api_image):
+ return None
+ image = image_from_api(api_image)
+ kccore.BNKernelCacheFreeImage(api_image)
+ return image
- def load_image_with_install_name(self, install_name: str) -> bool:
- """
- Load a kernel cache image by its install name.
- """
- return kccore.BNKCViewLoadImageWithInstallName(self.handle, install_name)
+ def get_image_containing(self, address: int) -> Optional[CacheImage]:
+ api_image = kccore.BNKernelCacheImage()
+ if not kccore.BNKernelCacheControllerGetImageContaining(self.handle, address, api_image):
+ return None
+ image = image_from_api(api_image)
+ kccore.BNKernelCacheFreeImage(api_image)
+ return image
- def load_image_containing_address(self, addr: int) -> bool:
- """
- Load the image that contains the given address.
- """
- return kccore.BNKCViewLoadImageContainingAddress(self.handle, addr)
+ def get_image_with_name(self, name: str) -> Optional[CacheImage]:
+ api_image = kccore.BNKernelCacheImage()
+ if not kccore.BNKernelCacheControllerGetImageWithName(self.handle, name, api_image):
+ return None
+ image = image_from_api(api_image)
+ kccore.BNKernelCacheFreeImage(api_image)
+ return image
- @property
- def image_names(self) -> list[str]:
+ def get_image_dependencies(self, image: CacheImage) -> [str]:
"""
- Return a list of available kernel cache image install names.
+ Returns a list of image names that this image depends on.
"""
count = ctypes.c_ulonglong()
- value = kccore.BNKCViewGetInstallNames(self.handle, count)
+ api_image: kccore.BNKernelCacheImage = image_to_api(image)
+ value = kccore.BNKernelCacheControllerGetImageDependencies(self.handle, api_image, count)
+ kccore.BNKernelCacheFreeImage(api_image)
if value is None:
return []
result = []
for i in range(count.value):
- result.append(value[i].decode('utf-8'))
+ result.append(value[i].decode("utf-8"))
BNFreeStringList(value, count)
return result
+ def get_symbol_at(self, address: int) -> Optional[CacheSymbol]:
+ api_symbol = kccore.BNKernelCacheSymbol()
+ if not kccore.BNKernelCacheControllerGetSymbolAt(self.handle, address, api_symbol):
+ return None
+ symbol = symbol_from_api(api_symbol)
+ kccore.BNKernelCacheFreeSymbol(api_symbol)
+ return symbol
+
+ def get_symbol_with_name(self, name: str) -> Optional[CacheSymbol]:
+ api_symbol = kccore.BNKernelCacheSymbol()
+ if not kccore.BNKernelCacheControllerGetSymbolWithName(self.handle, name, api_symbol):
+ return None
+ symbol = symbol_from_api(api_symbol)
+ kccore.BNKernelCacheFreeSymbol(api_symbol)
+ return symbol
+
@property
- def images(self) -> list[KCImage]:
- """
- Return all kernel cache images.
- """
+ def images(self) -> [CacheImage]:
count = ctypes.c_ulonglong()
- value = kccore.BNKCViewGetAllImages(self.handle, count)
+ value = kccore.BNKernelCacheControllerGetImages(self.handle, count)
if value is None:
return []
result = []
for i in range(count.value):
- mappings = []
- for j in range(value[i].mappingCount):
- mapping = KCImageMemoryMapping(
- name=value[i].mappings[j].name,
- vmAddress=value[i].mappings[j].vmAddress,
- rawViewOffset=value[i].mappings[j].rawViewOffset,
- size=value[i].mappings[j].size,
- )
- mappings.append(mapping)
- result.append(KCImage(
- name=value[i].name,
- headerFileAddress=value[i].headerFileAddress,
- mappings=mappings
- ))
- kccore.BNKCViewFreeAllImages(value, count)
+ result.append(image_from_api(value[i]))
+ kccore.BNKernelCacheFreeImageList(value, count)
return result
@property
- def loaded_images(self) -> list[KCImage]:
+ def loaded_images(self) -> [CacheImage]:
"""
- Return the kernel cache images that are currently loaded.
+ Get a list of images that are currently loaded in the view.
"""
count = ctypes.c_ulonglong()
- images = kccore.BNKCViewGetLoadedImages(self.handle, count)
- if images is None:
+ value = kccore.BNKernelCacheControllerGetLoadedImages(self.handle, count)
+ if value is None:
return []
result = []
for i in range(count.value):
- mappings = []
- for j in range(images[i].mappingCount):
- mapping = KCImageMemoryMapping(
- name=images[i].mappings[j].name,
- vmAddress=images[i].mappings[j].vmAddress,
- rawViewOffset=images[i].mappings[j].rawViewOffset,
- size=images[i].mappings[j].size,
- )
- mappings.append(mapping)
- result.append(KCImage(
- name=images[i].name,
- headerFileAddress=images[i].headerFileAddress,
- mappings=mappings
- ))
- kccore.BNKCViewFreeAllImages(images, count)
+ result.append(image_from_api(value[i]))
+ kccore.BNKernelCacheFreeImageList(value, count)
return result
- def load_all_symbols_and_wait(self) -> list[KCSymbol]:
- """
- Load all symbols from the kernel cache and wait for completion.
- """
+ @property
+ def symbols(self) -> [CacheSymbol]:
count = ctypes.c_ulonglong()
- value = kccore.BNKCViewLoadAllSymbolsAndWait(self.handle, count)
+ value = kccore.BNKernelCacheControllerGetSymbols(self.handle, count)
if value is None:
return []
result = []
for i in range(count.value):
- sym = KCSymbol(
- name=value[i].name,
- image=value[i].image,
- address=value[i].address
- )
- result.append(sym)
- kccore.BNKCViewFreeSymbols(value, count)
+ result.append(symbol_from_api(value[i]))
+ kccore.BNKernelCacheFreeSymbolList(value, count)
return result
- def get_name_for_address(self, address: int) -> str:
- """
- Return the symbol name for a given address.
- """
- name = kccore.BNKCViewGetNameForAddress(self.handle, address)
- if name is None:
- return ""
- return name
- def get_image_name_for_address(self, address: int) -> str:
- """
- Return the image name for a given address.
- """
- name = kccore.BNKCViewGetImageNameForAddress(self.handle, address)
- if name is None:
- return ""
- return name
+def _get_kernel_cache(instance: binaryninja.PythonScriptingInstance):
+ if instance.interpreter.active_view is None:
+ return None
+ controller = KernelCacheController(instance.interpreter.active_view)
+ if not controller.is_valid():
+ return None
+ return controller
- def get_macho_header_for_image(self, name: str):
- """
- Return a KernelCacheMachOHeader for the image with the given install name.
- """
- outputStr = kccore.BNKCViewGetImageHeaderForName(self.handle, name)
- if outputStr is None:
- return None
- return KernelCacheMachOHeader.LoadFromString(outputStr)
- def get_macho_header_for_address(self, address: int):
- """
- Return a KernelCacheMachOHeader for the image containing the given address.
- """
- outputStr = kccore.BNKCViewGetImageHeaderForAddress(self.handle, address)
- if outputStr is None:
- return None
- return KernelCacheMachOHeader.LoadFromString(outputStr)
+binaryninja.PythonScriptingProvider.register_magic_variable(
+ "kc",
+ _get_kernel_cache
+)
- @property
- def state(self):
- """
- Return the current state of the kernel cache.
- """
- return KCViewState(kccore.BNKCViewGetState(self.handle))
+binaryninja.PythonScriptingProvider.register_magic_variable(
+ "kernel_cache",
+ _get_kernel_cache
+)
diff --git a/view/kernelcache/api/python/kernelcache_enums.py b/view/kernelcache/api/python/kernelcache_enums.py
index e610c527..83cbf027 100644
--- a/view/kernelcache/api/python/kernelcache_enums.py
+++ b/view/kernelcache/api/python/kernelcache_enums.py
@@ -1,14 +1,38 @@
import enum
-class KCViewLoadProgress(enum.IntEnum):
- LoadProgressNotStarted = 0
- LoadProgressLoadingCaches = 1
- LoadProgressLoadingImages = 2
- LoadProgressFinished = 3
+class KernelCacheEntryType(enum.IntEnum):
+ KernelCacheEntryTypePrimary = 0
+ KernelCacheEntryTypeSecondary = 1
+ KernelCacheEntryTypeSymbols = 2
+ KernelCacheEntryTypeDyldData = 3
+ KernelCacheEntryTypeStub = 4
-class KCViewState(enum.IntEnum):
- Unloaded = 0
- Loaded = 1
- LoadedWithImages = 2
+class KernelCacheRegionType(enum.IntEnum):
+ KernelCacheRegionTypeImage = 0
+ KernelCacheRegionTypeStubIsland = 1
+ KernelCacheRegionTypeDyldData = 2
+ KernelCacheRegionTypeNonImage = 3
+
+
+class SegmentFlag(enum.IntEnum):
+ SegmentExecutable = 1
+ SegmentWritable = 2
+ SegmentReadable = 4
+ SegmentContainsData = 8
+ SegmentContainsCode = 16
+ SegmentDenyWrite = 32
+ SegmentDenyExecute = 64
+
+
+class SymbolType(enum.IntEnum):
+ FunctionSymbol = 0
+ ImportAddressSymbol = 1
+ ImportedFunctionSymbol = 2
+ DataSymbol = 3
+ ImportedDataSymbol = 4
+ ExternalSymbol = 5
+ LibraryFunctionSymbol = 6
+ SymbolicFunctionSymbol = 7
+ LocalLabelSymbol = 8