1.安装和配置 lldb
xcode自带,进入的方式:
➜ ~ /Applications/Xcode.app/Contents/Developer/usr/bin/lldb
(lldb) process connect connect://localhost:1234
2.安装和配置debug server
配置debugserver, 这部分都在OSX中操作
- 需要把设备连接xcode, 在Window->Devices中添加此设备, debugserver就会被安装到 /Developer/usr/bin目录下。
- 默认的debugserver是不能调试别人的app的,所以需要做一些配置。
- 把未经处理的debugserver从iOS拷贝到OSX的 ~/ 目录
- 减肥,注意要根据设备来决定用哪个cpu类型,iphone5s以上都是arm64, 5和5c是armv7s
➜ ~ lipo -thin arm64 ~/debugserver -output ~/debugserver
- 下载http://iosre.com/ent.xml到~/目录
- 给debugserver添加task_for_pid权限
➜ ~ /opt/theos/bin/ldid -Sent.xml debugserver
- 把修改后到debugserver拷贝到ios设备的/usr/bin目录,因为这个目录下的文件都可以直接运行。
启动debugserver
1.启动server的监听
ce6Plus:~ root# debugserver -x backboard localhost:1234 /var/mobile/Containers/Bundle/Application/CA27858D-C4E3-4FD8-B1C6-77DAAF1CF601/MomoChat.app/MomoChat
3.iOS内存地址概念
1. lldb 中 image list -o -f 的返回数据意义
[ 0] 0x0000000000008000 /private/var/mobile/Containers/Bundle/Application/CA27858D-C4E3-4FD8-B1C6-77DAAF1CF601/MomoChat.app/MomoChat(0x0000000100008000)
第一列[0]是模块序号。
第二列0x0000000000008000是ASLR偏移量。
这就是我们需要从lldb中找到的关键地址,后面调试的断点地址都是基于这个ASLR偏移量来计算的。
第三列是模块的文件位置,后面的括号是便宜后的地址,不用管
目前只需要知道偏移了0x74000
刚开始调试时的输出:
(lldb) process connect connect://localhost:1234
Process 27894 stopped
* thread #1: tid = 0x1aef82, 0x0000000197950e0c libsystem_kernel.dylib`mach_msg_trap + 8, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x0000000197950e0c libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
-> 0x197950e0c <+8>: ret
libsystem_kernel.dylib`mach_msg_overwrite_trap:
0x197950e10 <+0>: movn x16, #0x1f
0x197950e14 <+4>: svc #0x80
0x197950e18 <+8>: ret
2.如何打断点
在得到模块便宜量后,在IDA或者Hopper中找到想打断点的方法,找到他们的基地址,
基地址 + lldb拿到的ASLR偏移地址 = 需要打断点的地址
用momo来测试:
找到[MDRegisterBaseViewController enableNextBtn:]: 这个方法的入口地址
偏移前: 00000001009bad58
偏移后 = 0x74000 + 00000001009bad58 = 0x100A2ED58
设置断点:
(lldb) br s -a 0x100A2ED58
成功在输入数据后触发断点
(lldb) br s -a 0x100A2ED58
Breakpoint 2: where = MomoChat`_mh_execute_header + 10179032, address = 0x0000000100a2ed58
Process 27894 stopped
* thread #1: tid = 0x1aef82, 0x0000000100a2ed58 MomoChat`_mh_execute_header + 10202456, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
frame #0: 0x0000000100a2ed58 MomoChat`_mh_execute_header + 10202456
MomoChat`_mh_execute_header:
-> 0x100a2ed58 <+10202456>: stp x20, x19, [sp, #-32]!
0x100a2ed5c <+10202460>: stp x29, x30, [sp, #16]
0x100a2ed60 <+10202464>: add x29, sp, #16 ; =16
0x100a2ed64 <+10202468>: mov x19, x2
3.如何用快捷的方式直接找到方法调用的内存入口
- (lldb) po [ClassName _shortMethodDescription]
(lldb) po [MDApiBase _shortMethodDescription]
<MDApiBase: 0x102f61ee0>:
in MDApiBase:
Class Methods:
+ (void) postRequestWithUrl:(id)arg1 requestIdentifier:(id)arg2 param:(id)arg3 timeout:(unsigned long)arg4 userInfo:(id)arg5 target:(id)arg6 ok:(SEL)arg7 err:(SEL)arg8 fail:(SEL)arg9; (0x101851d1c)
+ (void) addExtraVerifyInfoToParaDictionary:(id)arg1; (0x1000a4c50)
+ (void) dataRequestWithUrl:(id)arg1 requestIdentifier:(id)arg2 param:(id)arg3 data:(id)arg4 timeout:(unsigned long)arg5 userInfo:(id)arg6 target:(id)arg7 ok:(SEL)arg8 err:(SEL)arg9 fail:(SEL)arg10; (0x10185311c)
+ (void) outRequestWithUrl:(id)arg1 requestIdentifier:(id)arg2 requestType:(id)arg3 param:(id)arg4 timeout:(unsigned long)arg5 userInfo:(id)arg6 target:(id)arg7 ok:(SEL)arg8 err:(SEL)arg9 fail:(SEL)arg10; (0x101853700)
+ (void) specialPostRequestWithUrl:(id)arg1 specifyCookie:(id)arg2 requestIdentifier:(id)arg3 param:(id)arg4 timeout:(unsigned long)arg5 userInfo:(id)arg6 target:(id)arg7 ok:(SEL)arg8 err:(SEL)arg9 fail:(SEL)arg10; (0x1018524ac)
+ (void) postRequestWithURLString:(id)arg1 requestType:(unsigned long)arg2 requestIdentifier:(id)arg3 para:(id)arg4 timeOut:(unsigned long)arg5 userInfo:(id)arg6 target:(id)arg7 ok:(SEL)arg8 err:(SEL)arg9 fail:(SEL)arg10; (0x103b0ec58)
+ (void) dataRequestWithUrl:(id)arg1 requestType:(unsigned long)arg2 requestIdentifier:(id)arg3 param:(id)arg4 data:(id)arg5 timeout:(unsigned long)arg6 userInfo:(id)arg7 target:(id)arg8 ok:(SEL)arg9 err:(SEL)arg10 fail:(SEL)arg11; (0x1018536c4)
+ (void) postRequestWithAPIPara:(id)arg1; (0x101853a60)
+ (void) backgroundPostWithUrl:(id)arg1 parameters:(id)arg2 target:(id)arg3 backgroundDelegate:(id)arg4 ok:(SEL)arg5 err:(SEL)arg6 fail:(SEL)arg7; (0x1018527c4)
+ (void) resumeWithTask:(id)arg1 apiParam:(id)arg2; (0x101853f64)
+ (void) realPostWithURLString:(id)arg1 requestType:(unsigned long)arg2 requestIdentifier:(id)arg3 para:(id)arg4 timeOut:(unsigned long)arg5 userInfo:(id)arg6 target:(id)arg7 ok:(SEL)arg8 err:(SEL)arg9 fail:(SEL)arg10 concurrentParseBlock:(^block)arg11; (0x101851dac)
+ (void) dataRequestWithUrl:(id)arg1 requestType:(unsigned long)arg2 requestIdentifier:(id)arg3 param:(id)arg4 data:(id)arg5 timeout:(unsigned long)arg6 userInfo:(id)arg7 target:(id)arg8 ok:(SEL)arg9 err:(SEL)arg10 fail:(SEL)arg11 concurrentParseBlock:(^block)arg12; (0x1018531b8)
+ (void) realBackgroundPostWithDelegate:(id)arg1; (0x101852a08)
+ (void) postRequestWithURLString:(id)arg1 requestType:(unsigned long)arg2 requestIdentifier:(id)arg3 para:(id)arg4 timeOut:(unsigned long)arg5 userInfo:(id)arg6 target:(id)arg7 ok:(SEL)arg8 err:(SEL)arg9 fail:(SEL)arg10 concurrentParseBlock:(^block)arg11; (0x101852244)
(NSObject ...)
- 找到需要打断点的方法的内存地址,设置断点:
b 0x1018536c4
- 进入断点后,就可以获取各个寄存器的内容了
po $x0 ; 这种是直接获取
p (char *)$x1 ; 如果是方法调用这个获取??
4.获取stack pointer中的入参
x/10 $sp
5.清除,禁用断点
br dis ; 禁用所有断点
br dis 6 ; 禁用某个断点
br en ; 启用所有断点
br en 6 ; 启用某个断点
br del ; 删除所有断点
br del 8 ; 删除某个断点