2026/1/17 7:29:44
网站建设
项目流程
佛山深圳建网站,Wordpress自动回复评论,推广公司网站,湖南环达公路桥梁建设总公司网站续更新#xff0c;最新内容也可以在公众号「非专业程序员Ping」一起交流#xff01;#xff01;一、工欲善其事#xff0c;必先利其器在开始之前#xff0c;需要先了解两个常用的逆向工具#xff1a;Hopper 和 IDA。具体安装和使用我们也有专门的文章介绍#xff1a;常见…续更新最新内容也可以在公众号「非专业程序员Ping」一起交流一、工欲善其事必先利其器在开始之前需要先了解两个常用的逆向工具Hopper 和 IDA。具体安装和使用我们也有专门的文章介绍常见逆向工具使用。一般而言我们都是结合两个工具一起看IDA 的反汇编通常比 Hopper 还原度更高所以我们主用的还是IDA。二、查找二进制文件路径分析的第一步肯定是找到我们想要分析的入口函数以CoreText中的字体级联/Font Fallback机制这篇文章的Case为例子我们要研究的是 CTFontCopyDefaultCascadeListForLanguages 的实现我们可以在LLDB中通过如下命令找到该符号所在库image lookup -rn CTFontCopyDefaultCascadeListForLanguages在这里插入图片描述通过这个命令我们可以得到两个信息1CTFontCopyDefaultCascadeListForLanguages 在CoreText库中2CoreText 二进制文件的路径得到路径之后在访达中可以通过快捷键 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整数/指针类型// 以如下调用为例let ctFont UIFont.systemFont(ofSize: 18)let languages [zh-HK, zh-Hans]CTFontCopyDefaultCascadeListForLanguages(ctFont, languages as CFArray)入参 返回值在这里插入图片描述 在这里插入图片描述2浮点数类型// 以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 的实现签名如下__int64 __usercall TBaseFont::CreateFallbacksX0(__int64 resultX0, __int64 a2X1, __int64 a3X2, __int64 a4X3, __int64 a5X4, _QWORD *a6X8)}其中第一个参数 result 通过调用的地方我们知道是 CTFont 中的一个成员变量但具体是什么不确定。我们最终结合LLDB做如下尝试分析出了 result 的具体含义在这里插入图片描述同理我们如果拿到一段地址要分析其含义的话也可以按这个步骤进行尝试。4.3 如何修改 if 条件我们以如下函数调用为例在这里插入图片描述我们传入的num是1正常逻辑会执行 num 2 返回 3那有没有办法不修改入参执行 num 1 的路径。我们来看下这段逻辑的汇编代码在这里插入图片描述图片注释说的比较明白if 条件在汇编层面一般被翻译成 tbzTest Bit and branch if Zero、tbnzTest 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 的常见用法如下在这里插入图片描述