对了 LLDB 有了一些认识之后,也能够更好的使用 LLDB
了,但是对于常用的一些指令使用起来还是过于麻烦,为了更简单的使用 LLDB
就需要一些插件帮助了,下面就介绍一些 LLDB
插件的安装和使用。
1、Chisel 安装
这个是 FaceBook
提供给开发者的 LLDB
的插件,打开终端使用 brew install chisel
安装。
安装完成后,在家目录下找 .lldbinit
文件,如果没有就 touch .lldbinit
新建一个,然后 vi .lldbinit
添加 fblld.py
的路径(我的路径为 /usr/local/Cellar/chisel/1.8.1/libexec/fblldb.py
)。
添加 command script import /usr/local/Cellar/chisel/1.8.1/libexec/fblldb.py
,最后 ESC
,输入 :wq
保存并退出。
安装完成后,如果已经打开了 Xcode
,可以在 Xcode
的 LLDB
上输入 command source ~/.lldbinit
重新加载,也可以重新打开 Xcode
。
Xcode
新建工程,随意一个断点, 然后 lldb
输入 pviews self.view
指令,回车后打印了 self.view
的详细信息,就说明安装成功了。
Xcode 11 注意:
因为 Xcode 11
版本不支持 python 2
,所以如果控制台出现如下报错:
error: module importing failed: Missing parentheses in call to 'print'. Did you mean print('Whoops! You are missing the <' + arg.argName + '> argument.')? (fblldb.py, line 98)
请点此处下载最新的 Chisel
,终端执行下方指令(我当前的是 Chisel 1.8.1
) ,进入 1.8.1
,用新下载的文件替换 1.8.1
里面相同名称的文件即可解决。
cd /usr/local/Cellar/chisel
open .
2、Chisel 使用
启动一个项目,随意进入一个页面,然后暂停项目。
1、pviews 指令
pviews
:可以查看图层,能清楚的看到图层关系,是以字符串输出的,成树状结构,很清晰。
Xcode
下方 LLDB
输入 pviews
就能查看所有图层关系。

2、pvc 指令
pvc
:可以查看控制器的层级。

3、pactions 指令
paction
:可以打印一个按钮的所在的页面和它的点击事件方法。
当前页面上有一个 设置 按钮 。

打开 ViewDebug
,这个不管在正向和逆向中都可以看到按钮的指针地址,所以获取到 设置 按钮的指针地址为:0x7fce735209e0
。

LLDB
上输入:pactions 0x7fce735209e0
,就可以打印 设置 按钮的所在的页面和它的点击事件方法。

4、presponder 指令
presponder
:获取按钮的响应链。
LLDB
输入:presponder 0x7fce735209e0
当前响应链比较少,所以就直接打印了自己和系统的响应链了。

4、pclass 指令
pclass
:可以查看一个类的继承关系。
当前类为 RootNavigationController
、地址为 0x7fce7386c600
、LLDB
:pclass 0x7fce7386c600
回车,输出了继承树。

5、pmethods 指令
pmethods
:查看一个类的所有方法。

6、pinternals 指令
pinternals
:查看一个类的成员变量以及在当前内存中的值。

7、fvc、fv 指令
fvc
:使用一个 Controller
类名获取 Controller
类的在内存中的地址(不一定100%能获取到)。
LLDB
输入:fvc RootNavigationController
,显示如下:

fv
:使用一个 View
类名获取 View
类的在内存中的地址(不一定100%能获取到)。
8、taplog 指令
taplog
:断点一次可处理响应事件的 View
。
暂停程序,然后 Xcode
下方 LLDB
输入 :taplog
,发现断点过掉了,随意点一个 UIButton
然后进会进入断点。

8、flicker 指令
flicker
:会让当前地址的视图隐藏并显示(闪烁)一次。
比如上方获取到的 Button
, flicker 0x7ffc03438290
,这个 Button
就会闪烁一次。

9、vs 指令
vs
:可以查看图层的当前层级,下一个层级,上一个层级。
LLDB
上输入 :vs 0x7ffc03438290
就会发现,界面上按钮变为红色,LLDB
控制台打印了一些的指令信息。

