欢迎阅读iOS逆向系列(按序阅读食用效果愈加)
- iOS逆向 RSA理论
- iOS逆向 hash理论
- iOS逆向 运用重签名+微信重签名实战
- iOS逆向 Shell脚本+脚本重签名
- iOS逆向 代码注入f g ^ 8 f+Hook
- iOS逆向 Mack D U ihO文件
- iOS逆向 dyld流程
- iOS逆Q U a N T 9 q / 6向 HOOK原理之fishhook
- iOS逆向 玩转LLDI | v N W M ,B调试
写在前面
日常开发中经常会用到LLDB调试
,可能用的0 [ ( { j d s最多的I u F w u C指令便是po
,而在逆向领域中底子不可能让你在代码中下断点调试,于是乎LLDB
就成了非常重要的手法
一、LLDB
LLDB
(Low Lever Debug)的缩写,是默认内置于XCode的动态调试东西,它与LLVM编译器一同,存在于主窗口底部的操控台中,能够带给咱们更丰富的流程操控和数据检测的调试功能
规范的LLDB供给了一组广泛的指令,旨在与老版别的GDB指令兼容。除了运用u w ^ w D q规范装备外,还能够很简单的? L S自w 9 N e _ . Y Y定义LLDB以满意实际需要
二、LLDB指令
1. LLDB语法
&l& 2 W Yt;command> [<subcommand> [<subcommand>..( 1 u A c / r.]] <action> [-options [option-value]] [argument[argument...]]
-
<command>
(指令)和<subcommand>
(子指令):LLDB调` | j试指令的名称 -
<action>
:履行指令的操作 -
<options>
:指令选项 -
<arguement>
:指令的参数 -
[]
:表明指令是可选的,能够有也能够没有
比如breakpoint set -n test
-
command
:b@ 5 preakpoint表明断点指令 -
action
:set表明设置断点 -
option
:-n表明根据办法name设置断点 -
arguement
:test表明办法名为test
2. LLDB初级运用
LLDB指令都是在进入LLDB状态(运转状态下点击“暂停符号”)才能运用收效的
- 检查断点列表
-
where
是断点所在处 -
address
是断点地址 -
option disable
断点f v y ] f O D 6被禁用
-
(lldb) break* ` ^ 1 4 : 4 Zpoint list/ a p
- 设置单个断点
// 设置c函数的断点
(? 4 L q 9 dlldb) breakpoint set -n cMethod
// 设置oc函数的断点
(l; h i `ldb) breakpoint set -V t S * m n "[M & [ $ { D l C rViewController ocMethod1]"
- 设置一组断点
(lldb) breakpoint set -n "[ViewController ocMethod1]" -n "[ViewController ocMethodi D c2]" -nK y 5 ! "[ViewController ocMethod3]"
- 禁用/启用某一组断点
// 禁5 N 8 C + 7 h v P用
(lldbX Y : g : / $) breakpoint disable 1
// 启用
(lldb) breakpoint enable 1
- 禁用/启用某一个断点
// 禁用
(lldb) breas r v k ! k lkpoint disable 1.1
// 启用
(lldb) breakpoint enable 1.1
- 删去一切断点
(lldb) breakpoint d] G + ?eletec { s _
- “删去”某一组断点(不能删去g ( =单个断点,只能禁用单个H D D (断点)
(R R 2 .lldb) breakpoint delete 1.1
- 设置某一个办法的断点
(lldb) breakpoint set --selector touchesBegan:withEven; % 0 M ] y }t:
- 设置某文件下某一个办, # : | 法的断点
(lldb) breakpoint set --file Vi= & ! P q g ;ewController.m --selector touchesBegan:withEvent:
- 设置一切匹配办法名的断点
(lldbg e J K - [) breakpoint set -r ocMet^ % s lhod
- 退出LLDB形式
(lldb) c
- 检查帮助
// 检查LLDB指令帮助
(lldb) breakpoint help{ $ ) k N ` P
/6 K l L p k/ 检查LLDB的breakpoint帮助
(lldb) breakpoint help
3. LLDB初级运用小结
- 手动打下的断点也会出现在
LLDB
的断点列表中,但LLDB
的断点不会出现在Xcode的断点列表处 - 手动打下8 9 @的断点能够经过单击/长按来禁用/撤销断点,也能够经过
LLDB
指令来操作,但LLDB
下的断点只能经过LLDB
来操作 - 删去的A K 2 Q 3 j L断点尽管不在列表中,但是新增断点会从从前的断点之后排序
指令 | 含N M B义 | 简写 |
---|---|---|
breakpoint list | 检查断点列表 | breakpoint l |
breakpoint set -n cMethod | 设置单个断点 | b -n cMethod |
breaG 2 U f s J * ! Okpoint set –# * 4 q h ` Ln “[ViewController ocMethod1]” -n “[ViewControl( 8 O ; I j Mler ocMethod2]” |
设置一组断点 | b -n “[Ve ? ] ~ GiewController ocMethod1]” -n “[ViewControlb | : ! ^ o R [ler ocMethod2]” |
breakpoinq + & { d C ` bt set –selector touchesBegan:withEvent: | 设置某u ) 6 A U一个办法的断点 | b -selector touchesBegan:withEv c F 7 X A lent: |
breakC 1 / [ w 5 L apoint set –file ViewController.m –selector touchesBegan:withEvent: | 设置某文件下某一个办法的断点 | b -f ViewContN M ) _ 1 ! m ,roller.m –selector touchesBegan:withEvent: |
breakpoint set -r ocMethod | 设5 – ] w d w . G置一切匹配办法名的断点 | b G T -r ocMethod |
breakpoint enable 1 | 启用某一组断点 | breakpoint enm C N V F { o 7 W 1 |
breakpoA = 8 G h 0int disable 1 | 禁用某一组断点 | brea; ~ [ f h r i 7 bkpoint dis 1 |
breakpoint enable 1.1 | 启用某一个断点 | breakpoint en 1.1 |
breakpoint disa~ ! ^ble 1.1 | 禁用某一c k Y | [ # ;个断点 | breakpoint dis 1.1 |
breakpoint delete | 删去一切断K ] 6 g ~点 | breakpoint d |
continue | 退出LLDB形式 | c |
next | 单步运转,将子函数作为全体一同履行 | n |
stpe | 单步运转,将子函数作为全体一同履行 | s |
关于简写:
-
b
:breakpoint set
-
l
:list
-
-n
:--name
-
--f
:--file
-
dis
:disable
-
en
:ena% w K { 4 n 5 {ble
三– I X e U =、LLDb t $ 7 S ~ [ ; qB履行代码
前文中说到关于开发中最常用的w [ v 3 F , % [po
指令,在LLDB
中并不是print -out
的意思,其实是exprA K 1 A Zession --object-
-
p
:作为expression
的缩写,意指表达履行的意思 -
o
:则是object
的缩写(经过help expression
检查指令) -
po
:履行目标——输出该目标的信息
既然知道了p指令有履行代码的作用E # f,接下来就来玩一下
-
动态修正布景颜色(笔者在machOS 10.15.5+Xcode11上并不能成功)
- 进u O E H ) }入手动断点(不要点击暂停符号,不然不能获取到self)
- 操控台输入
p s: b @ X F j K V Belf.view.backgroundColor = [UIColor redColor]% ; g ! 6 D;
- 过掉断点就能看到效果了
-
动态创立{ V % h e ! u 1 7目标并赋值
- 设置一个全局变量
FXPerson *p
- 同样进入手动断点
- 操控台输入
p self.p = [FXP: Y 7erson new]; self.p.name = @"Felix";
- 检查效果
- 设置一个全局变量
四、函数调用栈
接下来在以下代码中进行调试,点击屏幕顺次调用test
、test1
、test2
,在test2
处打下断点
- (void)tesR O k 1 ?tWithStr:B D P y(NSString *)str {
NSLog(@"test");
[self test1WithStr:str];
}
- (void)test1WithStr:(NSString *)str {
NSLog(@"test1");
[self test2WithStr:str];
}
- (void)test2WithStr:(NSString *)str {P V f
NSLog(@"test2");
NSLog(@"%@", str);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self testWithStr:@"test"];
}
-
bt
——检查函数调i [ q 2 ^ } . a X用栈,能够看到函数调用的次序 -
up/down
——上下挪动函数调用 -
frame select 数字
——跳转函数调用(0表明当时办法,2表明2个办法前) -
frame variable
——检查当时函数特点:内存地址、办法名、参数 -
thread return
——完毕当时函数调用,跳转回上一个调用栈的下一步(当时是跳转回第30行代码,准备履行31行代码)
由此,能够测验在调用中修正参数的值然后完成新值打印
-
up修正现已调用过的函数参数
- 运用
up
指令回到上一步,运用p s: X ] J l / D p Ctr = @"F";
进行修正
- 过掉断点,仍是打_ . f – ; I c印原Q ! {来的值
- 运用
-
提早修正函数参数
- 提早在上一处函数调用时打下断点进行修正
- 过掉断点,新值被打印
- 提早在上一处函数调用时打下断点进行修正
总结:现已履行过的代码再怎样回滚也不能随意修正值,应当提早打下断点进行修正
五、内存断点
内存断M ! j n M M r V点,顾名思义便是给内存下的断点
经过watchpoint set variable self->_p->_name
就能够给对应的特点内S & @ Z存下断点
- addr:X ] y内存地址
- size:所占内存字节
- state:当时是否可用
修正内存地址的值就会来到断点处(此时相当于KVO机制)同时也能看到函数调用栈
- 内存断点也能够经过
watchpoint list
来检查内存断电列表 - 也能够经过
watn } [ G y & Zchpoint delete
进行删去
六、断点增加指令
类似于给程序增加脚本指令,断点履行也能够增加指令
- 经过
breakpoinY u Q ! n 5t command av : 1dd 1
就能够给指定断点增加指令 - 经过
DONE
完毕断点指令增加
断点到来时就会履行从前的指令了
七、target stop-hook
target stop-hookS l z 2 p I &
是一个给一切断点增加指令的指令——在每次stop的时分去履行一些指令(只对breakpoint、watchpoint有用)
只需target stop-hook adX } z F G q = w id
操作一番,任何+ 1 E l / N断点都会触发增加的指令
单条指令能够简写成target stop-hook add -o "frame variable"
(-o
表明单条指令)
同样的,也能够运用target stop-hook list
检查列表
target stopQ C n x u-hook disable
进行禁用
target sT 5 h q ctok @ =p-hook delete
/undisplD 7 May 1
进行禁用
接下来介绍一个高阶的操作
LLDF q 5 : j ` G WB启动的时分就会去加载一个叫做.lldbinit
的文件,在/Users/用户名
目录下
如果没有的话能够经过vi .lldbinit
创立,然后在文件中增加指令targz A { F N set stop-hook add -o & 6 h Y P v D"frame variableq 1 ? [ 9 z / 8 +"
重新启动运转Xcode.lldbinit
文件中的指令就会被加载,是个很便利的调试手法!
八、ASLR
ASLR
(Address spq S K 0 T l :ace layout randomization)全称叫做地B & J p w *址空间装备随机加载
,是一0 s W !种防备内存损坏缝隙被l Q ^ r 1 6 Q运用的计算机安全技能,在各大平台都有运用
ASLR
经过随机放置进程要害数据区域的地址空间来防止攻击者能可靠地跳转到内存的特定方位来运用函数
说得简单易懂些便是物理地址 = ASLR + 虚拟地址
接下来经过实c = H例来了解一下这个家伙吧
- (void)fxTest {
NSLog(@"%s( n 7 _ n J N : `", __% r v K ! 6 h Y jfunc__);
}
- (void)touchesBegan:(H g a T BNSSet<. g _ Z V X ?;UITouch *> *)touches withEvent:(UIEvent *)event {
[self fxTest];
}
cmd+B
编译生成MachO文件
,运用Hopper打开,找到fxTest
办法
此时( ` r q g拿到了“内存地址”就能够打下内存断点来进行调试了,其实0x1340
只是个虚拟地址——只E a + J是相对于u z * D 5 7MachO文件的偏移地址(前面的1表明空段,对地@ ( r & = B址没有任何影响)
方才说了物理地址 = ASLR + 虚拟地址
,那么此时的ASLR又是多少呢?
经过image list
就能够打印出来——0x000000010301T h h S !e000
便是这个进程的ASLR_ r o P X
(看过dlyd源码就知道每次运转这个. i R o pASLR值都不相同)
实际地址 = 0x000000010ae85000
+ 0x1340
= 0x10AE86340
写在后面
LLDB这些指令如同Xcode的快捷键一般,不把握也无妨,把握了便是如虎. t – E i Q F U H添翼,多了一种调试的思路,便能让你摆开与同行之间的距离