参考书籍:《iOS应用逆向工程 分析与实战》(沙梓社,吴航)
参考书籍:《iOS应用逆向工程(第2版)》(沙梓社,吴航)
在分析iOS应用程序的时候,经常会用到Cycript这个工具,基本使用方法这里就不在啰嗦了,直接使用它从UI层面来定位目标函数:
查看当前界面UI层次结构
UIview中的私有函数recursiveDescription可以返回这个view的UI层次结构,一般来说,当前界面是由至少一个UIWindow构成的,而UIWindow继承自UIView,因此可以利用这个私有函数查看当前界面UI层次结构.用法如下:
cycript -p APP
cy# ?expand
(首先执行Cycript的?expand命令开启expand功能,翻译格式符号,提高可读性,接着:)
cy# [[UIApp keyWindow] recursiveDescription]
UIApp是[UIApplication sharedApplication]的简写调用上面的方法即可打印keyWindow的视图结构.
*执行 cy#[UIApp windows] 可以拿到app所有window
*执行 cy#[#viewAddress subviews] 可以拿到当前控件的子控件
*执行 cy#[#viewAddress superviews] 可以拿到当前控件的父控件
*通过 cy#[#viewAddress setHidden:YES] 定位到相应的控件
找出控件(按钮)的UI函数
按钮的UI函数就是点击它之后的响应函数,给UIView对象加上响应函数,一般是通过[UIcontrol addTarget:action:forControlEvents:]实现的,而UIControl提供了一个sctionsForTarget:forControlEvent:方法,来获得这个UIControl的响应函数.具体操作如下:
对于UIButton
cy# button = #0x1479840
s”UIToolbarButton: 0x1479840; frame = …….>”
cy# [button allTargets]
[NSSet setWithArray:@[#”ComposeButtonItem: 0x14609d00>”]]
cy# [button allControlEvents]
64
cy# [button actionsForTarget:#0x14609d00 forControlEvent:64]
@[“_sendAction: withEvent: ]
因此,按下按钮就会调用 _sendAction: withEvent: 函数.
对于UITableviewCell
与刚才按钮不同的是,这次的目标不是cell的响应函数(功能),而是它上面显示的内容(数据),根据MVC的设计标准,能够利用已知的V,获得C,就可以进一步访问M了,也就是说对于一个V调用nextResponder,要么返回它对应的C,要么返回它的superview.具体操作很简单,从cell处开始调用nextResponder,一直到返回一个C为止,命令如下:
cy# [#0x124846 nextResponder]
基本使用方法。以SpringBoard为例
在mac上ssh登录手机,或者在手机上安装 Terminal ,找到SpringBoard进程
didi:~ root# ps -e | grep SpringBoard
1759 ?? 0:22.40 /System/Library/CoreServices/SpringBoard.app/SpringBoard
1835 ttys000 0:00.01 grep SpringBoard
获取到进程的id是 1759 ,然后用 cycript - p 命令注入这个进程
didi:~ root# cycript - p 1759
想要在SpringBoard界面弹出一个提示框,上节使用Tweak工程实现了这个功能,但用cycript的话,只要两句代码就可以了,而且是实时注入的。
cy# alertView = [[UIAlertView alloc] initWithTitle:@”test” message:@”liuchendi” delegate:nil cancelButtonTitle:@”OK” otherButtonTitles:nil]
s#UIAlertView: 0x18b6c8d0; frame = (0 0; 0 0); opaque = NO; layer = >”
cy# [alertView show]
不要声明类型,不需要输入分号。使用过程中还能打印一些生成的信息。
知道内存地址,获取对象
通过 # 获取对象,比如刚刚生成的UIAlertView对象的内存地址是 0x18b6c8d0
cy# [#0x18b6c8d0 show]
一样可以弹出提示框
知道一个类,获取内存地址
通过 choose 命令可以查看,这个命令不一定百发百中,如果没找到需要自己手动找。
cy# choose(SBScreenShotter)
[#”SBScreenShotter: 0x18bc25c0>”]
例子:获取私有函数,登录iMessage
获取iMessage的控制器
cy# controller = [CNFRegController controllerForServiceType:1]
“CNFRegController: 0x18e9f990>”
登录iMessage,这里屏蔽了敏感的信息.用自己的帐号密码登录
cy# [controller beginAccountSetupWithLogin:@”appID” password:@”appPassword” foundExisting:NO]
s#IMAccount: 0x18fcbab0 [ID: 89E8048D-183C-460D-9438-719738CBBC13 Service: IMService[iMessage] Login: E:appID Active: YES LoginStatus: Connected]”
这里返回了一个 IMAccount 对象
选择收发的邮件地址
cy# [controller setAliases:@[@”[email protected]”] onAccount:#0x18fcbab0]
1
返回值为1表示成功登录了iMessage