文章目录
先在越狱手机上用登录,并且启动debugserver mac端启动lldb
如果没有安装请查看这篇文章
ios 让debugserver可以调试任意app
安装好debugserver并且都设置好ssh了就直接执行下面操作
mac端:
sh usb.sh
sh login.sh
手机端:
debugserver localhost:20001 -a 进程名字
mac端:
lldb
process connect connect://localhost:20001
计算大小app page0偏移量大小
登录上lldb以后
通过下面命令查看进程段落
image list -o -f
image list -o -f | grep 进程名区分大小写
例如微信就是:
image list -o -f | grep WeChat
得到wechat的page0段落大小是:0x0000000004220000 ,如下:
(lldb) image list -o -f |grep WeChat
[ 0] 0x0000000004220000 /private/var/containers/Bundle/Application/C9D99801-9F4C-41E4-824F-3213CAB26717/WeChat.app/WeChat(0x0000000104220000)
使用hopper给要调试函数找到函数地址
关于hopper计算的细节原理可以查看下面文章
使用lldb和hopper计算函数地址给运行中的app添加断点
找到自己要下断点的函数地址,如下图:00000001034cce18
lldb设置断点
用上面的app偏移量+函数地址,就是函数运行在内存中的地址,注意,加号两边不要有空格,并且数字前面加上0x表示16进制,hopper的地址没有自动加上0x
(lldb) br set -a 0x0000000004220000+0x00000001034cce18
设置断点成功如下:
(lldb) br set -a 0x0000000004220000+0x00000001034cce18
Breakpoint 2: where = WeChat`___lldb_unnamed_symbol242619$$WeChat, address = 0x00000001076ece18
设置完断点以后,例如现在下断点的函数是点击屏幕以后出发的,那么点击屏幕后会停在这个断点处
通过lldb 可以读取寄存器的值
例如输入re read查看寄存器的值
(lldb) re read
General Purpose Registers:
x0 = 0x000000011b276800
x1 = 0x0000000112e2f360 "touchesBegan_TableView:withEvent:"
x2 = 0x0000000280301560
x3 = 0x0000000283202b80
x4 = 0x000000016bbdc5c8
...
因为普通的oc方法会编译成c++方法,例如下面的test1::会改成objc_msgSend,
[vc test1:arg1 :arg2];
objc_msgSend(vc,@selector(test1::),arg1,arg2)
objc_msgSend的参数:
- 参数1是调用的控制器
- 参数2是方法名
- 参数3是test1函数参数1
- 参数4是test1函数参数2
参数1.2.3.4分别存在寄存器x0,x1,x2,x3里
所以在lldb调试方法的时候,寄存器内容如下:
po $x0. //打印是调用的控制器
x/s $x1 //打印方法名
po $x2 //打印参数1
po $x3 //打印参数2..
x0寄存器是调用这个方法的对象
(lldb) re read x0
x0 = 0x000000011b276800
(lldb) po $x0
<BaseMsgContentViewController: 0x11b276800>
x1寄存器是方法名
(lldb) re read x1
x1 = 0x0000000112e2f360 "touchesBegan_TableView:withEvent:"
(lldb) x/s 0x0000000112e2f360
0x112e2f360: "touchesBegan_TableView:withEvent:"
x2 是参数1
(lldb) re read x2
x2 = 0x0000000280301560
(lldb) po $x2
{(
<UITouch: 0x12bdd8050> phase: Began tap count: 1 force: 0.133 window: <iConsoleWindow: 0x11a928f20; baseClass = UIWindow; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x2809117a0>; layer = <UIWindowLayer: 0x28073d360>> view: <YYAsyncImageView: 0x130fe20a0; baseClass = UIImageView; frame = (-5 0; 239 84); layer = <YYAsyncLayer: 0x2813a4870>> location in window: {237, 189.5} previous location in window: {237, 189.5} location in view: {177, 40.5} previous location in view: {177, 40.5}
)}
x3是参数2
(lldb) re read x3
x3 = 0x0000000283202b80
(lldb) po $x3
<UITouchesEvent: 0x283202b80> timestamp: 465.034 touches: {(
<UITouch: 0x12bdd8050> phase: Began tap count: 1 force: 0.133 window: <iConsoleWindow: 0x11a928f20; baseClass = UIWindow; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x2809117a0>; layer = <UIWindowLayer: 0x28073d360>> view: <YYAsyncImageView: 0x130fe20a0; baseClass = UIImageView; frame = (-5 0; 239 84); layer = <YYAsyncLayer: 0x2813a4870>> location in window: {237, 189.5} previous location in window: {237, 189.5} location in view: {177, 40.5} previous location in view: {177, 40.5}
)}
通过lr寄存器查看调用函数的地址
(lldb) re read lr
lr = 0x000000011e12e3b0 tweek_wechat.dylib`___lldb_unnamed_symbol381$$tweek_wechat.dylib + 104
通过bt指令查看函数调用栈
下面frame #1刚好就是上面 lr的地址,就是调用本函数的函数地址
(lldb) bt
* frame #0: 0x00000001076ece18 WeChat`___lldb_unnamed_symbol242619$$WeChat
frame #1: 0x000000011e12e3b0 tweek_wechat.dylib`___lldb_unnamed_symbol381$$tweek_wechat.dylib + 104
frame #2: 0x0000000110590b2c WeChat`___lldb_unnamed_symbol1610700$$WeChat + 244
frame #3: 0x00000001ad369420 UIKitCore`forwardTouchMethod + 316
frame #4: 0x00000001ad3692d0 UIKitCore`-[UIResponder touchesBegan:withEvent:] + 60
frame #5: 0x00000001ad4cd0cc UIKitCore`-[UITableViewCell touchesBegan:withEvent:] + 136
frame #6: 0x00000001ad369420 UIKitCore`forwardTouchMethod + 316
frame #7: 0x00000001ad3692d0 UIKitCore`-[UIResponder touchesBegan:withEvent:] + 60
frame #8: 0x00000001ad369420 UIKitCore`forwardTouchMethod + 316
frame #9: 0x00000001ad3692d0 UIKitCore`-[UIResponder touchesBegan:withEvent:] + 60
frame #10: 0x0000000107acb060 WeChat`___lldb_unnamed_symbol259286$$WeChat + 96
计算函数调用栈里面函数的地址
tweek_wechat.dylib 的函数是自己用tweek里面添加的hook方法的打印函数参数的方法
第1个函数 0x00000001076ece18 地址,就是咱们下断点的函数地址.
第2个函数 0x000000011e12e3b0 不是代码段的函数
第3个函数0x0000000110590b2c 是代码段的函数
frame #10: 0x0000000107acb060 WeChat`___lldb_unnamed_symbol259286$$WeChat + 96
这里计算frame #10的地址
是带偏移量的,减去app偏移量,用计算器算:
0x0000000107acb060-0x0000000004220000=0x1038AB060
在hopper中找到地址对应的函数
快捷键g,把地址输入进去,跳转到汇编指令
也可以点击 上面Navigate->Go To Address or Symbol…
有的函数找不到,就多换几个
00000001038ab05c bl sub_107bfedbc+21112
00000001038ab060 adrp x8, #0x111753000 ; 0x111753314@PAGE
00000001038ab064 ldrsw x8, [x8, #0x314] ; 0x111753314@PAGEOFF, objc_ivar_offset_BaseMessageCellView_m_bDisableAllOperation
在cydia中删掉自己写的tweek方法
删掉自己写的tweek打印方法可以在bt的时候可以直接查看原始的函数调用栈
app从启动开始就用lldb调试
首先关闭app
然后查看app在手机上的包的位置
使用MJAppTools查看应用位置
MJAppTools -l
/private/var/containers/Bundle/Application/C9D99801-9F4C-41E4-824F-3213CAB26717/WeChat.app
debugserver -x auto localhost:20001 app包地址
例如:
debugserver -x auto localhost:20001 /private/var/containers/Bundle/Application/C9D99801-9F4C-41E4-824F-3213CAB26717/WeChat.app
mac端
lldb
process connect connect://localhost:20001
这样app会自动启动,然后停住
tdw@tdwdeMac-mini-m1 ~ % lldb
(lldb) process connect connect://localhost:20001
Process 2789 stopped
* thread #1, stop reason = signal SIGSTOP
frame #0: 0x0000000116135000 dyld`_dyld_start
dyld`_dyld_start:
-> 0x116135000 <+0>: mov x28, sp
0x116135004 <+4>: and sp, x28, #0xfffffffffffffff0
0x116135008 <+8>: mov x0, #0x0
0x11613500c <+12>: mov x1, #0x0
Target 0: (WeChat) stopped.
然后通过n或者si指令 或者c调试app