iOS逆向工程

iOS调试之chisel

2016-04-04  本文已影响2306人  comst

iOS调试之chisel

Chisel 是一个 LLDB 指令集合,用户辅助 iOS 应用差错。

安装
  1. chisel的安装需要使用Homebrew,如果还没有安装Homebrew,可以使用下面的命令安装,如果你已经安装了,可以跳过这一步

    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

  2. 用Homebrew安装chisel:

    brew update
    brew install chisel

  3. ~/.lldbinit中添加命令

    touch ~/.lldbinit
    echo "command script import /usr/local/opt/chisel/libexec/fblldb.py" >> ~/.lldbinit
    重启一下Xcode,安装完成。

更新

如果你想更新chisel,只需要输入更新的命令即可。

brew upgrade chisel

命令
Autolayout

autolayout中有一种bug叫Ambiguous Layouts,意思是你设置的约束不足以确定view的位置或大小。比如你只设置了X轴的位置,没有设置Y轴的位置。
autolayout提供了专门判断和查找这类问题的方法:

alamborder

给存在Ambiguous Layouts的view加上border,方便查找哪些View存在问题。
语法:

Syntax: alamborder --color=color --width=width

alamunborder

将alamborder设置的border去掉。
语法:

Syntax: alamunborder

paltrace

打印某个View的autolayout详细信息,相当于调用_autolayoutTrace
语法:

Syntax: paltrace <view>

print

在LLDB中,我们执行的最多的可能就是打印操作了,chisel专门为这类操作封装了一些打印命令。

pviews

循环打印view层级,正常情况下等效于调用recursiveDescription命令
// 下面2条命令等效
(lldb) po [self.view recursiveDescription]
(lldb) pviews self.view
语法:

pviews [--up] [--depth=depth] <aView>

pvc

循环打印viewController的层级。
语法:

Syntax: pvc <aViewController>

<aViewController>: 表示要打印的viewController,不传参数默认viewController为当前的VC。
e.g: 打印一下当前VC
(lldb) pvc
<UINavigationController 0x7fe2a2813800>, state: appeared, view: <UILayoutContainerView 0x7fe2a409bb30>
| <ViewController 0x7fe2a2428450>, state: appeared, view: <UIView 0x7fe2a409c660>

pclass

循环打印class的继承关系。
语法:

Syntax: pclass <object>
<object>: 要打印继承关系的对象。
e.g: 打印一个View对象的继承关系
(lldb) pclass [UIButton new]
UIButton
| UIControl
| | UIView
| | | UIResponder
| | | | NSObject

presponder

打印响应链。
语法:

