以下是一些常用的方法:

1.使用代码混淆工具:

代码混淆可以使反编译后的代码难以阅读和理解,从而增加二次打包的难度。

在 Android 开发中,常用的代码混淆工具是 ProGuard。下面是在 Android Studio 中配置 ProGuard 的相关代码:

1) 在 app 的 build.gradle 文件中,添加以下代码:

android {
    // 省略其他配置
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

2) 在项目根目录下创建 proguard-rules.pro 文件,用于指定混淆规则。以下是一些常用的规则:

# 基本规则
-optimizationpasses 5  # 优化次数
-dontusemixedcaseclassnames  # 不使用混合大小写的类名
-dontskipnonpubliclibraryclasses  # 不跳过非公共库的类
-dontpreverify  # 不预验证

# 代码混淆规则
-keep class com.example.** {*;}  # 保留 com.example 包及其子包中的所有类
-keepclassmembers class com.example.** {*;}  # 保留 com.example 包及其子包中的所有类成员
-dontwarn com.example.**  # 不警告 com.example 包及其子包中的类

# 其他规则
-keepattributes Signature
-keepattributes *Annotation*

以上代码只是一个简单示例,实际的混淆规则需要根据具体的应用进行调整和优化。完成以上步骤后,在进行 release 版本打包时,ProGuard 会自动对代码进行混淆和优化,从而增加应用的安全性。

2.加固APK:

可以使用一些加固工具对APK进行加密,使得恶意攻击者难以直接获取到APK包,从而减少二次打包的风险。

在 Android 开发中,常用的加固工具有 DexProtector 和 Bangcle 等,这些工具提供了命令行和 Gradle 插件两种方式进行加固。下面是使用 DexProtector Gradle 插件进行加固的相关代码:

1) 在 app 的 build.gradle 文件中,添加以下代码:

buildscript {
    repositories {
        maven {
            url 'https://oss.sonatype.org/content/repositories/snapshots/'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.3'
        classpath 'com.android.tools.build:gradle:3.5.3'
        classpath 'com.jeppsson:gradle-dexprotector:2.1.1-SNAPSHOT'
    }
}

apply plugin: 'dexprotector'

dexProtector {
    target 'all'
    productFlavors {
        demo {
            enable true
            activationUrl 'https://www.dexprotector.com/activation'
            activationKey '1234567890'
            libraryPath 'libs/dexprotector.jar'
            configurationFile 'dexprotector.xml'
        }
    }
    release {
        enable true
        activationUrl 'https://www.dexprotector.com/activation'
        activationKey '1234567890'
        libraryPath 'libs/dexprotector.jar'
        configurationFile 'dexprotector.xml'
    }
}

2)在项目根目录下创建 dexprotector.xml 文件,用于指定加固配置。以下是一些常用的配置:

<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:keep="@drawable/icon" tools:keepClassesWithMembers="true">
    <!-- 保留指定类和类成员不被混淆 -->
    <keep>
        <class name="com.example.MyActivity"/>
        <class name="com.example.MyFragment"/>
        <class name="com.example.MyService"/>
        <class name="com.example.MyReceiver"/>
        <class name="com.example.MyApplication"/>
        <class name="com.example.MyClass"/>
        <class name="com.example.MyInterface"/>
        <class name="com.example.MyEnum"/>
        <class name="com.example.MyAnnotation"/>
        <method name="onCreate" class="com.example.MyActivity"/>
        <method name="onCreateView" class="com.example.MyFragment"/>
        <method name="onStartCommand" class="com.example.MyService"/>
        <method name="onReceive" class="com.example.MyReceiver"/>
        <method name="onCreate" class="com.example.MyApplication"/>
        <field name="myField" class="com.example.MyClass"/>
        <method name="myMethod" class="com.example.MyInterface"/>
        <field name="myEnum" class="com.example.MyEnum"/>
        <class name="com.example.MyAnnotation"/>
    </keep>

    <!-- 重命名指定类和类成员 -->
    <rename>
        <class name="com.example.MyClass" to="com.example.RenamedClass"/>
        <method name="myMethod" class="com.example.MyInterface" to="renamedMethod"/>
        <field name="myField" class="com.example.MyClass" to="renamedField"/>
        <class name="com.example.MyAnnotation" to="RenamedAnnotation"/>
    </rename>

    <!-- 加密指定类和资源 -->
    <encrypt>
        <class name="com.example.MyClass

