Android修炼之混淆

news2024/11/15 11:19:23

自嘲时刻

作为Java和Android开发者,大家应该都对混淆很熟悉了。网上也有各路大神提供的混淆模板,基本上直接拿来用就好。但我还是想捋一捋,因为工作中被混淆这家伙“玩弄”了好几次,必须把它记在小本本上。

介绍

基本概念

混淆,字面上来说就是把项目中的包名、类名、方法名和变量名等进行更改,用以迷惑别人。但混淆其实包含了代码压缩、优化、校验等过程,把混淆称作ProGuard更合适。

ProGuard

ProGuard就是Java对Class文件进行“混淆”的工具。直接贴图吧:

(看到这个图,大家有没有想到什么?——设计模式中的责任链模式。)

1.shrink(压缩):ProGuard会递归地确定哪些类和类成员被使用,而其他的则被丢弃。
2.optimize(优化):ProGuard会进一步分析和优化方法。比如一些无用的参数会被丢弃,一些方法会做内联。
3.obfuscate(混淆):这个过程就是进行重命名了,把原来包含注释意义的类名、方法名等进行无意义重命名。
4.preverify(预校验):这个步骤是将预校验信息添加到类中。

这四个步骤其实都是可选的。当然,Android中一般情况下我们都会保留前三个步骤,而忽略preverify过程,这样可以加快混淆速度。

Android中的ProGuard

Android中默认集成了ProGuard工具,在sdk目录的/tools/proguard中。混淆开启方法:

android {...// AS自动生成buildTypes {release {// 混淆开关minifyEnabled true// 移除无用的resource文件shrinkResources true// proguard-android.txt表示默认的混淆规则// proguard-rules.pro表示自定义的混淆规则(文件名和后缀可以修改)proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}
} 

默认的proguard-android.txt文件在sdk目录/tools/proguard中。该目录下还有个proguard-android-optimize.txt文件。而我们自定义的proguard-rules.pro文件中有部分基础混淆规则就是来自proguard-android-optimize.txt

混淆语法

混淆的语法都可以在上述的ProGuard官网中找到,这里只介绍一些常用的语法规则。

1、保留类和类成员

保留反之被删除或重命名防止被重命名
类和类成员-keep-keepnames
仅类成员-keepclassmembers-keepclassmembernames
如果拥有某成员,保留类和类成员-keepclasseswithmembers-keepclasseswithmembernames

2、类成员中的一些符号

符号作用
匹配所有构造器
匹配所有域
匹配所有方法
*匹配所有域和方法

3、一些常用通配符

通配符作用
*匹配任意长度字符,但不含包名分隔符(.)
**匹配任意长度字符,并且包含包名分隔符(.)
***匹配任意参数类型
匹配任意长度的任意类型参数
%匹配任何原始类型
?匹配类名中的任何单个字符

其他的一些语法基本上属于无变化的那种,在混淆规则中基本都固定使用了,有需要的话可以自行在官方查询。

自定义混淆模板

嗯…这模板基本都是大同小异的,这里就直接贴出常用的混淆规则了。

# 优化算法,一般不用修改,来自Google
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
# 代码混淆压缩比,在0~7之间,默认为5,一般不做修改
-optimizationpasses 5
# 混合时不使用大小写混合,混合后的类名为小写
-dontusemixedcaseclassnames
# 不去忽略非公共库的类
-dontskipnonpubliclibraryclasses
# 优化时允许访问并修改有修饰符的类和类的成员 
-allowaccessmodification
# 项目混淆后产生映射文件
-verbose
# 不做预校验
-dontpreverify

# 保留Annotation不混淆
-keepattributes *Annotation*,InnerClasses
# 避免混淆泛型
-keepattributes Signature
# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable

# 保留四大组件,自定义的Application等
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class * extends android.view.View
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# 保留native方法
-keepclasseswithmembernames class * {native <methods>;
}

# 保留在Activity中的方法参数是view的方法,
# 这样以来我们在layout中写的onClick就不会被影响
-keepclassmembers class * extends android.app.Activity{public void *(android.view.View);
}

