Android 逆向工程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mazaiting/article/details/85085588

1. Apk签名

1). 创建签名文件

新建项目 -> build -> Generate Signed Bundle/APK... -> Create new...


3110861-5431ab3e68873d86.png
图1.png
2). 填写签名文件相关信息

点击确认会生成signed.jks文件,将signed.jks文件拷贝至<项目路径>/app/

3110861-33662ec441f1e736.png
图2.png

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文件。

3110861-a71e2316a394e73a.png
图3.png

5). 反编译

工具:dex2jar
下载完成后,将dex2jar的路径配置到环境变量中D:\Program\android\android_reverse\dex2jar;

3110861-057d79d2c1722786.png
图4.png

6). 反编译

将第4)步生成的app-release.apk解压并进入该文件夹,并使用d2j-dex2jar classes.dex命令将classes.dex文件转换为jar文件

3110861-b860890e9a61d42c.png
图5.png

解压完成后,会在当前目录生成一个classes-dex2jar.jar文件,我这里还生成了classes-error.zip文件,是由于转换过程中出现错误了,由于未影响之后的操作,所以这里我忽略了这个错误。

3110861-4ab93b783492a94f.png
图6.png

7). 查看classes-dex2jar.jar文件

工具:jd-gui
使用jd-gui打开classes-dex2jar.jar文件

3110861-c0138d925199c4a9.png
图7.png

2. 混淆

1). 打包混淆

修改app/build.gradle文件中的android-buildTypes-release中的minifyEnabled属性,设置为true,此时相关的混淆文件有proguard-android.txt和proguard-rules.pro。

3110861-617b9922051e21b7.png
图8.png

2). proguard-android.txt

位置:sdk\tools\proguard\proguard-android.txt

3). proguard-rules.pro

位置:<项目路径>\app\proguard-rules.pro

4). 打包并读取文件

签名 -> 打包 -> 反编译, 后classes.dex中的内容如下,


3110861-a680178ba8eb12ed.png
图9.png
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;
  }

工具下载

代码下载

猜你喜欢

转载自blog.csdn.net/mazaiting/article/details/85085588