summaryrefslogtreecommitdiff
path: root/view/kernelcache/api/kernelcacheapi.h
diff options
context:
space:
mode:
Diffstat (limited to 'view/kernelcache/api/kernelcacheapi.h')
-rw-r--r--view/kernelcache/api/kernelcacheapi.h272
1 files changed, 272 insertions, 0 deletions
diff --git a/view/kernelcache/api/kernelcacheapi.h b/view/kernelcache/api/kernelcacheapi.h
new file mode 100644
index 00000000..149f39bf
--- /dev/null
+++ b/view/kernelcache/api/kernelcacheapi.h
@@ -0,0 +1,272 @@
+#pragma once
+
+#include <binaryninjaapi.h>
+#include "../core/MetadataSerializable.hpp"
+#include "../api/view/macho/machoview.h"
+#include "kernelcachecore.h"
+
+using namespace BinaryNinja;
+
+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;
+ }
+
+ public:
+ std::atomic<int> m_refs;
+ T *m_object;
+
+ KCRefCountObject() : m_refs(0), m_object(nullptr) {}
+
+ virtual ~KCRefCountObject() {}
+
+ T *GetObject() const { return m_object; }
+
+ static T *GetObject(KCRefCountObject *obj) {
+ if (!obj)
+ return nullptr;
+ return obj->GetObject();
+ }
+
+ void AddRef() { AddRefInternal(); }
+
+ void Release() { ReleaseInternal(); }
+
+ void AddRefForRegistration() { AddRefInternal(); }
+ };
+
+
+ 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;
+ }
+ }
+
+ public:
+ std::atomic<int> m_refs;
+ bool m_registeredRef = false;
+ T *m_object;
+
+ KCCoreRefCountObject() : m_refs(0), m_object(nullptr) {}
+
+ virtual ~KCCoreRefCountObject() {}
+
+ T *GetObject() const { return m_object; }
+
+ static T *GetObject(KCCoreRefCountObject *obj) {
+ if (!obj)
+ return nullptr;
+ return obj->GetObject();
+ }
+
+ void AddRef() {
+ if (m_object && (m_refs != 0))
+ AddObjectReference(m_object);
+ AddRefInternal();
+ }
+
+ void Release() {
+ if (m_object)
+ FreeObjectReference(m_object);
+ ReleaseInternal();
+ }
+
+ void AddRefForRegistration() { m_registeredRef = true; }
+
+ void ReleaseForRegistration() {
+ m_object = nullptr;
+ m_registeredRef = false;
+ if (m_refs == 0)
+ delete this;
+ }
+ };
+
+ struct KCMemoryRegion {
+ uint64_t vmAddress;
+ uint64_t size;
+ std::string prettyName;
+ };
+
+ struct BackingCacheMapping {
+ uint64_t vmAddress;
+ uint64_t size;
+ uint64_t fileOffset;
+ };
+
+ struct BackingCache {
+ std::string path;
+ bool isPrimary;
+ std::vector<BackingCacheMapping> mappings;
+ };
+
+ struct KCImageMemoryMapping {
+ std::string name;
+ uint64_t vmAddress;
+ uint64_t size;
+ bool loaded;
+ uint64_t rawViewOffset;
+ };
+
+ struct KCImage {
+ std::string name;
+ uint64_t headerFileAddress;
+ std::vector<KCImageMemoryMapping> mappings;
+ };
+
+ struct KCSymbol {
+ uint64_t address;
+ std::string name;
+ std::string image;
+ };
+
+ 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;
+
+ std::vector<std::pair<uint64_t, bool>> entryPoints;
+ std::vector<uint64_t> m_entryPoints; //list of entrypoints
+
+ 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 {};
+
+ 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;
+
+ std::vector<section_64> symbolStubSections;
+ std::vector<section_64> symbolPointerSections;
+
+ std::vector<std::string> dylibs;
+
+ 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);
+ }
+
+ 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;
+ }
+ };
+
+
+ class KernelCache : public KCCoreRefCountObject<BNKernelCache, BNNewKernelCacheReference, BNFreeKernelCacheReference> {
+ public:
+ KernelCache(Ref<BinaryView> view);
+
+ BNKCViewState GetState();
+ static BNKCViewLoadProgress GetLoadProgress(Ref<BinaryView> view);
+ static uint64_t FastGetImageCount(Ref<BinaryView> view);
+
+ bool LoadImageWithInstallName(std::string installName);
+ bool LoadImageContainingAddress(uint64_t addr);
+ std::vector<std::string> GetAvailableImages();
+
+ std::vector<KCSymbol> LoadAllSymbolsAndWait();
+
+ std::string GetNameForAddress(uint64_t address);
+ std::string GetImageNameForAddress(uint64_t address);
+
+ std::vector<KCImage> GetImages();
+ std::vector<KCImage> GetLoadedImages();
+
+ std::optional<KernelCacheMachOHeader> GetMachOHeaderForImage(std::string name);
+ std::optional<KernelCacheMachOHeader> GetMachOHeaderForAddress(uint64_t address);
+ };
+} \ No newline at end of file