iOS应用安全7 -- LLDB动态调试

前言

LLDB全称是Low Level Debugger,并非low的调试器,而是轻量级的高性能调试器,xcode默认内置了它,所以咱们不须要再本身安装。笔者最近也是系统的学习了LLDB的用法,在此以前就用过p和po,哈哈😄。本篇文章主要为了将最近学习的LLDB记录并总结,加深记忆并方便之后查找。git

另外,本篇文章主要有两部分,一个是LLDB的基础用法,另外一个就是对基础LLDB使用插件进行扩展。express

基础LLDB用法

p、po、print、expression

首先就来介绍一下这几个经常使用命令之间的关系吧。 先看看expression指令。 xcode

expression
从这里能够发现, expression指令主要有如下做用:

  1. 打印变量的信息
  2. 执行语句,如:expression a = 100,一样这里你能够试试expression self.view.backgroundColor = [UIColor redColor],也是能修改背景颜色的。
  3. 经过$符号定义和使用lldb变量,如:expression int $b = 99

多是p太容易让人联想到print了,不少人都会认为p是print的缩写,po是print object的缩写,事实上并非这样。
p 和 print其实都是expression --的缩写,可使用help指令查看。 bash

help

po也并非print object(本来也就没这个写法)的缩写,而是expression -O --的缩写,一样可使用help指令查看。 服务器

po
接下来使用 help expression看看 expression -O --是什么意思,以下,能够看到 -O表明的是对象的 description(描述),即打印出变量的描述。
expression -O

breakpoint

断点调试在平常开发中都常常用到,而且在xcode中咱们也可以很轻易的设置、禁用、删除断点。下面就来看看如何使用LLDB达到而且超越界面化断点。微信

设置断点

经常使用设置断点的参数及表明的意义。app

缩写 全称 意义
-f --file 文件名称
-l --line 行数
-n --name 方法名
-S --selector SEL
-r --func-regex 方法正则
  1. 在ViewController.m文件的第28行设置断点。
// 举例
breakpoint set -f ViewController.m -l 28
复制代码
  1. 给方法名是click1:的方法设置断点。
breakpoint set -n click1:
复制代码
  1. 给SEL是click2:的方法设置断点。
breakpoint set -S click2:
复制代码
  1. 给包含click的地方设置断点。
breakpoint set -r click
复制代码

效果以下: curl

click
能够看到一次性设置了103个地方,显然想要的不是这样。条件拼接,和第一个例子那样。

  1. ViewController.m文件中包含click的地方设置断点。
breakpoint set -f ViewController.m -r click
复制代码

组合

breakpoint set虽然在拼写时lldb会提示,但感受仍是太长了,怎么办?
直接使用b便可。 函数

b

查看当前所有断点

// 缩写:br list
breakpoint list
复制代码

这里须要注意如下,因为这三个断点是使用一条语句设置的,所以它们三个会被分到同一个断点组里面。 oop

断点组

设置断点无效

这一步就至关于界面操做中,让断点颜色变半透明。

半透明
代码设置以下:

// 设置断点14.1无效
br disable 14.1
// 一样,将无效断点设置为有效
br enable 14.1
复制代码

无效

删除断点

br delete 14.3
复制代码

删除
能够看到,14.3并无被删除,而只是被设置为了无效。缘由就是14.3属于14这个组,不能只删除一个,要删必须将所有都删掉。
删除组

是否是感受很666?
其实这些东西基本上用不到,哈哈哈。
正向开发中可使用xcode提供的界面操做设置和删除断点。
而在逆向中,根本就获取不到这些符号(类名,文件名,方法名等)。
不信?看看下图:

微信
由于在逆向中,是没法获取符号的,由于可以获得的文件就只有一个,MachO文件。而在MachO文件中是没有这些符号的,有的只是地址。

内存断点

上面说了,在逆向中,因为没法获取到符号,是没法直接经过符号设置断点的,而咱们还须要使用断点怎么办?下内存断点。

这里在24行的断点处,获取了_name指针的地址,而后经过

watchpoint set expression 0x000000014b80b880
复制代码

_name变量设置了一个内存断点,接下来c--->continue过掉断点,点击按钮1,在_name = @"abc";语句调用时,因_name指向的空间变化了,就会打印出old valuenew value

内存断点
除了使用上面那种方法外,还可以使用 variable,效果是同样的,入下:
variable

