补齐Android技能树 - 从害怕到玩转Android代码混淆(上)

简介: 本节稍微深入点探索下Android中的代码混淆~

0x0、引言


Android代码混淆,老生常谈了,不过大部分Android仔对它的认识可能还处于这样的阶段(比如:写这篇文章前的我):


  • 1、日常开发Debug包时不用混淆,正式发布Release包前开启代码混淆;


  • 2、混淆好处① → 类、方法、变量名变成短且无意义的名字,提高反编译后代码的阅读成本;


  • 3、混淆好处② → 删除无用的类、方法与属性,缩减了APK包的大小;


  • 4、混淆好处③ → 对字节码进行优化,移除无用指令,应用运行更快;


  • 5、怎么混淆 → 主项目的 build.gradle 设置 minifyEnabled trueproguard-rules.pro 加入混淆规则;


  • 6、混淆规则哪里来 → 网上搜索通用混淆模板复制粘贴,项目依赖到的第三方库官方文档复制粘贴;


大都止步于此,好一点的还知道下 ProGuard 听过 R8,了解 混淆配置语法,会 自定义混淆规则


会上面这些,日常开发已经 很够用了,但是现在IT行业这么 "卷",面试时,面试官问下:


混淆具体做了啥?有看过混淆源码吗?说下底层原理...


所以本节稍微深入点探索下Android中的代码混淆~


0x1、日常使用


Tips:照惯例,写下简单例子演示日常使用,走走过场,只对混淆原理感兴趣的可以跳过这Part~


1. 混淆前后的APK对比


新建项目,引下Kotlin相关依赖,协程等 (app层级的build.gradle):


dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.0'
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7'
}


新建MainActivity.kt,请求URL,加载内容:


class MainActivity : AppCompatActivity(), CoroutineScope by MainScope()  {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        et_url.setText("https://www.baidu.com")
        bt_load.setOnClickListener {
            launch {
                tv_content.text = "开始加载请求..."
                tv_content.text = "加载完毕,网页内容如下:\n\n\n ${loadUrl(et_url.text.toString())}"
            }
        }
    }
    private suspend fun loadUrl(url: String) = withContext(Dispatchers.IO) {
        var content = ""
        (URL(url).openConnection() as HttpURLConnection).apply {
            requestMethod = "GET"
            content = dealResponse(inputStream)
            disconnect()
        }
        return@withContext content
    }
    private fun dealResponse(inputStream: InputStream): String {
        val reader = BufferedReader(InputStreamReader(inputStream))
        return StringBuffer().apply {
            var str = reader.readLine()
            while (null != str) {
                append(str)
                str = reader.readLine()
            }
        }.toString()
    }
    override fun onDestroy() {
        super.onDestroy()
        cancel()
    }
}


运行下康康


网络异常,图片无法展示
|


app层级的build.gradle加下release的签名和编译配置:


signingConfigs {
    release {
        storeFile file('test.jks')
        storePassword '123456'
        keyAlias 'test'
        keyPassword '123456'
    }
}
buildTypes {
    release {
        // 启用代码压缩、优化及混淆
        minifyEnabled true
        // 启用资源压缩,需配合 minifyEnabled=true 使用
        shrinkResources true
        // 指定混淆保留规则
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        // 包签名
        signingConfig signingConfigs.release
    }
}


执行 gradle assemble 打下包,静待打包完毕,先康康Debug包:


网络异常,图片无法展示
|


裸奔,把APK直接拖到反编译工具 jadx-gui 里,看代码无压力:


网络异常,图片无法展示
|


再康康Release包:


网络异常,图片无法展示
|


体积着实少了一些,而且变量名都变成了abcd,顺带提下这个**Load Proguard mappings**,点击加载混淆文件(mapping.txt)后可以去掉代码混淆:


网络异常,图片无法展示
|


同样拖到jadx-gui里康康:


网络异常,图片无法展示
|


可读性明显降低~


2. 混淆后App Crash日志定位问题


不知道你有没有想过:混淆后的APK如果报错,日志信息会是怎样的呢


改下代码验证下,直接在点击处抛出一个空指针异常试试康:


网络异常,图片无法展示
|


单凭这里的b.b.a.a.onClick(Unknow Srouce:2),似乎很难直接定位到错误代码的真实位置。


一种低效的解决方法:自行对照混淆后生成的 mapping.txt 文件,比如直接搜上面的b.b.a.a:


网络异常,图片无法展示
|


顺着往下看不难发现问题所在,但日常开发不建议用此法,这里好找只是因为示例代码简单,推荐另一种方法:


去混淆,如果你的应用有发布到Google Play的话,可以照着官方文档走:


对崩溃堆栈轨迹进行去混淆处理或符号化解析


网络异常,图片无法展示
|


没有上传到Google Play也没关系,直接用 android-

sdk/tools/proguard/bin/proguardgui.bat


网络异常,图片无法展示
|


ProGuard和R8的混淆都可以去,老版本的脚本可能不支持R8,更新下sdk即可,不想更新的也可以直接用我提供的脚本包去R8混淆,下载地址(提取码: 1234):R8-Retrace.7z,使用流程如下图所示:


网络异常,图片无法展示
|


去混淆前后对比:


网络异常,图片无法展示
|


可以的,日常使用就讲到这里,接着过一下混淆的详细规则。


相关文章
|
2月前
|
Ubuntu 网络协议 Java
【Android平板编程】远程Ubuntu服务器code-server编程写代码
【Android平板编程】远程Ubuntu服务器code-server编程写代码
|
4月前
|
人工智能 IDE 开发工具
Studio Bot - 让 AI 帮我写 Android 代码
Studio Bot - 让 AI 帮我写 Android 代码
170 1
|
3天前
|
Ubuntu Android开发 数据安全/隐私保护
【Android平板编程】远程Ubuntu服务器Code-Server编程写代码
【Android平板编程】远程Ubuntu服务器Code-Server编程写代码
|
3天前
|
Java Android开发
Android 长按桌面显示菜单的代码
Android 长按桌面显示菜单的代码
8 0
|
3天前
|
Java Android开发
Android 切换壁纸代码流程追踪
Android 切换壁纸代码流程追踪
12 0
|
4天前
|
Shell Android开发
Android Activity重写dump方法实现通过adb调试代码
Android Activity重写dump方法实现通过adb调试代码
10 0
|
4天前
|
Java API Android开发
Android系统升级A/B分区OTA升级应用层调用UpdateEngine代码
Android系统升级A/B分区OTA升级应用层调用UpdateEngine代码
8 0
|
1月前
|
Android开发
Android代码混淆
Android代码混淆
21 0
|
2月前
|
Android开发
android studio 重新将module中的代码加入到自己项目中,报错找不到SO文件。
android studio 重新将module中的代码加入到自己项目中,报错找不到SO文件。
9 1
|
3月前
|
Ubuntu 网络协议 Linux
【Linux】Android平板上远程连接Ubuntu服务器code-server进行代码开发
【Linux】Android平板上远程连接Ubuntu服务器code-server进行代码开发
65 0