使用 010 Editor 模板 MachO.bt 去分析 Mach-O 文件格式,提示一个错误 Hit an unknown or unsupported load command : [-2147483608],如下图:
对比出错的地方,仔细查看模板文件的代码,找到了是因为 LC_MAIN 这个 loadcommand 的错误信息,需要修改两个地方,第 331 行的
MAIN = 0x28 修改成 MAIN = 0x28 | REQ_DYLD,然后在 838 行 switch 语句的 default 上面添加以下代码。
case MAIN:
uint64 entryoff; /* file (__TEXT) offset of main() */
uint64 stacksize;/* if not zero, initial stack size */
break;
保存模板文件之后再运行,就发现解析正常了,效果如下图:
修改后的 MachO.bt 如下:
//------------------------------------------------
//--- 010 Editor v3.2.2 Binary Template
//
// File: MachO.bt
// Authors: Tim "diff" Strazzere
// Revisor: exchen
// E-mail: diff@lookout.com, strazz@gmail.com
// Version: 1.4
// 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.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 <uint> {
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 <format=hex>;
#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 <uint> {
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 <uint> {
i386_THREAD_STATE = 0x1,
i386_FLOAT_STATE = 0x2,
i386_EXCEPTION_STATE = 0x3
} i386ThreadFlavor <format=hex>;
typedef struct {
uint32 eax <format=hex>;
uint32 ebx <format=hex>;
uint32 ecx <format=hex>;
uint32 edx <format=hex>;
uint32 edi <format=hex>;
uint32 esi <format=hex>;
uint32 ebp <format=hex>;
uint32 esp <format=hex>;
uint32 ss <format=hex>;
uint32 eflags <format=hex>;
uint32 eip <format=hex>;
uint32 cs <format=hex>;
uint32 ds <format=hex>;
uint32 es <format=hex>;
uint32 fs <format=hex>;
uint32 gs <format=hex>;
} i386ThreadState;
typedef enum <uint> {
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 <format=hex>;
typedef struct {
uint64 rax <format=hex>;
uint64 rbx <format=hex>;
uint64 rcx <format=hex>;
uint64 rdx <format=hex>;
uint64 rdi <format=hex>;
uint64 rsi <format=hex>;
uint64 rbp <format=hex>;
uint64 rsp <format=hex>;
uint64 r8 <format=hex>;
uint64 r9 <format=hex>;
uint64 r10 <format=hex>;
uint64 r11 <format=hex>;
uint64 r12 <format=hex>;
uint64 r13 <format=hex>;
uint64 r14 <format=hex>;
uint64 r15 <format=hex>;
uint64 rip <format=hex>;
uint64 rflags <format=hex>;
uint64 cs <format=hex>;
uint64 fs <format=hex>;
uint64 gs <format=hex>;
} x86ThreadState;
typedef enum <uint> {
PPC_THREAD_STATE = 0x1,
PPC_FLOAT_STATE = 0x2,
PPC_EXCEPTION_STATE = 0x3,
PPC_VECTOR_STATE = 0x4,
PPC_THREAD_STATE64