新手小白也能看懂的LLDB技巧/逆向技巧

引言

在我们日常工作中,难免会遇到一些Crash等疑难问题需要查看系统实现,有时候在做一些高级定制功能时,比如自定义富文本渲染等,也需要查看系统是怎么做的;特别是对于iOS程序员来说,由于Apple的闭源生态,遇到以上问题基本只能靠逆向手段来逐步分析。学会汇编和逆向,可以说是一个程序员从入门走向进阶的第一步。

前面我们通过逆向手段分析了CoreText中的字体级联/Font Fallback机制,正好借此机会聊聊一些常用的逆向思路与技巧;本篇文章更多面向小白入门,不需要你有太多的汇编、LLDB知识,我们将结合一些典型场景来举一反三,当然,如果大家有更好的奇技淫巧欢迎一起交流、学习。

持续更新,最新内容也可以在公众号「非专业程序员Ping」一起交流!!

一、工欲善其事,必先利其器

在开始之前,需要先了解两个常用的逆向工具:Hopper 和 IDA。具体安装和使用我们也有专门的文章介绍:常见逆向工具使用。

一般而言我们都是结合两个工具一起看,IDA 的反汇编通常比 Hopper 还原度更高,所以我们主用的还是IDA。

二、查找二进制文件路径

分析的第一步,肯定是找到我们想要分析的入口函数,以CoreText中的字体级联/Font Fallback机制这篇文章的Case为例子,我们要研究的是 CTFontCopyDefaultCascadeListForLanguages 的实现,我们可以在LLDB中通过如下命令找到该符号所在库:

shell 复制代码
image lookup -rn CTFontCopyDefaultCascadeListForLanguages

通过这个命令我们可以得到两个信息:

1)CTFontCopyDefaultCascadeListForLanguages 在CoreText库中

2)CoreText 二进制文件的路径

得到路径之后,在访达中可以通过快捷键 Command + Shift + G 可以快速跳转到位置,得到CoreText的二进制文件:

三、善用AI

得到CoreText的二进制文件之后,我们通过IDA进行反汇编。

之后将 CTFontCopyDefaultCascadeListForLanguages 的主要调用逻辑Copy到单独的文件夹:

在AI没普及之前,我们一般是结合LLDB硬着头皮逐行分析,有了AI之后,我们可以直接将整个文件夹扔给AI(比如Cursor、GPT等),让AI给我们梳理流程、逐行注释,输出调用流程图等。

如下,是AI生成的函数调用流程;结合AI的逻辑梳理和注释,我们对 CTFontCopyDefaultCascadeListForLanguages 的整体逻辑会有一个大致的理解。

当然,AI也不是全能的,一些逻辑AI也只是猜测甚至乱说😩,具体的细节还需要我们结合LLDB、IDA一起分析,只是说有了AI之后,可以大大加快我们的分析效率。

下面我们将列举几个典型例子,我们日常分析中能遇到的也基本就这些。

四、典型例子

4.1 函数调用

不管是面向对象,还是面向过程,在汇编的世界里,程序逻辑都是由一个一个独立的函数调用组成的;对函数而言,最重要的就是它的输入输出,基本上我们只要读懂了每个函数的输入输出是什么,那我们就能理解整体的逻辑。

函数入参与返回值,按照数据类型不同可以总结为下面的表格:我们最常接触的,其实只有前两项

举个🌰:

1)整数/指针类型

swift 复制代码
// 以如下调用为例
let ctFont = UIFont.systemFont(ofSize: 18)
let languages = ["zh-HK", "zh-Hans"]
CTFontCopyDefaultCascadeListForLanguages(ctFont, languages as CFArray)
入参 返回值

2)浮点数类型

swift 复制代码
// 以getArea为例
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let area = getArea(frame: self.view.frame)
print(area)
}

func getArea(frame: CGRect) -> CGFloat {
return frame.width * frame.height
}
}
入参 返回值

4.2 怎么确定一段地址的含义

还是以举一个实际例子,在CoreText中的字体级联/Font Fallback机制文章中,我们要分析 TBaseFont::CreateFallbacks 的实现,签名如下:

assembly 复制代码
__int64 __usercall TBaseFont::CreateFallbacks@<X0>(__int64 result@<X0>, __int64 a2@<X1>, __int64 a3@<X2>, __int64 a4@<X3>, __int64 a5@<X4>, _QWORD *a6@<X8>)
}

