IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> [踩坑][Android]代码混淆引发的连环惨案 -> 正文阅读

[移动开发][踩坑][Android]代码混淆引发的连环惨案

背景

老规矩,先交代背景。
现状是这样:

  1. wifi-ext-service.jar是我们开发的wifi的扩展接口的实现;
  2. wifi-service.jar与wifi-ext-service.jar均在编译时将代码混淆;
  3. wifi-ext-service.jar依赖wifi-service.jar;
  4. AOSP原生编译规则中,wifi-service.jar会静态依赖android.hardware.wifi-V1.0-java;
    在这里插入图片描述
    一切都相安无事,直到现在有个开发需求,需要wifi-ext-service.jar依赖android.hardware.wifi-V1.0-java并调用其中的IWifiChip/IWifi的某些函数;

问题 - 如何依赖

首先遇到的第一个两难问题:wifi-ext-service.jar在编译时到底要不要静态依赖android.hardware.wifi-V1.0-java?

选择1 非静态依赖android.hardware.wifi-V1.0-java

结果: 启动system_server时crash:

08-20 14:01:54.801  2911  2911 I system_server: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.hardware.wifi.V1_0.IWifiChip$requestChipDebugInfoCallback" on path: DexPathList[[zip file "/system/framework/services.jar", zip file "/system/framework/ethernet-service.jar", zip file "/system/framework/wifi-service.jar", zip file "/system/framework/com.android.location.provider.jar", zip file "/system/framework/car-frameworks-service.jar", zip file "/system/framework/wifi-ext-service.jar"],nativeLibraryDirectories=[/system/lib64, /system/product/lib64, /system/lib64, /system/product/lib64]]
08-20 14:01:54.801  2911  2911 I system_server:   at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:134)
08-20 14:01:54.801  2911  2911 I system_server:   at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379)
08-20 14:01:54.801  2911  2911 I system_server:   at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
08-20 14:01:54.801  2911  2911 I system_server:   at void com.ext.server.wifi.q.<init>(android.content.Context) ((null):-1)
08-20 14:01:54.801  2911  2911 I system_server:   at void com.ext.server.wifi.WifiExtService.<init>(android.content.Context) ((null):-1)
08-20 14:01:54.801  2911  2911 I system_server:   at java.lang.Object java.lang.reflect.Constructor.newInstance0(java.lang.Object[]) (Constructor.java:-2)
08-20 14:01:54.801  2911  2911 I system_server:   at java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[]) (Constructor.java:343)
08-20 14:01:54.801  2911  2911 I system_server:   at com.android.server.SystemService com.android.server.SystemServiceManager.startService(java.lang.Class) (SystemServiceManager.java:98)
08-20 14:01:54.801  2911  2911 I system_server:   at com.android.server.SystemService com.android.server.SystemServiceManager.startService(java.lang.String) (SystemServiceManager.java:72)
08-20 14:01:54.801  2911  2911 I system_server:   at void com.android.server.SystemServer.startOtherServices() (SystemServer.java:1169)
08-20 14:01:54.801  2911  2911 I system_server:   at void com.android.server.SystemServer.run() (SystemServer.java:450)
08-20 14:01:54.801  2911  2911 I system_server:   at void com.android.server.SystemServer.main(java.lang.String[]) (SystemServer.java:303)
08-20 14:01:54.801  2911  2911 I system_server:   at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2)
08-20 14:01:54.801  2911  2911 I system_server:   at void com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run() (RuntimeInit.java:493)
08-20 14:01:54.801  2911  2911 I system_server:   at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:838)

原因分析:
由于非静态依赖并不会在编译时将需要的类打包进wifi-ext-service.jar中,而是需要在运行时,通过SYSTEMSERVERCLASSPATH环境变量,找到可能提供这些类的jar包,并依次查找。
而在此当中,唯一静态引入这些类的wifi-service.jar又将其混淆了,因此按照包名、类名查找的话,完全没法找到;

这里估计会有人想到,是不是可以修改proguard,使其在混淆时将指定包名下的类排除除去就可以了?确实如此,但是仍然会有概率遇到选择2时的这个问题:

选择2 静态依赖android.hardware.wifi-V1.0-java

结果: 开启热点后system_server进程crash:

08-20 14:22:26.449   984   984 E AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: main
08-20 14:22:26.449   984   984 E AndroidRuntime: java.lang.NoSuchMethodError: No static method p()Lb/a/a/a/b/a/a; in class Lb/a/a/a/b/a/a; or its super classes (declaration of 'b.a.a.a.b.a.a' appears in /system/framework/wifi-service.jar)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at com.ext.server.wifi.h.onReceive(Unknown Source:85)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1391)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run(Unknown Source:2)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at android.os.Handler.handleCallback(Handler.java:873)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:99)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:193)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at com.android.server.SystemServer.run(SystemServer.java:473)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at com.android.server.SystemServer.main(SystemServer.java:303)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:838)

原因分析:
看到这两行我就觉得大概率和混淆有关了:

08-20 14:22:26.449   984   984 E AndroidRuntime: java.lang.NoSuchMethodError: No static method p()Lb/a/a/a/b/a/a; in class Lb/a/a/a/b/a/a; or its super classes (declaration of 'b.a.a.a.b.a.a' appears in /system/framework/wifi-service.jar)
08-20 14:22:26.449   984   984 E AndroidRuntime: 	at com.ext.server.wifi.h.onReceive(Unknown Source:85)
  • 首先,调用栈停留在wifi-ext-service.jar中的类,因此没有理由报wifi-service.jar中的类找不到方法;(wifi-ext-service主要是扩展wifi-service的接口,正常情况下不会反向持有wifi-service中的对象,何况wifi-service是混淆过的,要反向调用几乎不可能);
  • 其次,通过反编译发现,wifi-service.jar与wifi-ext-service.jar中都存在b.a.a.a.b.a.a这个类,而前者的这个类没有p()方法,后者是有的,与报错信息显示一致;
  • 为了确认这一推测,我通过对比反编译后的代码与源代码,确认反编译代码中提到的b.a.a.a.b.a.a类的p()方法实际为一个我自己创建的HAL接口的JAVA侧getService()方法调用;通过另一个静态JAVA库导入;

那么综合来看,结果比较明显了:由于wifi-service与wifi-ext-service各自在编译时并不知晓对方的存在(没有静态依赖),因此混淆时出现了类命名冲突的情况,导致在调用时跳转到了错误的类中,出现异常;

要解决这个问题,同样我们需要修改proguard文件,将具备区分度的包名保留;

解决 - 方案选择

在修改Proguard后,貌似上面两个选择都可以了:

  • 首先,需要为wifi-service的混淆添加例外,将android.hardware.wifi-V1.0-java包含的类从混淆的目标中移除出来:
-keep class android.hardware.wifi.**{*;}
  • 其次,为了防止a.a.a.a这种高概率会重复的类名冲突,需要将wifi-ext-service中大部分的包名区分出来:
-keeppackagenames vendor.ext.**

修改完后,问题得以解决;

后记 - 选择

最后,虽然使用同样的改法可以解决两个选择的问题,但是由于CTS测试项(详见https://blog.csdn.net/u014175785/article/details/115333461)的原因,以及我在调试过程中出现的交叉依赖导致ClassLoader加载报错等问题(这个问题在我写这篇文章时没有复现出来,因此没法展开介绍,后续如果再次遇到这类问题,届时再更新),我不建议采用静态依赖的方式导入;

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-21 15:35:19  更:2021-08-21 15:36:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 9:58:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码