http://versprite.com/og/ios-reverse-engineering-part-two-debugging-and-tracing-with-lldb/

iOS Reverse Engineering Part Two: Debugging and Tracing with LLDB

Overview

In our previous post – http://versprite.com/og/ios-reverse-engineering-part-one-configuring-lldb/ – we learned how to configure and setup debugserver and LLDB on your iOS device. In this post we will demonstrate how to use LLDB to perform basic debugging and message tracing.

objc_msgSend()

This topic has already been covered numerous times, but lets run through a refresher on Objective-C’s objc_msgSend(). This function is one of the more important items within the libobjc.A.dylib library. During runtime objc_msgSend() is used to send messages to an object within memory. This can be considered the equivalent to calling functions in C.

The compiler will convert a message expression – [receiver message] into a call on objc_msgSend(). When we take a look at the objc_msgSend() declaration:

id objc_msgSend (id self, SEL op, arg1, arg2 ..)

We see as parameters it takes a pointer to the instance of the class that is to receive the message, and the selector of the method that handles the message. objc_msgSend() takes the id type, which is literally just a pointer to a C struct, being identified as objc_object. After an object is created, memory is allocated for the objc_object type that consists if an isa pointer, which is followed by the data for that object. In this usage, the id type is basically a pointer to the receiver’s class instance in memory.

The second argument SEL, is pretty much the method’s signature string representation. Whew! Hopefully this is making a bit of sense, and now we can move into learning about ARM, and the Procedure Call Standard for the ARM Architecture.

ARM Calling Conventions

The ARM architecture contains 16 registers numbered r0 – r15, each 32-bits wide. The procedure call standard state that the first four registers (r0 – r3) are used to pass argument values into a subroutine and to return a result value from a function.

The prolog for a function call goes something like this:

– PUSH the value of the link register (LR)(r14) to the stack
– PUSH the value of the frame pointer (r7) to the stack
– Update the frame pointer to the value of the stack pointer (SP)
– PUSH the preserved registers to the stack
– Make space for local storage

An example might look like this:

push    {r4-r7, lr} // save LR, R7, R4-R6
add r7, sp, #12 // adjust R7 to point to saved R7
push {r8, r10, r11} // save remaining GPRs (R8, R10, R11)
vstmdb sp!, {d8-d15} // save VFP/Advanced SIMD registers D8
sub sp, sp, #36 // allocate space for local storage

objc_msgSend() Tracing

In order to start tracing objc_msgSend(), let us combine everything we have learned so far. We know from the declaration that objc_msgSend() takes two parameters, which point to the class instance and method signature. We also know from the ARM calling conventions, that the registers r0, and r1 will probably contain those respective values being passed into the objc_msgSend() function.

We will be using the Damn Vulnerable iOS App for demonstration. The first thing I am going to do is set breakpoint at [InsecureDataStorageVulnVC saveinPlistFileTapped:], because I only really wanna to trace the objc_msgSend() calls within this subroutine.

(lldb) b -[InsecureDataStorageVulnVC saveInPlistFileTapped:] Breakpoint 1: where = DamnVulnerableIOSApp`-[InsecureDataStorageVulnVC saveInPlistFileTapped:], address = 0x000e5c2c

Now when we venture over to the application and attempt to save our data in the Plist file:

* thread #1: tid = 0x145aa, 0x000d0c2c DamnVulnerableIOSApp`-[InsecureDataStorageVulnVC saveInPlistFileTapped:], queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x000d0c2c DamnVulnerableIOSApp`-[InsecureDataStorageVulnVC saveInPlistFileTapped:]
DamnVulnerableIOSApp`-[InsecureDataStorageVulnVC saveInPlistFileTapped:]:
-> 0xd0c2c: push {r4, r5, r6, r7, lr}
0xd0c2e: add r7, sp, #0xc
0xd0c30: push.w {r8, r10, r11}
0xd0c34: sub sp, #0xc

To start tracing the objc_msgSend() calls within this subroutine let us disassemble where we are currently located.

