美文网首页
关闭打开APP蜂窝数据

关闭打开APP蜂窝数据

作者: 随惢所欲 | 来源:发表于2017-10-01 00:35 被阅读0次

    目标

    实现对App蜂窝数据开关控制。

    环境:

    iOS 9.1 arm64

    前言

    对于这方面的分析资料可能比较少,我把自己的一些分析过程和踩过的一些坑记录下来,花了几天时间调试和整理,分享在此。

    开始
    WechatIMG8.jpeg

    我们来查找地图开关,先用FLEX查看switch是属于哪个cell

    WechatIMG9.jpeg

    可以看到他是属于PSSubtitleSwitchTableCell,接下来我们ssh手机使用Cycript挂载。

    WX20170930-115301.png

    然后查看Preferences界面结构

    cy# [[UIApp keyWindow] _autolayoutTrace].toString()
    `
    UIWindow:0x1366c8060
    |   UILayoutContainerView:0x1366ec6c0
    |   |   UIView:0x136759130
    |   |   UILayoutContainerView:0x1365f0110
    |   |   |   UINavigationTransitionView:0x1365f7c30
    |   |   |   |   UIViewControllerWrapperView:0x13676bba0
    |   |   |   |   |   UILayoutContainerView:0x1367abcf0
    |   |   |   |   |   |   UINavigationTransitionView:0x13783e820
    |   |   |   |   |   |   |   UIViewControllerWrapperView:0x13799b0a0
    |   |   |   |   |   |   |   |   PSListContainerView:0x137987af0
    |   |   |   |   |   |   |   |   |   UITableView:0x136892000
    |   |   |   |   |   |   |   |   |   |   UITableViewWrapperView:0x136805600
    |   |   |   |   |   |   |   |   |   |   |   PSSubtitleSwitchTableCell:0x13700de00'PSSubtitleSwitchTableCell...'
    |   |   |   |   |   |   |   |   |   |   |   |   UITableViewCellContentView:0x1379f6480
    |   |   |   |   |   |   |   |   |   |   |   |   |   UITableViewLabel:0x137daa030'\u5fae\u4fe1'
    |   |   |   |   |   |   |   |   |   |   |   |   |   UITableViewLabel:0x137d5a070'19.8 MB'
    |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x137b66940
    |   |   |   |   |   |   |   |   |   |   |   |   _UITableViewCellSeparatorView:0x1378bc320
    |   |   |   |   |   |   |   |   |   |   |   |   UISwitch:0x1378b5750
    |   |   |   |   |   |   |   |   |   |   |   |   |   _UISwitchInternalViewNeueStyle1:0x13789de80
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137d84960
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137d67b10
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137d895c0
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137a357a0
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137b22360
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x1379995d0
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x1379ce5d0
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x1378bafc0
    |   |   |   |   |   |   |   |   |   |   |   PSSubtitleSwitchTableCell:0x13698f400'PSSubtitleSwitchTableCell...'
    |   |   |   |   |   |   |   |   |   |   |   |   UITableViewCellContentView:0x137d87f00
    |   |   |   |   |   |   |   |   |   |   |   |   |   UITableViewLabel:0x137dbd670'\u901a\u8baf\u5f55'
    |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x1379e33a0
    |   |   |   |   |   |   |   |   |   |   |   |   _UITableViewCellSeparatorView:0x1378812b0
    |   |   |   |   |   |   |   |   |   |   |   |   UISwitch:0x137a07b40
    |   |   |   |   |   |   |   |   |   |   |   |   |   _UISwitchInternalViewNeueStyle1:0x137a365b0
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137d888c0
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137d84fe0
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137da4280
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x13665a400
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137b2e140
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x137999230
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x1379854c0
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x1378f46f0
    |   |   |   |   |   |   |   |   |   |   |   PSSubtitleSwitchTableCell:0x1371ac400'PSSubtitleSwitchTableCell...'
    |   |   |   |   |   |   |   |   |   |   |   |   UITableViewCellContentView:0x1379bd1a0
    |   |   |   |   |   |   |   |   |   |   |   |   |   UITableViewLabel:0x137db1ee0'\u5929\u6c14'
    |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x137b36020
    |   |   |   |   |   |   |   |   |   |   |   |   _UITableViewCellSeparatorView:0x1379e1590
    |   |   |   |   |   |   |   |   |   |   |   |   UISwitch:0x1378bdef0
    |   |   |   |   |   |   |   |   |   |   |   |   |   _UISwitchInternalViewNeueStyle1:0x1378e9570
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137d87d60
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137a24e00
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137db1a50
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x137d678d0
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIView:0x1365a3740
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x137b22ec0
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x1379cdfe0
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   UIImageView:0x1378a64f0
    

    我们随便选取一个UISwitch地址定位其action selector:

    cy# [#0x137a07b40 allTargets]
    [NSSet setWithArray:@[#"<PSSubtitleSwitchTableCell: 0x13698f400; baseClass = UITableViewCell; frame = (0 1276; 320 45); text = '\xe9\x80\x9a\xe8\xae\xaf\xe5\xbd\x95'; autoresize = W; tag = 6; layer = <CALayer: 0x137d588b0>>"]]]
    cy# [#0x137a07b40 actionsForTarget:#0x13698f400 forControlEvent:[#0x137a07b40 allControlEvents]]
    @["controlChanged:"]
    cy#
    

    1 先用Cycript打印出[button allTargets],是一个数组不过我们这里只有一个对象
    2 遍历数组,得到每一个target,然后打印
    [button actionsForTarget:target forControlEvent:[button allControlEvents]]
    得到selector。

    controlChanged:就是Switch点击事件调用的函数
    下面我们来寻找它干了什么

    首先我们需要查找PSSubtitleSwitchTableCell.h头文件,如果你没有系统头文件点这里

    /*
    * This header is generated by classdump-dyld 0.7
    * on Thursday, January 14, 2016 at 3:32:07 AM Eastern European Standard Time
    * Operating System: Version 9.0.2 (Build 13A452)
    * Image Source: /System/Library/PrivateFrameworks/Preferences.framework/Preferences
    * classdump-dyld is licensed under GPLv3, Copyright © 2013-2014 by Elias Limneos.
    */
    
    #import <Preferences/PSSwitchTableCell.h>
    
    @interface PSSubtitleSwitchTableCell : PSSwitchTableCell
    +(long long)cellStyle;
    -(void)refreshCellContentsWithSpecifier:(id)arg1 ;
    -(BOOL)canReload;
    @end
    
    

    我们可以看到它是属于Preferences.framework
    /System/Library/PrivateFrameworks/Preferences.framework/Preferences

    继承关系:
    PSSubtitleSwitchTableCell
    PSSwitchTableCell
    PSControlTableCell
    PSTableCell
    UITableViewCell

    开启lldb

    一、SSH连接手机(USB模式)

    1.映射端口
    2.连接手机,并且用grep命令快速筛选当前我们要调试的应用Preferences,附加debugserver开始12345端口等待lldb调试
    3.完成以上两步接下来就可以进行lldb调试了,首先要把远端(手机)的12345端口映射到本地,跟前面提到的SSH端口映射一样

    WX20170930-135830@2x.png

    下面我们需要借助lldb找到/Preferences.framework/Preferences

    (lldb) image list -o -f
    [  0] 0x0000000000084000 /var/db/stash/_.E79Odv/Applications/Preferences.app/Preferences(0x0000000100084000)
    [  1] 0x00000001000bc000 /Library/MobileSubstrate/MobileSubstrate.dylib(0x00000001000bc000)
    [  2] 0x0000000003e18000 /Users/qweqwe/Library/Developer/Xcode/iOS DeviceSupport/9.1 (13B143)/Symbols/System/Library/PrivateFrameworks/BulletinBoard.framework/BulletinBoard
    `
    `
    `
    [ 44] 0x0000000003e18000 /Users/qweqwe/Library/Developer/Xcode/iOS DeviceSupport/9.1 (13B143)/Symbols/System/Library/PrivateFrameworks/Preferences.framework/Preferences
    

    看到[44]号地址就是我们要找的Preferences.framework二进制文件
    拉进IDA进行查找controlChanged

    WX20170930-141135@2x.png
    使用lldb动态调试

    我们对其函数头部下断点

    (lldb) br s -a 0x0000000003e18000+0x000000019087F7DC
    Breakpoint 3: where = Preferences`-[PSControlTableCell controlChanged:], address = 0x00000001946977dc
    (lldb)
    

    然后去设置里点一下Switch,我们看到断点命中。

    Process 1576 stopped
    * thread #1: tid = 0x166aa, 0x00000001946977dc Preferences`-[PSControlTableCell controlChanged:], queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
        frame #0: 0x00000001946977dc Preferences`-[PSControlTableCell controlChanged:]
    Preferences`-[PSControlTableCell controlChanged:]:
    ->  0x1946977dc <+0>:  stp    x24, x23, [sp, #-64]!
        0x1946977e0 <+4>:  stp    x22, x21, [sp, #16]
        0x1946977e4 <+8>:  stp    x20, x19, [sp, #32]
        0x1946977e8 <+12>: stp    x29, x30, [sp, #48]
    (lldb)
    

    使用命令n单步来到objc_msgSend函数


    WX20170930-144155@2x.png
    (lldb) dis
    Preferences`-[PSControlTableCell controlChanged:]:
        0x1946977dc <+0>:   stp    x24, x23, [sp, #-64]!
        0x1946977e0 <+4>:   stp    x22, x21, [sp, #16]
        0x1946977e4 <+8>:   stp    x20, x19, [sp, #32]
        0x1946977e8 <+12>:  stp    x29, x30, [sp, #48]
        0x1946977ec <+16>:  add    x29, sp, #48              ; =48
        0x1946977f0 <+20>:  mov    x19, x0
        0x1946977f4 <+24>:  adrp   x8, 53838
        0x1946977f8 <+28>:  ldr    x21, [x8, #2680]
        0x1946977fc <+32>:  mov    x1, x21
    ->  0x194697800 <+36>:  bl     0x19aa51bc0               ; objc_msgSend
        0x194697804 <+40>:  mov    x29, x29
        0x194697808 <+44>:  bl     0x19aa59ef0               ; objc_retainAutoreleasedReturnValue
        0x19469780c <+48>:  mov    x22, x0
        0x194697810 <+52>:  cbz    x22, 0x1946978ec          ; <+272>
    (lldb) po $x0
    <PSSubtitleSwitchTableCell: 0x13691c800; baseClass = UITableViewCell; frame = (0 967; 320 45); text = '地图'; autoresize = W; tag = 6; layer = <CALayer: 0x1378a0980>>
    
    (lldb) po (char*)$x1
    "cellTarget"
    
    (lldb)
    
    

    对应OC代码

    [PSSubtitleSwitchTableCell cellTarget]
    

    objc_retainAutoreleasedReturnValue作用是处理返回值是否跳过autorelease机制

    0x194697804 <+40>:  mov    x29, x29
    0x194697808 <+44>:  bl     0x19aa59ef0  ; objc_retainAutoreleasedReturnValue
    

    单步来到 0x194697810 <+52>: cbz x22, 0x1946978ec ; <+272>

    WX20170930-153825@2x.png

    x0返回值给了x22,cbz意思是为0则跳,打印x22

    0x19469780c <+48>:  mov    x22, x0
    0x194697810 <+52>:  cbz    x22, 0x1946978ec          ; <+272>
    (lldb) po $x22
    <PSUIAppCellularUsageGroupController: 0x1379c32c0>
    

    因为我们x22有值所以没跳,还原OC代码

    PSUIAppCellularUsageGroupController *vc = [PSSubtitleSwitchTableCell cellTarget];
    if(vc){
    ‘’‘’‘
    }

    然后我们单步来到0x194697824

        0x194697810 <+52>:  cbz    x22, 0x1946978ec          ; <+272>
        0x194697814 <+56>:  adrp   x8, 53837
        0x194697818 <+60>:  ldr    x20, [x8, #1168]
        0x19469781c <+64>:  mov    x0, x19
        0x194697820 <+68>:  mov    x1, x20
    ->  0x194697824 <+72>:  bl     0x19aa51bc0               ; objc_msgSend
    (lldb) po $x0
    <PSSubtitleSwitchTableCell: 0x13691c800; baseClass = UITableViewCell; frame = (0 967; 320 45); text = '地图'; autoresize = W; tag = 6; layer = <CALayer: 0x1378a0980>>
    
    (lldb) po (char*)$x1
    "specifier"
    
    (lldb)
    

    继续单步查看返回值

        0x194697814 <+56>:  adrp   x8, 53837
        0x194697818 <+60>:  ldr    x20, [x8, #1168]
        0x19469781c <+64>:  mov    x0, x19
        0x194697820 <+68>:  mov    x1, x20
        0x194697824 <+72>:  bl     0x19aa51bc0               ; objc_msgSend
        0x194697828 <+76>:  mov    x29, x29
        0x19469782c <+80>:  bl     0x19aa59ef0               ; objc_retainAutoreleasedReturnValue
    ->  0x194697830 <+84>:  mov    x23, x0
    (lldb) po $x0
    <PSSpecifier 0x137b79680: ID com.apple.Maps, Name '地图' target <PSUIAppCellularUsageGroupController: 0x1379c32c0>>
    
    

    发现是PSSpecifier,我们找到之前的类的头文件,发现这个类有一个叫做properties的实例方法

    (lldb) po [$x0 properties]
    {
        appIDForLazyIcon = "com.apple.Maps";
        cellClass = PSSubtitleSwitchTableCell;
        cellObject = "<PSSubtitleSwitchTableCell: 0x13691c800; baseClass = UITableViewCell; frame = (0 967; 320 45); text = '\U5730\U56fe'; autoresize = W; tag = 6; layer = <CALayer: 0x1378a0980>>";
        cellSubtitleText = "5.7 MB";
        control = "<UISwitch: 0x1378e3680; frame = (254 7; 51 31); layer = <CALayer: 0x137855c00>>";
        enabled = 1;
        id = "com.apple.Maps";
        roamingNetworkUsage = 0;
        totalNetworkUsage = 5981087;
        useLazyIcons = 1;
    }
    

    可以看到这个类包含了AppBundID和UISwitch一些信息

    继续走
        0x194697834 <+88>:  bl     0x19aa58150               ; objc_release
        0x194697838 <+92>:  mov    x0, x22
        0x19469783c <+96>:  bl     0x19aa58150               ; objc_release
        0x194697840 <+100>: cbz    x23, 0x1946978ec          ; <+272>
    
    来到这0x194697840
    

    还原OC代码

    PSSpecifier *specifier = [PSSubtitleSwitchTableCell specifier];
    if(specifier){

    }

        0x194697844 <+104>: adrp   x8, 53838
        0x194697848 <+108>: ldr    x1, [x8, #2688]
        0x19469784c <+112>: mov    x0, x19
        0x194697850 <+116>: bl     0x19aa51bc0               ; objc_msgSend
        0x194697854 <+120>: mov    x22, x0
        0x194697858 <+124>: mov    x0, x19
        0x19469785c <+128>: mov    x1, x21
        0x194697860 <+132>: bl     0x19aa51bc0               ; objc_msgSend
        0x194697864 <+136>: mov    x29, x29
        0x194697868 <+140>: bl     0x19aa59ef0               ; objc_retainAutoreleasedReturnValue
        0x19469786c <+144>: mov    x21, x0
        0x194697870 <+148>: adrp   x8, 53840
        0x194697874 <+152>: ldr    x1, [x8, #2376]
        0x194697878 <+156>: mov    x0, x19
        0x19469787c <+160>: bl     0x19aa51bc0               ; objc_msgSend
        0x194697880 <+164>: mov    x29, x29
        0x194697884 <+168>: bl     0x19aa59ef0               ; objc_retainAutoreleasedReturnValue
        0x194697888 <+172>: mov    x23, x0
        0x19469788c <+176>: mov    x0, x19
        0x194697890 <+180>: mov    x1, x20
        0x194697894 <+184>: bl     0x19aa51bc0               ; objc_msgSend
        0x194697898 <+188>: mov    x29, x29
        0x19469789c <+192>: bl     0x19aa59ef0               ; objc_retainAutoreleasedReturnValue
    

    这段汇编主要为取值为了节省时间读者可自行分析。
    对应OC代码
    SEL setAppCellularData = [PSSubtitleSwitchTableCell cellAction];

    PSUIAppCellularUsageGroupController *vc = [PSSubtitleSwitchTableCell cellTarget];

    NSinteger controlValue = [PSSubtitleSwitchTableCell controlValue];

        0x1946978a0 <+196>: mov    x19, x0
        0x1946978a4 <+200>: mov    x0, x22
        0x1946978a8 <+204>: mov    x1, x21
        0x1946978ac <+208>: mov    x2, x23
        0x1946978b0 <+212>: mov    x3, x19
    ->  0x1946978b4 <+216>: bl     0x1946bb2b4               ; PSPerformSelector2
    (lldb) po (char*)$x0
    "setAppCellularDataEnabled:forSpecifier:"
    
    (lldb) po $x1
    <PSUIAppCellularUsageGroupController: 0x1379c32c0>
    
    (lldb) po $x2
    0
    
    (lldb) po $x3
    <PSSpecifier 0x137b79680: ID com.apple.Maps, Name '地图' target <PSUIAppCellularUsageGroupController: 0x1379c32c0>>
    
    (lldb)
    

    PSPerformSelector2(setAppCellularData,vc, controlValue, specifier);
    等价于
    [PSUIAppCellularUsageGroupController setAppCellularDataEnabled:NO forSpecifier: specifier];

    完整OC

    
    PSUIAppCellularUsageGroupController *vc = [PSSubtitleSwitchTableCell cellTarget];
    if(vc){
          PSSpecifier *specifier = [PSSubtitleSwitchTableCell specifier];
          if(specifier){
              SEL setAppCellularData = [PSSubtitleSwitchTableCell cellAction];
    
              PSUIAppCellularUsageGroupController *vc = [PSSubtitleSwitchTableCell cellTarget];
    
              NSinteger controlValue = [PSSubtitleSwitchTableCell controlValue];
    
              PSPerformSelector2(setAppCellularData,vc, controlValue, specifier);
          }
    }
    

    setAppCellularDataEnabled看这个函数名字已经能确定了,也可以用Cycript试验一下,我这里就不试了。
    到这里我们已经找到了设置开关的函数,但是这是UI层面上的,我们还需要继续深入寻找底层函数。

    继续上边的套路查找PSUIAppCellularUsageGroupController头文件

    
    /*
    * This header is generated by classdump-dyld 0.7
    * on Thursday, January 14, 2016 at 3:32:09 AM Eastern European Standard Time
    * Operating System: Version 9.0.2 (Build 13A452)
    * Image Source: /System/Library/PrivateFrameworks/PreferencesUI.framework/PreferencesUI
    * classdump-dyld is licensed under GPLv3, Copyright © 2013-2014 by Elias Limneos.
    */
    
    #import <libobjc.A.dylib/UsageFeedDelegate.h>
    #import <libobjc.A.dylib/PSSpecifierGroupController.h>
    
    @class NSArray, NSNumber, PSExpandableAppListGroupController, NSDictionary, NSString;
    
    @interface PSUIAppCellularUsageGroupController : NSObject <UsageFeedDelegate, PSSpecifierGroupController> {
    

    我们看到他是定义在PreferencesUI.framework
    /System/Library/PrivateFrameworks/PreferencesUI.framework/PreferencesUI

    重复上边lldb寻找过程拖进IDA搜索setAppCellularDataEnabled:forSpecifier:

    WX20170930-191849@2x.png

    在函数头部下断点,并且命中。

    (lldb) br s -a 0x0000000003e18000+0x0000000190936274
    Breakpoint 6: where = PreferencesUI`-[PSUIAppCellularUsageGroupController setAppCellularDataEnabled:forSpecifier:], address = 0x000000019474e274
    Process 1576 stopped
    * thread #1: tid = 0x166aa, 0x000000019474e274 PreferencesUI`-[PSUIAppCellularUsageGroupController setAppCellularDataEnabled:forSpecifier:], queue = 'com.apple.main-thread', stop reason = breakpoint 6.1
        frame #0: 0x000000019474e274 PreferencesUI`-[PSUIAppCellularUsageGroupController setAppCellularDataEnabled:forSpecifier:]
    PreferencesUI`-[PSUIAppCellularUsageGroupController setAppCellularDataEnabled:forSpecifier:]:
    ->  0x19474e274 <+0>:  stp    x26, x25, [sp, #-80]!
        0x19474e278 <+4>:  stp    x24, x23, [sp, #16]
        0x19474e27c <+8>:  stp    x22, x21, [sp, #32]
        0x19474e280 <+12>: stp    x20, x19, [sp, #48]
    (lldb)
    

    单步往下走

    
        0x19474e274 <+0>:   stp    x26, x25, [sp, #-80]!
        0x19474e278 <+4>:   stp    x24, x23, [sp, #16]
        0x19474e27c <+8>:   stp    x22, x21, [sp, #32]
        0x19474e280 <+12>:  stp    x20, x19, [sp, #48]
        0x19474e284 <+16>:  stp    x29, x30, [sp, #64]
        0x19474e288 <+20>:  add    x29, sp, #64              ; =64
        0x19474e28c <+24>:  sub    sp, sp, #48               ; =48
        0x19474e290 <+28>:  mov    x20, x3
        0x19474e294 <+32>:  mov    x22, x0
        0x19474e298 <+36>:  adrp   x25, 46941
        0x19474e29c <+40>:  ldr    x25, [x25, #1672]
        0x19474e2a0 <+44>:  ldr    x25, [x25]
        0x19474e2a4 <+48>:  str    x25, [sp, #40]
        0x19474e2a8 <+52>:  mov    x0, x2
        0x19474e2ac <+56>:  bl     0x19aa580a0               ; objc_retain
        0x19474e2b0 <+60>:  mov    x19, x0
        0x19474e2b4 <+64>:  mov    x0, x20
    ->  0x19474e2b8 <+68>:  bl     0x19aa580a0               ; objc_retain
    

    对其一些参数做retain暂不关心

        0x19474e2bc <+72>:  mov    x20, x0
        0x19474e2c0 <+76>:  adrp   x8, 53665
        0x19474e2c4 <+80>:  ldr    x1, [x8, #760]
        0x19474e2c8 <+84>:  bl     0x19aa51bc0               ; objc_msgSend
    (lldb) po $x0
    <PSSpecifier 0x137b79680: ID com.apple.Maps, Name '地图' target <PSUIAppCellularUsageGroupController: 0x1379c32c0>>
    
    (lldb) po (char*)$x1
    "identifier"
    
    (lldb)
    

    这里获取PSSpecifier的identifier

    
        0x19474e2cc <+88>:  mov    x29, x29
        0x19474e2d0 <+92>:  bl     0x19aa59ef0  ;   objc_retainAutoreleasedReturnValue
        0x19474e2d4 <+96>:  mov    x21, x0
    (lldb) po $x0
    com.apple.Maps
    
        0x19474e2d8 <+100>: adrp   x8, 46941
        0x19474e2dc <+104>: ldr    x8, [x8, #1736]
        0x19474e2e0 <+108>: ldr    x0, [x8]
        0x19474e2e4 <+112>: movz   x3, #0
        0x19474e2e8 <+116>: adrp   x1, 46948
        0x19474e2ec <+120>: add    x1, x1, #3536             ; =3536
        0x19474e2f0 <+124>: adrp   x2, 46941
        0x19474e2f4 <+128>: ldr    x2, [x2, #1680]
    ->  0x19474e2f8 <+132>: bl     0x19320cbe4
    
    (lldb) po $x0
    <nil>
    
    (lldb) po $x1
    com.apple.Preferences
    
    (lldb) po $x2
    <OS_dispatch_queue: com.apple.main-thread[0x1a1d07080] = { xrefcnt = 0x80000000, refcnt = 0x80000000, suspend_cnt = 0x0, locked = 1, target = com.apple.root.default-qos.overcommit[0x1a1d07700], width = 0x0, running = 0x0, barrier = 1 , thread = 0xb07 }>
    
    (lldb) po $x3
    <nil>
    

    我们s跟进去看看他是什么函数

    (lldb) s
    Process 1576 stopped
    * thread #1: tid = 0x166aa, 0x000000019320cbe4, queue = 'com.apple.main-thread', stop reason = instruction step into
        frame #0: 0x000000019320cbe4
    ->  0x19320cbe4: b      0x18b4eedb4
        0x19320cbe8: b      0x18b4efbf0
        0x19320cbec: b      0x18b4ee68c
        0x19320cbf0: b      0x18b4ee818
    (lldb) s
    Process 1576 stopped
    * thread #1: tid = 0x166aa, 0x000000018b4eedb4, queue = 'com.apple.main-thread', stop reason = instruction step into
        frame #0: 0x000000018b4eedb4
    ->  0x18b4eedb4: b      0x186a1953c               ; _CTServerConnectionCreateOnTargetQueue
        0x18b4eedb8: b      0x186a21024               ; _CTServerConnectionDropIPPackets
        0x18b4eedbc: b      0x186a115c4               ; _CTServerConnectionGetRadioAccessTechnology
        0x18b4eedc0: b      0x186a11e54               ; _CTServerConnectionGetSignalStrength
    (lldb)
    

    _CTServerConnectionCreateOnTargetQueue私有的C函数
    它有4个参数

        0x19474e2fc <+136>: mov    x23, x0
        0x19474e300 <+140>: cbz    x23, 0x19474e3b0          ; <+316>
        0x19474e304 <+144>: adrp   x8, 46941
        0x19474e308 <+148>: ldr    x8, [x8, #1904]
        0x19474e30c <+152>: ldr    x8, [x8]
        0x19474e310 <+156>: stp    x8, x19, [sp, #24]
        0x19474e314 <+160>: adrp   x8, 53668
        0x19474e318 <+164>: ldr    x0, [x8, #2624]
        0x19474e31c <+168>: adrp   x8, 53665
        0x19474e320 <+172>: ldr    x1, [x8, #3168]
        0x19474e324 <+176>: add    x2, sp, #32               ; =32
        0x19474e328 <+180>: add    x3, sp, #24               ; =24
        0x19474e32c <+184>: orr    w4, wzr, #0x1
    ->  0x19474e330 <+188>: bl     0x19aa51bc0               ; objc_msgSend
        0x19474e334 <+192>: mov    x29, x29
        0x19474e338 <+196>: bl     0x19aa59ef0               ; objc_retainAutoreleasedReturnValue
        0x19474e33c <+200>: mov    x24, x0
    (lldb) po $x0
    NSDictionary
    
    (lldb) po (char*)$x1
    "dictionaryWithObjects:forKeys:count:"
    
    (lldb)
    

    单步看其返回值是kCTCellularUsagePolicyDataAllowed
    也就是构造一个字典,值是0和1

    (lldb) po $x0
    {
        kCTCellularUsagePolicyDataAllowed = 0;
    }
    
        0x19456e340 <+204>: mov    x0, x23
        0x19456e344 <+208>: mov    x1, x21
        0x19456e348 <+212>: mov    x2, x24
    ->  0x19456e34c <+216>: bl     0x19302d3cc
    (lldb) po $x0
    <CTServerConnection 0x130934e90 [0x1a1b2db68]>
    
    (lldb) po $x1
    com.apple.Maps
    
    (lldb) po $x2
    {
        kCTCellularUsagePolicyDataAllowed = 0;
    }
    
    (lldb) s
    Process 683 stopped
    * thread #1: tid = 0x0d99, 0x000000019302d3cc, queue = 'com.apple.main-thread', stop reason = instruction step into
        frame #0: 0x000000019302d3cc
    ->  0x19302d3cc: b      0x18b30fde0
        0x19302d3d0: b      0x18b30f1ac
        0x19302d3d4: b      0x18b30ef70
        0x19302d3d8: b      0x18b30f1c8
    (lldb) s
    Process 683 stopped
    * thread #1: tid = 0x0d99, 0x000000018b30fde0, queue = 'com.apple.main-thread', stop reason = instruction step into
        frame #0: 0x000000018b30fde0
    ->  0x18b30fde0: b      0x18685544c               ; _CTServerConnectionSetCellularUsagePolicy
        0x18b30fde4: b      0x185dccb38               ; CFTimeZoneResetSystem
        0x18b30fde8: b      0x1867fe9f4               ; CTCallDial
        0x18b30fdec: b      0x1867ffd34               ; CTCallGetCallSubType
    (lldb)'
    

    _CTServerConnectionSetCellularUsagePolicy私有C函数
    3个参数
    x0是_CTServerConnectionCreateOnTargetQueue它的返回值

    调用

    用到的是CoreTelephony.framework里的两个私有C函数

    CTServerConnection* _CTServerConnectionCreateOnTargetQueue(CFAllocatorRef, NSString *, dispatch_queue_t, void*/*一个block类型的参数*/)
    
    void _CTServerConnectionSetCellularUsagePolicy(CTServerConnection *, NSString *, NSDictionary *)
    

    要调用私有C函数,需要用dlsym,简单示意如下:

    void *CoreTelephonyHandle = dlopen("/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony", RTLD_LAZY);
    
    //用函数指针来调用私有C函数,用符号名从库里寻找函数地址
    CFTypeRef (*connectionCreateOnTargetQueue)(CFAllocatorRef, NSString *, dispatch_queue_t, void*) = dlsym(CoreTelephonyHandle, "_CTServerConnectionCreateOnTargetQueue");
    int (*changeCellularPolicy)(CFTypeRef, NSString *, NSDictionary *) = dlsym(CoreTelephonyHandle, "_CTServerConnectionSetCellularUsagePolicy");
    
    CFTypeRef connection = connectionCreateOnTargetQueue(kCFAllocatorDefault,@"com.apple.Preferences",dispatch_get_main_queue(),NULL);
    
    changeCellularPolicy(connection, @"需要授权的app的bundle id", @{@"kCTCellularUsagePolicyDataAllowed":@YES});
    
    dlclose(CoreTelephonyHandle);
    
    权限

    CommCenter就是这几个私有API通信的对应进程,用于管理设备的网络,如果想在其他进程与CommCenter通信改写数据状态需要Entitlements.plist添加相应权限后对其签名。

    相关文章

      网友评论

          本文标题:关闭打开APP蜂窝数据

          本文链接:https://www.haomeiwen.com/subject/ghegextx.html