欢迎阅读iOS逆向系列(按序阅读食用效果更加)html
平常开发中常常会用到LLDB调试
,可能用的最多的命令就是po
,而在逆向领域中根本不可能让你在代码中下断点调试,因而乎LLDB
就成了很是重要的手段express
LLDB
(Low Lever Debug)的缩写,是默认内置于XCode的动态调试工具,它与LLVM编译器一块儿,存在于主窗口底部的控制台中,可以带给咱们更丰富的流程控制和数据检测的调试功能sass
标准的LLDB提供了一组普遍的命令,旨在与老版本的GDB命令兼容。除了使用标准配置外,还能够很容易的自定义LLDB以知足实际须要安全
<command> [<subcommand> [<subcommand>...]] <action> [-options [option-value]] [argument[argument...]]
复制代码
<command>
(命令)和<subcommand>
(子命令):LLDB调试命令的名称<action>
:执行命令的操做<options>
:命令选项<arguement>
:命令的参数[]
:表示命令是可选的,能够有也能够没有好比breakpoint set -n test
bash
command
:breakpoint表示断点命令action
:set表示设置断点option
:-n表示根据方法name设置断点arguement
:test表示方法名为testLLDB命令都是在进入LLDB状态(运行状态下点击“暂停符号”)才能使用生效的 微信
where
是断点所在处address
是断点地址option disable
断点被禁用(lldb) breakpoint list
复制代码
// 设置c函数的断点
(lldb) breakpoint set -n cMethod
// 设置oc函数的断点
(lldb) breakpoint set -n "[ViewController ocMethod1]"
复制代码
(lldb) breakpoint set -n "[ViewController ocMethod1]" -n "[ViewController ocMethod2]" -n "[ViewController ocMethod3]"
复制代码
// 禁用
(lldb) breakpoint disable 1
// 启用
(lldb) breakpoint enable 1
复制代码
// 禁用
(lldb) breakpoint disable 1.1
// 启用
(lldb) breakpoint enable 1.1
复制代码
(lldb) breakpoint delete
复制代码
(lldb) breakpoint delete 1.1
复制代码
(lldb) breakpoint set --selector touchesBegan:withEvent:
复制代码
(lldb) breakpoint set --file ViewController.m --selector touchesBegan:withEvent:
复制代码
(lldb) breakpoint set -r ocMethod
复制代码
(lldb) c
复制代码
// 查看LLDB指令帮助
(lldb) breakpoint help
// 查看LLDB的breakpoint帮助
(lldb) breakpoint help
复制代码
LLDB
的断点列表中,但LLDB
的断点不会出如今Xcode的断点列表处LLDB
命令来操做,但LLDB
下的断点只能经过LLDB
来操做命令 | 意义 | 简写 |
---|---|---|
breakpoint list | 查看断点列表 | breakpoint l |
breakpoint set -n cMethod | 设置单个断点 | b -n cMethod |
breakpoint set -n "[ViewController ocMethod1]" -n "[ViewController ocMethod2]" |
设置一组断点 | b -n "[ViewController ocMethod1]" -n "[ViewController ocMethod2]" |
breakpoint set --selector touchesBegan:withEvent: | 设置某一个方法的断点 | b -selector touchesBegan:withEvent: |
breakpoint set --file ViewController.m --selector touchesBegan:withEvent: | 设置某文件下某一个方法的断点 | b -f ViewController.m --selector touchesBegan:withEvent: |
breakpoint set -r ocMethod | 设置全部匹配方法名的断点 | b -r ocMethod |
breakpoint enable 1 | 启用某一组断点 | breakpoint en 1 |
breakpoint disable 1 | 禁用某一组断点 | breakpoint dis 1 |
breakpoint enable 1.1 | 启用某一个断点 | breakpoint en 1.1 |
breakpoint disable 1.1 | 禁用某一个断点 | breakpoint dis 1.1 |
breakpoint delete | 删除全部断点 | breakpoint d |
continue | 退出LLDB模式 | c |
next | 单步运行,将子函数当作总体一块儿执行 | n |
stpe | 单步运行,将子函数当作总体一块儿执行 | s |
关于简写:dom
b
:breakpoint set
l
:list
-n
:--name
--f
:--file
dis
:disable
en
:enable
前文中提到关于开发中最经常使用的po
指令,在LLDB
中并非print -out
的意思,实际上是expression --object-
函数
p
:做为expression
的缩写,意指表达执行的意思o
:则是object
的缩写(经过help expression
查看指令)po
:执行对象——输出该对象的信息
既然知道了p指令有执行代码的做用,接下来就来玩一下工具
动态修改背景颜色(笔者在machOS 10.15.5+Xcode11上并不能成功)post
p self.view.backgroundColor = [UIColor redColor];
动态建立对象并赋值
FXPerson *p
p self.p = [FXPerson new]; self.p.name = @"Felix";
接下来在如下代码中进行调试,点击屏幕依次调用test
、test1
、test2
,在test2
处打下断点
- (void)testWithStr:(NSString *)str {
NSLog(@"test");
[self test1WithStr:str];
}
- (void)test1WithStr:(NSString *)str {
NSLog(@"test1");
[self test2WithStr:str];
}
- (void)test2WithStr:(NSString *)str {
NSLog(@"test2");
NSLog(@"%@", str);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self testWithStr:@"test"];
}
复制代码
bt
——查看函数调用栈,可以看到函数调用的顺序
up/down
——上下挪动函数调用
frame select 数字
——跳转函数调用(0表示当前方法,2表示2个方法前)
frame variable
——查看当前函数属性:内存地址、方法名、参数
thread return
——结束当前函数调用,跳转回上一个调用栈的下一步(当前是跳转回第30行代码,准备执行31行代码)
由此,能够尝试在调用中修改参数的值从而完成新值打印
up修改已经调用过的函数参数
up
指令回到上一步,使用p str = @"F";
进行修改
提早修改函数参数
总结:已经执行过的代码再怎么回滚也不能随意修改值,应当提早打下断点进行修改
内存断点,顾名思义就是给内存下的断点
watchpoint set variable self->_p->_name
就能够给对应的属性内存下断点
watchpoint list
来查看内存断电列表watchpoint delete
进行删除相似于给程序添加脚本命令,断点执行也能够添加命令
breakpoint command add 1
就能够给指定断点添加命令DONE
结束断点命令添加target stop-hook
是一个给全部断点添加命令的指令——在每次stop的时候去执行一些命令(只对breakpoint、watchpoint有效)
只要target stop-hook add
操做一番,任何断点都会触发添加的命令
单条命令能够简写成target stop-hook add -o "frame variable"
(-o
表示单条命令)
一样的,也可使用target stop-hook list
查看列表
target stop-hook disable
进行禁用
target stop-hook delete
/undisplay 1
进行禁用
接下来介绍一个高阶的操做
LLDB启动的时候就会去加载一个叫作.lldbinit
的文件,在/Users/用户名
目录下
若是没有的话能够经过vi .lldbinit
建立,而后在文件中添加命令target stop-hook add -o "frame variable"
从新启动运行Xcode.lldbinit
文件中的命令就会被加载,是个很方便的调试手段!
ASLR
(Address space layout randomization)全称叫作地址空间配置随机加载
,是一种防范内存损坏漏洞被利用的计算机安全技术,在各大平台都有应用
ASLR
经过随机放置进程关键数据区域的地址空间来防止攻击者能可靠地跳转到内存的特定位置来利用函数
说得简单易懂些就是物理地址 = ASLR + 虚拟地址
接下来经过实例来了解一下这个家伙吧
- (void)fxTest {
NSLog(@"%s", __func__);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self fxTest];
}
复制代码
cmd+B
编译生成MachO文件
,使用Hopper打开,找到fxTest
方法
此时拿到了“内存地址”就能够打下内存断点来进行调试了,其实0x1340
只是个虚拟地址——只是相对于MachO文件的偏移地址(前面的1表示空段,对地址没有任何影响)
刚才说了物理地址 = ASLR + 虚拟地址
,那么此时的ASLR又是多少呢?
经过image list
就能够打印出来——0x000000010301e000
就是这个进程的ASLR
(看过dlyd源码就知道每次运行这个ASLR值都不相同)
实际地址 = 0x000000010ae85000
+ 0x1340
= 0x10AE86340
LLDB这些指令如同Xcode的快捷键通常,不掌握也无妨,掌握了就是锦上添花,多了一种调试的思路,便能让你拉开与同行之间的差距