3.对APK进行数字签名:

数字签名可以确保APK的完整性和真实性,可以使攻击者无法在不改变APK签名的情况下进行二次打包。

在 Android Studio 中,可以使用以下步骤对 APK 进行数字签名:

1)在项目根目录下创建一个 keystore 文件,用于存储数字证书和私钥。可以使用 keytool 工具生成一个新的 keystore,命令如下:

keytool -genkey -v -keystore my-release-key.keystore -alias my_alias -keyalg RSA -keysize 2048 -validity 10000

其中,my-release-key.keystore 是 keystore 文件名,my_alias 是数字证书别名,RSA 是使用的加密算法,2048 是密钥大小,validity 是证书有效期。

2)在项目的 build.gradle 文件中添加以下代码:

android {
    ...
    signingConfigs {
        release {
            storeFile file("my-release-key.keystore")
            storePassword "password"
            keyAlias "my_alias"
            keyPassword "password"
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
    ...
}

其中,storeFile 指定 keystore 文件路径,storePassword 和 keyPassword 是 keystore 密码和数字证书密码,keyAlias 是数字证书别名。

3)在 Android Studio 中,使用 Build -> Generate Signed Bundle/APK 菜单项选择要签名的 APK,选择 release build type,输入 keystore 和数字证书密码,即可对 APK 进行数字签名。

4.检测应用运行环境:

应用可以检测当前运行的环境是否为真实设备,如果检测到运行环境不是真实设备,则应用可以自动关闭,以避免被二次打包。

要检测应用的运行环境,可以使用 Android 提供的 Build 类。以下是一些常用的方法:

1)检测设备的 CPU 架构:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    for (String abi : Build.SUPPORTED_ABIS) {
        Log.i("MyApp", "Supported ABI: " + abi);
    }
} else {
    Log.i("MyApp", "ABI: " + Build.CPU_ABI);
}

2)检测设备的屏幕分辨率:

DisplayMetrics metrics = getResources().getDisplayMetrics();
int screenWidth = metrics.widthPixels;
int screenHeight = metrics.heightPixels;

3)检测设备的操作系统版本:

int sdkVersion = Build.VERSION.SDK_INT;
String osVersion = Build.VERSION.RELEASE;

4)检测设备的品牌和型号:

String brand = Build.BRAND;
String model = Build.MODEL;

5)检测应用的包名和版本号:

String packageName = getPackageName();
PackageManager packageManager = getPackageManager();
try {
    PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 0);
    String versionName = packageInfo.versionName;
    int versionCode = packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
}

注意,某些设备可能存在定制化 ROM,例如小米、华为等,这些设备的系统属性可能与标准 Android 设备不同,需要进行额外的处理。

5.在应用中集成反调试技术:

可以在应用中添加一些反调试代码,以使攻击者无法通过调试工具获取应用的代码和资源。

在 Android 应用中集成反调试技术,可以在代码中检测是否处于调试状态,如果是,则采取相应的措施,例如退出应用或者强制关闭调试器。以下是一种常用的反调试技术实现方法:

public class DebugDetector {

    public static boolean isDebugging() {
        return Debug.isDebuggerConnected() || Debug.waitingForDebugger();
    }

    public static void detectDebugging() {
        if (isDebugging()) {
            Log.e("DebugDetector", "Debugging detected, exiting...");
            System.exit(0);
        }
    }

}

在应用中需要使用反调试技术时,可以调用 DebugDetector.detectDebugging() 方法进行检测。如果检测到正在进行调试,则会输出错误日志并退出应用。

需要注意的是,一些调试器可能会屏蔽调试检测,因此此种反调试技术并不能完全保证应用不被调试。

以上。


小飞象
80 声望5 粉丝