背景
本文主要通过分享一些静态分析定位关键函数的技巧,实际上逆向分析本质上就是在寻找关键点,因此有好的关键定位方法则能事半功倍
定位思路
- 通过Log分析找到关键词
- 通过弹框分析定位关键定
定位技巧
从某个按钮触发逻辑,怎么从该链路找到具体实现的逻辑?
- 调试定位?
- 字符串定位
- 函数名类名定位
- 通过监控UI事件的响应定位关键代码 ?
- 通过监控底层API的调用定位关键代码(如网络访问接口、文件读写接口等)?
- 通过观察数据的变化来定位关键代码和地址?
定位实践
- 利用Frida-Dump-Ui,分析UI控件类型
- 利用UI控件类型分析一些函数,如初始化,显示等
- Hook之后 打印调用栈即可定位到
附录 dump-ui.js
//Credit: http://blog.itselectlab.com/?p=10485
console.warn("[*] Started: Dumping UI")
if (ObjC.available)
{
var current_window = ObjC.classes.UIWindow.keyWindow()
console.log(current_window.recursiveDescription().toString());
}
else
{
console.log("Objective-C Runtime is not available!");
}
console.warn("[*] Completed: Dumping UI")
系统库分析
- 无符号系统库位置
/Users/xxx/Library/Developer/Xcode/iOS DeviceSupport/14.0.1 (18A393)/Symbols/System/Library/Frameworks
- 系统库头文件位置
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/CoreML.framework/Headers
- 有符号模拟器系统库位置 (推荐✅)
/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreML.framework/CoreML
- 背景
有时候在分析某个 crash 时,或者对某个系统功能感兴趣时,会需要分析特定版本的 iOS 系统库的实现,例如UIKit.framework Foundiation.framework。可以在iOS-System-Symbols下载对应的系统库。
真机的系统库和模拟器的有些差别。系统库在真机上经过了很多编译优化,去除了大部分私有的函数符号,交叉引用也不像模拟器版本的那样直接。真机上的所有系统 framework 都被整合成了一个大文件,名为dyld_shared_cache_arm64或者dyld_shared_cache_armv7。函数在寻址时,是基于整个dyld_shared_cache_xxx文件进行寻址的。
当你把真机连接到 Xcode,Xcode 会把真机上的系统库拷贝到~/Library/Developer/Xcode/iOS DeviceSupport,从dyld_shared_cache_xxx中切分出每个单独的 framework。但是当你反编译这些 framework 时,会发现代码里会使用很多无效地址的函数指针,难以分析。这是因为在dyld_shared_cache_xxx中,一个 framework 引用另一个 framework 中的函数时,是相当于在一个库中直接引用的,直接跳转到对应的地址,而不是再用函数符号经过 lazy binder 进行调用。当 framework 从dyld_shared_cache_xxx中切分出来后,这些函数调用的地址就会指向 framework 外,无法追踪。
所以在分析真机的系统库时,最好是配合模拟器版本的系统库辅助分析,可以看到私有的符号,也可以看到更明确的交叉引用。或者用 IDA 直接分析整个 dyld_shared_cache_xxx文件,不过这样做需要反汇编整个文件,耗时很大。