apk反编译(6)用ProGuard 混淆、压缩代码,压缩资源。
1.android官方文档
https://developer.android.com/studio/build/shrink-code 主要内容如下:
1.1 压缩代码
- 混淆生成的文件:
<module-name>/build/outputs/mapping/release/目录下
- 自定义要保留的代码,-keep与@keep
- 解码混淆,使用
<sdk-root>/tools/proguard/
下的工具。 - 通过 Instant Run 启用代码压缩
1.2 压缩资源
- shrinkResources
- 自定义要保留的资源
- 启用严格引用检查
- 移除未使用的备用资源
- 合并重复资源
- 排查资源压缩问题
1.3 官方proguard示例
Android SDK/tools/proguard/
proguard-android.txt
是默认混淆文件,同目录下的proguard-android-optimize.txt 是优化版本。
在proguard/examples下有很多示例,如android.pro:
#
# This ProGuard configuration file illustrates how to process Android
# applications.
# Usage:
# java -jar proguard.jar @android.pro
#
# If you're using the Android SDK (version 2.3 or higher), the android tool
# already creates a file like this in your project, called proguard.cfg.
# It should contain the settings of this file, minus the input and output paths
# (-injars, -outjars, -libraryjars, -printmapping, and -printseeds).
# The generated Ant build file automatically sets these paths. # Specify the input jars, output jars, and library jars.
# Note that ProGuard works with Java bytecode (.class),
# before the dex compiler converts it into Dalvik code (.dex). # -injars bin/classes
# -injars libs
# -outjars bin/classes-processed.jar # -libraryjars /usr/local/android-sdk/platforms/android-9/android.jar
#-libraryjars /usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar
# ... # Save the obfuscation mapping to a file, so you can de-obfuscate any stack
# traces later on. -printmapping bin/classes-processed.map # You can print out the seeds that are matching the keep options below. #-printseeds bin/classes-processed.seeds # Preverification is irrelevant for the dex compiler and the Dalvik VM. -dontpreverify # Reduce the size of the output some more. -repackageclasses ''
-allowaccessmodification # Switch off some optimizations that trip older versions of the Dalvik VM. -optimizations !code/simplification/arithmetic # Keep a fixed source file attribute and all line number tables to get line
# numbers in the stack traces.
# You can comment this out if you're not interested in stack traces. -renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable # RemoteViews might need annotations. -keepattributes *Annotation* # Preserve all fundamental application classes. -keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider # Preserve all View implementations, their special context constructors, and
# their setters. -keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
} # Preserve all classes that have special context constructors, and the
# constructors themselves. -keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
} # Preserve all classes that have special context constructors, and the
# constructors themselves. -keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
} # Preserve the special fields of all Parcelable implementations. -keepclassmembers class * implements android.os.Parcelable {
static android.os.Parcelable$Creator CREATOR;
} # Preserve static fields of inner classes of R classes that might be accessed
# through introspection. -keepclassmembers class **.R$* {
public static <fields>;
} # Preserve the required interface from the License Verification Library
# (but don't nag the developer if the library is not used at all). -keep public interface com.android.vending.licensing.ILicensingService -dontnote com.android.vending.licensing.ILicensingService # The Android Compatibility library references some classes that may not be
# present in all versions of the API, but we know that's ok. -dontwarn android.support.** # Preserve all native method names and the names of their classes. -keepclasseswithmembernames class * {
native <methods>;
} # Preserve the special static methods that are required in all enumeration
# classes. -keepclassmembers class * extends java.lang.Enum {
public static **[] values();
public static ** valueOf(java.lang.String);
} # Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
# You can comment this out if your application doesn't use serialization.
# If your code contains serializable classes that have to be backward
# compatible, please refer to the manual. -keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
} # Your application may contain more items that need to be preserved;
# typically classes that are dynamically created using Class.forName: # -keep public class mypackage.MyClass
# -keep public interface mypackage.MyInterface
# -keep public class * implements mypackage.MyInterface
2.proguard官方教程
https://www.guardsquare.com/en/products/proguard/manual 包含:
- sdk/tools/proguard/bin/proguardgui.sh 界面工具教程
- 混淆选项列表
- 混淆示例
- 解混淆
- Gradle plugin 配置教程
- 等等
sdk/tools/proguard/docs/index.html 是官方教程本地版本。
2.1 混淆选项列表
官方地址:https://www.guardsquare.com/en/products/proguard/manual/refcard
@ filename |
Short for '-include filename'. |
-include filename |
Read configuration options from the given file. |
-basedirectory directoryname |
Specifies the base directory for subsequent relative file names. |
-injars class_path |
Specifies the program jars (or apks, aabs, aars, wars, ears, jmods, zips, or directories). |
-outjars class_path |
Specifies the names of the output jars (or apks, aabs, aars, wars, ears, jmods, zips, or directories). |
-libraryjars class_path |
Specifies the library jars (or apks, aabs, aars, wars, ears, jmods, zips, or directories) |
-skipnonpubliclibraryclasses |
Ignore non-public library classes. |
-dontskipnonpubliclibraryclasses |
Don't ignore non-public library classes (the default). |
-dontskipnonpubliclibraryclassmembers |
Don't ignore package visible library class members. |
-keepdirectories [directory_filter] |
Keep the specified directories in the output jars (or wars, ears, zips, or directories). |
-target version |
Set the given version number in the processed classes. |
-forceprocessing |
Process the input, even if the output seems up to date. |
-keep [,modifier,...] class_specification |
Preserve the specified classes and class members. |
-keepclassmembers [,modifier,...] class_specification |
Preserve the specified class members, if their classes are preserved as well. |
-keepclasseswithmembers [,modifier,...] class_specification |
Preserve the specified classes and class members, if all of the specified class members are present. |
-keepnames class_specification |
Preserve the names of the specified classes and class members (if they aren't removed in the shrinking step). |
-keepclassmembernames class_specification |
Preserve the names of the specified class members (if they aren't removed in the shrinking step). |
-keepclasseswithmembernames class_specification |
Preserve the names of the specified classes and class members, if all of the specified class members are present (after the shrinking step). |
-if class_specification |
Specify classes and class members that must be present to activate the subsequent |
-printseeds [filename] |
List classes and class members matched by the various to the standard output or to the given file. |
-dontshrink |
Don't shrink the input class files. |
-printusage [filename] |
List dead code of the input class files, to the standard output or to the given file. |
-whyareyoukeeping class_specification |
Print details on why the given classes and class members are being kept in the shrinking step. |
-dontoptimize |
Don't optimize the input class files. |
-optimizations optimization_filter |
The optimizations to be enabled and disabled. |
-optimizationpasses n |
The number of optimization passes to be performed. |
-assumenosideeffects class_specification |
Assume that the specified methods don't have any side effects, while optimizing. |
-assumenoexternalsideeffects class_specification |
Assume that the specified methods don't have any external side effects, while optimizing. |
-assumenoescapingparameters class_specification |
Assume that the specified methods don't let any reference parameters escape to the heap, while optimizing. |
-assumenoexternalreturnvalues class_specification |
Assume that the specified methods don't return any external reference values, while optimizing. |
-assumevalues class_specification |
Assume fixed values or ranges of values for primitive fields and methods, while optimizing. |
-allowaccessmodification |
Allow the access modifiers of classes and class members to be modified,while optimizing. |
-mergeinterfacesaggressively |
Allow any interfaces to be merged, while optimizing. |
-dontobfuscate |
Don't obfuscate the input class files. |
-printmapping [filename] |
Print the mapping from old names to new names for classes and class members that have been renamed, to the standard output or to the given file. |
-applymapping filename |
Reuse the given mapping, for incremental obfuscation. |
-obfuscationdictionary filename 可自定义混淆字符 |
Use the words in the given text file as obfuscated field names and method names. |
-classobfuscationdictionary filename |
Use the words in the given text file as obfuscated class names. |
-packageobfuscationdictionary filename |
Use the words in the given text file as obfuscated package names. |
-overloadaggressively |
Apply aggressive overloading while obfuscating. |
-useuniqueclassmembernames |
Ensure uniform obfuscated class member names for subsequent incremental obfuscation. |
-dontusemixedcaseclassnames |
Don't generate mixed-case class names while obfuscating. |
-keeppackagenames [package_filter] |
Keep the specified package names from being obfuscated. |
-flattenpackagehierarchy [package_name] |
Repackage all packages that are renamed into the single given parent package. |
-repackageclasses [package_name] |
Repackage all class files that are renamed into the single given package. |
-keepattributes [attribute_filter] |
Preserve the given optional attributes; typically
|
-keepparameternames |
Keep the parameter names and types of methods that are kept. |
-renamesourcefileattribute [string] |
Put the given constant string in the SourceFile attributes. |
-adaptclassstrings [class_filter] |
Adapt string constants in the specified classes, based on the obfuscated names of any corresponding classes. |
-adaptresourcefilenames [file_filter] |
Rename the specified resource files, based on the obfuscated names of the corresponding class files. |
-adaptresourcefilecontents [file_filter] |
Update the contents of the specified resource files, based on the obfuscated names of the processed classes. |
-dontpreverify |
Don't preverify the processed class files. |
-microedition |
Target the processed class files at Java Micro Edition. |
-android |
Target the processed class files at Android. |
-verbose |
Write out some more information during processing. |
-dontnote [class_filter] |
Don't print notes about potential mistakes or omissions in the configuration. |
-dontwarn [class_filter] |
Don't warn about unresolved references at all. |
-ignorewarnings |
Print warnings about unresolved references, but continue processing anyhow. |
-printconfiguration [filename] |
Write out the entire configuration, in traditional ProGuard style, to the standard output or to the given file. |
-dump [filename] |
Write out the internal structure of the processed class files, to the standard output or to the given file. |
-addconfigurationdebugging |
Instrument the processed code with debugging statements that print out suggestions for missing ProGuard configuration. |
2.2 混淆选项通配符
Keep 选项后面的匹配条件中,经常需要用到通配符,例如上面默认 proguard-android.txt 规则中的 void set*(***);。
常见的
通配符如下:
通配符 | 描述 |
---|---|
<init> |
匹配所有构造函数 |
<fields> |
匹配所有字段 |
<methods> |
匹配所有方法,不包括构造函数 |
? | 匹配任意单个字符 |
% | 匹配任意原始数据类型,例如 boolean、int,但是不包括 void |
* | 匹配任意长度字符,但是不包括包名分隔符( . ),例如 android.support.* 不匹配 android.support.annotation.Keep |
** | 匹配任意长度字符,包括包名分隔符( . ),例如 android.support.** 匹配 support 包下的所有类 |
*** | 匹配任意类型,包括原始数据类型、数组 |
… | 匹配任意数量的任意参数类型 |
2.3 解混淆
- debug版本
如果有异常,直接点击行号就可以了。下图第25行。
- release版本:
找到对应版本的mapping.txt以及对应的异常日志,如果没有日志可以从android studio logcat中复制,
1.打开ProGuard图形工具,选择左侧ReTrace 栏
2.在右侧Mapping file中找到对应的mapping.txt
3.把异常的堆栈信息复制到Obfuscated stack track中,或者点Load stack trace...按钮找到对应的文件。
4.点右下角ReTrace!按钮。
3.哪些不应该混淆
对于某些情况,ProGuard 会移除所有(并且只会移除)未使用的代码。不过,ProGuard 难以对许多情况进行正确分析,可能会移除应用真正需要的代码。
不该混淆 |
原因 |
当应用引用的类只来自 AndroidManifest.xml 文件时 |
混淆处理之后,类名就会被篡改,实际使用的类与 如android常用4组件和Application类 |
当应用调用的方法来自 Java 原生接口 (JNI) 时 |
混淆后,会找不对对应的方法的实现 |
当应用在运行时(例如使用反射或自检)操作代码时 |
混淆后,找不到相应的名字,经常发生
|
序列化的类 |
经过混淆的"洗礼"之后,序列化之后的 同时,反序列化的过程创建对象从根本上来说还是借助于反射,混淆之后 所以也会违背我们预期的效果。 |
枚举 |
枚举类内部存在 Android 系统默认的混淆规则文件中已经添加了对于枚举类的处理,无需再去做额外工作。 |
自定义控件不需要被混淆 |
view的一些回调方法会被修改,导致出错或者显示不正常。 |
JavaScript 调用 Java 的方法不应混淆 |
容易找不到方法 |
第三方库也不建议混淆 |
通常第3库以jar或者so方式存在,工具很难分析其中的调用关系。容易出错。 |
注解不能混淆 |
很多场景下注解被用作在运行时反射确定一些元素的特征,Android工程默认的混淆配置 已经包含了保留注解的配置。 |
4.自定义混淆字典
4.1 以自定义混淆字典选项
-obfuscationdictionary
filename 混淆属性名、方法名参考的字典-classobfuscationdictionary
filename 混淆类参考的字典-packageobfuscationdictionary
filename 混淆包名参考的字典
4.2 混淆字典规则
- 一行一个单词
- 空行、空格忽略,
- 标点符号无效
- 重复的字符被忽略
#
后面的字符忽略- 混淆属性和方法时,最好使用类对应的class文件中经存在的字符
4.3 android提供的字典示例
在sdk/tools/proguard/examples/dictionaries/ 目录下有字典示例:
4.4 使用混淆字典
可把一份字典示例文件(如 windows.txt)或者自定义一个字典文件复制到项目中,与proguard-rules.pro同级。
在proguard-rules.pro中添加混淆选项,然后开始生成apk。
-obfuscationdictionary windows.txt
-classobfuscationdictionary windows.txt
-packageobfuscationdictionary windows.txt
如:
5.实例
5.1 自定义要保留的类或包
打完包后,用android studio分析下它。打开其中的dex文件,选择要保留的类,或者包 -> 右键 -> Generate Proguard keep rule
复制其中的内容到 proguard-rules.pro 下。
5.2 配置默认android混淆选项
把 sdk/tools/proguard/examples/android.pro 内容复制到 proguard-rules.pro中
把不必要的选项关掉。
5.3 打开混淆开关
在release配置里打开混淆开关
1 ...
2 buildTypes {
3 release {
4 minifyEnabled true
5 shrinkResources true
6 zipAlignEnabled = true
7 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
8 }
9 debug{
10 minifyEnabled false
11 shrinkResources false
12 // useProguard false
13 zipAlignEnabled = true
14 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
15 }
16 }
17 ...
apk反编译(6)用ProGuard 混淆、压缩代码,压缩资源。的更多相关文章
- apk反编译(7)用ProGuard混淆代码,初级防止反编译
eclipse为例 1,project.properties去掉 #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:pro ...
- Android开发学习总结(六)—— APK反编译
学习和开发Android应用有一段时间了,今天写一篇博客总结一下Android的apk文件反编译.我们知道,Android应用开发完成之后,我们最终都会将应用打包成一个apk文件,然后让用户通过手机或 ...
- Android开发学习总结(六)—— APK反编译(转)
学习和开发Android应用有一段时间了,今天写一篇博客总结一下Android的apk文件反编译.我们知道,Android应用开发完成之后,我们最终都会将应用打包成一个apk文件,然后让用户通过手机或 ...
- Android APK反编译(二)
参考:APK反编译 工具介绍 apktool 作用:资源文件获取,可以提取出图片文件和布局文件进行使用查看 dex2jar 作用:将apk反编译成java源码(classes.dex转化成jar文件) ...
- 【转】APK反编译
学习和开发Android应用有一段时间了,今天写一篇博客总结一下Android的apk文件反编译.我们知道,Android应用开发完成之后,我们最终都会将应用打包成一个apk文件,然后让用户通过手机或 ...
- android apk 反编译过程
一.准备必要的工具 apktool (资源文件获取) dex2jar(源码文件获取) jd-gui (源码查看) 以上三个文件的下载地址为:https://download.csdn.net/dow ...
- apk 反编译 - 最新版图文教程
apk 反编译 - 最新版图文教程 结合网上众多教程,整理一篇自己操作的,工具都是目前最新版 apk 反编译也就是将打包后的 apk 反编译为资源文件(图片).layout.样式.相关的实现代码等.( ...
- Android Studio 动态调试 apk 反编译出的 smali 代码
在信安大赛的准备过程中,主要通过 Android Studio 动态调试 apk 反编译出来的 smali 代码的方式来对我们分析的执行流程进行验证.该技巧的主要流程在此记录.以下过程使用 Andro ...
- Android: apk反编译 及 AS代码混淆防反编译
一.工具下载: 1.apktool(资源文件获取,如提取出图片文件和布局文件) 反编译apk:apktool d file.apk –o path 回编译apk:apktool b path –o f ...
随机推荐
- iOS开发系列-NSURLSession
概述 NSURLSession是从iOS7开始出现的.NSURLSession比NSURLConnection简单很多并且避免了很多坑,因此目前公司项目大部分由NSURLConnection过度为NS ...
- 编写Reduce处理逻辑
- UMP系统功能 资源管理
- JavaScript中获取HTML元素的方式
JavaScript中获取HTML元素的方式 1.使用id方式获取元素,返回一个具体对象 document.getElementById(id名) 2.使用className方式获取元素,返回类数 ...
- ubuntu下apache服务器操作方法小结,具有参考借鉴价值
这篇文章主要介绍了ubuntu下apache服务器操作方法小结,非常不错,具有参考借鉴价值,需要的朋友可以参考下(http://www.0831jl.com)Linux系统为Ubuntu 一.Star ...
- alias用于设置当前数据表的别名,
alias用于设置当前数据表的别名,便于使用其他的连贯操作例如join方法等. 示例: $Model = M('User'); $Model->alias('a')->join('__DE ...
- Ubuntu 快速安装配置Odoo 12
Odoo 12预计将于今年10月正式发布,这是一次大版本更新,带来了一些不错的新特性,如 文件管理系统(DMS) 用户表单中新增字段(Internal user, Portal, Public) HR ...
- Vue.js项目部署到服务器
1.申请服务器 2.配置Xshell 3.在服务器手动建自己的根目录,把根目录的文件名复制给项目里面config下面的index.js 4.项目开始打包 npm run build 5.打包完成之后把 ...
- HOOK NtCreateSection
本程序使用了hde32反汇编引擎,所以性能更加稳定! #pragma once #include <ntddk.h> NTSYSAPI NTSTATUS NTAPI NtCreateSec ...
- NoSQL 文档数据库