《九阴真经: iOS黑客攻防秘籍》新书发布,干货满满,快来看看吧!

iOS 安全论坛 - 专注于研究 iOS 安全

 找回密码
 立即注册
查看: 10574|回复: 4

【Frida 实战】在 iOS 上分析应用

[复制链接]

119

主题

582

帖子

2626

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2626
发表于 2020-4-8 01:47:08 | 显示全部楼层 |阅读模式
本文是 Frida 实战系列教程的第一篇,以 iOS 平台讲解 Frida 的基本使用,后续还会继续分享更多关于 Frida 实战的使用技巧。Frida 是一个跨平台的动态分析工具,支持 iOS、Android、macOS 等主流的操作系统,提供了功能丰富的 Python 和 JavaScript 接口,能够在运行时注入进程,获取进程相关信息、Hook 函数、修改参数、调用指定函数等等,逆向研究人员如果运用好 Frida 这一神兵利器,能够快速定位到关键点,提高分析的效率。
安装Frida
Frida 的使用类似于 LLDB 与 debugserver 那样需要安装在 macOS 和 iOS 上,macOS 做为控制端,iOS 做为被控端,由控制端发送指令去操作被控制端。默认 macOS 没有安装 pip,首先安装 pip,如果已经安装的可以忽略。
  1. sudo easy_install pip
复制代码
然后安装 frida 和 frida-tools
  1. pip install --user frida
  2. sudo easy_install --upgrade frida
  3. pip install --user frida-tools
复制代码
然后在 iOS 上打开 Cydia 添加源:https://build.frida.re,如果 iOS 设备是 64 位的安装 Frida,如果是 32 位的安装 Frida for 32-bit devices。需要注意的是由于 Frida 官方源服务器在国外,下载速度可能会非常慢,有时需要半个小时才能完成,我建议大家换成 iOS 安全论坛的源,这样下载会快很多,源地址是 http://apt.ioshacker.net

Frida 相关工具
Frida安装完后,打开 /Users/exchen/Library/Python/2.7/bin 目录可以看到分别有 frida、frida-ls-devices、frida-ps、frida-kill、frida-trace、frida-discover 这几个工具,下面我们介绍这些工具的使用方法。
1. frida-ls-devices
frida-ls-devices 用于查看当前的设备列表,一般在多个设备连接时会用到,它能显示当前所有连接设备的 Id,这个 Id 实际上就是设备的 UDID,获取的信息如下:
  1. $ frida-ls-devices
  2. Id                                        Type    Name        
  3. ----------------------------------------  ------  ------------
  4. local                                     local   Local System
  5. cca1b9055ac2684999cd81e525ac03fe6028b9f9  usb     iPhone      
  6. tcp                                       remote  Local TCP
复制代码
2. frida-ps
frida-ps 用于查看设备上当前所有运行的进程,我们来查看它的帮助信息:
  1. $ frida-ps -h
  2. Usage: frida-ps [options]

  3. Options:
  4.   --version             show program's version number and exit
  5.   -h, --help            show this help message and exit
  6.   -D ID, --device=ID    connect to device with the given ID
  7.   -U, --usb             connect to USB device
  8.   -R, --remote          connect to remote frida-server
  9.   -H HOST, --host=HOST  connect to remote frida-server on HOST
  10.   -a, --applications    list only applications
  11.   -i, --installed       include all installed applications
复制代码
下面这几个参数是比较重要,使用最多的:
--version 显示版本号。
-D 指定需要连接的设备 UDID,在多个设备连接时才会用到,如果只有一个设备不必用它。
-U 连接 USB 设备。
-a 只显示正在运行的应用。
-i 显示所有已安装的应用。
接下来我们看看实际操作 frida-ps 几个用法:
(1) 查看进程 USB 设备的进程,这里查看到的是所有正在运行的进程,包括 Daemon(守护程序)。
  1. $ frida-ps -U
  2. PID  Name
  3. ---  --------------------------------------------------------
  4. 1087  Cydia
  5. 647  doubleH3lix
  6. 229  ReportCrash
  7. 39  wifid
  8. ......
复制代码
还可以使用 grep 进行过滤,比如只需要查看 Cydia。
  1. $ frida-ps -U | grep Cydia
  2. 1087  Cydia
复制代码
(2) 查看正在运行的应用。
  1. $ frida-ps -U -a
  2. PID  Name         Identifier               
  3. ----  -----------  -------------------------
  4. 1161  App Store    com.apple.AppStore      
  5. 1087  Cydia        com.saurik.Cydia         
  6. 1167  Safari       com.apple.mobilesafari   
  7. ......
