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/core/KCView.cpp | 921 --------------------------------------- 1 file changed, 921 deletions(-) delete mode 100644 view/kernelcache/core/KCView.cpp (limited to 'view/kernelcache/core/KCView.cpp') diff --git a/view/kernelcache/core/KCView.cpp b/view/kernelcache/core/KCView.cpp deleted file mode 100644 index f166eafd..00000000 --- a/view/kernelcache/core/KCView.cpp +++ /dev/null @@ -1,921 +0,0 @@ -// -// Created by kat on 5/23/23. -// - -/* - * - * */ - -#include "KCView.h" -#include "view/macho/machoview.h" -#include "KernelCache.h" - -[[maybe_unused]] KCViewType* g_kcViewType; - - -#define COMPRESSION_DEBUG 1 - -using namespace BinaryNinja; - - -KCView::KCView(const std::string& typeName, BinaryView* data, bool parseOnly) : - BinaryView(typeName, data->GetFile(), data), m_parseOnly(parseOnly) -{ - CreateLogger("KernelCache"); -} - -KCView::~KCView() -{ -} - -enum KCPlatform { - KCPlatformMacOS = 1, - KCPlatformiOS = 2, - KCPlatformTVOS = 3, - KCPlatformWatchOS = 4, - KCPlatformBridgeOS = 5, // T1/T2 APL1023/T8012, this is your touchbar/touchid in intel macs. Similar to watchOS. - // KCPlatformMacCatalyst = 6, - KCPlatformiOSSimulator = 7, - KCPlatformTVOSSimulator = 8, - KCPlatformWatchOSSimulator = 9, - KCPlatformVisionOS = 11, // Apple Vision Pro - KCPlatformVisionOSSimulator = 12 // Apple Vision Pro Simulator -}; - -bool KCView::Init() -{ - BinaryReader reader(GetParentView()); - reader.Seek(0x4); - uint32_t cpuType = reader.Read32(); - reader.Seek(0x10); - uint64_t ncmds = reader.Read32(); - uint64_t sizeofcmds = reader.Read32(); - - // get __TEXT seg offset - uint64_t textSegOffset = 0; - uint64_t anyFilesetHeaderFileOffset = 0; - uint64_t offset = 0x20; - for (uint64_t i = 0; i < ncmds; i++) - { - reader.Seek(offset); - uint64_t cmd = reader.Read32(); - uint64_t cmdsize = reader.Read32(); - if (textSegOffset == 0 && cmd == LC_SEGMENT_64) - { - uint64_t segname = reader.Read64(); - reader.Read64(); - uint64_t vmaddr = reader.Read64(); - if (segname == 0x545845545f5f) // __TEXT - { - textSegOffset = vmaddr; - } - } - - if (anyFilesetHeaderFileOffset == 0 && cmd == LC_FILESET_ENTRY) - { - reader.SeekRelative(8); - anyFilesetHeaderFileOffset = reader.Read64(); - } - - offset += cmdsize; - if (textSegOffset && anyFilesetHeaderFileOffset) - break; - } - - Ref platform; - Ref architecture; - - if (anyFilesetHeaderFileOffset) - { - reader.Seek(anyFilesetHeaderFileOffset); - reader.SeekRelative(0x10); - - uint64_t ncmdsFH = reader.Read32(); - - reader.Seek(anyFilesetHeaderFileOffset + 0x20); - offset = anyFilesetHeaderFileOffset + 0x20; - bool foundBuildVersion = false; - for (uint64_t i = 0; i < ncmdsFH; i++) - { - reader.Seek(offset); - uint64_t cmd = reader.Read32(); - uint64_t cmdsize = reader.Read32(); - if (cmd == LC_BUILD_VERSION) - { - uint32_t platformID = reader.Read32(); - std::map> metadataMap = { - {"machoplatform", new Metadata((uint64_t) platformID)}, - }; - Ref metadata = new Metadata(metadataMap); - Ref plat = g_kcViewType->RecognizePlatform(cpuType, GetDefaultEndianness(), this, metadata); - SetDefaultArchitecture(plat->GetArchitecture()); - SetDefaultPlatform(plat); - foundBuildVersion = true; - } - offset += cmdsize; - } - if (!foundBuildVersion) - { - LogError("Failed to find LC_BUILD_VERSION in subheader"); - SetDefaultArchitecture(Architecture::GetByName("aarch64")); - SetDefaultPlatform(Platform::GetByName("macos-kernel-aarch64")); - } - } - else - { - LogError("MH_FILESET had no subheaders"); - return false; - } - - if (textSegOffset == 0) - { - LogError("Failed to find __TEXT segment"); - return false; - } - - - // Add Mach-O file header type info - EnumerationBuilder cpuTypeBuilder; - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ANY", MACHO_CPU_TYPE_ANY); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_VAX", MACHO_CPU_TYPE_VAX); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC680x0", MACHO_CPU_TYPE_MC680x0); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_X86", MACHO_CPU_TYPE_X86); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_X86_64", MACHO_CPU_TYPE_X86_64); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MIPS", MACHO_CPU_TYPE_MIPS); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC98000", MACHO_CPU_TYPE_MC98000); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_HPPA", MACHO_CPU_TYPE_HPPA); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM", MACHO_CPU_TYPE_ARM); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM64", MACHO_CPU_TYPE_ARM64); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM64_32", MACHO_CPU_TYPE_ARM64_32); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC88000", MACHO_CPU_TYPE_MC88000); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_SPARC", MACHO_CPU_TYPE_SPARC); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_I860", MACHO_CPU_TYPE_I860); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ALPHA", MACHO_CPU_TYPE_ALPHA); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_POWERPC", MACHO_CPU_TYPE_POWERPC); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_POWERPC64", MACHO_CPU_TYPE_POWERPC64); - Ref cpuTypeEnum = cpuTypeBuilder.Finalize(); - - Ref cpuTypeEnumType = Type::EnumerationType(nullptr, cpuTypeEnum, 4, false); - std::string cpuTypeEnumName = "cpu_type_t"; - std::string cpuTypeEnumId = Type::GenerateAutoTypeId("macho", cpuTypeEnumName); - DefineType(cpuTypeEnumId, cpuTypeEnumName, cpuTypeEnumType); - - EnumerationBuilder fileTypeBuilder; - fileTypeBuilder.AddMemberWithValue("MH_OBJECT", MH_OBJECT); - fileTypeBuilder.AddMemberWithValue("MH_EXECUTE", MH_EXECUTE); - fileTypeBuilder.AddMemberWithValue("MH_FVMLIB", MH_FVMLIB); - fileTypeBuilder.AddMemberWithValue("MH_CORE", MH_CORE); - fileTypeBuilder.AddMemberWithValue("MH_PRELOAD", MH_PRELOAD); - fileTypeBuilder.AddMemberWithValue("MH_DYLIB", MH_DYLIB); - fileTypeBuilder.AddMemberWithValue("MH_DYLINKER", MH_DYLINKER); - fileTypeBuilder.AddMemberWithValue("MH_BUNDLE", MH_BUNDLE); - fileTypeBuilder.AddMemberWithValue("MH_DYLIB_STUB", MH_DYLIB_STUB); - fileTypeBuilder.AddMemberWithValue("MH_DSYM", MH_DSYM); - fileTypeBuilder.AddMemberWithValue("MH_KEXT_BUNDLE", MH_KEXT_BUNDLE); - fileTypeBuilder.AddMemberWithValue("MH_FILESET", MH_FILESET); - Ref fileTypeEnum = fileTypeBuilder.Finalize(); - - Ref fileTypeEnumType = Type::EnumerationType(nullptr, fileTypeEnum, 4, false); - std::string fileTypeEnumName = "file_type_t"; - std::string fileTypeEnumId = Type::GenerateAutoTypeId("macho", fileTypeEnumName); - DefineType(fileTypeEnumId, fileTypeEnumName, fileTypeEnumType); - - EnumerationBuilder flagsTypeBuilder; - flagsTypeBuilder.AddMemberWithValue("MH_NOUNDEFS", MH_NOUNDEFS); - flagsTypeBuilder.AddMemberWithValue("MH_INCRLINK", MH_INCRLINK); - flagsTypeBuilder.AddMemberWithValue("MH_DYLDLINK", MH_DYLDLINK); - flagsTypeBuilder.AddMemberWithValue("MH_BINDATLOAD", MH_BINDATLOAD); - flagsTypeBuilder.AddMemberWithValue("MH_PREBOUND", MH_PREBOUND); - flagsTypeBuilder.AddMemberWithValue("MH_SPLIT_SEGS", MH_SPLIT_SEGS); - flagsTypeBuilder.AddMemberWithValue("MH_LAZY_INIT", MH_LAZY_INIT); - flagsTypeBuilder.AddMemberWithValue("MH_TWOLEVEL", MH_TWOLEVEL); - flagsTypeBuilder.AddMemberWithValue("MH_FORCE_FLAT", MH_FORCE_FLAT); - flagsTypeBuilder.AddMemberWithValue("MH_NOMULTIDEFS", MH_NOMULTIDEFS); - flagsTypeBuilder.AddMemberWithValue("MH_NOFIXPREBINDING", MH_NOFIXPREBINDING); - flagsTypeBuilder.AddMemberWithValue("MH_PREBINDABLE", MH_PREBINDABLE); - flagsTypeBuilder.AddMemberWithValue("MH_ALLMODSBOUND", MH_ALLMODSBOUND); - flagsTypeBuilder.AddMemberWithValue("MH_SUBSECTIONS_VIA_SYMBOLS", MH_SUBSECTIONS_VIA_SYMBOLS); - flagsTypeBuilder.AddMemberWithValue("MH_CANONICAL", MH_CANONICAL); - flagsTypeBuilder.AddMemberWithValue("MH_WEAK_DEFINES", MH_WEAK_DEFINES); - flagsTypeBuilder.AddMemberWithValue("MH_BINDS_TO_WEAK", MH_BINDS_TO_WEAK); - flagsTypeBuilder.AddMemberWithValue("MH_ALLOW_STACK_EXECUTION", MH_ALLOW_STACK_EXECUTION); - flagsTypeBuilder.AddMemberWithValue("MH_ROOT_SAFE", MH_ROOT_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_SETUID_SAFE", MH_SETUID_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_NO_REEXPORTED_DYLIBS", MH_NO_REEXPORTED_DYLIBS); - flagsTypeBuilder.AddMemberWithValue("MH_PIE", MH_PIE); - flagsTypeBuilder.AddMemberWithValue("MH_DEAD_STRIPPABLE_DYLIB", MH_DEAD_STRIPPABLE_DYLIB); - flagsTypeBuilder.AddMemberWithValue("MH_HAS_TLV_DESCRIPTORS", MH_HAS_TLV_DESCRIPTORS); - flagsTypeBuilder.AddMemberWithValue("MH_NO_HEAP_EXECUTION", MH_NO_HEAP_EXECUTION); - flagsTypeBuilder.AddMemberWithValue("MH_APP_EXTENSION_SAFE", _MH_APP_EXTENSION_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_NLIST_OUTOFSYNC_WITH_DYLDINFO", _MH_NLIST_OUTOFSYNC_WITH_DYLDINFO); - flagsTypeBuilder.AddMemberWithValue("MH_SIM_SUPPORT", _MH_SIM_SUPPORT); - flagsTypeBuilder.AddMemberWithValue("MH_DYLIB_IN_CACHE", _MH_DYLIB_IN_CACHE); - Ref flagsTypeEnum = flagsTypeBuilder.Finalize(); - - Ref flagsTypeEnumType = Type::EnumerationType(nullptr, flagsTypeEnum, 4, false); - std::string flagsTypeEnumName = "flags_type_t"; - std::string flagsTypeEnumId = Type::GenerateAutoTypeId("macho", flagsTypeEnumName); - DefineType(flagsTypeEnumId, flagsTypeEnumName, flagsTypeEnumType); - - StructureBuilder machoHeaderBuilder; - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "magic"); - machoHeaderBuilder.AddMember(Type::NamedType(this, QualifiedName("cpu_type_t")), "cputype"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "cpusubtype"); - machoHeaderBuilder.AddMember(Type::NamedType(this, QualifiedName("file_type_t")), "filetype"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "ncmds"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "sizeofcmds"); - machoHeaderBuilder.AddMember(Type::NamedType(this, QualifiedName("flags_type_t")), "flags"); - if (GetAddressSize() == 8) - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "reserved"); - Ref machoHeaderStruct = machoHeaderBuilder.Finalize(); - QualifiedName headerName = (GetAddressSize() == 8) ? std::string("mach_header_64") : std::string("mach_header"); - - std::string headerTypeId = Type::GenerateAutoTypeId("macho", headerName); - Ref machoHeaderType = Type::StructureType(machoHeaderStruct); - DefineType(headerTypeId, headerName, machoHeaderType); - - EnumerationBuilder cmdTypeBuilder; - cmdTypeBuilder.AddMemberWithValue("LC_REQ_DYLD", LC_REQ_DYLD); - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT", LC_SEGMENT); - cmdTypeBuilder.AddMemberWithValue("LC_SYMTAB", LC_SYMTAB); - cmdTypeBuilder.AddMemberWithValue("LC_SYMSEG", LC_SYMSEG); - cmdTypeBuilder.AddMemberWithValue("LC_THREAD", LC_THREAD); - cmdTypeBuilder.AddMemberWithValue("LC_UNIXTHREAD", LC_UNIXTHREAD); - cmdTypeBuilder.AddMemberWithValue("LC_LOADFVMLIB", LC_LOADFVMLIB); - cmdTypeBuilder.AddMemberWithValue("LC_IDFVMLIB", LC_IDFVMLIB); - cmdTypeBuilder.AddMemberWithValue("LC_IDENT", LC_IDENT); - cmdTypeBuilder.AddMemberWithValue("LC_FVMFILE", LC_FVMFILE); - cmdTypeBuilder.AddMemberWithValue("LC_PREPAGE", LC_PREPAGE); - cmdTypeBuilder.AddMemberWithValue("LC_DYSYMTAB", LC_DYSYMTAB); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_DYLIB", LC_LOAD_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ID_DYLIB", LC_ID_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_DYLINKER", LC_LOAD_DYLINKER); - cmdTypeBuilder.AddMemberWithValue("LC_ID_DYLINKER", LC_ID_DYLINKER); - cmdTypeBuilder.AddMemberWithValue("LC_PREBOUND_DYLIB", LC_PREBOUND_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ROUTINES", LC_ROUTINES); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_FRAMEWORK", LC_SUB_FRAMEWORK); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_UMBRELLA", LC_SUB_UMBRELLA); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_CLIENT", LC_SUB_CLIENT); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_LIBRARY", LC_SUB_LIBRARY); - cmdTypeBuilder.AddMemberWithValue("LC_TWOLEVEL_HINTS", LC_TWOLEVEL_HINTS); - cmdTypeBuilder.AddMemberWithValue("LC_PREBIND_CKSUM", LC_PREBIND_CKSUM); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_WEAK_DYLIB", LC_LOAD_WEAK_DYLIB); // (0x18 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT_64", LC_SEGMENT_64); - cmdTypeBuilder.AddMemberWithValue("LC_ROUTINES_64", LC_ROUTINES_64); - cmdTypeBuilder.AddMemberWithValue("LC_UUID", LC_UUID); - cmdTypeBuilder.AddMemberWithValue("LC_RPATH", LC_RPATH); // (0x1c | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_CODE_SIGNATURE", LC_CODE_SIGNATURE); - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT_SPLIT_INFO", LC_SEGMENT_SPLIT_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_REEXPORT_DYLIB", LC_REEXPORT_DYLIB); // (0x1f | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_LAZY_LOAD_DYLIB", LC_LAZY_LOAD_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ENCRYPTION_INFO", LC_ENCRYPTION_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_INFO", LC_DYLD_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_INFO_ONLY", LC_DYLD_INFO_ONLY); // (0x22 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_UPWARD_DYLIB", LC_LOAD_UPWARD_DYLIB); // (0x23 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_MACOSX", LC_VERSION_MIN_MACOSX); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_IPHONEOS", LC_VERSION_MIN_IPHONEOS); - cmdTypeBuilder.AddMemberWithValue("LC_FUNCTION_STARTS", LC_FUNCTION_STARTS); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_ENVIRONMENT", LC_DYLD_ENVIRONMENT); - cmdTypeBuilder.AddMemberWithValue("LC_MAIN", LC_MAIN); // (0x28 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_DATA_IN_CODE", LC_DATA_IN_CODE); - cmdTypeBuilder.AddMemberWithValue("LC_SOURCE_VERSION", LC_SOURCE_VERSION); - cmdTypeBuilder.AddMemberWithValue("LC_DYLIB_CODE_SIGN_DRS", LC_DYLIB_CODE_SIGN_DRS); - cmdTypeBuilder.AddMemberWithValue("LC_ENCRYPTION_INFO_64", _LC_ENCRYPTION_INFO_64); - cmdTypeBuilder.AddMemberWithValue("LC_LINKER_OPTION", _LC_LINKER_OPTION); - cmdTypeBuilder.AddMemberWithValue("LC_LINKER_OPTIMIZATION_HINT", _LC_LINKER_OPTIMIZATION_HINT); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_TVOS", _LC_VERSION_MIN_TVOS); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_WATCHOS", LC_VERSION_MIN_WATCHOS); - cmdTypeBuilder.AddMemberWithValue("LC_NOTE", LC_NOTE); - cmdTypeBuilder.AddMemberWithValue("LC_BUILD_VERSION", LC_BUILD_VERSION); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_EXPORTS_TRIE", LC_DYLD_EXPORTS_TRIE); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_CHAINED_FIXUPS", LC_DYLD_CHAINED_FIXUPS); - cmdTypeBuilder.AddMemberWithValue("LC_FILESET_ENTRY", LC_FILESET_ENTRY); - Ref cmdTypeEnum = cmdTypeBuilder.Finalize(); - - Ref cmdTypeEnumType = Type::EnumerationType(nullptr, cmdTypeEnum, 4, false); - std::string cmdTypeEnumName = "load_command_type_t"; - std::string cmdTypeEnumId = Type::GenerateAutoTypeId("macho", cmdTypeEnumName); - DefineType(cmdTypeEnumId, cmdTypeEnumName, cmdTypeEnumType); - - StructureBuilder loadCommandBuilder; - loadCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - loadCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - Ref loadCommandStruct = loadCommandBuilder.Finalize(); - QualifiedName loadCommandName = std::string("load_command"); - std::string loadCommandTypeId = Type::GenerateAutoTypeId("macho", loadCommandName); - Ref loadCommandType = Type::StructureType(loadCommandStruct); - DefineType(loadCommandTypeId, loadCommandName, loadCommandType); - - EnumerationBuilder protTypeBuilder; - protTypeBuilder.AddMemberWithValue("VM_PROT_NONE", MACHO_VM_PROT_NONE); - protTypeBuilder.AddMemberWithValue("VM_PROT_READ", MACHO_VM_PROT_READ); - protTypeBuilder.AddMemberWithValue("VM_PROT_WRITE", MACHO_VM_PROT_WRITE); - protTypeBuilder.AddMemberWithValue("VM_PROT_EXECUTE", MACHO_VM_PROT_EXECUTE); - // protTypeBuilder.AddMemberWithValue("VM_PROT_DEFAULT", MACHO_VM_PROT_DEFAULT); - // protTypeBuilder.AddMemberWithValue("VM_PROT_ALL", MACHO_VM_PROT_ALL); - protTypeBuilder.AddMemberWithValue("VM_PROT_NO_CHANGE", MACHO_VM_PROT_NO_CHANGE); - protTypeBuilder.AddMemberWithValue("VM_PROT_COPY_OR_WANTS_COPY", MACHO_VM_PROT_COPY); - // protTypeBuilder.AddMemberWithValue("VM_PROT_WANTS_COPY", MACHO_VM_PROT_WANTS_COPY); - Ref protTypeEnum = protTypeBuilder.Finalize(); - - Ref protTypeEnumType = Type::EnumerationType(nullptr, protTypeEnum, 4, false); - std::string protTypeEnumName = "vm_prot_t"; - std::string protTypeEnumId = Type::GenerateAutoTypeId("macho", protTypeEnumName); - DefineType(protTypeEnumId, protTypeEnumName, protTypeEnumType); - - EnumerationBuilder segFlagsTypeBuilder; - segFlagsTypeBuilder.AddMemberWithValue("SG_HIGHVM", SG_HIGHVM); - segFlagsTypeBuilder.AddMemberWithValue("SG_FVMLIB", SG_FVMLIB); - segFlagsTypeBuilder.AddMemberWithValue("SG_NORELOC", SG_NORELOC); - segFlagsTypeBuilder.AddMemberWithValue("SG_PROTECTED_VERSION_1", SG_PROTECTED_VERSION_1); - Ref segFlagsTypeEnum = segFlagsTypeBuilder.Finalize(); - - Ref segFlagsTypeEnumType = Type::EnumerationType(nullptr, segFlagsTypeEnum, 4, false); - std::string segFlagsTypeEnumName = "sg_flags_t"; - std::string segFlagsTypeEnumId = Type::GenerateAutoTypeId("macho", segFlagsTypeEnumName); - DefineType(segFlagsTypeEnumId, segFlagsTypeEnumName, segFlagsTypeEnumType); - - StructureBuilder loadSegmentCommandBuilder; - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - loadSegmentCommandBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "vmaddr"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "vmsize"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "fileoff"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "filesize"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "maxprot"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "initprot"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "nsects"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("sg_flags_t")), "flags"); - Ref loadSegmentCommandStruct = loadSegmentCommandBuilder.Finalize(); - QualifiedName loadSegmentCommandName = std::string("segment_command"); - std::string loadSegmentCommandTypeId = Type::GenerateAutoTypeId("macho", loadSegmentCommandName); - Ref loadSegmentCommandType = Type::StructureType(loadSegmentCommandStruct); - DefineType(loadSegmentCommandTypeId, loadSegmentCommandName, loadSegmentCommandType); - - StructureBuilder loadSegmentCommand64Builder; - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(4, false), "cmdsize"); - loadSegmentCommand64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "vmaddr"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "vmsize"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "fileoff"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "filesize"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "maxprot"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "initprot"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(4, false), "nsects"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("sg_flags_t")), "flags"); - Ref loadSegmentCommand64Struct = loadSegmentCommand64Builder.Finalize(); - QualifiedName loadSegment64CommandName = std::string("segment_command_64"); - std::string loadSegment64CommandTypeId = Type::GenerateAutoTypeId("macho", loadSegment64CommandName); - Ref loadSegment64CommandType = Type::StructureType(loadSegmentCommand64Struct); - DefineType(loadSegment64CommandTypeId, loadSegment64CommandName, loadSegment64CommandType); - - StructureBuilder sectionBuilder; - sectionBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "sectname"); - sectionBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "addr"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "size"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "offset"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "align"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reloff"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "nreloc"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "flags"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reserved1"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reserved2"); - Ref sectionStruct = sectionBuilder.Finalize(); - QualifiedName sectionName = std::string("section"); - std::string sectionTypeId = Type::GenerateAutoTypeId("macho", sectionName); - Ref sectionType = Type::StructureType(sectionStruct); - DefineType(sectionTypeId, sectionName, sectionType); - - StructureBuilder section64Builder; - section64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "sectname"); - section64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - section64Builder.AddMember(Type::IntegerType(8, false), "addr"); - section64Builder.AddMember(Type::IntegerType(8, false), "size"); - section64Builder.AddMember(Type::IntegerType(4, false), "offset"); - section64Builder.AddMember(Type::IntegerType(4, false), "align"); - section64Builder.AddMember(Type::IntegerType(4, false), "reloff"); - section64Builder.AddMember(Type::IntegerType(4, false), "nreloc"); - section64Builder.AddMember(Type::IntegerType(4, false), "flags"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved1"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved2"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved3"); - Ref section64Struct = section64Builder.Finalize(); - QualifiedName section64Name = std::string("section_64"); - std::string section64TypeId = Type::GenerateAutoTypeId("macho", section64Name); - Ref section64Type = Type::StructureType(section64Struct); - DefineType(section64TypeId, section64Name, section64Type); - - StructureBuilder symtabBuilder; - symtabBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "symoff"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "nsyms"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "stroff"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "strsize"); - Ref symtabStruct = symtabBuilder.Finalize(); - QualifiedName symtabName = std::string("symtab"); - std::string symtabTypeId = Type::GenerateAutoTypeId("macho", symtabName); - Ref symtabType = Type::StructureType(symtabStruct); - DefineType(symtabTypeId, symtabName, symtabType); - - StructureBuilder dynsymtabBuilder; - dynsymtabBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "ilocalsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nlocalsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "iextdefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextdefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "iundefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nundefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "tocoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "ntoc"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "modtaboff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nmodtab"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "extrefsymoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextrefsyms"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "indirectsymoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nindirectsyms"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "extreloff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextrel"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "locreloff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nlocrel"); - Ref dynsymtabStruct = dynsymtabBuilder.Finalize(); - QualifiedName dynsymtabName = std::string("dysymtab"); - std::string dynsymtabTypeId = Type::GenerateAutoTypeId("macho", dynsymtabName); - Ref dynsymtabType = Type::StructureType(dynsymtabStruct); - DefineType(dynsymtabTypeId, dynsymtabName, dynsymtabType); - - StructureBuilder uuidBuilder; - uuidBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - uuidBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - uuidBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, false), 16), "uuid"); - Ref uuidStruct = uuidBuilder.Finalize(); - QualifiedName uuidName = std::string("uuid"); - std::string uuidTypeId = Type::GenerateAutoTypeId("macho", uuidName); - Ref uuidType = Type::StructureType(uuidStruct); - DefineType(uuidTypeId, uuidName, uuidType); - - StructureBuilder linkeditDataBuilder; - linkeditDataBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "dataoff"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "datasize"); - Ref linkeditDataStruct = linkeditDataBuilder.Finalize(); - QualifiedName linkeditDataName = std::string("linkedit_data"); - std::string linkeditDataTypeId = Type::GenerateAutoTypeId("macho", linkeditDataName); - Ref linkeditDataType = Type::StructureType(linkeditDataStruct); - DefineType(linkeditDataTypeId, linkeditDataName, linkeditDataType); - - StructureBuilder encryptionInfoBuilder; - encryptionInfoBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptoff"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptsize"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptid"); - Ref encryptionInfoStruct = encryptionInfoBuilder.Finalize(); - QualifiedName encryptionInfoName = std::string("encryption_info"); - std::string encryptionInfoTypeId = Type::GenerateAutoTypeId("macho", encryptionInfoName); - Ref encryptionInfoType = Type::StructureType(encryptionInfoStruct); - DefineType(encryptionInfoTypeId, encryptionInfoName, encryptionInfoType); - - StructureBuilder versionMinBuilder; - versionMinBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "version"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "sdk"); - Ref versionMinStruct = versionMinBuilder.Finalize(); - QualifiedName versionMinName = std::string("version_min"); - std::string versionMinTypeId = Type::GenerateAutoTypeId("macho", versionMinName); - Ref versionMinType = Type::StructureType(versionMinStruct); - DefineType(versionMinTypeId, versionMinName, versionMinType); - - StructureBuilder dyldInfoBuilder; - dyldInfoBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "rebase_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "rebase_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "weak_bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "weak_bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "lazy_bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "lazy_bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "export_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "export_size"); - Ref dyldInfoStruct = dyldInfoBuilder.Finalize(); - QualifiedName dyldInfoName = std::string("dyld_info"); - std::string dyldInfoTypeId = Type::GenerateAutoTypeId("macho", dyldInfoName); - Ref dyldInfoType = Type::StructureType(dyldInfoStruct); - DefineType(dyldInfoTypeId, dyldInfoName, dyldInfoType); - - StructureBuilder dylibBuilder; - dylibBuilder.AddMember(Type::IntegerType(4, false), "name"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "timestamp"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "current_version"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "compatibility_version"); - Ref dylibStruct = dylibBuilder.Finalize(); - QualifiedName dylibName = std::string("dylib"); - std::string dylibTypeId = Type::GenerateAutoTypeId("macho", dylibName); - Ref dylibType = Type::StructureType(dylibStruct); - DefineType(dylibTypeId, dylibName, dylibType); - - StructureBuilder dylibCommandBuilder; - dylibCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - dylibCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dylibCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("dylib")), "dylib"); - Ref dylibCommandStruct = dylibCommandBuilder.Finalize(); - QualifiedName dylibCommandName = std::string("dylib_command"); - std::string dylibCommandTypeId = Type::GenerateAutoTypeId("macho", dylibCommandName); - Ref dylibCommandType = Type::StructureType(dylibCommandStruct); - DefineType(dylibCommandTypeId, dylibCommandName, dylibCommandType); - - StructureBuilder filesetEntryCommandBuilder; - filesetEntryCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(8, false), "vmaddr"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(8, false), "fileoff"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "entry_id"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "reserved"); - Ref filesetEntryCommandStruct = filesetEntryCommandBuilder.Finalize(); - QualifiedName filesetEntryCommandName = std::string("fileset_entry_command"); - std::string filesetEntryCommandTypeId = Type::GenerateAutoTypeId("macho", filesetEntryCommandName); - Ref filesetEntryCommandType = Type::StructureType(filesetEntryCommandStruct); - DefineType(filesetEntryCommandTypeId, filesetEntryCommandName, filesetEntryCommandType); - - StructureBuilder unixThreadCommandBuilder; - unixThreadCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - unixThreadCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - unixThreadCommandBuilder.AddMember(Type::IntegerType(4, false), "flavor"); - unixThreadCommandBuilder.AddMember(Type::IntegerType(4, false), "count"); - // The 'state' field is intentionally ignored. - Ref unixThreadCommandStruct = unixThreadCommandBuilder.Finalize(); - QualifiedName unixThreadCommandName = std::string("unix_thread_command"); - std::string unixThreadCommandTypeId = Type::GenerateAutoTypeId("macho", unixThreadCommandName); - Ref unixThreadCommandType = Type::StructureType(unixThreadCommandStruct); - DefineType(unixThreadCommandTypeId, unixThreadCommandName, unixThreadCommandType); - - std::vector regionsMappedIntoMemory; - if (auto metadata = KernelCacheCore::KernelCacheMetadata::LoadFromView(GetParentView())) - { - for (const auto& image : metadata->LoadedImages()) - { - auto header = KernelCacheCore::KernelCache::LoadHeaderForAddress(this, image.headerFileLocation, image.installName); - if (!header) - { - LogError("Failed to load header for image %s", image.installName.c_str()); - return false; - } - if (!KernelCacheCore::KernelCache::InitializeSegmentsForHeader(this, *header, image)) - { - LogError("Failed to initialize segments for image %s", image.installName.c_str()); - return false; - } - KernelCacheCore::KernelCache::InitializeHeader(this, *header); - } - } - - // Technically the header is executable, but there shouldn't reasonably be code in the header. - AddAutoSegment(textSegOffset, sizeofcmds + 0x20, 0, sizeofcmds + 0x20, SegmentReadable); - AddAutoSection("kernelcache_header", textSegOffset, sizeofcmds + 0x20, ReadOnlyDataSectionSemantics); - - if (m_parseOnly) - return true; - - DefineDataVariable(textSegOffset, Type::NamedType(this, QualifiedName("mach_header_64"))); - DefineAutoSymbol( - new Symbol(DataSymbol, "kernelcache_header", textSegOffset, LocalBinding)); - - try - { - reader.Seek(sizeof(mach_header_64)); - size_t sectionNum = 0; - for (size_t i = 0; i < ncmds; i++) - { - load_command load; - uint64_t curOffset = reader.GetOffset(); - load.cmd = reader.Read32(); - load.cmdsize = reader.Read32(); - uint64_t nextOffset = curOffset + load.cmdsize; - switch (load.cmd) - { - case LC_SEGMENT: - { - DefineDataVariable(reader.GetOffset() + textSegOffset, Type::NamedType(this, QualifiedName("segment_command"))); - reader.SeekRelative(5 * 8); - size_t numSections = reader.Read32(); - reader.SeekRelative(4); - for (size_t j = 0; j < numSections; j++) - { - DefineDataVariable( - reader.GetOffset() + textSegOffset, Type::NamedType(this, QualifiedName("section"))); - DefineAutoSymbol(new Symbol(DataSymbol, - "__macho_section::kernelcache[" + std::to_string(sectionNum++) + "]", - reader.GetOffset() + textSegOffset, LocalBinding)); - reader.SeekRelative((8 * 8) + 4); - } - break; - } - case LC_SEGMENT_64: - { - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("segment_command_64"))); - reader.SeekRelative(7 * 8); - size_t numSections = reader.Read32(); - reader.SeekRelative(4); - for (size_t j = 0; j < numSections; j++) - { - DefineDataVariable( - reader.GetOffset() + textSegOffset, Type::NamedType(this, QualifiedName("section_64"))); - DefineAutoSymbol(new Symbol(DataSymbol, - "__macho_section_64::kernelcache[" + std::to_string(sectionNum++) + "]", - reader.GetOffset() + textSegOffset, LocalBinding)); - reader.SeekRelative(10 * 8); - } - break; - } - case LC_SYMTAB: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("symtab"))); - break; - case LC_DYSYMTAB: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("dysymtab"))); - break; - case LC_UUID: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("uuid"))); - break; - case LC_ID_DYLIB: - case LC_LOAD_DYLIB: - case LC_REEXPORT_DYLIB: - case LC_LOAD_WEAK_DYLIB: - case LC_LOAD_UPWARD_DYLIB: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("dylib_command"))); - if (load.cmdsize - 24 <= 150) - DefineDataVariable( - curOffset + textSegOffset + 24, Type::ArrayType(Type::IntegerType(1, true), load.cmdsize - 24)); - break; - case LC_CODE_SIGNATURE: - case LC_SEGMENT_SPLIT_INFO: - case LC_FUNCTION_STARTS: - case LC_DATA_IN_CODE: - case LC_DYLIB_CODE_SIGN_DRS: - case LC_DYLD_EXPORTS_TRIE: - case LC_DYLD_CHAINED_FIXUPS: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("linkedit_data"))); - break; - case LC_ENCRYPTION_INFO: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("encryption_info"))); - break; - case LC_VERSION_MIN_MACOSX: - case LC_VERSION_MIN_IPHONEOS: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("version_min"))); - break; - case LC_DYLD_INFO: - case LC_DYLD_INFO_ONLY: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("dyld_info"))); - break; - case LC_FILESET_ENTRY: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("fileset_entry_command"))); - break; - case LC_UNIXTHREAD: - { - DefineDataVariable( - curOffset + textSegOffset, Type::NamedType(this, QualifiedName("unix_thread_command"))); - reader.SeekRelative(4); - uint32_t count = reader.Read32(); - DefineDataVariable(reader.GetOffset() + textSegOffset, Type::ArrayType(Type::IntegerType(8, true), count)); - break; - } - default: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("load_command"))); - break; - } - - DefineAutoSymbol(new Symbol(DataSymbol, - "__macho_load_command::kernelcache[" + std::to_string(i) + "]", curOffset + textSegOffset, - LocalBinding)); - reader.Seek(nextOffset); - } - } - catch (ReadException&) - { - LogError("Error when applying Mach-O header types at %" PRIx64, textSegOffset); - } - - return true; -} - - -KCViewType::KCViewType() : BinaryViewType(KC_VIEW_NAME, KC_VIEW_NAME) -{ -} - -BinaryNinja::Ref KCViewType::Create(BinaryNinja::BinaryView* data) -{ - uint32_t magic; - data->Read(&magic, data->GetStart(), 4); - if (magic != MH_CIGAM_64 && magic != MH_MAGIC_64) // FIXME 32 bit - { - uint32_t im4pMagic; - data->Read(&im4pMagic, data->GetStart() + 0x8, 4); - if (im4pMagic == 0x50344d49) // P4MI - { - auto img4 = Transform::GetByName("IMG4-Unencrypted"); - - DataBuffer img4Payload; - img4->Decode(data->ReadBuffer(data->GetStart(), data->GetLength()), img4Payload); - - DataBuffer machOPayload; - uint32_t magic = ((uint32_t*)img4Payload.GetData())[0]; - if (magic == FAT_MAGIC_64 || magic == MH_MAGIC_64 || magic == MH_MAGIC - || magic == MH_CIGAM_64 || magic == MH_CIGAM ) - { - machOPayload = img4Payload; - } - else if (strncmp((char*)img4Payload.GetData(), "bvx2", 4) == 0) - { - auto lzfse = Transform::GetByName("LZFSE"); - if (lzfse) - lzfse->Decode(img4Payload, machOPayload); - } - else - { -#ifdef COMPRESSION_DEBUG - LogError("Unknown compression type in IMG4 Payload, writing img4 payload to RAW view for debug purposes."); - LogError("KernelCache parsing will now fail to proceed."); - data->WriteBuffer(0, img4Payload); - return new KCView(KC_VIEW_NAME, data, false); -#else - LogError("Unknown compression type in IMG4 Payload, unable to proceed."); - LogError("You can manually extract the kernelcache using `kerneldec`,`ipsw`, or other tools.") - return nullptr; -#endif - } - - if (machOPayload.GetLength() == 0) - { -#ifdef COMPRESSION_DEBUG - LogError("Failed to perform extraction on IMG4 Payload, writing img4 payload to RAW view for debug purposes."); - LogError("KernelCache parsing will now fail to proceed."); - data->WriteBuffer(0, img4Payload); - return new KCView(KC_VIEW_NAME, data, false); -#else - return nullptr; -#endif - } - - uint32_t machoMagic = ((uint32_t*)machOPayload.GetData())[0]; - if (machoMagic == FAT_MAGIC_64) - { - DataBuffer output = machOPayload.GetSlice(0x1c, machOPayload.GetLength()-0x1c); - data->WriteBuffer(0, output); - } - else if (machoMagic == MH_MAGIC_64 || machoMagic == MH_MAGIC || machoMagic == MH_CIGAM_64 || machoMagic == MH_CIGAM) - { - data->WriteBuffer(0, machOPayload); - } - else - { -#ifdef COMPRESSION_DEBUG - LogError("Unknown Mach-O magic in IMG4 Payload, writing img4 payload to RAW view for debug purposes."); - LogError("KernelCache parsing will now fail to proceed."); - data->WriteBuffer(0, machOPayload); - return new KCView(KC_VIEW_NAME, data, false); -#else - return nullptr; -#endif - } - - return new KCView(KC_VIEW_NAME, data, false); - } - - return nullptr; - } - - return new KCView(KC_VIEW_NAME, data, false); -} - - -Ref KCViewType::GetLoadSettingsForData(BinaryView* data) -{ - Ref viewRef = Parse(data); - if (!viewRef || !viewRef->Init()) - { - LogWarn("Failed to initialize view of type '%s'. Generating default load settings.", GetName().c_str()); - viewRef = data; - } - - Ref settings = GetDefaultLoadSettingsForData(viewRef); - - // specify default load settings that can be overridden - std::vector overrides = {"loader.imageBase", "loader.platform"}; - settings->UpdateProperty("loader.imageBase", "message", "Note: File indicates image is not relocatable."); - - for (const auto& override : overrides) - { - if (settings->Contains(override)) - settings->UpdateProperty(override, "readOnly", false); - } - - // Merge existing load settings if they exist. This allows for the selection of a specific object file from a Mach-O - // Universal file. The 'Universal' BinaryViewType generates a schema with 'loader.universal.architectures'. This - // schema contains an appropriate 'Mach-O' load schema for selecting a specific object file. The embedded schema - // contains 'loader.macho.universalImageOffset'. - Ref loadSettings = viewRef->GetLoadSettings(GetName()); - if (loadSettings && !loadSettings->IsEmpty()) - settings->DeserializeSchema(loadSettings->SerializeSchema()); - - return settings; -} - - -BinaryNinja::Ref KCViewType::Parse(BinaryNinja::BinaryView* data) -{ - uint32_t magic; - data->Read(&magic, data->GetStart(), 4); - if (magic != MH_CIGAM_64 && magic != MH_MAGIC_64) // FIXME 32 bit - { - uint32_t im4pMagic; - data->Read(&im4pMagic, data->GetStart() + 0x8, 4); - if (im4pMagic == 0x50344d49) // P4MI - { - auto img4 = Transform::GetByName("IMG4-Unencrypted"); - auto lzfse = Transform::GetByName("LZFSE"); - - DataBuffer img4Payload; - img4->Decode(data->ReadBuffer(data->GetStart(), data->GetLength()), img4Payload); - DataBuffer machOPayload; - lzfse->Decode(img4Payload, machOPayload); - - uint32_t magic = ((uint32_t*)machOPayload.GetData())[0]; - auto id = data->BeginUndoActions(); - if (magic == FAT_MAGIC_64) - { - DataBuffer output = machOPayload.GetSlice(0x1c, machOPayload.GetLength()-0x1c); - data->WriteBuffer(0, output); - } - else - { - data->WriteBuffer(0, machOPayload); - } - data->ForgetUndoActions(id); - return new KCView(KC_VIEW_NAME, data, true); - } - - return nullptr; - } - - return new KCView(KC_VIEW_NAME, data, true); -} - -bool KCViewType::IsTypeValidForData(BinaryNinja::BinaryView* data) -{ - if (!data) - return false; - - uint32_t magic; - data->Read(&magic, data->GetStart(), 4); - - if (magic != MH_CIGAM_64 && magic != MH_MAGIC_64) // FIXME 32 bit - { - uint32_t im4pMagic; - data->Read(&im4pMagic, data->GetStart() + 0x8, 4); - if (im4pMagic == 0x50344d49) // P4MI - { - auto img4 = Transform::GetByName("IMG4-Unencrypted"); - auto lzfse = Transform::GetByName("LZFSE"); - - DataBuffer img4Payload; - img4->Decode(data->ReadBuffer(data->GetStart(), data->GetLength()), img4Payload); - DataBuffer machOPayload; - lzfse->Decode(img4Payload, machOPayload); - - uint32_t magic = ((uint32_t*)machOPayload.GetData())[0]; - if (magic == FAT_MAGIC_64 || magic == MH_CIGAM_64 || magic == MH_MAGIC_64) - return true; - - return false; - } - - return false; - } - - uint32_t fileType; - data->Read(&fileType, data->GetStart() + 0xc, 4); - if (fileType != MH_FILESET) - { - return false; - } - - return true; -} - -extern "C" { - void InitKCViewType() - { - static KCViewType type; - BinaryViewType::Register(&type); - g_kcViewType = &type; - } -} - -- cgit v1.3.1