7.3 KiB
7.3 KiB
name, description, capabilities
| name | description | capabilities | |
|---|---|---|---|
| re-lldb | lldb 调试(macOS/iOS):attach、expr、image。 触发词:lldb、macOS调试、iOS调试 |
|
lldb 动态调试(macOS/iOS)
何时使用 / 何时不用
- 用: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.SBDebuggerAPI 时跨版本兼容性需验证(见 gotchas)
SIP 关闭或授权(attach 前置)
- 系统设置 > 隐私与安全性 > 开发者工具 > 授权使用 lldb 的终端(TCC 授权)
- 旧系统:
sudo DevToolsSecurity -enable - 说明: 一般不要关 SIP(可只对调试需求临时处理);iOS 内核级调试需 KDK/开发内核,属 re-mobile 域
操作步骤
-
Developer Tools 权限确认:
lldb -p <测试进程pid> # 若报 "please check the developer mode" / 权限拒绝 → 去系统设置授权终端授权后重启终端;仍失败再检查 SIP 状态:
csrutil status。 注意: TCC 授权弹窗需在系统设置手动确认,无法命令行绕过。 -
attach/启动:
(lldb) process attach --pid <pid> # 附加 (lldb) process attach --name Safari # 按名字附加(需唯一) (lldb) target create ./sample # 或直接启动 (lldb) run --args arg1 (lldb) continue / ciOS 设备:
platform select remote-ios+process connect connect://<device>(需配合调试服务,越狱/证书要求见 re-mobile)- attach 时机注意: 目标已运行过初始化逻辑,入口前行为看不到——需要从入口看就
target create+run启动模式 - 启动停在入口:
process launch --stop-at-entry(等价-s)
- attach 时机注意: 目标已运行过初始化逻辑,入口前行为看不到——需要从入口看就
-
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)
- 模块基址:
-
内存表达式
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
-
断点与脚本:
(lldb) breakpoint set -n main (lldb) breakpoint set -a 0x100004000 -c '*(int*)($rsp) == 0x1234' # 条件断点 (lldb) breakpoint command add 1 > frame variable > expr $rax > continue > DONEPython 自动化: lldb 内置 Python——
script import lldb,或用lldb -s script.lldb批处理。- 符号断点:
breakpoint set -n objc_msgSend(按符号名,模块加载后自动生效);正则:-r '^check_' - 断点管理:
breakpoint list/breakpoint delete/breakpoint disable 1
- 符号断点:
-
单步/栈/线程:
(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配合返回寄存器看结果,是「验证函数返回」最快路径
- 单步跳过 call 后的
-
内存搜索与区域:
(lldb) memory find 0x100000000 0x101000000 -e 0xdeadbeef # 区间内搜值/字节串 (lldb) memory find -s "password" 0x100000000 0x101000000 # 搜字符串 (lldb) memory region 0x100004000 # 该地址所属区域权限/边界- 找密钥/常量: 先
memory find定位,再断写入点;区域权限(RWX)异常段先看(壳/解密段)
- 找密钥/常量: 先
-
证据核对(收尾):断点命中记录、
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