(lldb) di
DamnVulnerableIOSApp`-[InsecureDataStorageVulnVC saveInPlistFileTapped:]:
-> 0xd0c2c: push {r4, r5, r6, r7, lr}
0xd0c2e: add r7, sp, #0xc
0xd0c30: push.w {r8, r10, r11}
0xd0c34: sub sp, #0xc
0xd0c36: mov r4, r0
0xd0c38: movs r0, #0x9
0xd0c3a: movs r1, #0x1
0xd0c3c: movs r2, #0x1
0xd0c3e: blx 0x291db0 ; symbol stub for: NSSearchPathForDirectoriesInDomains
0xd0c42: mov r7, r7
0xd0c44: blx 0x291e44 ; symbol stub for: objc_retainAutoreleasedReturnValue
0xd0c48: str r0, [sp, #0x8]
0xd0c4a: movw r1, #0x76b8
0xd0c4e: movt r1, #0x1d
0xd0c52: movs r2, #0x0
0xd0c54: add r1, pc
0xd0c56: ldr r1, [r1]
0xd0c58: blx 0x291e28 ; symbol stub for: objc_msgSend
0xd0c5c: mov r7, r7

We can set a breakpoint at the address 0x291e28 for the objc_msgSend() call.

(lldb) b 0x291e28

Breakpoint 2: where = DamnVulnerableIOSApp`symbol stub for: objc_msgSend, address = 0x00291e28

However once we hit this breakpoint, we need to perform additional inspection. We can do this by adding a stop-hook:

(lldb) target stop-hook add
Enter your stop hook command(s). Type 'DONE' to end.
> register read
> x/s $r1
> expr -o -- $r0
> DONE
Stop hook #1 added.

Through this stoop-hook we will read the values in the current registers, examine the contents of r1 as a string, and print the object description of the pointer located in r0. Remember r1 should contain the selector and r0 should contain the class instance.

After resuming execution, we hit the next breakpoint that we have set, and our stoop-hook is invoked.

General Purpose Registers:
r0 = 0x176f6d70
r1 = 0x335c9122 "objectAtIndex:"
r2 = 0x00000000
r3 = 0x00000000
r4 = 0x176d50d0
r5 = 0x001402bf "saveInPlistFileTapped:"
r6 = 0x175d8d30
r7 = 0x27d40528
r8 = 0x17664620
r9 = 0x00000000
r10 = 0x175f1180
r11 = 0x00000000
r12 = 0x3d47f1d0 (void *)0x3b627959: _os_lock_handoff_unlock$VARIANT$mp + 1
sp = 0x27d40504
lr = 0x000d0c5d DamnVulnerableIOSApp`-[InsecureDataStorageVulnVC saveInPlistFileTapped:] + 49
pc = 0x00291e28 DamnVulnerableIOSApp`symbol stub for: objc_msgSend
cpsr = 0x40000010 0x335c9122: "objectAtIndex:"
<__NSArrayI 0x176f6d70>(
/var/mobile/Applications/04A94C51-51CD-4633-9649-ACE1BCCFED72/Documents
)

Everything looks to be working, now we have a little homemade tracer, and can start moving through the rest of the calls.

