lldb 动态调试(macOS/iOS)

SkillMedia

lldb 调试(macOS/iOS):attach、expr、image。 触发词:lldb、macOS调试、iOS调试

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 lldb 动态调试(macOS/iOS) skill

What this skill tells your AI

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

何时使用 / 何时不用

  • 用:macOS/iOS 目标动态调试(attach/启动/断点/表达式求值/符号查找)
  • 用:Linux 上调试带 DWARF 的调试版程序(lldb 与 clang 工具链同源,DWARF 处理成熟)
  • 不用:Linux 目标([[re-gdb]])、Windows 目标([[re-x64dbg]])
  • 不用:iOS 越狱/证书环境问题(属 [[re-mobile]] 域);只读内存([[re-memdump]] 默认转储优先)
  • 不用:脚本化大批量内存转储/取证([[re-memdump]] / [[re-mem-forensics]] 更对口)

工具准备

参考 [[re-analyze/platform-tips]] macOS 分支——SIP 与 TCC 限制 attach,需 Developer Tools 授权。

lldb

  • macOS: 自带(Xcode Command Line Tools: xcode-select --install
  • Linux: apt install lldb / dnf install lldb / pacman -S lldb
  • macOS 更全: brew install llvm(含新版 lldb)
  • 验证: lldb --version
  • 版本差异: Xcode 自带 lldb、llvm.org 的 lldb、Swift 工具链 lldb 功能近似但版本号不同(lldb --version 确认);脚本依赖 lldb.SBDebugger API 时跨版本兼容性需验证(见 [[gotchas]])

SIP 关闭或授权(attach 前置)

  • 系统设置 > 隐私与安全性 > 开发者工具 > 授权使用 lldb 的终端(TCC 授权)
  • 旧系统: sudo DevToolsSecurity -enable
  • 说明: 一般不要关 SIP(可只对调试需求临时处理);iOS 内核级调试需 KDK/开发内核,属 [[re-mobile]] 域

操作步骤

  1. Developer Tools 权限确认

    lldb -p <测试进程pid>   # 若报 "please check the developer mode" / 权限拒绝 → 去系统设置授权终端
    

    授权后重启终端;仍失败再检查 SIP 状态: csrutil status。 注意: TCC 授权弹窗需在系统设置手动确认,无法命令行绕过。

  2. attach/启动

    (lldb) process attach --pid <pid>     # 附加
    (lldb) process attach --name Safari   # 按名字附加(需唯一)
    (lldb) target create ./sample         # 或直接启动
    (lldb) run --args arg1
    (lldb) continue / c
    

    iOS 设备: platform select remote-ios + process connect connect://<device>(需配合调试服务,越狱/证书要求见 [[re-mobile]])

    • attach 时机注意: 目标已运行过初始化逻辑,入口前行为看不到——需要从入口看就 target create + run 启动模式
    • 启动停在入口: process launch --stop-at-entry(等价 -s
  3. image lookup 符号

    (lldb) image lookup -n main            # 按名字查符号
    (lldb) image lookup -a $pc             # 按地址查当前所在函数/源行
    (lldb) image list                      # 已加载镜像(dylib 基址表)
    (lldb) image lookup -rn dispatch       # 正则匹配符号
    

    stripped 二进制用 image lookup -a 反查地址归属模块,配合 image dump symtab

    • 模块基址: image list -o 加偏移列——ASLR 下每次运行基址不同,脚本里先拿基址再算绝对地址(见 [[gotchas]])
  4. 内存表达式 expr

    (lldb) expr $rax
    (lldb) expr $rax = 0                   # 写寄存器
    (lldb) expr (char*)0x100000000         # 类型化读地址
    (lldb) expr -O -- @"hello"             # Objective-C 求值(objc 运行时)
    (lldb) memory read -c 20 -s 4 -f x $rsp     # 读内存(缺 -f x 会报格式冲突错误)
    (lldb) memory write -s 1 0x100000000 0x90  # 写字节(绕过校验)
    
    • 表达式求值有副作用(会执行代码)——别在敏感路径上乱求值,见 [[gotchas]]
  5. 断点与脚本

    (lldb) breakpoint set -n main
    (lldb) breakpoint set -a 0x100004000 -c '*(int*)($rsp) == 0x1234'   # 条件断点
    (lldb) breakpoint command add 1
    > frame variable
    > expr $rax
    > continue
    > DONE
    

    Python 自动化: lldb 内置 Python——script import lldb,或用 lldb -s script.lldb 批处理。

    • 符号断点: breakpoint set -n objc_msgSend(按符号名,模块加载后自动生效);正则: -r '^check_'
    • 断点管理: breakpoint list / breakpoint delete / breakpoint disable 1
  6. 单步/栈/线程

    (lldb) thread step-over / step-into / step-out   # 步过/步入/出函数(别名 next/step/finish)
    (lldb) thread backtrace                          # 当前线程栈(别名 bt)
    (lldb) thread list                               # 全部线程
    (lldb) frame select 1                            # 切栈帧
    (lldb) frame variable                            # 当前帧局部变量
    (lldb) register read                             # 全部寄存器
    
    • 单步跳过 call 后的 step-out 配合返回寄存器看结果,是「验证函数返回」最快路径
  7. 内存搜索与区域

    (lldb) memory find 0x100000000 0x101000000 -e 0xdeadbeef   # 区间内搜值/字节串
    (lldb) memory find -s "password" 0x100000000 0x101000000   # 搜字符串
    (lldb) memory region 0x100004000                           # 该地址所属区域权限/边界
    
    • 找密钥/常量: 先 memory find 定位,再断写入点;区域权限(RWX)异常段先看(壳/解密段)
  8. 证据核对(收尾):断点命中记录、frame variable/expr 输出、memory read 转储(memory read --force -o 文件 导出)对照 [[re-triage]] 初勘值入档,结论写 [[re-analyze/analysis-contract]]

跨域联合

  • [[re-binary-core]]:工作流第 6 步(macOS/iOS 调试器)
  • [[re-mobile]]:iOS App/越狱动态调试的底层工具
  • [[re-format-macho]]:先解析结构再调试(入口/LC_MAIN 与签名状态)
  • attach 失败时按 [[re-analyze/platform-tips]] 转 [[re-memdump]]

常见坑与陷阱

  • SIP/TCC 拦截 attach:非授权终端 attach 被拒(permission denied 或静默失败)——去系统设置开发者工具授权;关闭 SIP 只在极端情况
  • 权限弹窗需手动确认:TCC 每次对新的调试目标弹窗,脚本化 attach 会被卡住——预先授权目标程序
  • 内核调试需额外配置:macOS 内核调试要 KDK 匹配版本 + 开发内核启动,普通逆向用不上,别在用户态调试上浪费时间
  • 签名状态: 修改过的 Mach-O 未重签无法运行(见 [[re-format-macho]])——先 codesign -f -s - 重签再调试
  • task_for_pid entitlement/SIP/Hardened Runtime 三层限制:现象——Developer Tools 已授权仍 attach 失败或目标启动即崩溃;原因——除 TCC 外还有三层:调试器需 task_for_pid entitlement,目标启用 Hardened Runtime 时调试 API 受限,SIP 限制系统进程 attach;对策——逐层排查(csrutil status、检查目标签名与 entitlement),测试目标可先去签名/重签([[re-format-macho]])再调试,参考 [[re-analyze/platform-tips]] macOS 分支
  • ASLR 基址漂移:每次启动 dylib 基址不同——脚本里硬编码地址会失效;用 image list -o 拿基址换算,断点尽量下符号名(-n/-s
  • 表达式求值有副作用expr 会真实执行代码(调用函数/改内存)——在 hook 点求值可能改变目标行为,验证场景用 frame variable 只读优先
  • 版本差异、调试服务器与边界见 [[gotchas]]

Signals

GitHub stars
57
Forks
8
Last commit
Sep 2026

ahel review

  • K1binfo
    installs-packages
  • K1binfo
    installs-packages (in references/gotchas.md)

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

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