复制代码
(3) 查看所有安装的应用。
  1. frida-ps -U -a -i
  2. PID  Name             Identifier                     
  3. ----  ---------------  -------------------------------
  4. 1161  App Store        com.apple.AppStore            
  5. 1087  Cydia            com.saurik.Cydia               
  6. 1167  Safari           com.apple.mobilesafari            
  7. 1163  电话               com.apple.mobilephone                  
  8.    -  QQ               com.tencent.mqq               
  9.    -  邮件               com.apple.mobilemail                     
  10.    -  音乐               com.apple.Music               
  11. ......
复制代码
(4) 如果有多个设备时,可以指定查看某个设备的进程。
  1. frida-ps -D cca1b9055ac2684999cd81e525ac03fe6028b9f9 -a -i
复制代码
3. frida-kill
frida-kill 用于结束进程,需要指定应用名称或 PID,比如结束 App Store 进程
  1. frida-kill -U "App Store"
复制代码
如果 App Store 进程的 PID 是 1161
  1. frida-kill -U 1161
复制代码
4. frida-trace
frida-trace 用于跟踪函数或者 Objective-C 方法的调用,frida-trace -h 能够查看它的帮助,最重要的有下面几个参数:
-i 跟踪某个函数,-x 排除某个函数。
-m 跟踪某个 Objective-C 方法,-M 排除某个 Objective-C 方法。
-a 跟踪某一个地址,需要指名模块的名称。
接下来实际操作一下,比如需要跟踪 Cydia 点击关于的操作,输入以下命令,它会在当前目录下生成一个 handlers 目录,然后再生成一个 HomeController_aboutButtonClicked.js 文件,在 Cydia 点击关于时,会输出以下信息,按 Ctrl-C 可以停止跟踪。
  1. $ frida-trace -U -m "-[HomeController aboutButtonClicked]" Cydia
  2. Instrumenting functions...                                             
  3. -[HomeController aboutButtonClicked]: Loaded handler at "/Users/exchen/__handlers__/__HomeController_aboutButtonClicked_.js"
  4. Started tracing 1 function. Press Ctrl+C to stop.                       
  5.            /* TID 0x403 */
  6. 91314 ms  -[HomeController aboutButtonClicked]
