Mach-O 格式解析

SkillDev tools

Mach-O 格式解析:mach_header、LC_*、segment、dyld 信息。 触发词:Mach-O、解析mac程序、dyld

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Mach-O 格式解析 skill

What this skill tells your AI

The instructions your AI receives, as published by dslsdzc/rev-skills in .claude/skills/re-format-macho/SKILL.md and read by ahel’s review.

何时使用 / 何时不用

  • 用:目标是 macOS/iOS 的 Mach-O 二进制(可执行文件/.dylib/.bundle/Framework),需要理解结构、load commands、入口、代码签名、动态库依赖链
  • 用:检查 dylib 注入(LC_LOAD_DYLIB 异常条目)、签名/公证状态、通用二进制多架构片
  • 不用:PE(走 [[re-format-pe]])、ELF(走 [[re-format-elf]])
  • 不用:只需函数逻辑(直接反编译技能);iOS 越狱环境问题属 [[re-mobile]] 域

工具准备

参考 [[re-analyze/platform-tips]] macOS 分支——attach/调试受 SIP 与 TCC 限制;静态解析不受影响。

otool(Apple 自带)

  • macOS: Xcode Command Line Tools: xcode-select --install
  • 验证: otool --version
  • Linux 替代: llvm-otoolapt install llvm / brew install llvm / pacman -S llvm),功能覆盖 otool 常用子命令

llvm-objdump(跨平台)

  • macOS: brew install llvm;Linux: apt install llvm / dnf install llvm / pacman -S llvm
  • 验证: llvm-objdump --version
  • 用法: llvm-objdump --macho --private-headers sample(Linux 上可直接解析 Mach-O,与 macOS 输出一致)

jtool2(深入 Mach-O 结构,macOS)

  • macOS: 从 GitHub(intezer/jtool2)clone 后 make,或下载 release 二进制
  • 验证: jtool2 -h sample 输出 load commands

codesign / lipo(macOS 自带)

  • 验证: codesign --versionlipo -info sample
  • Linux 替代: llvm-lipo -info sample(llvm 自带)

dyld_shared_cache_util(macOS)

  • 系统自带(/usr/bin/dyld_shared_cache_util);用途: 解析 dyld 共享缓存中的系统 dylib 时把单个库抽出来

