iOS逆向-LLDB(VII)

LLDB(Low Lever Debug),默认内置于Xcode中的动态调试工具。标准的 LLDB 提供了一组广泛的命令,旨在与老版本的 GDB 命令兼容。 除了使用标准配置外,还可以很容易地自定义 LLDB 以满足实际需要。

如果逆向别人的代码可以通过暂停程序执行来使程序进入LLDB状态

LLDB有很多指令,如果忘了相关指令,我们可以通过help命令查看

(lldb) help
Debugger commands:
  apropos           -- List debugger commands related to a word or subject.
  breakpoint        -- Commands for operating on breakpoints (see 'help b' for
                       shorthand.)
...

也可以通过apropos列出与某个单词或主题相关的调试器命令

(lldb) apropos breakpoint
The following commands may relate to 'breakpoint':
  _regexp-break                           -- Set a breakpoint using one of
                                             several shorthand formats.
  _regexp-tbreak                          -- Set a one-shot breakpoint using
                                             one of several shorthand formats.
  breakpoint                              -- Commands for operating on
                                             breakpoints (see 'help b' for
                                             shorthand.)
  breakpoint clear                        -- Delete or disable breakpoints
                                             matching the specified source file
                                             and line.
...

常用命令

  • 给所有名为xxx的C函数设置一个断点
(lldb) breakpoint set -name xxx
(lldb) br s -n xxx
(lldb) b xxx
  • 给一个OC函数[objc msgSend:]设置一个断点
(lldb) breakpoint set -n "[objc msgSend:]"
(lldb) b -n "[objc msgSend:]"
  • 给所有名为xxx的OC方法设置一个断点
(lldb) breakpoint set -selector xxx:
  • 给指定文件的某个OC方法设置一个断点
(lldb) breakpoint set --file ViewController.m --selector touchesBegan:withEvent:
  • 给所有包含xxx的字段设置断点
(lldb) breakpoint set -r xxx
  • 给指定文件F的某一行L设置一个断点
(lldb) breakpoint set --file F -line L
  • 断点查看
(lldb) breakpoint list
(lldb) br l
  • 断点删除
(lldb) breakpoint delete index//index是组号
(lldb) breakpoint delete //删除所有断点
(lldb) br del index
  • 禁用/开启断点
(lldb) breakpoint disable index
(lldb) breakpoint enable index

断点的流程控制

  • 继续
(lldb) process continue
(lldb) continue
(lldb) c
  • 单步运行,将子函数当做整体一步执行
(lldb) thread step -over
(lldb) next
(lldb) n
(lldb) ni //单步运行汇编级别
  • 单步运行,遇到子函数会进去
(lldb) thread step -in
(lldb) step
(lldb) s
(lldb) si //单步运行可跳转指令内部,汇编级别
  • 跳出方法,返回上层调用栈
(lldb) thread step -out
(lldb) finish
(lldb) f

expression

expression其实是p的缩写,它的主要作用是在当前线程执行一个表达式,并将结果按照LLDB的默认格式返回。

(lldb) help p
     Evaluate an expression on the current thread.  Displays any returned value
     with LLDB's default formatting.  Expects 'raw' input (see 'help
     raw-input'.)

Syntax: p <expr>

Command Options Usage:
  p <expr>


'p' is an abbreviation for 'expression --'

下面是这个例子,可以看到expression执行了表达式,给属性变量name赋值,并返回了新赋的值,它可以动态的修改变量在内存中的值。

(lldb) po self.name
xiaoli

(lldb) p self.name = @"David"
(NSTaggedPointerString *) $5 = 0xc2f9f48bff645c0d @"David"
(lldb) p self.name
(NSTaggedPointerString *) $6 = 0xc2f9f48bff645c0d @"David"
(lldb) 

查看堆栈信息

