在iOS的逆向开发中cycript与Reveal是不可缺少的分析第三方app的利器,利用它们可以很快的定位到UI,找到对应的控制器,进而缩小了代码的区域。最近实用lldb进行调试,发现lldb也可以达到类似的效果。
首先需要在非越狱设备调试任意第三方app参考这篇文章
这边还是以微信作为例子:
这边要达到的效果是找到登录按钮所在内存地址,并且找到所属控制器,修改登录按钮的文字。开始吧!
开始之前先简单介绍一下lldb常用命令,p & po — 打印变量或者对象
因为LLDB支持前缀匹配,因此你可以将print简写为p或者pri,而print则代表expression –;po则代表expression -O –,意为print object,打印对象。输入p指令可打印其对象类型、内存地址以及该对象的值等具体信息,而po指令则是打印其调用description方法得到的值。
(注:打印集合类型对象时,p指令会省略具体的值,只提示集合的数量等信息,因此若需查看集合中的值应使用 po指令,如下图所示:)
expression
expression命令的作用是执行一个表达式,并将表达式返回的结果输出。expression的完整语法是这样的:
|
|
:命令选项,一般情况下使用默认的即可,不需要特别标明。
–: 命令选项结束符,表示所有的命令选项已经设置完毕,如果没有命令选项,–可以省略
: 要执行的表达式
说expression是LLDB里面最重要的命令都不为过。因为他能实现2个功能。
我们在代码运行过程中,可以通过执行某个表达式来动态改变程序运行的轨迹。
假如我们在运行过程中,突然想把self.view颜色改成红色,看看效果。我们不必写下代码,重新run,只需暂停程序,用expression改变颜色,再刷新一下界面,就能看到效果
|
|
也就是说我们可以通过expression来打印东西。
假如我们想打印self.view:
|
|
命令就介绍这个几个有用到的,其他的可以自行百度,下面就来调试吧!
以上两张截图中其实已经包含了很多的我们想要的信息,包括UI的布局结构,层次,每个UIView对应的内容地址,以及父控件或容器.选中一下登录按钮,你回发现xcode右边的调试界面中如下内容:
包含了很多有用的信息,包括按钮的类名,内存地址以及Action和Target等
这样的话可以通过调用UIButton的nextResponder方法一直找到其所在的控制器,怎么去调用这个方法?,这时候lldb的expression命令就派上用场了,(e 0x105651b50)登录按钮的内存地址,执行以下命令:
|
|
会打印出:
|
|
其中$188就代表登录按钮对象,当然你可以直接使用0x105651b50(即登录按钮对象),改变登录按钮的文字试试:
|
|
结果报错如下:
这是因为缺少UIKit库
e @import UIKit
引入UIKit库在试试,What??还是错!
这是因为$188只是代表登录按钮所在内存地址,lldb并不知道他是什么类型对象,试着把$188强转换类型:
由图可知是登录按钮FixTitleColorButton类型
|
|
这回没有报错,也没有提示任何信息,但是UI 界面中也没看到任何变化,试着刷新界面的命令:
|
|
命令执行后也没有任何任何输出,单步调试下一步:
|
|
执行后看看UI界面:
成功了,expression很强大,可以执行OC代码(和cycript一样,你可以通过方法recursiveDescription打印UIView结构,并且查看到每个UIView的相关信息),我们可以这样来定义一个变量
:
###找出登录按钮所在控制器,利用nextResponder方法
12345678 (lldb) po [$loginButton nextResponder]<UIView: 0x15dd0e080; frame = (0 582; 375 65); autoresize = W+TM; layer = <CALayer: 0x174039640>>(lldb) po [(UIView *)0x15dd0e080 nextResponder]<UIView: 0x15de27410; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x17022f760>>(lldb) po [(UIView *)0x15de27410 nextResponder]<WCAccountLoginFirstViewController: 0x15e80dc00>