欢迎阅读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 Sw 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状态(运转状态下点击“暂停符号”)才能运用收效的

iOS逆向 玩转LLDB调试
iOS逆向 玩转LLDB调试
  • 检查断点列表
    • where是断点所在处
    • address是断点地址
    • option disable断点f v y ] f O D 6被禁用
(lldb) break* ` ^ 1 4 : 4 Zpoint list/ a p
iOS逆向 玩转LLDB调试
  • 设置单个断点
// 设置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]"
iOS逆向 玩转LLDB调试
  • 设置一组断点
(lldb) breakpoint set -n "[ViewController ocMethod1]" -n "[ViewController ocMethodi D c2]" -nK y 5 ! "[ViewController ocMethod3]"
iOS逆向 玩转LLDB调试
  • 禁用/启用某一组断点
// 禁5 N 8 C + 7 h v P用
(lldbX Y : g : / $) breakpoint disable 1
// 启用
(lldb) breakpoint enable 1
iOS逆向 玩转LLDB调试
  • 禁用/启用某一个断点
// 禁用
(lldb) breas r v k ! k lkpoint disable 1.1
// 启用
(lldb) breakpoint enable 1.1
iOS逆向 玩转LLDB调试
  • 删去一切断点
(lldb) breakpoint d] G + ?eletec { s _ 
iOS逆向 玩转LLDB调试
  • “删去”某一组断点(不能删去g ( =单个断点,只能禁用单个H D D (断点)
(R R 2 .lldb) breakpoint delete 1.1
iOS逆向 玩转LLDB调试
  • 设置某一个办法的断点
(lldb) breakpoint set --selector touchesBegan:withEven; % 0 M ] y }t:
iOS逆向 玩转LLDB调试
  • 设置某文件下某一个办, # : | 法的断点
(lldb) breakpoint set --file Vi= & ! P q g ;ewController.m --selector touchesBegan:withEvent:
iOS逆向 玩转LLDB调试
  • 设置一切匹配办法名的断点
(lldbg e J K - [) breakpoint set -r ocMet^ % s lhod
iOS逆向 玩转LLDB调试
  • 退出LLDB形式
(lldb) c
iOS逆向 玩转LLDB调试
  • 检查帮助
// 检查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

关于简写:

  • bbreakpoint set
  • llist
  • -n--name
  • --f--file
  • disdisable
  • enena% 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:履行目标——输出该目标的信息

    iOS逆向 玩转LLDB调试

既然知道了p指令有履行代码的作用E # f,接下来就来玩一下

  • 动态修正布景颜色(笔者在machOS 10.15.5+Xcode11上并不能成功)

    1. u O E H ) }入手动断点(不要点击暂停符号,不然不能获取到self)
    2. 操控台输入p s: b @ X F j K V Belf.view.backgroundColor = [UIColor redColor]% ; g ! 6 D;
    3. 过掉断点就能看到效果了
  • 动态创立{ V % h e ! u 1 7目标并赋值

    1. 设置一个全局变量FXPerson *p
    2. 同样进入手动断点
    3. 操控台输入p self.p = [FXP: Y 7erson new]; self.p.name = @"Felix";
    4. 检查效果
      iOS逆向 玩转LLDB调试

四、函数调用栈

接下来在以下代码中进行调试,点击屏幕顺次调用testtest1test2,在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"];
}
  1. bt——检查函数调i [ q 2 ^ } . a X用栈,能够看到函数调用的次序

    iOS逆向 玩转LLDB调试
  2. up/down——上下挪动函数调用

    iOS逆向 玩转LLDB调试
    iOS逆向 玩转LLDB调试
  3. frame select 数字——跳转函数调用(0表明当时办法,2表明2个办法前)

    iOS逆向 玩转LLDB调试
  4. frame variable——检查当时函数特点:内存地址、办法名、参数

    iOS逆向 玩转LLDB调试
  5. thread return——完毕当时函数调用,跳转回上一个调用栈的下一步(当时是跳转回第30行代码,准备履行31行代码)

    iOS逆向 玩转LLDB调试

由此,能够测验在调用中修正参数的值然后完成新值打印

  1. up修正现已调用过的函数参数

    • 运用up指令回到上一步,运用p s: X ] J l / D p Ctr = @"F";进行修正
      iOS逆向 玩转LLDB调试
    • 过掉断点,仍是打_ . f – ; I c印原Q ! {来的值
      iOS逆向 玩转LLDB调试
  2. 提早修正函数参数

    • 提早在上一处函数调用时打下断点进行修正
      iOS逆向 玩转LLDB调试
    • 过掉断点,新值被打印
      iOS逆向 玩转LLDB调试

总结:现已履行过的代码再怎样回滚也不能随意修正值,应当提早打下断点进行修正

五、内存断点

内存断M ! j n M M r V点,顾名思义便是给内存下的断点

iOS逆向 玩转LLDB调试

经过watchpoint set variable self->_p->_name就能够给对应的特点内S & @ Z存下断点

  • addr:X ] y内存地址
  • size:所占内存字节
  • state:当时是否可用
iOS逆向 玩转LLDB调试

修正内存地址的值就会来到断点处(此时相当于KVO机制)同时也能看到函数调用栈

iOS逆向 玩转LLDB调试
  • 内存断点也能够经过watchpoint list来检查内存断电列表
  • 也能够经过watn } [ G y & Zchpoint delete进行删去

六、断点增加指令

类似于给程序增加脚本指令,断点履行也能够增加指令

iOS逆向 玩转LLDB调试
  • 经过breakpoinY u Q ! n 5t command av : 1dd 1就能够给指定断点增加指令
  • 经过DONE完毕断点指令增加
iOS逆向 玩转LLDB调试

断点到来时就会履行从前的指令了

七、target stop-hook

target stop-hookS l z 2 p I &是一个给一切断点增加指令的指令——在每次stop的时分去履行一些指令(只对breakpoint、watchpoint有用)

iOS逆向 玩转LLDB调试

只需target stop-hook adX } z F G q = w id操作一番,任何+ 1 E l / N断点都会触发增加的指令

iOS逆向 玩转LLDB调试

单条指令能够简写成target stop-hook add -o "frame variable"-o表明单条指令)

iOS逆向 玩转LLDB调试

同样的,也能够运用target stop-hook list检查列表

iOS逆向 玩转LLDB调试

target stopQ C n x u-hook disable进行禁用

iOS逆向 玩转LLDB调试

target sT 5 h q ctok @ =p-hook delete/undisplD 7 May 1进行禁用

iOS逆向 玩转LLDB调试

接下来介绍一个高阶的操作

LLDF q 5 : j ` G WB启动的时分就会去加载一个叫做.lldbinit的文件,在/Users/用户名目录下

iOS逆向 玩转LLDB调试

如果没有的话能够经过vi .lldbinit创立,然后在文件中增加指令targz A { F N set stop-hook add -o & 6 h Y P v D"frame variableq 1 ? [ 9 z / 8 +"

iOS逆向 玩转LLDB调试

重新启动运转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办法

iOS逆向 玩转LLDB调试

此时( ` 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值都不相同)

iOS逆向 玩转LLDB调试

实际地址 = 0x000000010ae85000 + 0x1340 = 0x10AE86340

iOS逆向 玩转LLDB调试

写在后面

LLDB这些指令如同Xcode的快捷键一般,不把握也无妨,把握了便是如虎. t – E i Q F U H添翼,多了一种调试的思路,便能让你摆开与同行之间的距离