//------------------------------------------------ //--- 010 Editor v3.2.2 Binary Template // // File: MachO.bt // Authors: Tim "diff" Strazzere // E-mail: diff@lookout.com, strazz@gmail.com // Version: 1.5 // Purpose: Quick template for parsing Mach-o binaries, // including Mac OS X executables, .o and .dylib files. // Category: Executable // File Mask: *,*.o,*.dylib // ID Bytes: CF FA ED FE, CE FA ED FE, BE BA FE CA, CA FE BA BE // History: // 1.5 2018-11-09 swigger at gmail.com: support LC_BUILD_VERSION load command. // 1.4 2017-03-17 swigger at gmail.com: enable encryption segment 64. // 1.3 2016-06-08 N Moinvaziri: Fixed definition of section_64. Offset should have been uint64 and reserved3 missing. // 1.2 2016-02-12 SweetScape Software: Updated header for repository submission. // 1.1 T Strazzere: - Minimum version load command now properly outputs the format for better readability // - Added a readvalue function for the header, helps understand headers at a glance // 1.0 T Strazzere: - Correctly parses FAT headers and will continue to parse the rest of the combined // binary // - Added many todo's to make the output more pretty // - Fixed some broken LoadCommands (64bit ones mainly), will gracefully fail if unknown // LoadCommand is hit // - Found some bugs in 010Editor and added fixes to try to avoid those // 1.0 T Strazzere: - First stab it this, lots of issues - FAT binaries don't work at all // // Known issues: // - Needs optimized structures otherwise anything of a decent size will kill it // (Related to an 010Editor template bug) //------------------------------------------------ // Mach-o's should be Little Endian only -- except for the fat_header/fat_arch LittleEndian(); typedef enum { MACHO_32 = 0xFEEDFACE, // 32-bit mach object file MACHO_64 = 0xFEEDFACF, // 64-bit mach object file MACHO_FAT = 0xCAFEBABE, // Universal object file / FAT_MAGIC MACHO_FAT_CIGAM = 0xBEBAFECA } Magic ; #define CPU_ARCH_MASK 0xff000000 #define CPU_ARCH_ABI64 0x01000000 // This looks ugly due to a limitation (bug?) in 010Editor template processing, // basically we're unable to define more constant using other constants - it doesn't // see them as already being processed when trying to define others (though it won't // error on this until it hits this when trying to access that constant) #define CPU_TYPE_X86 0x7 #define CPU_TYPE_I386 0x7 // CPU_TYPE_X86 #define CPU_TYPE_X86_64 (0x7 | 0x01000000) // (CPU_TYPE_X86 | CPU_ARCH_ABI64) #define CPU_TYPE_POWERPC 0x12 #define CPU_TYPE_POWERPC64 (0x12 | 0x01000000) // (CPU_TYPE_POWERPC | CPU_ARCH_ABI64) #define CPU_TYPE_ARM 0xC typedef enum { MACH_OBJECT = 0x1, MACH_EXECUTE = 0x2, MACH_FVMLIB = 0x3, MACH_CORE = 0x4, MACH_PRELOAD = 0x5, MACH_DYLIB = 0x6, MACH_DYLINKER = 0x7, MACH_BUNDLE = 0x8, MACH_DYLIB_STUB = 0x9, MACH_DSYM = 0xA, MACH_KEXT_BUNDLE = 0xB, } FileType; typedef enum { i386_THREAD_STATE = 0x1, i386_FLOAT_STATE = 0x2, i386_EXCEPTION_STATE = 0x3 } i386ThreadFlavor ; typedef struct { uint32 eax ; uint32 ebx ; uint32 ecx ; uint32 edx ; uint32 edi ; uint32 esi ; uint32 ebp ; uint32 esp ; uint32 ss ; uint32 eflags ; uint32 eip ; uint32 cs ; uint32 ds ; uint32 es ; uint32 fs ; uint32 gs ; } i386ThreadState; typedef enum { x86_THREAD_STATE32 = 0x1, x86_FLOAT_STATE32 = 0x2, x86_EXCEPTION_STATE32 = 0x3, x86_THREAD_STATE64 = 0x4, x86_FLOAT_STATE64 = 0x5, x86_EXCEPTION_STATE64 = 0x6, x86_THREAD_STATE = 0x7, x86_FLOAT_STATE = 0x8, x86_EXCEPTION_STATE = 0x9, x86_DEBUG_STATE32 = 0xA, x86_DEBUG_STATE64 = 0xB, x86_DEBUG_STATE = 0xC, THREAD_STATE_NONE = 0xD } x86ThreadFlavor ; typedef struct { uint64 rax ; uint64 rbx ; uint64 rcx ; uint64 rdx ; uint64 rdi ; uint64 rsi ; uint64 rbp ; uint64 rsp ; uint64 r8 ; uint64 r9 ; uint64 r10 ; uint64 r11 ; uint64 r12 ; uint64 r13 ; uint64 r14 ; uint64 r15 ; uint64 rip ; uint64 rflags ; uint64 cs ; uint64 fs ; uint64 gs ; } x86ThreadState; typedef enum { PPC_THREAD_STATE = 0x1, PPC_FLOAT_STATE = 0x2, PPC_EXCEPTION_STATE = 0x3, PPC_VECTOR_STATE = 0x4, PPC_THREAD_STATE64 = 0x5, PPC_EXCEPTION_STATE64 = 0x6 } PPCThreadFlavor ; typedef struct { uint32 r0 ; uint32 r1 ; uint32 r2 ; uint32 r3 ; uint32 r4 ; uint32 r5 ; uint32 r6 ; uint32 r7 ; uint32 r8 ; uint32 r9 ; uint32 r10 ; uint32 r11 ; uint32 r12 ; uint32 r13 ; uint32 r14 ; uint32 r15 ; uint32 r16 ; } ARMThreadState; typedef struct { uint32 __srr0 ; uint32 __srr1 ; uint32 __r0; uint32 __r1; uint32 __r2; uint32 __r3; uint32 __r4; uint32 __r5; uint32 __r6; uint32 __r7; uint32 __r8; uint32 __r9; uint32 __r10; uint32 __r11; uint32 __r12; uint32 __r13; uint32 __r14; uint32 __r15; uint32 __r16; uint32 __r17; uint32 __r18; uint32 __r19; uint32 __r20; uint32 __r21; uint32 __r22; uint32 __r23; uint32 __r24; uint32 __r25; uint32 __r26; uint32 __r27; uint32 __r28; uint32 __r29; uint32 __r30; uint32 __r31; uint32 __cr ; uint32 __xer ; uint32 __lr ; uint32 __ctr ; uint32 __mq ; uint32 __vrsave ; } PPCThreadState; typedef enum { MACH_NOUNDEFS = 0x1, MACH_INCRLINK = 0x2, MACH_DYLDLINK = 0x4, MACH_BINDATLOAD = 0x8, MACH_PREBOUND = 0x10, MACH_SPLIT_SEGS = 0x20, MACH_LAZY_INIT = 0x40, MACH_TWOLEVEL = 0x80, MACH_FORCE_FLAT = 0x100, MACH_NOMULTIDEFS = 0x200, MACH_NOFIXPREBINDING = 0x400, MACH_PREBINDABLE = 0x800, MACH_ALLMODSBOUND = 0x1000, MACH_SUBSECTIONS_VIA_SYMBOLS = 0x2000, MACH_CANONICAL = 0x4000, MACH_WEAK_DEFINES = 0x8000, MACH_BINDS_TO_WEAK = 0x10000, MACH_ALLOW_STACK_EXECUTION = 0x20000, MACH_ROOT_SAFE = 0x40000, MACH_SETUID_SAFE = 0x80000, MACH_NO_REEXPORTED_DYLIBS = 0x100000, MACH_PIE = 0x200000, MACH_DEAD_STRIPPABLE_DYLIB = 0x400000, MACH_HAS_TLV_DESCRIPTORS = 0x800000, MACH_NO_HEAP_EXECUTION = 0x1000000 } Flags; typedef struct { uint32 cpu_type ; // TODO : Extract out capabilities here uint32 cpu_sub_type ; uint32 file_offset ; uint32 size ; uint32 align ; } Fat_Arch; typedef struct { Magic magic ; if(magic == MACHO_FAT || magic == MACHO_FAT_CIGAM) { // Need to switch to BigEndian! BigEndian(); uint32 fat_arch_size ; Fat_Arch fat_arch[fat_arch_size]; // Switch back to LittleEndian for rest of parsing LittleEndian(); } else { uint32 cpu_type ; uint32 cpu_sub_type ; FileType file_type; uint32 num_load_commands; uint32 size_of_load_commands; Flags flags; } if(magic == MACHO_64) { uint32 reserved; } } Header ; string HeaderRead(Header &header) { local string header_string; switch(header.magic) { case MACHO_FAT : case MACHO_FAT_CIGAM : header_string = "FAT header"; break; case MACHO_32 : header_string = "32bit Mach-O header"; break; case MACHO_64 : header_string = "64bit Mach-O header"; break; default : header_string = "Unknown header!"; } return header_string; } #define REQ_DYLD (0x80000000) typedef enum { SEGMENT = 0x1, SYM_TAB = 0x2, SYM_SEG = 0x3, THREAD = 0x4, UNIX_THREAD = 0x5, LOAD_FVM_LIB = 0x6, ID_FVM_LIB = 0x7, IDENT = 0x8, FVM_FILE = 0x9, PREPAGE = 0xA, DY_SYM_TAB = 0xB, LOAD_DYLIB = 0xC, ID_DYLIB = 0xD, LOAD_DYLINKER = 0xE, ID_DYLINKER = 0xF, PREBOUND_DYLIB = 0x10, ROUTINES = 0x11, SUB_FRAMEWORK = 0x12, SUB_UMBRELLA = 0x13, SUB_CLIENT = 0x14, SUB_LIBRARY = 0x15, TWOLEVEL_HINTS = 0x16, PREBIND_CKSUM = 0x17, LOAD_WEAK_DYLIB = 0x18 | REQ_DYLD, SEGMENT_64 = 0x19, ROUTINES_64 = 0x1A, UUID = 0x1B, RPATH = 0x1C | REQ_DYLD, CODE_SIGNATURE = 0x1D, SEGMENT_SPLIT_INFO = 0x1E, REEXPORT_DYLIB = 0x1F | REQ_DYLD, LAZY_LOAD_DYLIB = 0x20, ENCRYPTION_INFO = 0x21, DYLD_INFO = 0x22, DYLD_INFO_ONLY = 0x22 | REQ_DYLD, LOAD_UPWARD_DYLIB = 0x23 | REQ_DYLD, VERSION_MIN_MAC_OSX = 0x24, VERSION_MIN_IPHONE_OS = 0x25, FUNCTION_STARTS = 0x26, DYLD_ENVIRONMENT = 0x27, MAIN = 0x28, DATA_IN_CODE = 0x29, SOURCE_VERSION = 0x2A, DYLIB_CODE_SIGN_DRS = 0x2B, ENCRYPTION_INFO_64 = 0x2c, LC_BUILD_VERSION = 0x32, } LoadCommandType ; string LoadCommandTypeRead(LoadCommandType &loadCommandType) { switch(loadCommandType) { case SEGMENT : return "SEGMENT"; case SYM_TAB : return "SYM_TAB"; case SYM_SEG : return "SYM_SEG"; case THREAD : return "THREAD"; case UNIX_THREAD : return "UNIX_THREAD"; case LOAD_FVM_LIB : return "LOAD_FVM_LIB"; case ID_FVM_LIB : return "ID_FVM_LIB"; case IDENT : return "IDENT"; case FVM_FILE : return "FVM_FILE"; case PREPAGE : return "PREPAGE"; case DY_SYM_TAB : return "DY_SYM_TAB"; case LOAD_DYLIB : return "LOAD_DYLIB"; case ID_DYLIB : return "ID_DYLIB"; case LOAD_DYLINKER : return "LOAD_DYLINKER"; case ID_DYLINKER : return "ID_DYLINKER"; case PREBOUND_DYLIB : return "PREBOUND_DYLIB"; case ROUTINES : return "ROUTINES"; case SUB_FRAMEWORK : return "SUB_FRAMEWORK"; case SUB_UMBRELLA : return "SUB_UMBRELLA"; case SUB_CLIENT : return "SUB_CLIENT"; case SUB_LIBRARY : return "SUB_LIBRARY"; case TWOLEVEL_HINTS : return "TWOLEVEL_HINTS"; case PREBIND_CKSUM : return "PREBIND_CKSUM"; case LOAD_WEAK_DYLIB : return "LOAD_WEAK_DYLIB"; case SEGMENT_64 : return "SEGMENT_64"; case ROUTINES_64 : return "ROUTINES_64"; case UUID : return "UUID"; case RPATH : return "RPATH"; case CODE_SIGNATURE : return "CODE_SIGNATURE"; case SEGMENT_SPLIT_INFO : return "SEGMENT_SPLIT_INFO"; case REEXPORT_DYLIB : return "REEXPORT_DYLIB"; case LAZY_LOAD_DYLIB : return "LAZY_LOAD_DYLIB"; case ENCRYPTION_INFO : return "ENCRYPTION_INFO"; case DYLD_INFO : return "DYLD_INFO"; case DYLD_INFO_ONLY : return "DYLD_INFO_ONLY"; case LOAD_UPWARD_DYLIB : return "LOAD_UPWARD_DYLIB"; case VERSION_MIN_MAC_OSX : return "VERSION_MIN_MAC_OSX"; case VERSION_MIN_IPHONE_OS : return "VERSION_MIN_IPHONE_OS"; case FUNCTION_STARTS : return "FUNCTION_STARTS"; case DYLD_ENVIRONMENT : return "DYLD_ENVIRONMENT"; case MAIN : return "MAIN"; case DATA_IN_CODE : return "DATA_IN_CODE"; case SOURCE_VERSION : return "SOURCE_VERSION"; case DYLIB_CODE_SIGN_DRS : return "DYLIB_CODE_SIGN_DRS"; case ENCRYPTION_INFO_64: return "ENCRYPTION_INFO_64"; case LC_BUILD_VERSION: return "LC_BUILD_VERSION"; default : return "Error"; } } typedef struct { char section_name[16]; char segment_name[16]; uint32 address ; uint32 size ; uint32 offset; uint32 section_alignment; uint32 relocation_entry_offset; uint32 number_of_relocation_entries; uint32 flags ; uint32 reserved1; uint32 reserved2; } Section ; typedef struct { char section_name[16]; char segment_name[16]; uint64 address ; uint64 size ; uint32 offset; uint32 section_alignment; uint32 relocation_entry_offset; uint32 number_of_relocation_entries; uint32 flags ; uint32 reserved1; uint32 reserved2; uint32 reserved3; } Section64 ; typedef uint vm_proc; typedef enum { HIGH_VM = 0x1, FVM_LIB = 0x2, NO_RELOC = 0x4, PROTECTION_VERSION_1 = 0x8 } SegmentFlags ; typedef struct { uint32 load_command_string_offset ; local int64 pos = FTell(); // We need to goto beginning of LoadCommand, then goto the offset FSeek(FTell() - (sizeof(uint32) * 3) + load_command_string_offset); string string_data ; FSeek(pos); } LoadCommandString ; string LoadCommandStringRead(LoadCommandString &loadCommandString) { return loadCommandString.string_data; }; typedef ubyte Uuid[16] ; // TODO : Clean this ugly thing up string UuidRead(Uuid uuid) { local string ret, tmp; local int i; for(i = 0; i<4; i++) { SPrintf(tmp, "%.2X", uuid[i]); ret += tmp; } ret += "-"; for(i = 0; i<2; i++) { SPrintf(tmp, "%.2X", uuid[i+4]); ret += tmp; } ret += "-"; for(i = 0; i<2; i++) { SPrintf(tmp, "%.2X", uuid[i+6]); ret += tmp; } ret += "-"; for(i = 0; i<2; i++) { SPrintf(tmp, "%.2X", uuid[i+8]); ret += tmp; } ret += "-"; for(i = 0; i<6; i++) { SPrintf(tmp, "%.2X", uuid[i+10]); ret += tmp; } return ret; } typedef struct { uint32 version; } Version ; string VersionRead(Version &version) { local string version_string; if(version.version & 0xFF == 0) { SPrintf(version_string, "%u.%u", version.version >> 16, (version.version >> 8) & 0xFF); } else { SPrintf(version_string, "%u.%u.%u", version.version >> 16, (version.version >> 8) & 0xFF, version.version & 0xFF); } return version_string; } typedef struct { uint32 tool; // enum for the tool Version version; // version of the tool }build_tool_version; typedef struct { //LoadCommandHead loadCommandHead ; LoadCommandType command; uint command_size; // Process rest of load command based on command type switch(command) { case ID_DYLIB : case LOAD_DYLIB : case LOAD_WEAK_DYLIB : case REEXPORT_DYLIB : LoadCommandString name; // TODO : Pretty print this uint32 timestamp; // TODO : Pretty print this uint32 current_version; // TODO : Pretty print this uint32 compatibility_version; // Seek to the beginning of the LoadCommand FSeek(FTell() - (sizeof(uint32) * 6)); // Then skip to the end of the command based on the command_size FSkip(command_size); break; case SYM_TAB : uint32 symbol_table_offset ; uint32 number_of_symbol_table_entries ; uint32 string_table_offset ; uint32 string_table_size ; break; case DYLD_INFO : case DYLD_INFO_ONLY : uint32 rebase_offset; uint32 rebase_size; uint32 bind_offset; uint32 bind_size; uint32 weak_bind_offset; uint32 weak_bind_size; uint32 lazy_bind_offset; uint32 lazy_bind_size; uint32 export_offset; uint32 export_size; break; case DY_SYM_TAB : uint32 index_local_symbols; uint32 local_symbols_size; uint32 index_externally_defined_symbols; uint32 externally_defined_symbols_size; uint32 index_undefined_symbols; uint32 undefined_symbols_size; uint32 table_contents_offset; uint32 enteries_toc_size; uint32 file_offset_module_table; uint32 module_table_entries_size; uint32 external_references_symbol_table_offset; uint32 external_references_symbol_table_size; uint32 indirect_symbol_table_offset; uint32 indirect_symbol_table_size; uint32 external_relocation_entries_offset; uint32 external_relocation_entries_size; uint32 local_relocation_entries_offset; uint32 local_relocation_entries_size; break; case UUID : Uuid uuid; break; case VERSION_MIN_MAC_OSX : case VERSION_MIN_IPHONE_OS : // TODO : Pretty print this Version version; uint32 reserved ; break; case FUNCTION_STARTS : case CODE_SIGNATURE : case SEGMENT_SPLIT_INFO: case DATA_IN_CODE: uint32 data_offset; uint32 data_size; break; case UNIX_THREAD : case THREAD : switch(cpu_typer) { case CPU_TYPE_X86 : case CPU_TYPE_I386 : i386ThreadFlavor flavor; // TODO : Pretty print this uint32 count; switch(flavor) { case i386_THREAD_STATE : i386ThreadState threadState; // TODO : Flesh these guys out case i386_FLOAT_STATE : case i386_EXCEPTION_STATE : } break; case CPU_TYPE_X86_64 : x86ThreadFlavor flavor; // TODO : Pretty print this uint32 count; switch(flavor) { case x86_THREAD_STATE64 : x86ThreadState threadState; break; // TODO : Flesh these guys out case x86_FLOAT_STATE64 : case x86_EXCEPTION_STATE64 : case x86_DEBUG_STATE64 : } break; case CPU_TYPE_POWERPC : case CPU_TYPE_POWERPC64 : PPCThreadFlavor flavor; // TODO : Pretty print this uint32 count; switch(flavor) { case PPC_THREAD_STATE : PPCThreadState threadState; break; // TODO : Flesh these guys out case PPC_FLOAT_STATE : case PPC_EXCEPTION_STATE : case PPC_VECTOR_STATE : case PPC_THREAD_STATE64 : case PPC_EXCEPTION_STATE64 : } break; case CPU_TYPE_ARM : // TODO: Unsure if this is correct ? // uint32 flavor; // uint32 count; ARMThreadState threadState; break; } break; case FVM_LIB : case ID_FVM_LIB : LoadCommandString name ; uint32 minor_version ; uint32 header_address ; // Reposition(command_size, sizeof(uint32) * 5); // Seek to the beginning of the LoadCommand FSeek(FTell() - (sizeof(uint32) * 5)); // Then skip to the end of the command based on the command_size FSkip(command_size); break; case SUB_FRAMEWORK : LoadCommandString umbrella ; // Seek to the beginning of the LoadCommand FSeek(FTell() - (sizeof(uint32) * 3)); // Then skip to the end of the command based on the command_size FSkip(command_size); break; case SUB_CLIENT : LoadCommandString client ; // Seek to the beginning of the LoadCommand FSeek(FTell() - (sizeof(uint32) * 3)); // Then skip to the end of the command based on the command_size FSkip(command_size); break; case SUB_UMBRELLA : LoadCommandString sub_umbrella ; // Seek to the beginning of the LoadCommand FSeek(FTell() - (sizeof(uint32) * 3)); // Then skip to the end of the command based on the command_size FSkip(command_size); break; case SUB_LIBRARY : LoadCommandString sub_library ; // Seek to the beginning of the LoadCommand FSeek(FTell() - (sizeof(uint32) * 3)); // Then skip to the end of the command based on the command_size FSkip(command_size); break; case PREBOUND_DYLIB : LoadCommandString name ; uint32 modules_size ; LoadCommandString linked_modules ; // Seek to the beginning of the LoadCommand FSeek(FTell() - (sizeof(uint32) * 5)); // Then skip to the end of the command based on the command_size FSkip(command_size); break; case ID_DYLINKER : case LOAD_DYLINKER : LoadCommandString name ; // Seek to the beginning of the LoadCommand FSeek(FTell() - (sizeof(uint32) * 3)); // Then skip to the end of the command based on the command_size FSkip(command_size); break; case ROUTINES_64 : uint64 init_address ; uint64 init_module ; uint32 reversed_1; uint32 reversed_2; uint32 reversed_3; uint32 reversed_4; uint32 reversed_5; uint32 reversed_6; break; case ROUTINES : uint32 init_address ; uint32 init_module ; uint32 reversed_1; uint32 reversed_2; uint32 reversed_3; uint32 reversed_4; uint32 reversed_5; uint32 reversed_6; break; case TWOLEVEL_HINTS : uint32 offset ; uint32 hints_size ; break; case PREBIND_CKSUM : uint32 cksum ; break; case RPATH: LoadCommandString path ; // Seek to the beginning of the LoadCommand FSeek(FTell() - (sizeof(uint32) * 3)); // Then skip to the end of the command based on the command_size FSkip(command_size); break; case ENCRYPTION_INFO : uint32 crypt_offset ; uint32 crypt_size ; uint32 crypt_id ; break; case IDENT : break; case FVM_FILE : LoadCommandString name ; uint32 header_address ; // Seek to the beginning of the LoadCommand FSeek(FTell() - (sizeof(uint32) * 4)); // Then skip to the end of the command based on the command_size FSkip(command_size); break; case SEGMENT_64 : char segment_name[16]; uint64 vm_address ; uint64 vm_size ; uint64 file_off; uint64 file_size; vm_proc maximum_protection ; vm_proc initial_protection ; uint32 number_of_sections; // TODO : Fix this enum SegmentFlags flags; // Having this if statement will prevent warnings in 010Editor if(number_of_sections > 0) { Section64 section[number_of_sections]; } break; case SEGMENT : char segment_name[16]; uint32 vm_address ; uint32 vm_size ; uint32 file_off; uint32 file_size; vm_proc maximum_protection ; vm_proc initial_protection ; uint32 number_of_sections; // TODO : Fix this enum SegmentFlags flags; // Having this if statement will prevent warnings in 010Editor if(number_of_sections > 0) { Section section[number_of_sections]; } break; case SOURCE_VERSION: uint32 unka; uint32 unkb; break; case ENCRYPTION_INFO_64: uint32 cryptoff ; /* file offset of encrypted range */ uint32 cryptsize ; /* file size of encrypted range */ uint32 cryptid; /* which enryption system, 0 means not-encrypted yet */ uint32 pad; /* padding to make this struct's size a multiple of 8 */ break; case LC_BUILD_VERSION: uint32 platform; // platform Version minos; // X.Y.Z is encoded in nibbles xxxx.yy.zz Version sdk; // X.Y.Z is encoded in nibbles xxxx.yy.zz uint32 ntools; if (ntools > 0) { build_tool_version tools[ntools]; } break; default : Warning("Hit an unknown or unsupported load command : [%d]", command); Exit(-1); } } LoadCommand ; string LoadCommandReader(LoadCommand &loadCommand) { return LoadCommandTypeRead(loadCommand.command) + " load command"; } Header header ; local uint32 cpu_typer; if(header.magic == MACHO_32 || header.magic == MACHO_64) { cpu_typer = header.cpu_type; // If we didn't find a FAT header, then just process the load commands LoadCommand loadCommand[header.num_load_commands]; } else { // Otherwise we need to grab the new headers again local int i; for(i = 0; i < header.fat_arch_size; i++) { FSeek(header.fat_arch[i].file_offset); Header machHeader; cpu_typer = machHeader.cpu_type; LoadCommand loadCommand[machHeader.num_load_commands]; } }