这里是有点取巧了,变量的内存地址也是直接经过符号获取的,而且这里也只是演示了给变量打内存断点,那么如何给方法打内存断点呢?
假设我如今要给click2:方法打个断点,那么就须要这样计算:

  1. 先找到ASLR的值。
    ASLR
  2. 使用MachOView或者hooper打开App的MachO文件。
    hooper
    MachOView
  3. 使用ASLR+方法在MachO文件中的地址 = 方法在内存中的地址。
    内存地址
  4. 测试如下是否是真的断住了click2:方法。点击按钮2,发现程序停到了这个方法。断点设置成功。
    按钮2

LLDB的其余经常使用命令

image list

上面咱们查看MachO文件的ASLR时使用了这个命令。这里的image不是图片的意思,而是镜像。
能够理解为每个MachO都是一个image,主程序是一个image,主程序连接的每个动态库也各自是一个image
image list就是打印出App中所有的image信息,每一个image信息的那个地址就是这个image在内存中的首地址,也即这个imageASLR

bt

bt命令是用来查看函数调用栈的,以下,我在click1:中调了click2:,click2:中又调用了click3:,再在click3:中设置一个断点,点击按钮1,输入bt命令,以下:

bt
能够看到函数之间的调用关系。而且还可使用

frame select [调用栈的编号]
复制代码

查看该调用栈的详细信息,包括调用者的内存地址,调用的方法,参数的内存地址等。

frame
在此基础上,还可以使用 updown命令查看临近的调用栈信息。
updown

c,n,s

这个就简单了,以下图:

cns

LLDB插件扩展

上面记录的都是xcode自带的lldb所具备的功能,接下来要说的是使用插件对lldb进行扩展,使得lldb更简单,更强大。

chisel

对于chisel的安装,最方便的仍是使用Homebrew安装了,使用mac电脑,安装一个Homebrew是很是有用的,不过这个玩意由于是国外的服务器,因此安装更新都特别慢,甚至很是容易出错,一旦出错就要重来。对此,咱们可使用国内的源。

这里提供一种使用国内源进行安装的方法,终端执行下面的语句便可。若是使用的不是zsh,那么能够尝试将zsh改为bash。

/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
复制代码

安装完Homebrew以后,直接终端下面的命令便可安装chisel。

brew install chisel
复制代码

完成后在/Users/[username]/.lldbinit文件里面添加一句(没有就建立一个文件)。

command script import /usr/local/Cellar/chisel/2.0.0/libexec/fblldb.py
复制代码

安装完chisel以后,能够来尝试一下chisel对lldb的扩展。

pviews

递归获取所有的视图类对象,而且按照视图的层级结构打印出来。

pviews

pvc

打印当前所有的控制器对象及层级关系。这里代码进行来一点修改,点击屏幕空白时跳转到NextViewController

pvc
由于 ViewControllerNextViewController盖住了,能够看到控制器对象的 stateViewController 的 state 是 disappeared

caflush

用来刷新UI,在动态调试时,咱们可能会修改UI控件的布局,此时直接使用caflush便可刷新视图。

fv 和 fvc

f-->find,这两个命令是用来查找viewViewController的。

fv

taplog

这个就比较厉害了,直接输入taplog,而后你会发现程序正常运行了,此时点击任意一个按钮,那么就会打印出点击的这个按钮的信息。

taplog
这个对于逆向调试是很是有帮助的,直接定位到点击的那个控件的内存地址。有了内存地址,什么都好办了。

presponder

打印出responder响应链。

pclass

打印对象所属的类的继承关系。

pclass

pactions

经过按钮的内存地址,直接找到按钮响应的actions。

pactions

methods

打印对象所属类的所有方法以及属性。相似于class-dump的功能。

methods

flicker

让内存地址对应的控件在手机上闪烁一下。

flicker

vs

让内存地址对应的控件变成半透明的红色,而且进入一个编辑模式,使用

  • w:定位到当前视图的父视图。
  • s:定位到当前视图的第一个子视图。
  • a:定位到当前视图的兄弟视图的前一个。
  • d:定位到当前视图的兄弟视图的后一个。
  • p:打印定位到的视图的信息。
  • q:退出这个编辑模式。

vs

还有其余的一些功能,使用help命令能够进行查看。

总结

这篇文章主要记录了

  1. xcode自带的LLDB的使用方法。
  2. 逆向时如何设置断点。
  3. 使用插件chisel对LLDB进行功能扩展(更利于逆向)。

本文地址

相关文章
相关标签/搜索