在一个函数的断点出,输入bt可查看调用堆栈信息

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x000000010056e1c0 002--LLDB调试`-[ViewController test3:](self=0x0000000151e07750, _cmd="test3:", str=@"hook") at ViewController.m:64:20
    frame #1: 0x000000010056e180 002--LLDB调试`-[ViewController test2:](self=0x0000000151e07750, _cmd="test2:", str=@"hook") at ViewController.m:60:5
    frame #2: 0x000000010056e11c 002--LLDB调试`-[ViewController test1:](self=0x0000000151e07750, _cmd="test1:", str=@"hook") at ViewController.m:56:5
    frame #3: 0x000000010056e258 002--LLDB调试`-[ViewController touchesBegan:withEvent:](self=0x0000000151e07750, _cmd="touchesBegan:withEvent:", touches=1 element, event=0x00000002806d0fa0) at ViewController.m:71:5
    frame #4: 0x0000000193692b64 UIKitCore`forwardTouchMethod + 328
    frame #5: 0x0000000193692a08 UIKitCore`-[UIResponder touchesBegan:withEvent:] + 60
    frame #6: 0x00000001936a0af0 UIKitCore`-[UIWindow _sendTouchesForEvent:] + 1692
    frame #7: 0x00000001936a20a8 UIKitCore`-[UIWindow sendEvent:] + 3352
    frame #8: 0x000000019367eae8 UIKitCore`-[UIApplication sendEvent:] + 336
    frame #9: 0x00000001936f623c UIKitCore`__dispatchPreprocessedEventFromEventQueue + 5880
    frame #10: 0x00000001936f8798 UIKitCore`__handleEventQueueInternal + 4924
    frame #11: 0x00000001936f160c UIKitCore`__handleHIDEventFetcherDrain + 108
    frame #12: 0x000000018f5d67e0 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
    frame #13: 0x000000018f5d6738 CoreFoundation`__CFRunLoopDoSource0 + 80
    frame #14: 0x000000018f5d5ed0 CoreFoundation`__CFRunLoopDoSources0 + 180
    frame #15: 0x000000018f5d101c CoreFoundation`__CFRunLoopRun + 1080
    frame #16: 0x000000018f5d08bc CoreFoundation`CFRunLoopRunSpecific + 464
    frame #17: 0x000000019943c328 GraphicsServices`GSEventRunModal + 104
    frame #18: 0x00000001936666d4 UIKitCore`UIApplicationMain + 1936
    frame #19: 0x000000010056e518 002--LLDB调试`main(argc=1, argv=0x000000016f8978c8) at main.m:14:16
    frame #20: 0x000000018f45b460 libdyld.dylib`start + 4

可以通过updown指令跟进堆栈的调用信息

(lldb) up
frame #1: 0x000000010056e180 002--LLDB调试`-[ViewController test2:](self=0x0000000151e07750, _cmd="test2:", str=@"hook") at ViewController.m:60:5
   57   }
   58   
   59   -(void)test2:(NSString *)str{
-> 60       [self test3:str];
            ^
   61   }
   62   
   63   -(void)test3:(NSString *)str{
(lldb) down
frame #0: 0x000000010056e1c0 002--LLDB调试`-[ViewController test3:](self=0x0000000151e07750, _cmd="test3:", str=@"hook") at ViewController.m:64:20
   61   }
   62   
   63   -(void)test3:(NSString *)str{
-> 64       NSLog(@"!!!%@",str);
                           ^
   65   }

也可以通过frame select index(堆栈的序号)命令来查看具体序号堆栈的调用信息