-
(q) to quit.
:输入q
退出。 -
(w) move to superview
:输入w
移动到父View
。 -
(s) move to first subview
:输入s
移动到我当前子控件的第一个(subviews.firstObject
)。 -
(a) move to previous sibling
:输入a
移动到当前视图平级关系的前一个视图。 -
(d) move to next sibling
:输入d
移动到当前视图平级关系的后一个视图。 -
(p) print the hierarchy
:输入p
打印当前控件的层级关系。
3、lldb_commands 的安装
这也是一个功能比较强大的 LLDB
插件。点此处下载
安装方式如下:
To Install, copy/clone the lldb_commands folder to a dir of your choosing
Open up (or create) ~/.lldbinit
Add the following command to your ~/.lldbinit file: command script import /path/to/lldb_commands/dslldb.py
配置方式和 Chisel
一样,不过就是这个需要自己下载,个人建议可以把 lldb_commands
和 Chisel
放在一个路径下 /usr/local/Cellar/
下。
终端输入 vi ~/.lldbinit
,按 i
,再添加一条 command script import /usr/local/Cellar/lldb_commands/dslldb.py
,然后按 ESC
,在输入 :wq
保存退出。
Xcode
输入 command source ~/.lldbinit
导入一下。
4、lldb_commands 的使用
1、search 指令
search
:如果上方的 fvc
、fv
指令查找不到的话,可以使用 search
指令,比如:search UIView
:

2、sbt 指令
sbt
:逆向中是没有符号表的,所以给一个内存地址下断点后,使用并 bt
不能显示详细信息。但是 lldb_commands
就可以帮助恢复一些函数名称,但是不一定能恢复全部。
当前给 下一步 按钮添加断点,然后打印调用队栈。

