Android代码混淆后的定位

  • 什么是代码混淆
  • 如何开启Android Studio的代码混淆
  • 如何在程序奔溃后定位到奔溃的代码行
    • mapping.txt
    • 分析流程

什么是代码混淆

在java写的.java文件后,使用javac编译成.class文件,在编译的过程,不像C/C++或C#那样编译时进行加密或混淆,它是直接对其进行符号化、标记化的编译处理,于是,也产生了一个逆向工程的问题:可以根据.class文件反向解析成原来的java文件!
Android应用程序很大一部分都是使用Java语言编写的,在发布自己的程序的时候,有一些十分重要的功能或者组件,我们并不希望被别人反编译后直接使用,所以才有了代码混淆的做法,当然一些极其重要的东西一般会用C/C++编写然后通过动态库的方式进行调用。
如图所示,在未开启代码混淆的时候,反编译后的代码和左边的源代码基本上一一对应,能够十分轻松的找到代码的逻辑:

而在进行了代码混淆之后,所反编译出来的源码如图所示:

可以看出,在开启反编译的情况下,程序的代码暂且算是得到了一定程度上的保护。
目前代码混淆的方式有很多种,其中Android Studio就自带一种,他是通过将包名、类名、方法名用相似的名字进行“重命名”,这样一来对于反编译后的代码阅读起来也是极其困难:

当然目前还有更加安全的做法就是将字节码文件转换成为动态库,这样一来通过极大地增加了反编译的难度(比如腾讯应用加固)。

如何开启Android Studio的代码混淆

对于android应用程序的代码混淆目前也有着多种方式,最简单的方法就是Android Studio自带的代码混淆功能,在应用模块的build.gradleminifyEnabled改为true即可打开代码混淆功能:

另外,我们还可以自定义配置混淆规则,Android Studio系统默认的混淆规则文件为同级目录下的proguard-rules.pro这个文件,我们只需修改proguard-rules.pro即可,这里介绍一下一些比较常用的混淆规则,具体的可以参考:缩减、混淆处理和优化应用

#指定压缩级别(在0~7之间,默认为5,一般不需要更改)
-optimizationpasses 7#混淆时不使用大小写混合,混淆后的类名为小写(大小写混淆容易导致class文件相互覆盖)
-dontusemixedcaseclassnames#保护代码中的Annotation不被混淆(这在Json实体映射是非常重要,例如FastJson)
-keepattributes *Annotation*#避免混淆泛型,这在JSON实体映射时非常重要,比如fastJson
-keepattributes Signature#保留本地方法不被混淆
-keepclasseswithmembernames class * {native <methods>;
}#设置抛出异常时保留代码行号
-keepattributes SourceFile.LineNumberTable#忽略警告 (慎用)
-ignorewarnings#未混淆的类和成员
-printseeds seeds.txt
#列出从apk中删除的代码
-printusage unused.txt#保留所有的本地native方法不被混淆
-keepclasseswithmembernames class *{native <methods>;}#保留继承自android.view.View类的子类
-keep public class * extends android.view.View#保留在Activity中的方法参数是view的方法,从而我们在layout里面编写onClick就不会被影响
-keepclassmembers class * extends android.app.Activity{public void *(android.view.View);
}#枚举类不能被混淆
-keepclassmembers enum *{public static **[] values();public static ** valueOf(java.lang.String);
}#保留Parcelable序列化的类不能被混淆
-keep class * implements android.os.Parcelable{public static final android.os.Parcelable$Creator *;
}#对于回调函数onXXEvent的,不能被混淆
-keepclassmembers class * {void *(**Event);
}

如何在程序奔溃后定位到奔溃的代码行

mapping.txt

代码混淆的好处有,但是也有他的缺点:对于开发人员来说,在不添加日志的情况下,程序奔溃以后很难定位到具体的代码位置。

就像图里所展示的一样,在Crash日志里面根本定位不到异常位置。要是大概了解Crash的位置并且该类的代码量不多,可以通过添加日志慢慢分析定位,那要是别的情况呢?
幸运的是,Android Studio在对代码进行混淆的时候,同时也会生成一份名为 mapping.txt的索引文件,通过这份文件还是可以比较轻松的定位出问题来源的,该文件位置为 build/outputs/mapping/debug/mapping.txt ,当然这个文件的位置会根据你的配置也许会有所不同的。