其中第一个参数 result@ 通过调用的地方我们知道是 CTFont 中的一个成员变量,但具体是什么不确定。

我们最终结合LLDB做如下尝试分析出了 result@ 的具体含义:

同理,我们如果拿到一段地址要分析其含义的话,也可以按这个步骤进行尝试。

4.3 如何修改 if 条件

我们以如下函数调用为例:

我们传入的num是1,正常逻辑会执行 num + 2 返回 3,那有没有办法不修改入参,执行 num + 1 的路径。

我们来看下这段逻辑的汇编代码:

图片注释说的比较明白;if 条件在汇编层面一般被翻译成 tbz(Test Bit and branch if Zero)、tbnz(Test Bit and branch if Not Zero)等,我们可以通过修改寄存器的值来更改执行分支;这在分析系统API时,是一个很有用的思路。

举一反三,通过LLDB,我们可以实时修改任何寄存器、内存地址的值,这可以非常方便的帮我们浮现一些偶现的Bug、Crash等。

4.4 如果跳过函数执行/修改函数返回值

我们还是以上面的addNum为例,如果我们不修改入参,但是想修改返回值,应该怎么做:

最直接的方式是等addNum执行完后,修改返回值寄存器,如下,返回值存储在w0,我们可以修改成任意想要的值:

但这种方式有个弊端是,需要等函数执行完,在实际的场景中,我们往往希望不执行函数且能让函数返回我们想要的值 ,比如:函数中可能会修改其他参数,函数可能有复杂的鉴权逻辑无法通过鉴权等,这些场景我们往往不希望或者不能让函数执行,这种情况下就需要另一个指令:thread return

以addNum为例,按如下步骤操作:

使用 thread return 时,需要注意,我们的断点需要打在 objc_msgSend 的入口处,如果在 addNum 的入口打断点执行 thread return,最终可能会得到非预期值;原因是 thread return 改的是当前 frame 的返回寄存器,由于Objective-C的runtime特性,函数调用实际上是经过 objc_msgSend 给对象发消息,addNum 的上一个frame其实是 objc_msgSend,而 objc_msgSend 返回时可能会继续修改 w0 寄存器的值,会导致最终上层取到的值非预期。

4.5 善用 watchpoint 命令

在实际场景中,我们可能会遇到某个变量被很多地方修改,但是我们又无法一一断点,比如我们要查看哪些地方修改了 UIView 的 frame;或者某个值的修改链路很深,一般在系统库中比较常见,比如iOS中闭包嵌套闭包调用的场景。

针对以上场景,我们可以使用 watchpoint 命令,来观测变量的修改,watchpoint 的常见用法如下:

五、总结

本文总结了我们在逆向的通用分析思路,以及LLDB调试汇编逻辑中可能遇到的常见技巧和场景;本文会长期更新,觉得有用的小伙伴可以关注下公众号,及时接收更新;当然,各路大神有更多有用技巧,也欢迎指教!

相关推荐
黑化旺仔11 小时前
【OC】Runtime:类元数据、加载初始化与消息派发
开发语言·macos·ios·objective-c
songgeb12 小时前
iOS App支持设置RTL语言的实践
ios·swift·ui kit
软泡芙12 小时前
【iOS】swift启动屏显示黑屏
ios
用户693717500138414 小时前
当你向领导申请 AI 编程工具预算时,如果领导追问“能提效多少,有量化数据吗”,你该怎么回答?
android·后端·ios
Layer14 小时前
一些脱离 Mac 依赖的 Agent 操作 iPhone 实现
ios·ai编程·测试
用户693717500138416 小时前
当我说 Claude 搭配 GLM-5.3-Flash 太好用了,同事却提醒我:你可能正在失去对代码的掌控
android·后端·ios
茶底世界之下16 小时前
一键裁方会丢掉什么?用 Awaking 给园林照片做两种画幅
ios
Marco_Marco13517 小时前
定位SDK接入实战:Android/iOS/鸿蒙三端怎么选、怎么接
android·ios·harmonyos
老李IT笔记1 天前
关掉设备上的 AI 扩展:两个键各管一层,配错了等于没配
人工智能·ios·智能手机
2501_915921431 天前
iOS应用耗电测试:使用Energy Log、Keymob和Instruments进行性能监控与能源消耗分析
android·ios·小程序·https·uni-app·iphone·webview