V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
s82kd92l
V2EX  ›  Android

为啥不利用修改 apk 的 manifest 来控制软件行为?

  •  
  •   s82kd92l · 2018-01-17 17:07:34 +08:00 · 13390 次点击
    这是一个创建于 2503 天前的主题,其中的信息可能已经有所发展或是发生改变。
    现有控制软件行为的方案,绿守 /黑域 /写轮眼 /xposed 无一不是入侵式的,对 root/adb 要求很高效果却不完美,为啥没大神做基于 manifest 编辑+自签名打包来做到免 root 限制流氓呢?

    Manifest 就像是 apk 和 android 系统签订的一份合约, 其内容完全决定了 android 沙盒如何限制 apk 的行为。Google 目前的做法是让用户无条件接受这份合约( 6.0 之前)或者只有极小协商空间(就是 6.0 的可选权限)。如果能修改 manifest,用户可以达到这些效果(从简单到难):
    1. 修改 targetSdkVersion 很多新系统对流氓的控制,流氓都会通过 target 老旧的 sdk 来应付,如果能自己改 targetSdkVersion,流氓们只能在 8.1 下面乖乖睡觉,在 6.0 下面乖乖把部分敏感权限选择权交给用户
    2. 直接删除 /添加权限申明。6.0 下面的权限只有部分是可选的,通过修改 manifest,所有权限用户都能控制
    3. 直接修改 /删除四大组件的申明 让 broadcastreceiver 再也收不到“开机 /网络变更 /摄像头开启”之类的唤醒,直接禁用 service/content provider, 或者使其无法向第三方开放。

    如此以来,再也不需要在运行时控制自启动 /切断唤醒路径, 因为新合约让流氓无路可走。还有 Oreo 对 bound service/content provider 没有约束的情况,manifest 也可以弥补。只要限制得当,这个沙盒能比 iOS 更加给力。
    改完后重新打包,尽量做到每个 apk 单独签名。还有就是最好把 apk 的原始签名加入 manifest 中,这样升级的时候可防止下载到一个已经被人动过手脚的 apk。

    如果要做这种修改软件,界面可以像写轮眼那样非常清晰明了。如果能借绿色守护的处方语法就更好了,那样小白就可以利用网上现成的处方来决定哪些权限 /组建可删可改以及怎么改。免 root,流程简单,效果超过现有方案,为啥没人做呢?
    65 条回复    2018-01-21 12:41:37 +08:00
    ju5t4fun
        1
    ju5t4fun  
       2018-01-17 17:28:10 +08:00
    很多 APP 启动的时候会校验自身签名,你怎么跳过?
    s82kd92l
        2
    s82kd92l  
    OP
       2018-01-17 17:34:50 +08:00
    @ju5t4fun 这种应该不占大多数吧,实在不行就把保存在 manifest 里面的原始签名发给他。(用 xposed 可做到...门槛开始有点高了)
    leafleave
        3
    leafleave  
       2018-01-17 17:42:28 +08:00 via iPhone
    幸运破解器,破解安装包可以做到
    s82kd92l
        4
    s82kd92l  
    OP
       2018-01-17 17:45:33 +08:00
    @leafleave 能改 targetSdkVersion 吗?
    s82kd92l
        5
    s82kd92l  
    OP
       2018-01-17 17:47:04 +08:00
    之前听说过 lucky patcher 貌似要 root
    Leafove
        6
    Leafove  
       2018-01-17 17:54:18 +08:00
    App 启动先检查自身是否完整,如果不完整直接更新或者弹窗提示程序损坏..
    你能把联网禁了?
    s82kd92l
        7
    s82kd92l  
    OP
       2018-01-17 18:02:02 +08:00
    @Leafove App 通过什么途径检查自身完整呢?还是只能通过系统提供的 api 吧。这种一般都是付费软件防盗版用的,要不就不装,要不就用 xposed 治理。
    honeycomb
        8
    honeycomb  
       2018-01-17 18:03:54 +08:00
    改 manifest 有这些问题:

    1,破坏了应用的签名,这肯定是不可取的。
    有的应用自己还会检查签名,特别是那些特意做了加固的,也就是说,这是一个普遍行为。

    2,在 manifest 禁用权限以后,应用使用相关权限控制的 API 时,会抛出 SecurityException,应用基本不可能去 catch 这些东西,意味着这不实用,比 AppOps 返回 null/empty 对象的做法更不实用。

    --------------------------------------

    关于主题里琐碎的项目:

    “如果能自己改 targetSdkVersion,流氓们只能在 8.1 下面乖乖睡觉”
    有现成的 workaround,直接把应用在 AppOps 的 RUN_IN_BACKGROUND 改成 ignore 即可。

    注:
    应用的电池选项里,有时可以直接改这个设置(8.0 和 8.1 的表现不同,8.0 是只需要应用运行过就可以开启这个限制,8.1 需要别的条件,我没看过具体的源代码)
    AOSP 上的 8.1 及 pixel 2 代的全部官方 rom 的开发者选项-->background check 可直接改


    “直接修改 /删除四大组件的申明 让 broadcastreceiver 再也收不到“开机 /网络变更 /摄像头开启”之类的唤醒,直接禁用 service/content provider, 或者使其无法向第三方开放。 ”

    在 Android 8.0,绝大部分隐式广播已经无法触发系统定义的那些 receiver。
    除此以外可以用修改 IFW 配置的方法(如绿色守护的处方特性),pm disable(MyAndroidTools)来处理它们


    “ Oreo 对 bound service/content provider 没有约束”
    似乎没什么好办法
    Totato5749
        9
    Totato5749  
       2018-01-17 18:04:21 +08:00
    太理想了。。。不可能实现的
    manifest 如同字面意思,只是清单不是合约,只是告诉了系统 app 的全部功能与要求。

    比如将 targetsdk 改为 6.0,那么在 6.0 以上的系统中权限必须是动态申请的,但是 app 原来并不是给 6.0 适配的,根本没有申请权限的代码,这样的 app 是跑不起来的。

    楼主可能以为 6.0 以上的申请权限是系统行为?并不是的,这个是需要开发者自己添加代码弹出申请权限对话框并在回调中检查是否获取到对应权限的。所以简单地将 targetsdk 小于 6.0 的 app 改为 targetsdk 为 6.0 会导致应用无法使用
    tscat
        10
    tscat  
       2018-01-17 18:07:35 +08:00
    幸运破解器就是这么个路子。
    然后 App 是会做签名验证的。。
    而且一般都是用 so 做校验,你得反汇编二进制文件去修改。
    然后这个不只是为了反盗版,还有为了做安全校验的,防止去广告的。比如腾讯视频会校验签名。
    geelaw
        11
    geelaw  
       2018-01-17 18:10:55 +08:00   ❤️ 1
    比如这样做是非法的。
    ysc3839
        12
    ysc3839  
       2018-01-17 18:15:17 +08:00 via Android
    @s82kd92l 不需要 root,root 模式修改只是为了保留应用数据以及绕过自校验。
    s82kd92l
        13
    s82kd92l  
    OP
       2018-01-17 18:16:31 +08:00
    @honeycomb 那也得 targetSdkVersion>O,限制才有效吧。我自己在用 oreo+appops,可是对于广大非 root 的手机,和那些无法升级到 oreo 的这个是值得一试的方案。

    @Totato5749 6.0 的权限除了动态申请,用户也可以在软件管理界面里手动赋予的。

    @Leafove @ju5t4fun 这个是个现成的 xposed 签名修改模块,目前用于欺骗 google sdk,应该也能用于欺骗那些做加固自签名校验的:
    http://repo.xposed.info/module/com.thermatk.android.xf.fakegapps
    XinLake
        14
    XinLake  
       2018-01-17 18:16:49 +08:00
    我觉得 8 楼说的挺好。从策略出发,你改别人的东西总是不太好的吧。

    我觉得这个要宏观层面提高国产 APP 的素质,要国内的那些巨头,带好头,做好榜样。其次也要加强监管、监督,让 APP 的开发企业不能为所欲为,要有个可约束的良性发展循环。
    s82kd92l
        15
    s82kd92l  
    OP
       2018-01-17 18:26:55 +08:00
    @XinLake 这个不是我们改,而是授之以渔让用户自己改,区别很大的。

    指望提高素质是没用的,道德永远没有制度管用。Android 生态最大的问题在于,既没有 apple 的人工审核机制,也不让用户有更多选择权,而是在权限问题上做 all-or-nothing 的一锤子买卖,从而赋予开发者最大的话语权。我这个想法无非是给用户更多权利罢了。
    s82kd92l
        16
    s82kd92l  
    OP
       2018-01-17 18:35:37 +08:00
    还想说一点,很多人指责国内 android 环境太差,说国外月亮更圆。然而事实上国外的 app 并没有更安分到哪里去,去搜一搜 android information flow leak 就能知道即使在 google play 上面上架的应用,照样普遍利用 android 不完善机制达到各种泄漏。
    国内不好的地方在于没有推送机制所以要各种保活,以至于使用户卡顿。然而就算有了推送机制,有了统一的 app 发布平台,只要开发者有一锤子买卖的权力,那么 android 沙盒照样是漏洞百出,用户隐私依然形同虚设。
    zjp
        17
    zjp  
       2018-01-17 18:39:16 +08:00 via Android
    还有一种方式,安卓自带的 IFW
    Qlccks2
        18
    Qlccks2  
       2018-01-17 18:45:28 +08:00 via iPhone
    全家桶都验证签名
    honeycomb
        19
    honeycomb  
       2018-01-17 18:52:57 +08:00 via Android
    @s82kd92l

    RUN_IN_BACKGROUND 设置成 ignore 后的限制不受 targetSDK 影响,具体看源代码,最初的 commit 是 dianne hackborn 签署的,这人也是 Android 团队的老人了。

    这里的关系是,targetSDK 从 26 开始,应用默认受到这个限制,并且在用户界面没有关闭的选项( appops 的值为未设置,即 appops get 是获取不到值得)。

    有人说 appops 层可以设置为 allow 以关闭,我没有验证过。
    huclengyue
        20
    huclengyue  
       2018-01-17 18:58:46 +08:00 via Android
    @s82kd92l 如果你说的这中做法成为普遍,那 apk 效验会成为常态
    mortal
        21
    mortal  
       2018-01-17 19:00:29 +08:00
    UU 安全好像就是这个路子?
    s82kd92l
        22
    s82kd92l  
    OP
       2018-01-17 19:03:48 +08:00
    @Qlccks2 @huclengyue @tscat apk 签名校验是可以通过 xposed 或者对 rom 本身做修改来绕过的,连谷歌全家桶都能被欺骗,参见
    https://github.com/Lanchon/haystack
    https://github.com/thermatk/FakeGApps

    如果哪一天签名校验成了常态,装个 xposed 就好了。
    honeycomb
        23
    honeycomb  
       2018-01-17 19:14:57 +08:00 via Android
    @s82kd92l 所以你就知道系统的签名校验是一个很重要的机制,关闭它换取 hack/workaround 程度的控制代价太大(伤敌一千自损三千)
    meisky6666
        24
    meisky6666  
       2018-01-17 19:19:52 +08:00 via Android
    改了那个文件,里面的函数请求不到那个权限会闪退
    s82kd92l
        25
    s82kd92l  
    OP
       2018-01-17 19:29:04 +08:00
    @honeycomb 并不是对所有程序关闭校验,而是可以让用户选择性替换。

    再说了,签名机制对用户的保护无非就是防止升级包被篡改,但这个功能可以让修改 manifest 的 app 自己做到,提供相同级别的保护。

    这里有一个安装前 /安装后签名校验的区别。所有对自身签名验证的 apk,都是利用系统提供的 api,因为他们没法直接读取自身的 apk 文件,只能依靠系统服务。而安装前我们是可以直接读取 apk 文件的,得到的签名信息是绝对可靠的,不存在安全问题。
    honeycomb
        26
    honeycomb  
       2018-01-17 19:30:38 +08:00 via Android
    @s82kd92l
    这么重要的东西变得可选就是很大的攻击面。
    签名保护的不仅仅是升级,随便举个例子,Android 里
    honeycomb
        27
    honeycomb  
       2018-01-17 19:32:31 +08:00 via Android
    @s82kd92l
    抱歉手滑了没写完就发出来

    例如:
    Android 里有一种权限是 signature 级别的
    didikee
        28
    didikee  
       2018-01-17 19:33:22 +08:00 via Android
    不知道楼主对安卓理解有多少,现实是你估计也就禁用广播和服务,其他的你改了配置没有用,代码没改该怎么还是怎么。而且崩溃概率大幅度上升。而且广播可以动态注册,不需要写在清单文件里
    est
        29
    est  
       2018-01-17 19:37:06 +08:00
    直接底层改 chroot + setns
    s82kd92l
        30
    s82kd92l  
    OP
       2018-01-17 19:38:41 +08:00
    @meisky6666 修改 2 确实可能出现这个问题,但还有 1 和 3 可以改,风险相对小。

    还可以利用社区的力量,做些类似于绿守处方的东西,让小白也知道对于某些特定 apk,哪些服务 /权限能禁哪些不能禁。比如*.permission.MIPUSH_RECEIVE 这种权限,我打赌你全禁掉也没事。
    s82kd92l
        31
    s82kd92l  
    OP
       2018-01-17 19:40:41 +08:00
    @honeycomb 所以我在原帖了说了“尽量做到每个 apk 单独签名",这样不同的 app 就没法利用相同签名获取别人家的权限。
    tscat
        32
    tscat  
       2018-01-17 19:48:28 +08:00 via Android
    @s82kd92l 欺骗自然是可以的。没有存在完全不可破解的。但是你这么做,还不如直接用 xposed 直接给个假的隐私。
    s82kd92l
        33
    s82kd92l  
    OP
       2018-01-17 19:51:25 +08:00   ❤️ 1
    @didikee java 代码是孙悟空,manifest 是如来神掌。java 代码怎么写也不能脱离 manifest 控制,动态广播没有权限是没用的,哪怕有权限,app 不在后台运行时也是没用的。
    meisky6666
        34
    meisky6666  
       2018-01-17 19:59:18 +08:00 via Android
    @s82kd92l 我刷的 cm 有隐私保护功能,可以看到每个权限的使用次数,还可以把摄像头和位置设置成每次询问,这是最安全的了
    skylancer
        35
    skylancer  
       2018-01-17 20:44:14 +08:00
    发帖前我建议你先试试看可不可行
    另外,Android 拿 IMEI 当年禁止 READ_PHONE_STATE 还能用 API 取到,改了 manifest 根本不会有用
    pq
        36
    pq  
       2018-01-17 20:50:39 +08:00
    在百度输入法 2.x 时代,我就曾经是这么干的,但 3.x 之后,不仅没法正常用 apktools 解包,而且,用其它办法解包修改之后再打包,它会在启动时提示包损坏然后直接退出。

    腾讯的许多 app,都是没法解包修改并重新打包的,也是在启动时先检查包的完整性。
    skylancer
        37
    skylancer  
       2018-01-17 20:53:08 +08:00
    @pq 还是有很多方法能解包修改并重新打包的,不然 ROMer 很多时候没法插 smali,但是最大的问题是在于会检查签名.. 就很蛋疼
    s82kd92l
        38
    s82kd92l  
    OP
       2018-01-17 21:17:10 +08:00
    @skylancer 之前改过 whatsapp 和另外一款依赖 gcm 的开源软件,可以运行。国内流氓还没试过。待会儿试试高德地图
    zjb861107
        39
    zjb861107  
       2018-01-17 21:20:15 +08:00
    我为什么不信任大厂,反而来信任一个小作坊?谁来保证重签名过程中的安全?
    xingda920813
        40
    xingda920813  
       2018-01-17 21:27:41 +08:00   ❤️ 1
    @honeycomb

    "有人说 appops 层可以设置为 allow 以关闭,我没有验证过。"

    不行的, 具体可以看 int ActivityManagerService.appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk),

    target O+ 的直接 return ActivityManager.APP_START_MODE_DELAYED_RIGID, 然后 Legacy 的才会去读 AppOps 的值.

    // Apps that target O+ are always subject to background check
    if (packageTargetSdk >= Build.VERSION_CODES.O) {
    return ActivityManager.APP_START_MODE_DELAYED_RIGID;
    }
    // ...and legacy apps get an AppOp check
    int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, packageName);
    honeycomb
        41
    honeycomb  
       2018-01-17 21:36:54 +08:00
    @xingda920813

    谢谢!

    我觉得也是,其它 appops 项目的也都是这样,在最后做一次兜底,如果有什么高级别 target SDK 新增的限制会在前面。
    s82kd92l
        42
    s82kd92l  
    OP
       2018-01-17 21:39:08 +08:00
    @zjb861107 开源即可
    skylancer
        43
    skylancer  
       2018-01-17 21:47:00 +08:00   ❤️ 1
    @s82kd92l 都来用 xposed 治理了我为什么还要用修改 manifest 来 revoke 权限呢,事实上 Lucky Patcher 也是利用了 art
    cache 修改来覆盖 manifeat 的。签名常态都要靠 xposed 来欺骗,我为什么不用 xposed 插件来 revoke app 权限? 所以你一切想法就是不合实际的脱裤子放屁
    skylancer
        44
    skylancer  
       2018-01-17 21:47:18 +08:00
    fest.. 拼写错了
    manhere
        45
    manhere  
       2018-01-17 23:36:40 +08:00 via Android
    my android tools 就是这种工具啊
    fan123199
        46
    fan123199  
       2018-01-18 00:09:11 +08:00
    权限的话,如果原来 apptarget 小于 26,那么应该是没适配,改了 target 一样跑不起来。
    DioV
        47
    DioV  
       2018-01-18 01:49:58 +08:00
    别的不说,对于一般用户来说修改权限带来的直接影响就是应用的无法使用。因为代码对于用户是一个黑盒的状态,要像修改 /关闭权限而不影响使用几乎是不可能实现的。
    windflyer
        48
    windflyer  
       2018-01-18 07:21:53 +08:00
    补充一点。

    如果直接在 AndroidManifest.xml 里禁用(我猜是删除掉声明),app 即使可以启动,但可能会有未被捕获的异常抛出,导致崩溃。
    huclengyue
        49
    huclengyue  
       2018-01-18 08:40:00 +08:00 via Android
    @s82kd92l java 有反射,禁用也可以拿到,你说的那些,禁用了都可以拿到就是麻烦点
    lackywind
        50
    lackywind  
       2018-01-18 09:43:41 +08:00
    说了这么多,或许你需要一份源码自己定制系统吧
    find2bHusky
        51
    find2bHusky  
       2018-01-18 10:14:12 +08:00
    异想天开
    honeycomb
        52
    honeycomb  
       2018-01-18 10:48:22 +08:00 via Android
    @huclengyue 今天有个新闻说 P 可能会进一步限制(包括通过反射)访问私有 API
    s82kd92l
        53
    s82kd92l  
    OP
       2018-01-18 11:19:16 +08:00
    @huclengyue @honeycomb 获取签名的函数是通过 IBinder 在 ActivityMangerService 的系统进程中实现的,java 反射怎么可能穿越进程甚至穿越不同 UID 呢?
    honeycomb
        54
    honeycomb  
       2018-01-18 12:30:10 +08:00 via Android
    @s82kd92l 应该不是同一件事。今天的新闻内容是说 aosp 出了几个 commit,进一步阻止使用源码里被 hide 注解掉的方法(目前有一些可以通过反射调用)。
    yuriko
        55
    yuriko  
       2018-01-18 13:28:02 +08:00
    @s82kd92l 我用反射取到过别的 apk 的代码,取决于 dexloader 的逻辑,我觉得顺着这个上去应该有办法?
    yingfengi
        56
    yingfengi  
       2018-01-18 21:23:20 +08:00
    my android tools 是个好东西
    有个论坛,一个网友搞的,bbs.letitfly.me 应该是这个链接?
    或者我的友链里面找找。
    imcczy
        57
    imcczy  
       2018-01-19 01:51:11 +08:00 via iPhone
    楼主应该是没有了解过 Android 应用安全以及 Android 系统安全这些,想的太简单了,牵一发而动全身……而且这本身就是一个攻防博弈的过程,不存在一劳永逸的方法。楼主的方法可能对小厂的应用有用,大厂的想都别想…
    s82kd92l
        58
    s82kd92l  
    OP
       2018-01-19 15:18:13 +08:00
    @skylancer 试了试改高德地图,配合这个补丁 https://github.com/Lanchon/haystack,有效运行。

    @yuriko 反射只能对自身进程有效,哪怕是对同一个 app 下的另一个进程都无效,更何况是对不同 UID 下的进程。

    @imcczy 应用安全 apk 加壳我不熟,但系统安全,包括 linux 内核 /selinux/binder/permission 机制我都很熟,aosp 各种系统服务源代码也没少看。


    还有最近有了免 root 的 xposed 的方案:https://github.com/haygcao/VAExposed,这个是一个薄容器,里面甚至自带签名伪造功能,无需 xposed: https://github.com/haygcao/VAExposed/blob/master/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/parser/PackageParserEx.java#L53
    当然,这个东西既然与 apk 本身运行与同一个进程中,那么就容易利用反射来针对。
    s82kd92l
        59
    s82kd92l  
    OP
       2018-01-19 15:29:08 +08:00
    imcczy
        60
    imcczy  
       2018-01-19 16:04:48 +08:00
    @s82kd92l #58 既然你接触过这些那也应该了解你的方法只对部分应用有效嘛。。你提到的方法,以及类似 VA 这样的沙盒这块学术界目前已经有非常多的研究了,其实就是权限隔离,方法五花八门,但是我目前还没有看到比较好的能用实际运用的方案。主要是,修改应用以及签名欺骗这些太容易被针对了。
    imcczy
        61
    imcczy  
       2018-01-19 16:27:02 +08:00
    @s82kd92l #58 另外补充一点,应用内部是可以通过反射调用系统 API 的,这个就涉及到 BInder 本身的机制说起来太麻烦,其实就是反射的对象是一个本地代理对象。其他 App 的代码话,只要能够获取到对应的 Application 对象就可以了,或者直接手动加载 dex。
    yuriko
        62
    yuriko  
       2018-01-19 18:12:40 +08:00
    @s82kd92l 没错啊,我说的是跨应用反射,所以取到的代码当然是跑在自己进程里的没问题。如果 DexLoader 能找到对应的代码,反射一份说不定可以跑啊。
    s82kd92l
        63
    s82kd92l  
    OP
       2018-01-19 21:07:36 +08:00
    @yuriko 你要是能做到跨应用反射,去谷歌那领几百万美元奖金绝对没问题。
    yuriko
        64
    yuriko  
       2018-01-21 10:59:04 +08:00
    @s82kd92l 如果你不信我也没办法,我现在就是用的这反射去操作别的 APK 实现 UI 耦合剥离,APK1 去加载 APK2 里的 UI 组件,这样就不用同时更新两个 APK 了的意思。

    @imcczy 基本一个意思,能拿到对应的 Application 或者 DexLoader 相关就能加载对应的代码,反射可以随便玩。我这边用的 SystemUID 和 platform 的签名,不知道这方面有什么特别的限制么?
    s82kd92l
        65
    s82kd92l  
    OP
       2018-01-21 12:41:37 +08:00
    @yuriko @imcczy 你们是说拿到别人的 Application Context,还是说在 PackageManager 里面的 ApplicationInfo ? SystemUID,你是说你写的是随系统安装的 priv-app 吗?

    稍微警醒点的 app 应该不会随便把 context 拱手送人,因为这就菊花外漏任人宰割了。当然很多第三方 sdk 可能会强行索取 context 不给就罢工,然后 sdk 可能偷偷把 context 走私出去?可是 android 系统级服务又不是傻子不会用调用第三方 sdk.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   6047 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 02:33 · PVG 10:33 · LAX 18:33 · JFK 21:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.