内容简介:最近在学习iOS逆向,就顺手拿个App练练手,顺便分享一下。
一、前言
最近在学习iOS逆向,就顺手拿个App练练手,顺便分享一下。
二、准备
本文使用皮皮搞笑 1.5.5 iOS 版本为例,逆向分析关注功能。
工具: IDA 7.0、Reveal 21(11690)、Cycript、lldb、Charles
环境:i Phone6 IOS 9.1、Macos Mojave 10.14.5
三、界面分析
通过分析App UI界面为突破口,来进行逆向分析。
打开App后,如下图,可以看到一个关注按钮,通过点击按钮,可以实现关注该用户动态。
通过抓包分析,点击关注按钮时,会发送add?sign=xxxxxx数据包,想要分析数据来源,可以从界面上的关注按钮着手。
为了更直观分析,这里使用Reveal神器来分析UI界面,在使用 Reveal 前要在手机设置 > Reveal->Enabled Applications 里面打开需要分析的 App。
配置好 Reveal 后,在手机上打开需要分析的 App 界面,再在笔记本上打开 Reveal 工具,Reveal 支持 USB 和网络连接两种方式,一般选择USB。
打开 Reveal 后,如下图,可以看到 AppUI 应用结构层级。
通过分析 AppUI 应用结构层级,可以明显看到红色关注按钮,直接点击按钮,可以看到的确是一个 UIButton ,内存地址 0x143883f80 ,视图控制器 Class 为 LJJUSerProfileVC ,内存地址 0x140abb400 。
为了验证数据是否正确,使用 Cycript (动态调式工具),来获取运行时信息。
使用SSH登录 iPhone ,执行命令 crcript -p pi d 或进程名。
Davinde-iPhone:/var root# cycript -p PPSocial cy# #0x143883f80 #"<UIButton: 0x143883f80; frame = (270 29; 50 26); alpha = 0; opaque = NO; layer = <CALayer: 0x1438a4cc0>>"
通过以上信息可以判断, 0x143883f80 的确是 UIButton 按钮的地址,如果不确定,可以通过调用 hidden 方法,并且观察app对应的按钮是否有变化。
cy# #0x143883f80.hidden=YES //隐藏按钮 true cy# #0x143883f80.hidden=NO //显示按钮 false
光知道 UiButto n 内存地址好像没有用,如何得到 UiBtton 的点击事件的所调用函数呢?通过 cycript 脚可以来遍历。
@import mycript //导入mycript 脚本 cy# MyBtnTouchUpEvent(#0x143883f80) [@["followClick"]]
下面是 MyBtnTouchUpEvent 代码,获取该 Button 对象所有的 Target 对象,并将事件相关所有 A ction 遍历输出,顺提一下, Action 可能有多个。
// 获取按钮绑定的所有TouchUpInside事件的方法名 MyBtnTouchUpEvent = function(btn) { var events = []; var allTargets = btn.allTargets().allObjects() var count = allTargets.count; for (var i = count - 1; i >= 0; i--) { if (btn != allTargets[i]) { var e = [btn actionsForTarget:allTargets[i] forControlEvent:UIControlEventTouchUpInside]; events.push(e); } } return events; };
通过 MyBtnTouchUpEvent 得到 followClick 方法,需要测试下这个方法是否正确,通过调用 LJJUSerProfileVC 控制器的 followClick 方法来测试一下 :
cy# [#0x140abb400 followClick] //#0x140abb400为LJJUSerProfileVC对象
通过反复 [#0x140abb400 followClick] 方法调用,可以实现手动点击关注效果,现在可以确定 LJJUSerProfileVC followClick 就是关注按钮的 Action方法。
四、静态分析
接下来对 App 进行脱壳。再使用 IDA 加载脱壳后的 Mach-o 文件,恢复App符号表可参考( http://blog.imjun.net/posts/restore-symbol-of-iOS-app/ )。
为了方便查看,使用 F5 后的伪代码来进行观察。
LJJUSerProfileVC followClick 又调用了 LJJUSerProfileVC followClick]_block 函数。
因为函数调用较多,就不一一贴图了,经过分析,以下为主要函数调用流程:
LJJUSerProfileVC followClick LJJUSerProfileVC attention: LJJAttentionManager userAttentionOther:isAttened:from:success:failure: ZYAPIClient postWithPath:parameters:userInfo:progress:success:retry:failure: ZYAPIClient postWithURL:parameters:userInfo:progress:success:retry:failure: ZYURLManager requestHeaderDictionaryWithParameters: ZYCrypto signWithParameters:
分析过程中发现比较重要的函数是 ZYURLManager requestHeaderDictionaryWithParameters: 和 ZYCrypto signWithParameters:
ZYURLManager requestHeaderDictionaryWithParameters :主要功能就是 h_model,u_id,h_ch,h_app,h_ts,token 等字段进行填充,其中h_ts为时间戳。
以下是 ZYURLManager requestHeaderDictionaryWithParameters :部分伪代码:
ZYAPIClient signWithParameters :从名字可以看出是对参数进行签名的,里面调用了- ZYCrypto signWithParameters :
进入 -ZYCrypto signWithParameters :函数
从调用图可以看出 sub_100200C40 又调用了 sub_1002003C4 和 sub_100200BB 0 函数。
sub_100200C40 流程图:
放大后更清楚:
上图中,其中蓝小方块为调用 sub_1002003C4 和 sub_100200BB0 函数,是整个函数必经之路。
sub_1002003C4 流程图
sub_1002003C4 部分伪代码
我们知道md5算法中需要 0x67452301 0xefcdab89 0x98badcfe 0x10325476 数据做为初始值,以分组为单位进行处理,分别对每一块信息块进行MD5计算,每次计算4轮,每轮16次计算。
根据以上信息可以推断 sub_1002003C4 md5 算法或其变形,不过还需要进一步分析才能确定。
sub_100200BB0 伪代码
LJJUSerProfileVC followClick LJJUSerProfileVC attention: LJJAttentionManager userAttentionOther:isAttened:from:success:failure: ZYAPIClient postWithPath:parameters:userInfo:progress:success:retry:failure: ZYAPIClient postWithURL:parameters:userInfo:progress:success:retry:failure: ZYURLManager requestHeaderDictionaryWithParameters: ZYCrypto signWithParameters: -ZYCrypto signWithParameters: sub_100200C40 sub_1002003C4 sub_100200BB0
小结一下
ZYURLManager requestHeaderDictionaryWithParameters :将需要提交的数据进行字段进行填充,大部分都是都是固定字段的如 h_model,u_id,h_ch,h_app,h_ts,token 等字段,这里就不做详细分析。
ZYCrypto signWithParameters 调用 sub_100200C40 函数将数据进行签名。
五、动态调试
为了验证推测是否正确,需要对App进行动态调试。
iphone ssh 登录,开启 debugserver 。
Davinde-iPhone:~ root# debugserver *:10011 -a PPSocial debugserver-@(#)PROGRAM:debugserver PROJECT:debugserver-340.3.51.1 for arm64. Attaching to process PPSocial... Listening to port 10011 for a connection from *... Waiting for debugger instructions for process 0.
mac lldb 附加
process connect connect://192.168.31.199:10011
获取 ASLR 偏移
(lldb) image list -o -f PPSocial [ 0] 0x0000000000024000 /var/mobile/Containers/Bundle/Application/C3170E24-F5A3-4FD8-AB42-532DA856722E/PPSocial.app/PPSocial(0x0000000100024000)
函数的内存地址 (VM Address ) = File Offset + ASLR Offset IDA 中的地址是未使用ASLR的 VM Address 。
对关键的函数下断点,查看其参数和返回值。
sub_1002003C4 函数头地址为 0x100200c40 + 0x24000 = 0x100224c40 。
(lldb) br s -a 0x100224c40 Breakpoint 1: where = PPSocial`_mh_execute_header + 2079508, address = 0x0000000100224c40
成功下断后,运行App,点击关注。
Process 1457 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x0000000100224c40 PPSocial`_mh_execute_header + 2100288 PPSocial`_mh_execute_header: -> 0x100224c40 <+2100288>: sub sp, sp, #0x90 ; =0x90 0x100224c44 <+2100292>: stp x22, x21, [sp, #0x60] 0x100224c48 <+2100296>: stp x20, x19, [sp, #0x70] 0x100224c4c <+2100300>: stp x29, x30, [sp, #0x80] (lldb) memory read $x0 $x0+400 0x12876f268: 7b 22 68 5f 6d 6f 64 65 6c 22 3a 22 69 50 68 6f {"h_model":"iPho 0x12876f278: 6e 65 20 36 22 2c 22 68 5f 63 68 22 3a 22 61 70 ne 6","h_ch":"ap 0x12876f288: 70 73 74 6f 72 65 22 2c 22 75 69 64 22 3a 39 37 pstore","uid":97 0x12876f298: 35 31 37 32 39 30 2c 22 68 5f 61 70 70 22 3a 22 517290,"h_app":" 0x12876f2a8: 7a 75 69 79 6f 75 5f 6c 69 74 65 22 2c 22 68 5f zuiyou_lite","h_ 0x12876f2b8: 74 73 22 3a 31 35 35 38 39 36 36 35 30 31 35 36 ts":155896650156 0x12876f2c8: 34 2c 22 68 5f 61 76 22 3a 22 34 2e 35 2e 35 22 4,"h_av":"4.5.5" 0x12876f2d8: 2c 22 68 5f 6e 74 22 3a 31 2c 22 68 5f 64 69 64 ,"h_nt":1,"h_did 0x12876f2e8: 22 3a 22 64 38 30 36 62 65 35 35 34 61 61 31 34 ":"d806be554aa14 0x12876f2f8: 34 63 34 37 34 64 30 35 61 63 38 61 37 66 35 36 4c474d05ac8a7f56 0x12876f308: 64 63 31 22 2c 22 68 5f 6d 22 3a 31 36 37 31 33 dc1","h_m":16713 0x12876f318: 35 32 34 39 2c 22 68 5f 70 69 70 69 22 3a 22 31 5249,"h_pipi":"1 0x12876f328: 2e 35 2e 35 22 2c 22 64 69 64 22 3a 22 64 38 30 .5.5","did":"d80 0x12876f338: 36 62 65 35 35 34 61 61 31 34 34 63 34 37 34 64 6be554aa144c474d 0x12876f348: 30 35 61 63 38 61 37 66 35 36 64 63 31 22 2c 22 05ac8a7f56dc1"," 0x12876f358: 68 5f 6f 73 22 3a 39 31 30 30 30 30 2c 22 74 6f h_os":910000,"to 0x12876f368: 6b 65 6e 22 3a 22 54 30 4b 35 4e 6a 64 75 79 53 ken":"T0K5NjduyS 0x12876f378: 39 39 69 42 61 72 47 71 56 4c 52 62 52 51 74 68 99iBarGqVLRbRQth 0x12876f388: 78 37 63 4b 45 77 46 6e 4b 5f 45 6a 45 54 6a 7a x7cKEwFnK_EjETjz 0x12876f398: 5f 58 62 53 65 54 71 58 73 61 6d 68 45 79 61 46 _XbSeTqXsamhEyaF 0x12876f3a8: 74 48 4e 77 4c 6b 75 36 42 55 39 22 2c 22 68 5f tHNwLku6BU9","h_ 0x12876f3b8: 64 74 22 3a 31 7d 00 00 00 00 00 00 00 00 00 e0 dt":1}.........� 0x12876f3c8: 00 00 00 00 00 00 00 e0 08 00 ff ff f5 01 00 00 .......�..���... 0x12876f3d8: f5 01 00 00 f5 01 00 00 f5 01 00 00 61 00 00 00 �...�...�...a... 0x12876f3e8: 00 00 00 00 62 00 00 00 70 b5 0d 28 01 00 00 00 ....b...p�.(.... (lldb)
查看参数可以看到就是post字符串数据。接下来再分析 sub_1002003c4 参数和返回值。
分别对 sub_1002003c4 入口和返回后地址下断:
(lldb) br s -a 0x100224e30 Breakpoint 2: where = PPSocial`_mh_execute_header + 2080004, address = 0x0000000100224e30 (lldb) br s -a 0x100224e34 Breakpoint 3: where = PPSocial`_mh_execute_header + 2080008, address = 0x0000000100224e34
sub_1002003c4 有三个参数分别为 x0,x1,x2。
-> 0x100224e30 <+2100784>: bl 0x1002243c4 ; PPSocial.__TEXT.__text + 2077336 0x100224e34 <+2100788>: sub x0, x29, #0x38 ; =0x38 0x100224e38 <+2100792>: mov x8, sp 0x100224e3c <+2100796>: bl 0x100224bb0 ; PPSocial.__TEXT.__text + 2079364 Target 0: (PPSocial) stopped. (lldb) register read General Purpose Registers: x0 = 0x0000000128773ef0 x1 = 0x0000000000000162 x2 = 0x000000016fdd8ef8 x3 = 0x0000000000000016 x4 = 0x0000000000000158 x5 = 0x0000000000000010 x6 = 0x0000000000000022 x7 = 0x000000016fdd8eb0 x8 = 0x0000000000000080
x0为字符串数据,x1字符串长度,x2传出参数,字符串头尾进行处理。
lldb) memory read $x0 $x0+$x1 0x128773ef0: 59 30 4d 54 42 6c 4f 44 63 78 3a 22 69 50 68 6f Y0MTBlODcx:"iPho 0x128773f00: 6e 65 20 36 22 2c 22 68 5f 63 68 22 3a 22 61 70 ne 6","h_ch":"ap 0x128773f10: 70 73 74 6f 72 65 22 2c 22 75 69 64 22 3a 39 37 pstore","uid":97 0x128773f20: 35 31 37 32 39 30 2c 22 68 5f 61 70 70 22 3a 22 517290,"h_app":" 0x128773f30: 7a 75 69 79 6f 75 5f 6c 69 74 65 22 2c 22 68 5f zuiyou_lite","h_ 0x128773f40: 74 73 22 3a 31 35 35 38 39 36 36 35 30 31 35 36 ts":155896650156 0x128773f50: 34 2c 22 68 5f 61 76 22 3a 22 34 2e 35 2e 35 22 4,"h_av":"4.5.5" 0x128773f60: 2c 22 68 5f 6e 74 22 3a 31 2c 22 68 5f 64 69 64 ,"h_nt":1,"h_did 0x128773f70: 22 3a 22 64 38 30 36 62 65 35 35 34 61 61 31 34 ":"d806be554aa14 0x128773f80: 34 63 34 37 34 64 30 35 61 63 38 61 37 66 35 36 4c474d05ac8a7f56 0x128773f90: 64 63 31 22 2c 22 68 5f 6d 22 3a 31 36 37 31 33 dc1","h_m":16713 0x128773fa0: 35 32 34 39 2c 22 68 5f 70 69 70 69 22 3a 22 31 5249,"h_pipi":"1 0x128773fb0: 2e 35 2e 35 22 2c 22 64 69 64 22 3a 22 64 38 30 .5.5","did":"d80 0x128773fc0: 36 62 65 35 35 34 61 61 31 34 34 63 34 37 34 64 6be554aa144c474d 0x128773fd0: 30 35 61 63 38 61 37 66 35 36 64 63 31 22 2c 22 05ac8a7f56dc1"," 0x128773fe0: 68 5f 6f 73 22 3a 39 31 30 30 30 30 2c 22 74 6f h_os":910000,"to 0x128773ff0: 6b 65 6e 22 3a 22 54 30 4b 35 4e 6a 64 75 79 53 ken":"T0K5NjduyS 0x128774000: 39 39 69 42 61 72 47 71 56 4c 52 62 52 51 74 68 99iBarGqVLRbRQth 0x128774010: 78 37 63 4b 45 77 46 6e 4b 5f 45 6a 45 54 6a 7a x7cKEwFnK_EjETjz 0x128774020: 5f 58 62 53 65 54 71 58 73 61 6d 68 45 79 61 46 _XbSeTqXsamhEyaF 0x128774030: 74 48 4e 77 4c 6b 75 36 42 55 39 22 2c 22 68 5f tHNwLku6BU9","h_ 0x128774040: 64 74 22 3a 31 7d 5a 44 7b 22 68 5f 6d 6f 64 65 dt":1}ZD{"h_mode 0x128774050: 6c 22
按c 继续,查看 sub_1002003c4 返回值。
(lldb) c Process 1457 resuming Process 1457 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1 frame #0: 0x0000000100224e34 PPSocial`_mh_execute_header + 2100788 PPSocial`_mh_execute_header: -> 0x100224e34 <+2100788>: sub x0, x29, #0x38 ; =0x38 0x100224e38 <+2100792>: mov x8, sp 0x100224e3c <+2100796>: bl 0x100224bb0 ; PPSocial.__TEXT.__text + 2079364 0x100224e40 <+2100800>: ldrsb w20, [sp, #0x17] Target 0: (PPSocial) stopped. (lldb) memory read 0x000000016fdd8ef8 0x16fdd8ef8: 27 dd a1 ce 26 ed 16 f3 00 d5 51 93 5c 4c 10 a4 'ݡ�&�.�.�Q.\L.� 0x16fdd8f08: 76 8e 2b 21 e1 de 00 eb e8 90 dd 6f 01 00 00 00 v.+!��.��.�o....
经过抓包分析对比这个就是返回的签名数据。
六、代码还原
直接将伪代码稍微修改就可以使用,以下是关键代码。由于代码过长,请点击“阅读原文”查看。
- End -
看雪ID: 轩野
https://bbs.pediy.com/user-573745.htm
本文由看雪论坛 轩野 原创
转载请注明来自看雪社区
热门图书推荐
戳 立即购买!
:warning: 注意
2019 看雪安全开发者峰会门票正在热售中!
长按识别下方 二维码 , 即可享受 2.5折 优惠!
公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com
↙ 点击下方“阅读原文”,查看更多干货
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 「小程序JAVA实战」小程序的关注功能(64)
- 需要关注的5种预测性存储分析功能
- 别光顾着新系统,这些功能改进更值得你在 WWDC 上关注
- 巡云轻论坛系统 3.3 发布,增加话题点赞和关注用户功能
- 代码审查关注什么:性能
- 关注程序异常流
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。