前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >逆向开发从零到整(LLDB)

逆向开发从零到整(LLDB)

作者头像
CC老师
发布2019-01-23 17:32:47
9910
发布2019-01-23 17:32:47
举报
文章被收录于专栏:HelloCode开发者学习平台

前言 LLDB是我们平时调试中使用最多的工具之一,p或者po是使用最多的指令。除了ppo之外,还有什么指令可以使用呢?今天再次来提升一下对LLDB的使用吧。

一、LLDB

LLDB是个开源的内置于XCode的具有REPL(read-eval-print-loop)特征的Debugger,其可以安装C++或者Python插件。在日常的开发和调试过程中给开发人员带来了非常多的帮助。

二、设置断点(breakPoint set)

代码语言:javascript
复制
试试
代码语言:javascript
复制
代码语言:javascript
复制

还有没有其他设置断点的方式呢?列举几个常用的。

  • 给所有名为xx的函数设置一个断点
代码语言:javascript
复制
  • 在文件F指定行L设置断点
代码语言:javascript
复制
  • 给所有名为xx的C++函数设置一个断点(希望没有同名的C函数)
代码语言:javascript
复制
  • 给一个OC函数[objc msgSend:]设置一个断点
代码语言:javascript
复制
  • 给所有名为xx的OC方法设置一个断点(希望没有名为xx的C或者C++函数)
代码语言:javascript
复制
  • 给所有函数名正则匹配成功的函数设置一个断点
代码语言:javascript
复制
  • 给指定函数地址func_addr的位置设置一个断点
代码语言:javascript
复制
  • 断点查看
代码语言:javascript
复制
断点删除
代码语言:javascript
复制
  • 禁用断点
代码语言:javascript
复制
  • 开启断点
代码语言:javascript
复制

三、断点的流程控制

设置好断点后怎么控制前进、下一步呢? Xcode已经为我们提供了可视化的工具,但是如果你习惯了命令行操作不希望双手离开键盘降低你的效率,了解一下也是很有帮助的。

流程控制可视化界面

  • 继续
代码语言:javascript
复制
  • 下一步
代码语言:javascript
复制
  • 进入 ,进入主要是进入函数中查看相关代码或者汇编代码
代码语言:javascript
复制
  • 跳出 和进入相反
代码语言:javascript
复制

四、hook概念(stop-hook )

  • target stop-hook

我们知道,用LLDB debug,大多数时候需要让程序stop。 target stop-hook命令就是让你可以在每次stop的时候去执行一些命令 target stop-hook只对breakpoint和watchpoint的程序stop生效,直接点击Xcode上的pause或者debug view hierarchy不会生效 假如我们想在每次程序stop的时候,都用命令打印当前view。我们可以添加一个stop-hook:

代码语言:javascript
复制
  • target stop-hook add & display

target stop-hook add表示添加stop-hook,-o的全称是--one-liner,表示添加一条命令。

代码语言:javascript
复制

在程序stop的时候,他会自动执行frame variable,打印出了所有的变量。

e.g: 下面2行代码效果相同

代码语言:javascript
复制
  • target stop-hook list

当添加完stop-hook之后,我们想看当前所有的stop-hook怎么办呢?使用stop-hook list

代码语言:javascript
复制

我们可以看到,我们添加了4个stop-hook,每个stop-hook都有一个id,他们分别是4,5,6

  • target stop-hook delete & undisplay

有添加的命令,当然也就有删除的命令。使用target stop-hook delete可以删除stop-hook,如果你觉得这个命令有点长,懒得敲。你也可以用undisplay

代码语言:javascript
复制

我们用target stop-hook delete和undisplay分别删除了id为4和5的stop-hook

  • target stop-hook disable/enable

当我们暂时想让某个stop-hook失效的时候,可以使用target stop-hook disable

代码语言:javascript
复制

如果我们想让所有的stop-hook失效,只需不传入stop-hookid即可:

代码语言:javascript
复制

有disable就有enable,我们又想让stop-hook生效了。可以使用target stop-hook enable

代码语言:javascript
复制

同理,不传入参数表示让所有stop-hook生效

代码语言:javascript
复制
五、image

当我们有一个地址,想查找这个地址具体对应的文件位置,可以使用image lookup --address,简写为image lookup -a e.g: 当我们发生一个crash。

代码语言:javascript
复制

我们可以看到是由于-[__NSArray0 objectAtIndex:]:超出边界而导致的crash,但是objectAtIndex:的代码到底在哪儿呢?

代码语言:javascript
复制

根据0x000000010a1c3e36 -[ViewController viewDidLoad]里面的地址,使用image lookup -address查找,我们可以看到代码位置在ViewController.m里面的32行。

  • 还可以通过image查看类信息
代码语言:javascript
复制
  • 还可以通过(lldb) image lookup -t "method name"来定位方法位置。
代码语言:javascript
复制

可以看到LLDB定位到test1在第25行 通过以上的命令完全可以看不出image到底是干嘛的!? 所以暂时只能记得其拥有特殊功效。

  • 通过help可以看到更多命令,描述很详细的解释了各个命令的功效。想要了解每个功能,还需要平时多加练习和记忆。