(lldb) frame select 3
frame #3: 0x000000010056e258 002--LLDB调试`-[ViewController touchesBegan:withEvent:](self=0x0000000151e07750, _cmd="touchesBegan:withEvent:", touches=1 element, event=0x00000002806d0fa0) at ViewController.m:71:5
  68   
  69   -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
  70   {
-> 71       [self test1:@"hook"];
           ^
  72       //Person * p1 = self.models.firstObject;
  73   }
  74   - (IBAction)save:(id)sender {

通过frame variable命令查看具体序号堆栈的参数

(lldb) frame variable
(ViewController *) self = 0x0000000151e07750
(SEL) _cmd = "touchesBegan:withEvent:"
(__NSSetM *) touches = 0x00000002837f34a0 1 element
(UITouchesEvent *) event = 0x00000002806d0fa0

回滚thread return命令,会回到上一层调用堆栈,但是不会向下继续执行

(lldb) thread return
2019-10-26 16:24:54.495174+0800 002--LLDB调试[13707:437713] XPC connection interrupted

内存断点watchpoint

watchpoint可以对方法或者对象的内存地址设置断点,如果对属性操作,类似KVO观察者,如下是对一个属性变量设置的内存断点,如果属性变量的值发生改变了,程序就会自动中断

(lldb) po self
<ViewController: 0x1033040d0>

(lldb) n
(lldb) watchpoint set variable self->_name
Watchpoint created: Watchpoint 1: addr = 0x103304428 size = 8 state = enabled type = w
    watchpoint spec = 'self->_name'
    new value: 0x0000000102c10098
(lldb) c
Process 14669 resuming

Watchpoint 1 hit:
old value: 0x0000000102c10098
new value: 0x0000000102c10158
2019-10-28 10:52:01.935109+0800 002--LLDB调试[14669:514790] !!!hook
(lldb) po 0x0000000102c10098
lilei

(lldb) po 0x0000000102c10158
David

也可以通过如下方式操作

(lldb) p &self->_name
(NSString **) $0 = 0x0000000103303b48
(lldb) watchpoint set expression 0x0000000103303b48
Watchpoint created: Watchpoint 1: addr = 0x103303b48 size = 8 state = enabled type = w
    new value: 4343234712
(lldb) c
Process 14731 resuming

Watchpoint 1 hit:
old value: 4343234712
new value: 4343234872
(lldb) po 4343234712
lilei

(lldb) po 4343234872
David

watchpoint类似breakpoint也有listdelete等相关命令,可以通过help watchpoint命令来熟悉

(lldb) help watchpoint
     Commands for operating on watchpoints.

Syntax: watchpoint <subcommand> [<command-options>]

The following subcommands are supported:

      command -- Commands for adding, removing and examining LLDB commands
                 executed when the watchpoint is hit (watchpoint 'commands').
      delete  -- Delete the specified watchpoint(s).  If no watchpoints are
                 specified, delete them all.
      disable -- Disable the specified watchpoint(s) without removing it/them. 
                 If no watchpoints are specified, disable them all.
      enable  -- Enable the specified disabled watchpoint(s). If no watchpoints
                 are specified, enable all of them.
      ignore  -- Set ignore count on the specified watchpoint(s).  If no
                 watchpoints are specified, set them all.
      list    -- List all watchpoints at configurable levels of detail.
      modify  -- Modify the options on a watchpoint or set of watchpoints in
                 the executable.  If no watchpoint is specified, act on the
                 last created watchpoint.  Passing an empty argument clears the
                 modification.
      set     -- Commands for setting a watchpoint.

For more help on any particular subcommand, type 'help <command> <subcommand>'.

command

command可以用来给一个断点添加命令,如下所示,先给test1方法设置断点,然后用command添加命令,当再一次调用test1方法的时候,程序就会执行test1方法添加的指令

(lldb) breakpoint set -n "[ViewController test1:]"
Breakpoint 3: where = 002--LLDB调试`-[ViewController test1:] + 48 at ViewController.m:57:6, address = 0x0000000104b86100
(lldb) breakpoint command add 3
Enter your debugger command(s).  Type 'DONE' to end.
> po self
> p self.view
> DONE
(lldb) c
Process 14830 resuming
 po self
<ViewController: 0x105107580>

 p self.view
(UIView *) $1 = 0x0000000105209550

(lldb) breakpoint command list 3
Breakpoint 3:
    Breakpoint commands:
      po self
      p self.view
(lldb) breakpoint command delete 3
(lldb) breakpoint command list 3
Breakpoint 3 does not have an associated command.

target stop-hook

target stop-hook让每个断点都去执行一些命令,可以把它当作初始化的配置,如下所示,在每个断点处添加target stop-hook add -o "frame variable"查看每个断点的参数信息,当断点触发的时候,该断点的参数信息就会打印出来

(lldb) breakpoint list
Current breakpoints:
1: file = '/Users/niujf/Desktop/ios逆向/007--LLDB/代码/002--LLDB调试/002--LLDB调试/ViewController.m', line = 56, exact_match = 0, locations = 1, resolved = 1, hit count = 0

  1.1: where = 002--LLDB调试`-[ViewController test1:] + 48 at ViewController.m:57:6, address = 0x00000001027ba100, resolved, hit count = 0 

2: file = '/Users/niujf/Desktop/ios逆向/007--LLDB/代码/002--LLDB调试/002--LLDB调试/ViewController.m', line = 70, exact_match = 0, locations = 1, resolved = 1, hit count = 0

  2.1: where = 002--LLDB调试`-[ViewController touchesBegan:withEvent:] + 80 at ViewController.m:72:6, address = 0x00000001027ba240, resolved, hit count = 0 

(lldb) target stop-hook add -o "frame variable" //查看每个断点的参数信息
Stop hook #1 added.
(lldb) c
Process 14962 resuming
(ViewController *) self = 0x0000000143e06f90
(SEL) _cmd = "touchesBegan:withEvent:"
(__NSSetM *) touches = 0x00000002800e5a20 1 element
(UITouchesEvent *) event = 0x00000002831f8c80

(lldb) c
Process 14962 resuming
(ViewController *) self = 0x0000000143e06f90
(SEL) _cmd = "test1:"
(__NSCFConstantString *) str = 0x00000001027bc138 @"hook"

image

image lookup -t xxxx可以查看文件的详细信息

(lldb) image lookup -t ViewController
Best match found in /Users/niujf/Library/Developer/Xcode/DerivedData/002--LLDB调试-hblhlghervytczgywjtrdblfcdga/Build/Products/Debug-iphoneos/002--LLDB调试.app/002--LLDB调试:
id = {0x10000002b}, name = "ViewController", byte-size = 24, decl = ViewController.h:11, compiler_type = "@interface ViewController : UIViewController{
    NSMutableArray * _models;
    NSString * _name;
}
@property ( getter = models,setter = setModels:,readwrite,nonatomic ) NSMutableArray * models;
@property ( getter = name,setter = setName:,readwrite,copy,nonatomic ) NSString * name;
@end"

image list查看调用的库

(lldb) image list
[  0] EE92FCA2-C78B-31CC-8C2C-C7A123E92F28 0x00000001029b8000 /Users/niujf/Library/Developer/Xcode/DerivedData/002--LLDB调试-hblhlghervytczgywjtrdblfcdga/Build/Products/Debug-iphoneos/002--LLDB调试.app/002--LLDB调试 
[  1] 571392A7-E1E6-369F-8805-C1A141F3C1C5 0x0000000102cdc000 /Users/niujf/Library/Developer/Xcode/iOS DeviceSupport/13.1.3 (17A878)/Symbols/usr/lib/dyld 
...
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容