# 保留自定义View
-keepclassmembers public class * extends android.view.View { void set*(***); *** get*(); public <init>(android.content.Context); public <init>(android.content.Context, android.util.AttributeSet); public <init>(android.content.Context, android.util.AttributeSet, int);
}

# 保留枚举
-keepclassmembers enum * {public static **[] values();public static ** valueOf(java.lang.String);
}

# 保留Parcelable序列化对象
-keepclassmembers class * implements android.os.Parcelable {public static final android.os.Parcelable$Creator CREATOR;
}

# 保留R文件中的成员
-keepclassmembers class **.R$* {public static <fields>;
}

# 保留Serializable序列化的类不被混淆
-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {static final long serialVersionUID;private static final java.io.ObjectStreamField[] serialPersistentFields;!static !transient <fields>;!private <fields>;!private <methods>;private void writeObject(java.io.ObjectOutputStream);private void readObject(java.io.ObjectInputStream);java.lang.Object writeReplace();java.lang.Object readResolve();
}

# -------------------------------------------------------------------------------
# webView处理,项目中没有使用到webView忽略即可
-keepclassmembers class fqcn.of.javascript.interface.for.webview {public *;
}
-keepclassmembers class * extends android.webkit.webViewClient {public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);public boolean *(android.webkit.WebView, java.lang.String);
}
-keepclassmembers class * extends android.webkit.webViewClient {public void *(android.webkit.webView, jav.lang.String);
}

# --------------------------保留JS接口-------------------------------------------

# --------------------------保留反射类-------------------------------------------

# --------------------------保留实体类-------------------------------------------

# --------------------------第三方库的混淆规则----------------------------------- 

以上都是一些常用的混淆规则,其中部分规则其实都在Android默认混淆文件中声明过了。所以具体的自定义混淆规则还是得根据项目进行变化。

混淆产物

混淆后一般都有下面几个文件:

1.dump.txt:描述APK文件中所有类的内部结构;
2.mapping.txt:提供混淆前后类、方法、类成员等的对照表
3.seeds.txt:列出没有被混淆的类和成员
4.usage.txt:列出被移除的代码

遇到混淆问题时,我通常是通过查看mapping.txt文件来分析原因的。如果在进行Crash追踪中遇到了困难,可以使用sdk目录下/tools/proguard/bin中的proguardgui.bat可视化工具进行混淆定位。示例如图:

混淆引发的“Xue案”

场景一****问题描述:业务方集成了我们的一个SDK,SDK的一个页面中会显示Banner图,而Banner图所用的是SDK中自定义的ViewPager组件,结果业务方那边无法显示Banner图。原因分析:通过反编译apk,比对mapping.txt文件,发现Banner图的自定义Adapter中关键方法都被清除了。查看混淆文件,发现只keep了support v4的ViewPager,并没有keep住PagerAdapter。而SDK中又是通过compileOnly(provided)方式依赖v4包的,导致自定义的Adapter在工程编译的时候找不到被引用的关系,然后就被混淆给优化掉了。经验:针对compileOnly(provided)依赖的库,一定要注意相关类的混淆,特别是SDK开发者,因为混淆导致的问题一般较难定位。

场景二****问题描述:业务方又集成了我们的一个SDK(没错,是“又”),SDK有一个换肤功能,业务方可以通过构造特定格式的资源文件来实现皮肤替换。但在业务通过公司编译工具编译后的apk中无法实现换肤功能。原因分析:机智的我很快想到了混淆问题,于是让业务方加上保留所有R文件的规则,结果还是失败。于是开始了长时间的打log看log过程,还是确定问题出在资源名的混淆上。最后发现业务方虽然在本地编译环境中keep了资源名,但在公司的编译环境中还是对资源进行了混淆,导致换肤失败。经验:对于和资源相关的功能,一定要注意R文件的混淆。不要轻易相信业务,因为他们经常有你预料不到的操作(手动滑稽…)。

工作中遇到过很多次混淆相关的问题,这里就不多说了,只要大家细心点就好了。

总结