操作步骤

  1. 初勘(先确认类型与架构)

    file sample                  # 可执行文件 / dylib / 通用二进制 / 字节序
    lipo -info sample            # 通用二进制列出各架构片;单架构提示 "non-fat file"
    xxd -l 16 sample             # 魔数: cffaedfe=64位小端, feedfacf=64位大端, cebafaed=32位小端, cafebabe=fat
    

    魔数(文件里看到的字节):cffa edfe(MH_MAGIC_64)、cefa edfe(MH_MAGIC 32 位)、cafe babe(FAT,后跟 4 字节架构数)。通用二进制先 lipo -thin <arch> -output piece sample 提取单片再解析。

  2. mach_header 与 load commands(核心)

    otool -h sample                 # magic/cputype/filetype/ncmds/flag 一行全出
    otool -l sample | head -80      # 全部 load commands
    

    64 位 mach_header 固定 32 字节(32 位为 28 字节):magic(4) + cputype(4) + cpusubtype(4) + filetype(4) + ncmds(4) + sizeofcmds(4) + flags(4) + reserved(4,仅 64 位)。load commands 是 Mach-O 的"节表+导入表+入口+签名"综合体——从头到尾按 cmdsize 顺序遍历,ncmds 计数、sizeofcmds 为总字节数,两者互相校验。filetype: 2=MH_EXECUTE 6=MH_DYLIB 8=MH_BUNDLE。常见 LC 值与字段表见 [[layout]]。

  3. 段与节(__TEXT/__DATA/__LINKEDIT)

    otool -l sample | grep -A8 'segname __TEXT'
    otool -l sample | grep -A8 'segname __DATA'
    llvm-objdump --macho --section-headers sample
    

    记录各段 vmaddr/vmsize/fileoff;__TEXT,__text 是代码,__DATA,__data 是可写数据,GOT 在 __DATA_CONST,__got(只读常量段;旧二进制在 __DATA,__got);__LINKEDIT有 vmaddr/vmsize 的正常段,通常映射为只读区域(vmmap 里能看到),存放符号表/字符串表/重定位/签名等链接元数据——具体存在方式受 dyld 与 shared cache 影响。

  4. 入口(LC_MAIN / LC_UNIXTHREAD)

    otool -l sample | grep -A6 LC_MAIN
    

    entryoff 是入口相对文件头的偏移,入口 VA = __TEXT 段 vmaddr + entryoff(64 位下 __TEXT 基址通常 0x100000000)。老二进制用 LC_UNIXTHREAD(寄存器 state 含入口)。可执行文件无 LC_MAIN 且无 LC_UNIXTHREAD 属畸形,重点排查。

  5. dyld 信息(LC_DYLD_INFO_ONLY / 导出 trie)

    otool -l sample | grep -A9 LC_DYLD_INFO_ONLY
    llvm-objdump --macho --exports-trie sample   # 导出符号(trie 解码)
    

    rebase(基址修正点)、bind/lazy_bind(外部符号绑定)、export(导出 trie)四张表的 offset+size 都在 LC_DYLD_INFO_ONLY(48 字节)里;新版二进制用 LC_DYLD_CHAINED_FIXUPS(链式修正,iOS 13+ 默认)。dylib 的导出符号在 trie 里,nm -gU 同效果。

  6. 动态库依赖链(注入检测)

    otool -L sample                 # LC_LOAD_DYLIB 列表(依赖库 + install name)
    otool -l sample | grep -A4 LC_LOAD_DYLIB
    

    每个 LC_LOAD_DYLIB:name(绝对路径或 @rpath/@executable_path 相对)+ timestamp/current_version。恶意 dylib 持久化 = 新增 LC_LOAD_DYLIB 条目——与签名时列表比对不一致是重要告警(详见坑)。two-level namespace 下符号查找按 (库, 符号) 二元组,导入解析严格。

  7. 符号表(nlist_64)

    llvm-nm -m sample                # 含段归属与 N_EXT 标记;undefined = 导入
    llvm-nm -gU sample               # 仅外部定义符号(导出)
    otool -l sample | grep -A3 LC_SYMTAB   # symoff/nsyms/stroff/strsize 定位表
    

    nlist_64 每条 16 字节:n_strx(字符串表偏移)+ n_type(N_EXT/N_SECT 等)+ n_sect + n_desc + n_value。stripped 后 .symtab 消失,只剩 LC_DYLD_INFO 的导出 trie 与动态绑定信息——恢复思路同 ELF([[re-imports]] 签名匹配 + 字符串交叉引用)。

  8. 代码签名检查

    codesign -dv sample 2>&1          # 签名类型(adhoc / Apple Development / not signed)
    codesign --verify --deep sample   # 完整性验证
    jtool2 --sig sample | head -20    # LC_CODE_SIGNATURE 细节(CodeDirectory/哈希)
    
    • adhoc:自签,可被修改后重签(codesign -f -s - sample
    • Apple 签名:修改任何字节都会失效;Library Validation 开启时注入 dylib 会失败
    • 无 LC_CODE_SIGNATURE = 未签名(iOS 上无法直接运行)
  9. 手工解析与验证:load command 输出异常/头字段被伪造时,用 xxd + Python struct 按偏移直接解析 mach_header 与各 LC(最小可运行示例与字节样例见 [[examples]]),别把解析失败当"损坏文件"丢弃。

跨域联合

  • [[re-binary-core]]:工作流第 3 步,Mach-O 目标格式解析
  • [[re-mobile]]:iOS App/越狱环境分析的前置(arm64 Mach-O 主二进制与 dylib)
  • [[re-ios]] / [[re-macos]]:生态衔接(App 层、签名公证、TCC/SIP 限制)
  • [[re-cracking]]:macOS 破解类任务(补丁后重签流程见本技能步骤 8)
  • [[re-imports]]:dylib 依赖与导出符号的劫持面分析
  • 动态调试配合 [[re-lldb]](SIP/TCC 限制见 [[re-analyze/platform-tips]])

常见坑与陷阱

  • 签名验证会拦调试/注入:修改过的二进制 codesign 校验失败无法运行——先 codesign -f -s - 重签(仅限自签/adhoc 场景);Library Validation 开启时 DYLD_INSERT_LIBRARIES 失效
  • iOS 上需越狱环境:真机调试要开发者证书或越狱,模拟器进程受沙盒限制——静态解析可先行,动态部分交给 [[re-mobile]]
  • LC_LOAD_DYLIB 注入检测:恶意 dylib 通过新增 LC_LOAD_DYLIB 实现持久化——otool -L 列表与签名时列表不一致是重要告警
  • 通用二进制含多架构片:先 lipo -info 确认架构再 lipo -thin 提取,别对全片解析;fat 头里各片 offset 是绝对文件偏移,按 (offset, size) 切出单片
  • GOT 位置随版本迁移:新产物 GOT 在 __DATA_CONST,__got(只读,装载后重定位一次);旧产物在 __DATA,__got(可写)——找 GOT 先 otool -l 看段名,别假设
  • dyld 共享缓存里没有独立 dylib 文件:系统库(libSystem.dylib 等)实际在 /System/Library/dyld/ 缓存内,文件系统里只有 stub——分析系统库用 dyld_shared_cache_util -extract 抽出
  • load command 遍历错位:现象——otool -l 输出中途乱码/报错;原因——ncmds 与 sizeofcmds 被伪造或某条 LC 的 cmdsize 异常;对策——按 32/64 位结构体逐条校验 cmdsize(64 位下 LC 最小 16 字节),从 sizeofcmds 总量反推合法性
  • __LINKEDIT 是映射段,但内容可能被 dyld 加工:它有自己的 vmaddr/vmsize,通常以只读映射存在(vmmap 可见);不过 shared cache 共享库的链接元数据驻留在共享缓存里,直接从进程内存按文件偏移找符号表常常对不上——定位符号表优先用 nm/dyldinfo/MachOView 等按 LC_SYMTAB 解析,而不是照抄文件偏移

Signals

GitHub stars
57
Forks
8
Last commit
Sep 2026

ahel review

  • K1binfo
    installs-packages

Automated review, not a security audit. Ruleset v1+k2.

Advanced
Catalog kind
skill
Gateway key
re-format-macho
Source
github.com/dslsdzc/rev-skills