当前按钮是在 WCAccountMainLoginViewController
上,Action
为 onNext
,使用 mehthods
查找 onNext
的指针地址,然后下断点。
-
search WCAccountMainLoginViewController
:获取WCAccountMainLoginViewController
在内存中的地址:0x11307ea00
-
methods 0x11307ea00
:获取WCAccountMainLoginViewController
的所有方法,查找onNext
的指针地址为0x108aab4cc
-
b -a 0x108aab4cc
:给onNext
方法下内存断点
(lldb) search WCAccountMainLoginViewController
<WCAccountMainLoginViewController: 0x11307ea00>
(lldb) methods 0x11307ea00
Instance Methods:
- (void) WCBaseInfoItemBeginEdit:(id)arg1; (0x108aac7bc)
- (void) WCBaseInfoItemEndEdit:(id)arg1; (0x108aac870)
- (void) WCBaseInfoItemPressReturnKey:(id)arg1; (0x108aad3f0)
- (void) WCBaseInfoItemEditChanged:(id)arg1; (0x108aac924)
- (void) initMoreView; (0x108aa9838)
- (void) setupWithData:(id)arg1; (0x108aa6e0c)
- (void) onNext; (0x108aab4cc)
(lldb) b -a 0x108aab4cc
Breakpoint 1: where = WeChat`___lldb_unnamed_symbol273847$$WeChat, address = 0x0000000108aab4cc
(lldb)
这样方法的内存断点就下好了,点击一下进入了一个断点。
LLDB
输入 bt
,因为没有符号文件表的关系,看不到函数名称。

然后使用 lldb_commands
的 sbt
指令,能恢复一些函数名称,看到了刚才的点击方法。

如果发现恢复的不是当前想要的,就只能重新运行,再次尝试恢复。
5、Cycript 的介绍
Cycript
是由 Cydia
创始人 Saurik
推出的一款脚本语言。Cycript
混合了 OC
、JavaScript
语法的解释器,这意味着我们能够在一个命令中使用 OC
或者 JavaScript
,甚至两者并用。它能够挂钩正在运行的进程,能够在运行时修改很多东西。
6、Cycript 的安装
首先点此处下载 Cycript
,下载完成后,建议放在 ~/opt
目录下面。打开目录,复制粘贴。
cd ~/opt
open .
接下来需要配置一下环境变量,以便于在任何地方使用。
可以配置在 .bash_profile
下(如果你使用的不是 bash
,那么你可以在你所使用的 Shell
下添加一句 source /Users/XXX(前面改成你的用户名,并删掉括号和括号里的更改描述)/.bash_profile
)。
然后 vi ~/.bash_profile
,在 export PATH="/opt/local/bin:/opt/local/sbin:$PATH"
前添加 export CYCRIPT=/opt/cycript_0.9.594/
(等号前面的命名可以随意,保证不重复就行,等号后面的就是你的 cycript
的路径) ,然后在 export PATH
:$PATH
前添加 :$CYCRIPT
名称就可以了。
然后 :wq
保存退出,iTerm
输入 :cycript
,回车出现了 cy#
,说明安装成功了。control D
退出。
注意,如果安装过程中出现如下报错:

解决方案:
iTerm
输入:cd /System/Library/Frameworks/Ruby.framework/Versions
,open .

7、MonkeyDev 的安装
因为要使用 Cycript
,在非越狱环境下,不能将 Cycript
注入手机,所以需要借助 MonkeyDev 注入 Framework
库来实现。
环境要求
使用工具前确保如下几点:
- 安装最新的theos
sudo git clone --recursive https://github.com/theos/theos.git /opt/theos
- 安装ldid(如安装theos过程安装了ldid,跳过)
brew install ldid
安装
你可以通过以下命令选择指定的Xcode进行安装:
sudo xcode-select -s /Applications/Xcode-beta.app
默认安装的Xcode为:
xcode-select -p
执行安装命令:
sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-install)"
卸载
sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-uninstall)"
更新
如果没有发布特殊说明,使用如下命令更新即可:
sudo /bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/AloneMonkey/MonkeyDev/master/bin/md-update)"
安装/更新之后重启下Xcode再新建项目。
8、Cycript 的使用
iTerm
输入 :cycript
,就开始使用 cycript
了。
1、简单的判断字符串
cy# "STRING" == "string"
false
2、简单的两数相加
cy# a = 100
100
cy# b = a + 10
110
3、Cycript 的准备工作
上面的2个仅仅是为了认识一下 Cycript
,我们使用 Cycript
是因为它的进程附加能力。
在逆向中,LLDB
虽然也非常好用,但是使用 LLDB
必须要把程序断点下来,有时候对程序的执行有一些影响,更改完一些东西需要过掉断点才能看到修改的结果,并不能及时的反馈给我们。
但是,Cycript
是动态调试程序的,不需要把程序断点下来,能及时的反馈修改的结果,这样就非常方便了。
接下来,尝试进程附加。因为上方说过要在非越狱环境下使用 Cycript
,需要借助 MonkeyDev 注入 Framework
库来实现。
所以打开 Xcode
使用 MonkeyDev
(在 Xcode
的最下方) 新建工程。
注意:MonkeyDev
工程目录中不能有中文路径,否则有问题,这个问题是 Theos
的问题,Theos
是外国人开发的,没有考虑中文情况。
首先运行一下空工程,然后把砸过壳的 xxx.app
或者 xxx.ipa
放入 TargetApp
目录下。再次运行工程,就能重签名 xxx.app
了。

MonkeyDev
帮我们把 Cycript.framework
注入了,查看 XxxDylib
文件夹下文件 XxxDylib.m
中有一行 CYListenServer(6666);
这个就是注入 Cycript
时的端口号。
打开 iPhone
-> 设置
-> 无线局域网
-> 点击当前正在使用的WiFi
-> 查看IP 地址
。
获取到的 IP 地址
为:192.168.50.49
。
注意: 电脑使用的 WiFi 和手机使用的 WiFi 必须是同一 WiFi,运行的 App
不要进入后台。
4、Cycript 的使用
接下来继续 iTerm
操作,如果在 cycript
下,先 control D
退出 cycript
,然后iTerm
输入:cycript -r 192.168.50.49:6666
回车就进入了 cycript
了。
1、keyWindow 的获取
想要获取当前的 keyWindow
:UIWindow.keyWindow()
就可以获取。
cy# UIWindow.keyWindow()
#"<iConsoleWindow: 0x10e45a9d0; baseClass = UIWindow; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x280f063a0>; layer = <UIWindowLayer: 0x28003ea80>>"
2、UIApplication 的获取
想要获取当前的 UIApplication
:[UIApplication sharedApplication]
或者 UIApp
就可以。
cy# [UIApplication sharedApplication]
#"<UIApplication: 0x10e41a1a0>"
cy# UIApp
#"<UIApplication: 0x10e41a1a0>"
3、变量的定义和使用
和 OC
的语法很像。当前需要定义一个变量 keyWindow
:var keyWindow = UIWindow.keyWindow()
,然后就可以使用 keyWindow
变量了。比如:获取 rootViewController
输入:keyWindow.rootViewController
。
可以使用 tab
进行语法补全,但是没有提示。
cy# var keyWindow = UIWindow.keyWindow()
#"<iConsoleWindow: 0x10e45a9d0; baseClass = UIWindow; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x280f063a0>; layer = <UIWindowLayer: 0x28003ea80>>"
cy# keyWindow
#"<iConsoleWindow: 0x10e45a9d0; baseClass = UIWindow; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x280f063a0>; layer = <UIWindowLayer: 0x28003ea80>>"
cy# keyWindow.rootViewController
#"<MMUINavigationController: 0x111921a00>"
4、# 的使用
在 cycript
上可以使用 #
跟上一个地址,相当于 LLDB
中 p
跟上一个地址的 功能,执行一个对象。比如:#0x111921a00
回车打印如下:

5、* 的使用
*
跟上一个定义的变量,比如上方的 var keyWindow = UIWindow.keyWindow()
,然后 *keyWindow
就会打印所有的成员变量。

6、recursiveDescription() 的使用
在 cycript
上想查看一个页面的 UI
层级,可以使用 keyWindow.recursiveDescription()
循环遍历层级并打印。如果想要格式化 keyWindow.recursiveDescription().toString()
。


7、choose 的使用
在 LLDB
上可以使用 fvc
、fv
、search
跟一个类名去查找对象,在 cycript
可以使用 choose
跟一个类名去查找对象,cycript
输入:choose(UIButton)
回车。

8、一些其他说明
在 cycript
下 只要我们的 App
不关闭(即所谓的进程不关闭),那刚才申请的 keyWindow
就会一直存在,退出了 App
就需要重新定义变量了。再次启动就不需要 Xcode
了,因为当前安装的 App
已经注入好了 Framework
,直接使用 cycript
即可。
5、使用脚本启动 Cycript
为了能够快速的使用 Cycript
,避免每次都输入繁琐的命令,就可以使用脚本辅助。
比如连接上方已经注入好 Cycript.framework
的其他 App
,把连接指令 cycript -r 192.168.50.49:6666
放入脚本 cylogin.sh
里,下次启动如果在IP 地址没有变化的情况下,直接输入 ./cylogin.sh
就可以了。
为了想能够在任何地方都可以使用这些脚本,就需要配置一下环境变量。
既然需要配置环境变量,那不如新建一个文件夹专为此服务,之后还可以给这个文件夹里添加更多脚本。
在家目录下创建一个文件夹 TCShell
(你可以在任何目录创建,叫任何名称,只要配置环境变量时,填写好你放的目录和名称即可),cd TCShell
,vi cylogin.sh
将上方的指令 cycript -r 192.168.50.49:6666
放入,然后保存退出。再 chomd 755 cylogin.sh
给 cylogin.sh
添加执行权限。

在配置环境变量前,验证一下 cylogin.sh
脚本是否正确。sh cylogin.sh
或者 ./cylogin.sh
如果进入了 Cycript
显示 cy#
说明我们配置好了。

接下来需要配置环境变量了(和第6条 Cycript 的安装 同理),vi ~/.bash_profile
打开,export
路径后保存退出。重启一下终端,这样就可以在任何地方使用 sh cylogin.sh
进入 Cycript
了。


6、Cycript 练习
微信登录页面有一个国家和地区选择,点击进入后,阿尔巴尼亚的编号是 +355
,现在把这个改成 +1008611
。
猜测+355
是一个 UILabel
,cy#
输入 choose(UILabel)
回车,commadn F
搜索 +355
,复制地址 0x110351910
,然后 #0x110351910.text = '+1008611';
回车就发现更改成功了。

tancheng@tanchengdeMacBook-Pro /~ : sh cylogin.sh
cy# choose(UILabel)
//...
cy# #0x110351910.text = '+1008611';
"+1008611"
cy#

注意:在重新进入这个页面发现又变成 +355
了,但是执行 #0x110351910
时,打印还是 '+1008611' 这是因为这个对象还没有完全销毁,所以如果页面变了,之前的地址就不要再次使用了。
9、Monkey Dev 中 CY 文件命令的使用
使用 Monkey Dev
注入的 Cycript
时候有一些指令还是很好用的。
-
APPID
: 获取 Bundle ID -
pviews()
:获取子视图层级 -
pvcs()
:获取控制器层级
10、封装 CY 文件
如果不是 Monkey Dev
注入的 Cycript
那是没有这些的,这就需要我们自己封装了。
现在借助 Monkey Dev
帮我们重签的 WeChat
的时候,将我们自定义的 CY 文件 Copy
到工程中。
新建 Monkey Dev
工程,运行一下空工程(每次必做的事情),添加 Target App
。
Xcode
在第一个 target
新建文件, iOS
-> Others
-> Empty File
,命名为 CurrentCY.cy
,在这个 target
的 Bulid Phases
下方 Copy Files
添加 CurrentCY.cy
。

然后我们写点东西,运行工程。
sum=function(a,b) {
return a+b;
}
CurrentKeyWindow=function(){
return UIApp.keyWindow;
}
CurrentRootVC=function(){
return UIApp.keyWindow.rootViewController;
}
打开 iTerm
进入 Cycript
,导入 CurrentCY.cy
这是必须要做的事情,输入 @import CurrentCY
,回车出现 {}
代表导入成功了,试试导入的指令。
//...
tancheng@tanchengdeMacBook-Pro ~ : sh cylogin.sh
cy# @import CurrentCY
{}
cy# sum(10,20);
30
cy# CurrentKeyWindow ()
#"<iConsoleWindow: 0x135d4a890; baseClass = UIWindow; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x282626e50>; layer = <UIWindowLayer: 0x28296ab40>>"
cy# CurrentRootVC()
#"<MMUINavigationController: 0x136849c00>"
cy#
这样自己封装的 CY
文件就可以使用了,后续还可以继续往里面添加一些东西。
以上就是 LLDB高级调试+Cycript 的全部内容了。
关于 Chisel 和 lldb_commands 常用指令整理,请点击这里。
Cycript 常用指令整理,请点击这里。
网友评论