1.混淆其实不算是什么新鲜的话题,但对于Java和Android开发者来说是必不可少的,还是要对其有敬畏之心(严肃脸…)。
2.混淆的好处不言而喻增加了反编译的难度,优化了代码。但仅仅是增加难度而已,对于有心之人还是能从反编译中找到蛛丝马迹。所以,对于敏感代码和数据使用更安全的保护措施是非常必要的,比如加固。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/132152.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cesium中使用Sampler3D,3D纹理,实现体渲染

Cesium中使用Sampler3D&#xff0c;3D纹理&#xff0c;实现体渲染 Cesium目前&#xff08;20221231&#xff09;还不支持直接使用3D纹理&#xff0c;但是其实内部已经可以WebGL2&#xff0c;而且内置常量也有3DTexture。所以&#xff0c;可以通过仿Texture&#xff0c;来实现3…

如何彻底的理解需求,做出更好的软件

背景&#xff1a; 最近接到了一个需求&#xff0c;大概的需求就是我们有一些数据&#xff0c;默认分为了两类。如果变多的话&#xff0c;用户找起来非常的困难&#xff0c;针对这个现象我们提出了两点解决方案。1&#xff1a;添加搜索。2&#xff1a;添加分组。 第一波设计&…

Android的adb命令实战篇-1

2023年 —— 是充满希望的一年. 对于Android开发者而言&#xff0c;ADB命令或多或少都使用过&#xff0c;今天我们就一起来整体回顾一下吧。 ADB的全称&#xff1a;Android Debug Bridge 1. ADB(Android Debug Bridge) 在实际工作中&#xff0c;周围同事会抱怨记不住常用的a…

过寒假

小时候&#xff0c;每到一放假就被父亲送回奶奶家。除了寒假作业&#xff0c;我还会带一堆书回去看。我小时候特别喜欢到邮电局大厅去订阅报刊杂志&#xff0c;就连学校也会报名订阅报刊。我小学时看完梁羽生的《七剑下天山》就是翻日报上每天的小说连载看完的。那时候过年时家…

Unity AR小游戏(玩具小车)踩坑记

最近对AR产生了兴趣。先科普一下什么是AR吧。AR是Augmented Reality&#xff08;增强现实&#xff09;的简称&#xff0c;是基于摄像头对现实世界的实时图像采集、分析和理解&#xff0c;然后在此基础上融入虚拟物体&#xff08;信息&#xff09;&#xff0c;以达到增强体验的目…

Three.js学习(一)初识three.js

文章目录1.基本配置2.基本概念3.Api4.实现一个旋转动画1.基本配置 &#xff08;1&#xff09;安装 ​ npm install three &#xff08;2&#xff09;引入 import * as THREE from three2.基本概念 Three.js是基于原生WebGL封装运行的三维引擎。 &#xff08;1&#xff09;一…

【Linux】实验四 进程信号通信

文章目录一、实验目的二、 实验内容三、 实验原理1、信号3.1.1 信号的基本概念3.1.2、信号的发送2、所涉及的系统函数调用3.2.1 fork()3.2.2 kill( )This is my question.3.2.3 signal( )代码例子3.2.4 getpid()3.2.5 wait()四、 实验内容五、程序代码运行结果六、实验总结及心…

来玩,前端性能优化(+面试必问:宏任务和微任务)

前端性能优化相关的“技能点”笔者之前也写过几篇&#xff0c;但是大多都是小打小闹。我重新整理了曾经使用过的性能优化手段。本文介绍三种方案&#xff1a;页面资源预加载、服务请求优化和非首屏视图延迟加载。 页面资源预加载 页面是不可能真正预加载的&#xff0c;但是有…

Linux | PCIe Hotplug | 概念及工作原理的不完全总结

本文对 PCIe 热插拔的概念及工作原理进行不完全总结。 更新&#xff1a; 2022 / 12 / 31 Linux | PCIe Hotplug | 概念及工作原理的不完全总结热插拔组成部件实现代码通知式热插拔线程中断功耗管理意外移除错误处理整合移除BAR参考链接参考这里 1’ 2’ 3‘ 4’ 5 1992年初始…

postgresql数据库安装,备份还原

一.postgresql数据库安装 1.下载软件包 地址&#xff1a;PostgreSQL: File Browser 2.解压安装 [rootpostgresql u01]# tar -zxf postgresql-14.2.tar.gz安装环境 yum install -y perl-ExtUtils-Embed readline-devel zlib-devel pam-devel libxml2-devel libxslt-devel op…