Syntax: presponder <startResponder>
<startResponder>: UIResponder对象,响应链开始位置。
e.g: 打印一个button的响应链
pclass self.btn
UIButton
| UIControl
| | UIView
| | | UIResponder
| | | | NSObject
(lldb) presponder self.btn
<UIButton: 0x7fb16342f610; frame = (65 226; 45 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x7fb163410fc0>>
| <UIView: 0x7fb163425810; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7fb16341de90>>
| | <ViewController: 0x7fb163524a60>
| | | <UIViewControllerWrapperView: 0x7fb165900050; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7fb163721990>>
| | | | <UINavigationTransitionView: 0x7fb16371cf70; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x7fb163712920>>
| | | | | <UILayoutContainerView: 0x7fb163715e40; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x7fb16371f1d0>; layer = <CALayer: 0x7fb16370b2e0>>

   |    |    |    |    |    | <UINavigationController: 0x7fb164022a00>
   |    |    |    |    |    |    | <UIWindow: 0x7fb163533440; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x7fb163534680>; layer = <UIWindowLayer: 0x7fb1635241b0>>
   |    |    |    |    |    |    |    | <UIApplication: 0x7fb163700aa0>
   |    |    |    |    |    |    |    |    | <AppDelegate: 0x7fb163709d10>
ptv

打印屏幕中显示的tableView,主要是与pcells联合使用。如果有多个tableView,打印View层级中最上面的一个。
语法:

Syntax: ptv
e.g: 看看当前最上面是哪个tableView
(lldb) ptv
<UITableView: 0x7fde52811800; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7fde526418d0>; layer = <CALayer: 0x7fde5260adc0>; contentOffset: {0, -64}; contentSize: {414, 176}>

pcells

打印tableView中当前可见的cell,如果有多个tableView,打印View层级中最上面的tableView的可见cell。
语法:

Syntax: pcells
e.g: 看看当前可见的cell有哪些
(lldb) pcells
<__NSArrayI 0x7fde52565a00>(
<UITableViewCell: 0x7fde52551180; frame = (0 0; 414 44); text = 'BasicViewController'; autoresize = W; layer = <CALayer: 0x7fde52537140>>,
<UITableViewCell: 0x7fde5255bea0; frame = (0 44; 414 44); text = 'DateViewController'; autoresize = W; layer = <CALayer: 0x7fde5255b1a0>>,
<UITableViewCell: 0x7fde5255e2d0; frame = (0 88; 414 44); text = 'PPTViewController'; autoresize = W; layer = <CALayer: 0x7fde5255e270>>,
<UITableViewCell: 0x7fde5255fce0; frame = (0 132; 414 44); text = 'TableViewController'; autoresize = W; layer = <CALayer: 0x7fde5255fa90>>
)

pinternals

打印一个对象内部的成员变量,这个方法我一般用来看model属性。
语法:

Syntax: pinternals <object>

pdata

对编码过的NSData进行解码打印,等效于调用-[NSString initWithData:encoding:]
语法:

Syntax: pdata [--encoding=encoding] <data>

pkp

通过-valueForKeyPath:打印key path对应的值。
语法:

Syntax: pkp <keypath>

pivar

打印对象成员变量。
语法:

Syntax: pivar <object> <ivarName>

Find

debug的时候,我们经常需要查找一些东西,比如View,viewController等。

fvc

根据viewController的Class名字查找VC。
语法:

Syntax: fvc [--name=classNameRegex] [--view=view]

fv

根据view的class名字查找view。
语法:

Syntax: fv <classNameRegex>

taplog

将点击的view打印出来,这个命令对于查找哪个view非常有帮助。
说明:要查看的view必须能接收点击事件,也就是他的userInteractionEnabled必须为YES才能被找到,UILabel和UIImageView默认userInteractionEnabled为NO。
用法:我们需要先将程序暂停,输入taplog,程序会自己运行,这时候点击你需要查看的view,控制台上就会显示出你刚刚点击的view相关信息。
e.g: 我们先将程序暂停,输入taplog
(lldb) taplog
Process 28421 resuming
程序会自己运行,我们再点击一个UIButton:
<UIButton: 0x7fe6785284e0; frame = (54 244; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x7fe678528a50>>

flicker

将view闪烁一下,以便于查找view的位置。
语法:

Syntax: flicker <viewOrLayer>

vs

在view层级中搜索view,并显示出来。
语法:

Syntax: vs <view>

Display

debug的时候,可能有一小半的工作是跟UI打交道,关于UI显示上的东西,也有几个命令。

caflush

刷新UI界面。一般我们用LLDB命令改变UI,UI并不会立即更新,我们需要使用caflush刷新界面。
语法:

Syntax: caflush

e.g: 我们用命令将label的背景色改为红色
(lldb) fv uilabel
0x7fb3919189d0 UILabel
(lldb) e [((UILabel*)0x7fb3919189d0) setBackgroundColor:[UIColor redColor]]
(lldb) caflush

border

给View或者layer加上border。
语法:

Syntax: border [—color=color] [--width=width] <viewOrLayer>

unborder

去掉view或者layer的border。
语法:

Syntax: unborder <viewOrLayer>
e.g: 将刚刚加上的border去掉。

(lldb) unborder 0x7fe713901f10
mask

给view添加一个半透明的矩形mask,用来查看view的位置。
语法:

Syntax: mask [--color=color] [--alpha=alpha] <viewOrLayer>

unmask

将添加的mask去掉。
语法:

Syntax: unmask <viewOrLayer>

show

显示一个view或者layer,相当于执行view.hidden = NO。
语法:

Syntax: show <viewOrLayer>

hide

隐藏一个view或者layer,相当于执行view.hidden = YES。
语法:

Syntax: hide <viewOrLayer>

Preview

预览功能,帮助我们用命令查看一个view或者图片的真正样子。

visualize

用预览App打开UIImage, CGImageRef, UIView, CALayer等对象。
语法:

Syntax: visualize <target>

wivar

为对象的成员变量设置watchpoint。
语法:

Syntax: wivar <object> <ivarName>

bmessage

根据方法名设置断点
语法:

Syntax: bmessage <expression>

上一篇 下一篇

猜你喜欢

热点阅读