复制代码
打开 HomeController_aboutButtonClock.js 文件,会看到有两个函数,onEnter 是进入该函数时会执行的代码,onLeave 是该函数执行完离开时会执行的代码,在相应的位置添加 Thread.backrace 这句代码可以打印出调用栈。
  1. {
  2.   onEnter: function (log, args, state) {
  3.     log("-[HomeController aboutButtonClicked]");
  4.     log('\tBacktrace:\n\t' + Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n\t'));
  5.   },

  6.   onLeave: function (log, retval, state) {
  7.   }
  8. }
复制代码
再次执行 frida-trace, HomeController_aboutButtonClicked.js 不会覆盖,会调用刚才我们添加好的代码,打印调用栈信息如下:
  1. $ frida-trace -U -m "-[HomeController aboutButtonClicked]" Cydia
  2. Instrumenting functions...                                             
  3. -[HomeController aboutButtonClicked]: Loaded handler at "/Users/exchen/Cydia/__handlers__/__HomeController_aboutButtonClicked_.js"
  4. Started tracing 1 function. Press Ctrl+C to stop.                       
  5.            /* TID 0x403 */
  6.   6701 ms  -[HomeController aboutButtonClicked]
  7.   6701 ms    Backtrace:
  8.   0x19145dc54 UIKit!-[UIApplication sendAction:to:from:forEvent:]
  9.   0x1915ce22c UIKit!-[UIBarButtonItem(UIInternal) _sendAction:withEvent:]
  10.   0x19145dc54 UIKit!-[UIApplication sendAction:to:from:forEvent:]
  11.   0x19145dbd4 UIKit!-[UIControl sendAction:to:forEvent:]
  12.   0x191448148 UIKit!-[UIControl _sendActionsForEvents:withEvent:]
  13.   0x1914482b0 UIKit!-[UIControl _sendActionsForEvents:withEvent:]
  14.   0x19145d4b8 UIKit!-[UIControl touchesEnded:withEvent:]
  15.   0x19145cfd4 UIKit!-[UIWindow _sendTouchesForEvent:]
  16.   0x19145836c UIKit!-[UIWindow sendEvent:]
  17.   0x191428f80 UIKit!-[UIApplication sendEvent:]
  18.   0x191c22a20 UIKit!__dispatchPreprocessedEventFromEventQueue
  19.   0x191c1d17c UIKit!__handleEventQueue
  20.   0x191c1d5a8 UIKit!__handleHIDEventFetcherDrain
  21.   0x18b2a542c CoreFoundation!__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
  22.   0x18b2a4d9c CoreFoundation!__CFRunLoopDoSources0
  23.   0x18b2a29a8 CoreFoundation!__CFRunLoopRun
复制代码
frida-trace 可以支持通配符,比如我们想跟踪 Home 开头的类,方法名是任意的,可以执行下面的命令:
  1. $ frida-trace -U -m "-[Home* *]" Cydia
  2. Instrumenting functions...                                             
  3. -[HomeController navigationURL]: Loaded handler at "/Users/exchen/__handlers__/__HomeController_navigationURL_.js"
  4. -[HomeController aboutButtonClicked]: Loaded handler at "/Users/exchen/__handlers__/__HomeController_aboutButtonClicked_.js"
  5. -[HomeController init]: Loaded handler at "/Users/exchen/__handlers__/__HomeController_init_.js"
  6. -[HomeController dealloc]: Loaded handler at "/Users/exchen/__handlers__/__HomeController_dealloc_.js"
  7. -[HomeController leftButton]: Loaded handler at "/Users/exchen/__handlers__/__HomeController_leftButton_.js"
  8. Started tracing 5 functions. Press Ctrl+C to stop.                     
  9.            /* TID 0x403 */
  10. 20323 ms  -[HomeController aboutButtonClicked]
  11. 22986 ms  -[HomeController navigationURL]
复制代码
跟踪函数实例
在上面我们简单地了解 frida-trace 的使用,趁热打铁,我们来做一个实例。很多应用在登录时都会加密数据,我们的目标是获取某个应用的 AES 加密的原文和密钥。AES 加解密一般会调用 CCCrypt 这个函数,该函数原型如下:
  1. CCCryptorStatus CCCrypt(
  2.   CCOperation op, //kCCEncrypt为加密,kCCDecrypt为解密
  3.   CCAlgorithm alg, //加密方式 kCCAlgorithmAES128为AES加密
  4.   CCOptions options, //增充方式
  5.   const void *key,   //密钥
  6.   size_t keyLength,  //密钥长度
  7.   const void *iv,    // IV
  8.   const void *dataIn, //待加密的原文
  9.   size_t dataInLength, //原文长度
  10.   void *dataOut,       //加密后输出的数据
  11.   size_t dataOutAvailable,  
  12.   size_t *dataOutMoved)
复制代码
尝试对 CCCrypt 进行跟踪,命令如下:
  1. $ frida-trace -U -i CCCrypt xxx
  2. Instrumenting functions...                                             
  3. CCCrypt: Auto-generated handler at "/Users/exchen/xxx/__handlers__/xxx/CCCrypt.js"
  4. Started tracing 1 function. Press Ctrl+C to stop.                       
  5.            /* TID 0x1f917 */
  6. 56944 ms  CCCrypt(op=0x1, alg=0x0, options=0x3, key=0x170a5e2a0, keyLength=0x10, iv=0x0, dataIn=0x2826e5830, dataInLength=0x20, dataOut=0x2826e5200, dataOutAvailable=0x30, dataOutMoved=0x170a5e290)
复制代码
在 CCCrypt.js 里添加以下代码:
  1. {
  2.   onEnter: function (log, args, state) {
  3.     log("CCCrypt(" +
  4.       "op=" + args[0] +
  5.       ", alg=" + args[1] +
  6.       ", options=" + args[2] +
  7.       ", key=" + args[3] +
  8.       ", keyLength=" + args[4] +
  9.       ", iv=" + args[5] +
  10.       ", dataIn=" + args[6] +
  11.       ", dataInLength=" + args[7] +
  12.       ", dataOut=" + args[8] +
  13.       ", dataOutAvailable=" + args[9] +
  14.       ", dataOutMoved=" + args[10] +
  15.     ")");

  16.     //保存参数
  17.     this.operation   = args[0]
  18.     this.CCAlgorithm = args[1]
  19.     this.CCOptions   = args[2]
  20.     this.keyBytes    = args[3]
  21.     this.keyLength   = args[4]
  22.     this.ivBuffer    = args[5]
  23.     this.inBuffer    = args[6]
  24.     this.inLength    = args[7]
  25.     this.outBuffer   = args[8]
  26.     this.outLength   = args[9]
  27.     this.outCountPtr = args[10]

  28.   //this.operation == 0 代表是加密
  29.     if (this.operation == 0) {
  30.       //打印加密前的原文
  31.         console.log("In buffer:")
  32.         console.log(hexdump(ptr(this.inBuffer), {
  33.             length: this.inLength.toInt32(),
  34.             header: true,
  35.             ansi: true
  36.         }))
  37.         //打印密钥
  38.         console.log("Key: ")
  39.         console.log(hexdump(ptr(this.keyBytes), {
  40.             length: this.keyLength.toInt32(),
  41.             header: true,
  42.             ansi: true
  43.         }))
  44.         //打印 IV
  45.         console.log("IV: ")
  46.         console.log(hexdump(ptr(this.ivBuffer), {
  47.             length: this.keyLength.toInt32(),
  48.             header: true,
  49.             ansi: true
  50.         }))
  51.     }
  52.   },
  53.   onLeave: function (log, retval, state) {
  54.   }
  55. }
复制代码
再次执行 frida-trace 跟踪,在登录时可以发现原文、密钥,IV 都打印出来了,一目了然。
  1. $ frida-trace -U -i CCCrypt xxx
  2. Instrumenting functions...                                             
  3. CCCrypt: Loaded handler at "/Users/exchen/xxx/__handlers__/xxx/CCCrypt.js"
  4. Started tracing 1 function. Press Ctrl+C to stop.                       
  5. In buffer:
  6.             0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
  7. 10acea400  7B 22 75 73 65 72 69 64 22 3A 22 31 37 37 36 35  {"userid":"17765
  8. 10acea410  34 33 22 2C 22 70 61 73 73 77 6F 64 22 3A 22 65  43","passwod":"e
  9. 10acea420  31 30 61 64 63 33 39 34 39 62 61 35 39 61 62 62  10adc3949ba59abb
  10. 10acea430  65 35 36 65 30 35 37 66 32 30 66 38 38 33 65 22  e56e057f20f883e"
  11. 10acea440  7D                                               }
  12. Key:
  13.             0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
  14. 16fb969e0  39 36 65 37 39 32 31 38 39 36 35 65 62 37 32 63  96e79218965eb72c

  15. IV:
  16.             0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
  17. 16fb969c0  39 32 61 35 34 39 64 64 35 61 33 33 30 31 31 32  92a549dd5a330112
复制代码
通过一个实例我们见证到 Frida 的强大,不需要编译代码,所有的操作都是编写脚本语言进行的,区区十几行 JavaScript 脚本代码即可轻松获取 AES 加密的密钥和相关参数。试想如果没有 Frida,我们的分析方法可能是编写动态库注入,对 CCCrypt 进行 Hook,然后打印相关的参数,或者是使用 LLDB 连接程序给 CCCrypt 添加断点,这些方法都不如使用 Frida 跟踪函数功能的效率高。
Frida 官网:https://frida.re,Frida 源码:https://github.com/frida

想了解最新的iOS安全资讯、技术干货请关注 iOS安全论坛(ioshacker.net)微信公众号
回复

使用道具 举报

1

主题

9

帖子

378

积分

中级会员

Rank: 3Rank: 3

积分
378
发表于 2020-4-8 10:31:15 | 显示全部楼层
顶,学习了。
回复

使用道具 举报

7

主题

56

帖子

285

积分

中级会员

Rank: 3Rank: 3

积分
285
发表于 2020-4-8 13:41:27 | 显示全部楼层
学习了,收藏
回复

使用道具 举报

6

主题

26

帖子

292

积分

中级会员

Rank: 3Rank: 3

积分
292
发表于 2020-4-8 19:10:47 | 显示全部楼层
66666666666666666666
回复

使用道具 举报

0

主题

1

帖子

14

积分

新手上路

Rank: 1

积分
14
发表于 2021-12-4 17:59:10 | 显示全部楼层
本帖最后由 billy3422022 于 2021-12-4 18:08 编辑

hi, 楼主,我用 macOS 10.15.7, 调试 iPhone 6S plus,12.5,frida-ls-devices 和 frida-ps 都正常。但用这条命令的时候
$ frida-trace -U -m "-[HomeController aboutButtonClicked]" Cydia 不成功,返回的信息也不一样
不打开 Cydia 是这种
Failed to attach: need Gadget to attach on jailed iOS; its default location is: /Users/mac/.cache/frida/gadget-ios.dylib
打开 Cydia 开始是这种
Failed to spawn: ambiguous name; it matches: Cydia (pid: 1994), Cydia (pid: 1997), Cydia (pid: 1981), Cydia (pid: 1993), Cydia (pid: 1996), Cydia (pid: 1999), Cydia (pid: 1992), Cydia (pid: 1995), Cydia (pid: 1998)
打开市场长了是这种
Failed to attach: need Gadget to attach on jailed iOS; its default location is: /Users/mac/.cache/frida/gadget-ios.dylib
我找了一下,iPhone 下面确认没有 gadget-ios.dylib。是 Cydia 下安装的 frida 不够完整还是什么其它原因?
已解决,谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|iOSHacker

GMT+8, 2022-8-15 14:37 , Processed in 0.022191 second(s), 19 queries .

iOS安全论坛

© 2017-2020 iOS Hacker Inc. 京ICP备17074153号-2

快速回复 返回顶部 返回列表