(深度学习快速入门)第一章:深度学习概述、应用、学习路线和框架选择

文章目录一&#xff1a;基本概念&#xff08;1&#xff09;神经网络&#xff08;2&#xff09;感知器&#xff08;3&#xff09;深度学习&#xff08;4&#xff09;前向运算和反向传播二&#xff1a;DeepLearning学习路线三&#xff1a;深度学习应用&#xff08;1&#xff09;生…

基于Stream的Redis消息队列

目录一、消息队列二、基于List结构模拟消息队列基于List的消息队列的优点&#xff1a;基于List的消息队列的缺点&#xff1a;三、基于PubSub的消息队列基于PubSub的消息队列的优点&#xff1a;基于PubSub的消息队列的缺点&#xff1a;四、基于Stream的消息队列1、XADD语法2、XR…

C++ Primer笔记——allocator、unique_ptr和release、智能指针与动态数组、阻止拷贝

目录 一.P418 unique_ptr和release 二.P426 智能指针与动态数组 &#xff08;一&#xff09;.unique_ptr &#xff08;二&#xff09;.shared_ptr 三.P428 allocator &#xff08;一&#xff09;.申请空间 &#xff08;二&#xff09;.初始化构造 &#xff08;三&#…

活动星投票少儿模特大赛网络评选制作一次图文分组投票怎么制作

关于微信投票&#xff0c;我们现在用的最多的就是小程序投票&#xff0c;今天的网络投票&#xff0c;在这里会教大家如何用“活动星投票”小程序来进行投票。我们现在要以“国际车展少儿模特大赛”为主题进行一次投票活动&#xff0c;我们可以在在微信小程序搜索&#xff0c;“…

aws cloudformation 使用模板配置 ecs 蓝绿部署

参考资料 Perform ECS blue/green deployments through CodeDeploy using AWS CloudFormationAWS::CodeDeployBlueGreen 在之前的文章中&#xff0c;使用codepipeline中通过控制台的方式创建了ecs蓝绿部署的demo。实际上可以单独通过codedeploy完成ecs服务的蓝绿部署 参考官…

【ARMv8 SIMD和浮点指令编程】Libyuv I420 转 ARGB 流程分析

Libyuv 可以说是做图形图像相关从业者绕不开的一个常用库&#xff0c;它使用了单指令多数据流提升性能。以 ARM 处理为主线&#xff0c;通过 I420 转 ARGB 流程来分析它是如何流转的。 Libyuv 是一个开源项目&#xff0c;包括 YUV 的缩放和转换功能。 使用邻近、双线性或 box…

QThread、moveToThread用法详述

1.吐槽 QThread类提供了一种平台无关的方法对线程进行管理。但对于QThread类的熟练使用&#xff0c;即使是从事Qt开发多年的程序猿们&#xff0c;往往也会踩雷、入坑。总之&#xff1a;QThread类不好用、如果对该类理解不透&#xff0c;很容易导致程序崩溃。本人强烈建议&#…

(函数介绍)puts()函数

功能介绍 1. puts()函数用来向标准输出设备屏幕输出字符串并换行。 2. 函数的参数就是一个起始的地址&#xff0c;然后就从这个地址开始一直输出字符串&#xff0c;直到碰到\0就停止&#xff0c;然后这个\0是不进行输出的&#xff0c;是不能够算在里面的。与此同时&#xff…

十、字节缓冲流、字符流、转换流、对象操作流、对象序列化流

字节缓冲流 构造方法 字节缓冲流介绍 BufferedOutputStream&#xff1a;该类实现缓冲输出流.通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用BufferedInputStream&#xff1a;创建BufferedInputStream将创建一个内部缓冲区数…

2022年为什么要学习C语言?

为什么学习c语言 为什么学C语言逻辑&#xff1f; 为什么要学习C语言&#xff1f; 学习C语言的主要理由有以下几点&#xff1a; C语言可以作为学习计算机程序设计语言的入门语言&#xff1b; C语言是编写操作系统的首选语言&#xff0c;与计算机硬件打交道时灵巧且高效&…