1. Apk签名
1). 创建签名文件
新建项目 -> build -> Generate Signed Bundle/APK... -> Create new...
2). 填写签名文件相关信息
点击确认会生成signed.jks文件,将signed.jks文件拷贝至<项目路径>/app/
下
3). 在app/build.gradle文件中配置
在android节点下配置signingConfigs节点,并在其节点下配置别名,密码,文件,文件密码属性,最后在buildTypes下的release结点下配置signingConfig
android {
// 签名配置
signingConfigs {
release {
keyAlias 'test'
keyPassword 'password'
storeFile file('signed.jks')
storePassword 'password'
}
}
buildTypes {
release {
minifyEnabled false
// 配置签名
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
4). 打包
在<项目路径>
下执行gradlew aR
命令打包,完成后提示信息如图3所示,并在<项目路径>\app\build\outputs\apk\release\
路径下查看app--release.apk文件。
5). 反编译
工具:dex2jar
下载完成后,将dex2jar的路径配置到环境变量中D:\Program\android\android_reverse\dex2jar;
6). 反编译
将第4)步生成的app-release.apk解压并进入该文件夹,并使用d2j-dex2jar classes.dex
命令将classes.dex文件转换为jar文件
解压完成后,会在当前目录生成一个classes-dex2jar.jar
文件,我这里还生成了classes-error.zip文件,是由于转换过程中出现错误了,由于未影响之后的操作,所以这里我忽略了这个错误。
7). 查看classes-dex2jar.jar文件
工具:jd-gui
使用jd-gui打开classes-dex2jar.jar文件
2. 混淆
1). 打包混淆
修改app/build.gradle
文件中的android-buildTypes-release
中的minifyEnabled
属性,设置为true,此时相关的混淆文件有proguard-android.txt和proguard-rules.pro。
2). proguard-android.txt
位置:sdk\tools\proguard\proguard-android.txt
3). proguard-rules.pro
位置:<项目路径>\app\proguard-rules.pro
4). 打包并读取文件
签名 -> 打包 -> 反编译, 后classes.dex中的内容如下,
5). 问题
此时的问题是,混淆了一些本不该混淆的文件,那么我们就需要自己去配置混淆规则,我们必须要自己修改proguard-rules.pro文件
6). 添加混淆规则模板
-ignorewarnings # 忽略警告
-optimizationpasses 5 # 指定代码的压缩级别
-dontusemixedcaseclassnames # 是否使用大小写混合
-dontpreverify # 混淆时是否做预校验
-verbose # 混淆时是否记录日志
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采用的算法
# 保持子类不被混淆
-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
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
# 保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
# 保持自定义控件类不被混淆
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
# 保持自定义控件类不被混淆
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
# 保持自定义控件类不被混淆
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# 保持枚举 enum 类不被混淆
-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 *;
}
# Explicitly preserve all serialization members. The Serializable interface
# is only a marker interface, so it wouldn't save them.
# 保持序列号类不被混淆
-keep public class * implements java.io.Serializable {*;}
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private 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();
}
3.
1). 获取签名信息
public int getSignature() {
PackageManager packageManager = this.getPackageManager();
PackageInfo pi;
int sign = 0;
try {
pi = packageManager.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
Signature[] signingInfo = pi.signatures;
sign = signingInfo[0].hashCode();
} catch (Exception ignored) {}
return sign;
}