代码语言:javascript
复制

六、register

register指令能够获取和修改各个寄存器的信息。 官方的解释是这样的:

代码语言:javascript
复制

我们可以通过register read来获取当前断点中寄存器中的内容:

代码语言:javascript
复制

具体怎么用我还没学到?。见谅见谅

七、expression 指令

expression命令是执行一个表达式,并将表达式返回的结果输出,是LLDB调试命令中最重要的命令,也是我们常用的ppo 命令的 鼻祖。 他主要有2个功能:

  • 执行表达式
代码语言:javascript
复制
  • 输出返回值
代码语言:javascript
复制
  • 衍生出的扩展命令
    • p
    • print
    • e
    • call
    • po

其实都是expression的别名,甚至我们还可以自己设置别名。这里不展开描述了。

八、frame 参数检查

  • frame
  • frame 官方解释
代码语言:javascript
复制

frame 框架的意思,但它应解释成(帧)它能显示堆栈信息, 我们在控制台上输入命令bt,可以打印出来所有的frame。如果仔细观察,这些frame和左边红框里的堆栈是一致的。平时我们看到的左边的堆栈就是frame。

image.png

  • frame variable

平时Debug的时候我们经常做的事就是查看变量的值,通过frame variable命令,可以打印出当前frame的所有变量

代码语言:javascript
复制

可以看到,他将self,_cmd,ret,a等本地变量都打印了出来 如果我们要需要打印指定变量,也可以给frame variable传入参数:

代码语言:javascript
复制

不过frame variable只接受变量作为参数,不接受表达式,也就是说我们无法使用frame variable self.string,因为self.string是调用string的getter方法。所以一般打印指定变量,我更喜欢用p或者po。

  • frame info

frame info: 查看当前frame的信息

代码语言:javascript
复制

frame select: 选择某个frame

代码语言:javascript
复制

当我们选择frame 1的时候,他会把frame1的信息和代码打印出来。不过一般我都是直接在Xcode左边点击某个frame,这样更方便

九、watchpoint

  • watchpoint

breakpoint有一个孪生兄弟watchpoint。如果说breakpoint是对方法生效的断点,watchpoint就是对地址生效的断点。 官方解释:

代码语言:javascript
复制

如果我们想要知道某个属性什么时候被篡改了,我们该怎么办呢?有人可能会说对setter方法打个断点不就行了么?但是如果更改的时候没调用setter方法呢? 这时候最好的办法就是用watchpoint。我们可以用他观察这个属性的地址。如果地址里面的东西改变了,就让程序中断。

watchpoint set命令用于添加一个watchpoint。只要这个地址中的内容变化了,程序就会中断。

  • watchpoint set variable 通过这个命令可以为array对象设置观察点
代码语言:javascript
复制

watchpoint set variable传入的是变量名。需要注意的是,这里不接受方法。 设置成功后可以通过watchpoint list 可以查看到所有被标记的watchpoint。 当我执行p array = @[@"a",@"b"]修改array后,watchpoint打印出了我旧值和新值。

代码语言:javascript
复制

除了以上指令之外,watchpoint当然也有和breakpoint一样的指令。 例如:

  • watchpoint disable
  • watchpoint enable
  • watchpoint delete

十 、thread

  • thread backtrace & bt

有时候我们想要了解线程堆栈信息,可以使用thread backtrace thread backtrace作用是将线程的堆栈打印出来。 e.g: 当发生crash的时候,我们可以使用thread backtrace(线程回溯)查看堆栈调用 。 bt则是 backtrace 的缩写,输入bt等同于thread backtrace

线程回溯

  • thread return

Debug的时候,也许会因为各种原因,我们不想让代码执行某个方法,或者要直接返回一个想要的值。这时候就该thread return上场了 thread return可以接受一个表达式,调用命令之后直接从当前的frame返回表达式的值。

结语

以上篇幅介绍的只是冰山一角。希望这篇文章能够给大家一些帮助,来更多的了解LLDB

作者:韩哒哒

感谢 韩哒哒 提供此原文给HelloCode 开发者学习平台.

人人为师,终身学习! 全栈开发从学习开始!

寒冬很冷,动动小手关注分享!

关注公众号,分享文章到朋友圈

作者:韩哒哒 链接:https://www.jianshu.com/p/995319aa8a41 來源:简书。

本公众号转载内容已尽可能注明出处,如未能核实来源或转发内容图片有权利瑕疵,请及时联系本公众号进行修改或者删除[联系方式QQ: 374487334 邮箱:374487334@qq.com].文章内容为作者独立观点,不代表本公众号立场.版本归原作者所有,如申请授权请联系作者,因文章侵权本公众号不承担任何法律以及连带责任.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 HelloCode开发者学习平台 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、LLDB
  • 二、设置断点(breakPoint set)
    • 试试
      • 还有没有其他设置断点的方式呢?列举几个常用的。
      • 三、断点的流程控制
      • 四、hook概念(stop-hook )
      • 六、register
      • 七、expression 指令
      • 八、frame 参数检查
      • 九、watchpoint
      • 十 、thread
      • 结语
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档