分析流程

在日志中的输出为:

java.lang.NullPointerExceptionat java.io.File.<init>(File.java:283)at com.imorning.demo.MainActivity.F(:26)at com.imorning.demo.MainActivity.E(Unknown Source:0)at k1.a.onClick(Unknown Source:2)at android.view.View.performClick(View.java:7448)at com.google.android.material.button.MaterialButton.performClick(:1119)at android.view.View.performClickInternal(View.java:7425)at android.view.View.access$3600(View.java:810)at android.view.View$PerformClick.run(View.java:28305)at android.os.Handler.handleCallback(Handler.java:938)at android.os.Handler.dispatchMessage(Handler.java:99)at android.os.Looper.loop(Looper.java:223)at android.app.ActivityThread.main(ActivityThread.java:7656)at java.lang.reflect.Method.invoke(Native Method)at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

在这其中,比较重要的几句就是

at java.io.File.<init>(File.java:283)
at com.imorning.demo.MainActivity.F(:26)
at com.imorning.demo.MainActivity.E(Unknown Source:0)

首先通过 java.io.File.<init> 这一句可以确定该异常发生的位置是在构造 File 对象的时候,类似于 new File(filePath) 这种情况,然后根据

at com.imorning.demo.MainActivity.F(:26)
at com.imorning.demo.MainActivity.E(Unknown Source:0)

这两句可以判断是在 MainActivity 这个类里面,具体的方法是FE,但是很显然我们的源代码里面是不存在这两个方法的,所以这两个方法是由于代码混淆后产生的,那如何确定他们在源代码中的名字是啥呢?
打开 mapping.txt 文件,搜索 com.imorning.demo.MainActivity 这个类,然后可以找到如下内容:

......
com.imorning.demo.MainActivity -> com.imorning.demo.MainActivity:java.lang.String path -> o13:15:void <init>() -> <init>void $r8$lambda$jbVq07liQWCDW9wfWoMM5fMjaN0(com.imorning.demo.MainActivity,android.view.View) -> E26:28:void lambda$onCreate$0(android.view.View) -> F19:31:void onCreate(android.os.Bundle) -> onCreate
......
k1.MainActivity$$ExternalSyntheticLambda0 -> k1.a:com.imorning.demo.MainActivity com.imorning.demo.MainActivity$$InternalSyntheticLambda$0$b73ef46b845bbab58eb3dd9efa4049f61728e93353f15e1a854468e6cd9441d6$0.f$0 -> avoid com.imorning.demo.MainActivity$$InternalSyntheticLambda$0$b73ef46b845bbab58eb3dd9efa4049f61728e93353f15e1a854468e6cd9441d6$0.<init>(com.imorning.demo.MainActivity) -> <init>void com.imorning.demo.MainActivity$$InternalSyntheticLambda$0$b73ef46b845bbab58eb3dd9efa4049f61728e93353f15e1a854468e6cd9441d6$0.onClick(android.view.View) -> onClick
......

可以在第一部分很明显找到EF两个函数的定义,分别是:

$r8$lambda$jbVq07liQWCDW9wfWoMM5fMjaN0(com.imorning.demo.MainActivity,android.view.View) -> E
26:28:void lambda$onCreate$0(android.view.View) -> F

这里由于使用了lambda表达式,因此对于函数E的确认有点问题,不过问题不大,可以通过其两个参数确定出来大致范围,并且由于使用了lambda表达式也是比较好确认的。
对于函数F则可以直接看出来它的函数名是onCreate(),因此定位比较简单,同时也就确认了函数E是在onCreate()中的某个方法,并且使用了File的构造函数,这样一来便可以确定出来位置了:

Android代码混淆后的定位相关推荐

  1. Android代码混淆后查看日志

    Android中可以通过混淆减少apk的大小,提高apk反编译的难度. 但是在混淆过后会遇到一个问题,就是日志,比如说错误日志的函数会变成abcd. 怎么解决这个问题呢 通过mapping文件 map ...

  2. android 混淆后的机制,Android 代码混淆机制

    Android 代码混淆机制 由于Android项目是基于java语言的,而java属于高层抽象语言,易于反编译,其编译后的程序包包含了大量的源代码变量.函数名.数据结构等信息,根据其编译打包后的AP ...

  3. Android代码混淆工具Proguard学习

    概述 Proguard代码混淆工具:可以对代码进行去冗余压缩,代码优化,代码混淆等.在Android中的主要应用就是对代码混淆:就是将类名,方法名,Field名变成如a,b,c或者1,2,3等难以阅读 ...

  4. android代码混淆个人总结及踩坑

    android代码混淆个人总结及踩坑 前言 公司项目使用组件化开发的形式,需要对自己负责的模块进行一些混淆配置,关于混淆相信做android开发的都或多或少有过一些接触,通过对混淆文件的配置从而将代码 ...

  5. android 代码混淆

    简介 Java代码是非常容易反编译的.为了很好的保护Java源代码,我们往往会对编译好的class文件进行混淆处理. ProGuard是一个混淆代码的开源项目.它的主要作用就是混淆,当然它还能对字节码 ...

  6. android混淆语法(android代码混淆工具)

    android 代码混淆算法有哪些 根据SDK的版本不同有2中不同的代码混淆方式,以上的proguard.cfg参数详解中所涉及到的信息是在较低版本SDK下的混淆脚本,事实上在高版本的SDK下混淆的原 ...

  7. Android代码混淆配置说明

    1.为什么需要代码混淆 Proguard混淆用于保护APP不被破解和逆向分析,Proguard通过移除没有用到的代码以及通过特定规则重命名类.变量.方法来压缩.优化.混淆你的代码.这样可以让你APK更 ...

  8. Android 代码混淆规则

    1. Proguard介绍 Android SDK自带了混淆工具Proguard.它位于SDK根目录\tools\proguard下面. ProGuard是一个免费的Java类文件收缩,优化,混淆和预 ...

  9. Android 代码混淆Proguard

    混淆概念 Android代码混淆,又称Android混淆,是伴随着Android系统的流行而产生的一种APP保护技术,用于保护APP不被破解和逆向分析. 在Android的具体表现就是打包时,将项目里 ...

最新文章

  1. java 支持 shards 的jar_Hibernate Shards 数据的水平、垂直切割(一)- Hibernate测试环境...
  2. 蓝图中实现人物移动1
  3. 【转】关于CLR内存管理一些深层次的讨论[下篇]
  4. SQL Server XML转Table
  5. C#LeetCode刷题之#589-N叉树的前序遍历(N-ary Tree Preorder Traversal)
  6. python程序设计简明教程知识点总结_Python程序设计简明教程 在线阅读
  7. maven 按业务拆分模块_gradle|springboot+gradle多模块化应用
  8. AndroidStudio安卓原生开发_Activity的启动方法_隐式启动2种方法_activity关闭---Android原生开发工作笔记83
  9. 80 后技术人的中年危机
  10. 刷新iframe内容
  11. 查看服务器风扇转速等
  12. 小学计算机网络教室简介,陆桥实验小学计算机网络教室配备情况一览表(6页)-原创力文档...
  13. 基于车载以太网的音视频传输 AVB vs RTP
  14. 程序员双节假期如何小赚一笔?
  15. 上海BFC外滩金融中心潮流新店,aaddd揭秘全新生活美学
  16. Java 基础知识总结—HashMap
  17. 苹果xr如何截屏_苹果手机如何单手操作截屏
  18. 华为IoT生态品牌扩大朋友圈,方舟实验室首度亮相...
  19. 滴滴C2C模式隐忧暴露,神州专车却仍无力逆风翻盘?
  20. 技术贴,关于Rhino各类版本无法打开问题

热门文章

  1. 狗头无穷小和躺平条件
  2. touchesBegan: withEvent: 不执行/完美收起键盘
  3. 登录金蝶显示服务器地址不能为空,金蝶k3 云平台服务器地址为空
  4. HTML 注册案例 学习 制作
  5. 电脑开机一两秒就断电怎么办?
  6. 面向对象:晚点遇见你,余生都是你
  7. 用 Python 制作关不掉的端午安康弹窗!恶作剧一下!
  8. TeamViewer修改绑定设备
  9. 聊聊改变世界的5大算法
  10. 【攻防世界】十二、功夫再高也怕菜刀