General Purpose Registers:
r0 = 0x3b7b8df4 (void *)0x3b7b8dcc: NSMutableDictionary
r1 = 0x380953cd "alloc"
r2 = 0x002aa198 (void *)0x3b7b8df4: NSMutableDictionary
r3 = 0x00000001
r4 = 0x176d50d0
r5 = 0x001402bf "saveInPlistFileTapped:"
r6 = 0x175d8d30
r7 = 0x27d40528
r8 = 0x17664620
r9 = 0x17902868
r10 = 0x175f1180
r11 = 0x00000000
r12 = 0x3b011479 libobjc.A.dylib`-[NSObject autorelease] + 1
sp = 0x27d40504
lr = 0x000d0ca3 DamnVulnerableIOSApp`-[InsecureDataStorageVulnVC saveInPlistFileTapped:] + 119
pc = 0x00291e28 DamnVulnerableIOSApp`symbol stub for: objc_msgSend
cpsr = 0x60000010 0x380953cd: "alloc"
NSMutableDictionary

https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/lldb-command-examples.html

转载一篇debug文章的更多相关文章

  1. [转载]转载一篇好文章作为Java与面向对象之随感(3)

    关于对象与引用之间的一些基本概念. 初学Java时,在很长一段时间里,总觉得基本概念很模糊.后来才知道,在许多Java书中,把对象和对象的引用混为一谈.可是,如果我分不清对象与对象引用, 那实在没法很 ...

  2. 上一篇括号配对让人联想起catalan数,顺便转载一篇归纳的还不错的文章

    转载请注明来自souldak,微博:@evagle 怎么样才是合法的组合? 只要每一时刻保证左括号的数目>=右括号的数目即可. 直接递归就行,每次递归加一个括号,左括号只要还有就能加,右括号要保 ...

  3. 前两篇转载别人的精彩文章,自己也总结一下python split的用法吧!

    前言:前两篇转载别人的精彩文章,自己也总结一下吧! 最近又开始用起py,是为什么呢? 自己要做一个文本相似度匹配程序,大致思路就是两个文档,一个是试题,一个是材料,我将试题按每题分割出来,再将每题的内 ...

  4. MySQL优化篇系列文章(二)——MyISAM表锁与InnoDB锁问题

    我可以和面试官多聊几句吗?只是想... MySQL优化篇系列文章(基于MySQL8.0测试验证),上部分:优化SQL语句.数据库对象,MyISAM表锁和InnoDB锁问题. 面试官:咦,小伙子,又来啦 ...

  5. 开博客这么久以来,第一篇技术文章,python与c的接口对接

    在博客园开博客已经有了蛮长时间了,但是从来只是看别人的文章,自己却从未写过一篇技术文章,深表惭愧.内心还是希望能够给大家提供一些帮助的,希望这第一篇技术博客,能够给大家一些帮助.闲话少叙,开始正文. ...

  6. C++语言,统计一篇英文文章中的单词数(用正则表达式实现)

    下面的例子展示了如何在C++11中,利用regex_search()统计一篇英文文章中的单词数: #include <iostream> #include <regex> #i ...

  7. SAP成都研究院2018年总共87篇技术文章合集

    2018年很快就要结束了.Jerry在2017年年底准备开始写这个公众号时,给自己定的目标是:2018年至少保证每周发布一篇高质量的文章.如今2018年就快过去了,高质量与否需要大家来反馈,至少从量上 ...

  8. 跟我学SpringCloud | 终篇:文章汇总(持续更新)

    SpringCloud系列教程 | 终篇:文章汇总(持续更新) 我为什么这些文章?一是巩固自己的知识,二是希望有更加开放和与人分享的心态,三是接受各位大神的批评指教,有任何问题可以联系我: inwsy ...

  9. 【Jmeter】他人总结篇链接(共八篇相关文章)

    [Jmeter]他人总结篇链接(共八篇相关文章) https://blog.csdn.net/mu_wind/article/category/9029006

随机推荐

  1. Java环境变量配置错误

    1,由于Java的环境变量配置错误,导致用到Java的编译过程中出现错误: 改正办法: wget http://download.oracle.com/otn-pub/java/jdk/8u181-b ...

  2. VC/MFC程序开启关闭和打开自己或其他软件,更改窗口类

    一. 关闭自身软件 直接在需要关闭的位置输入 HANDLE hself = GetCurrentProcess(); TerminateProcess(hself, 0); 二.关闭其他软件 流程: ...

  3. 前端开发利器 Emmet 介绍与基础语法教程

    在前端开发的过程中,编写 HTML.CSS 代码始终占据了很大的工作比例.特别是手动编写 HTML 代码,效率特别低下,因为需要敲打各种“尖括号”.闭合标签等.而现在 Emmet 就是为了提高代码编写 ...

  4. Linux下常用命令wget的使用技巧

    Linux下wget是一个下载文件的工具,它用在命令行下.对于Linux用户是必不可少的工具,尤其对于网络管理员 经常要下载一些软件或从远程服务器恢复备份到本地服务器.如果我们使用虚拟主机,处理这样的 ...

  5. [转]Android Activity的加载模式和onActivityResult方法之间的冲突

    前言 今天在调试程序时,发现在某一Activity上点击返回键会调用该Activity的onActivityResult()方法.我一开始用log,后来用断点跟踪调试半天,还是百思不得其解.因为之前其 ...

  6. django的queryset和objects对象

    1. queryset是查询集,就是传到服务器上的url里面的内容.Django会对查询返回的结果集QerySet进行缓存,这里是为了提高查询效率. 也就是说,在你创建一个QuerySet对象的时候, ...

  7. POJ-1189 钉子和小球(动态规划)

    钉子和小球 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 7452 Accepted: 2262 Description 有一个 ...

  8. PAT天梯赛L2-003 月饼【贪心】

    L2-003. 月饼 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不 ...

  9. OpenCV学习笔记之课后习题练习3-3

    3.3 创建一个100*100的拥有三个通道的二维字节类型矩阵,将其元素全部置0.通过cvPtr2D函数将指针指向中间通道(绿色),以(20,5)和(40,20)为顶点间画一个绿色的长方形. cvPt ...

  10. 【紫书】【重要】Not so Mobile UVA - 839 递归得漂亮

    题意:判断某个天平是否平衡,输入以递归方式给出. 题解:递归着输入,顺便将当前质量作为 &参数 维护一下,顺便再把是否平衡作为返回值传回去. 坑:最后一行不能多回车 附:天秀代码 #defin ...