跳转至

Application code not obfuscated

应用程序代码未混淆

描述

混淆是指模糊代码并使其难以理解的方法。如果在编译阶段没有进行混淆,已编译的 Java 类是可以被反编译的。它的工作原理是修改应用程序的代码和元数据,使得攻击者难以理解代码并对其进行修改以引入漏洞或添加恶意功能。混淆器通常通过将类、方法和变量重命名为无意义的名称、删除调试信息并添加虚假代码以迷惑反编译器来实现这一点。

攻击者可以窃取代码和敏感信息,引入可能危及应用程序安全的漏洞,或在新的应用程序中重新利用和出售该代码,或基于初始应用程序创建恶意的伪造应用程序。 如果此代码未被混淆,它可以很容易地使用 Apktool 或 JADX 等工具进行反编译。

代码混淆只会减缓攻击者进行逆向工程的速度,但不能使其变得不可能。

建议

以下是您可以考虑采取的步骤,以使您的应用程序不易受到逆向工程的攻击:

使用 Proguard 混淆 Java 源代码。

要将 Proguard 添加到您的应用程序中,请将以下内容添加到 build.gradle 文件中:

buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

这会告诉 Gradle 在发布构建中使用 ProGuard 进行代码混淆。然后,您可以在应用程序的“app”目录中创建一个“proguard-rules.pro” 文件来配置混淆规则。

示例 proguard-rules.pro

# 保留此包中的类名
-keep class com.example.myapplication.** { *; }

# 保留这些类中的所有公共和受保护方法
-keepclassmembers class com.example.myapplication.** {
    public protected *;
}

# 保留所有原生方法名
-keepclassmembers class * {
    native <methods>;
}

# 保留所有具有指定名称的字段
-keepclassmembers class * {
    private int myField;
}

# 保留所有实现 Parcelable 的类
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

# 保留所有 Enum 类
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 保留所有注解
-keepattributes *Annotation*

# 保留所有入口点 (如 main 方法)
-keep public class * {
    public static void main(java.lang.String[]);
}

# 保留所有 Serializable 类
-keep class * implements java.io.Serializable {
    *;
}

使用 Dexguard 混淆 Java 源代码。

要在您的应用程序中启用 Dexguard,您可以将以下内容添加到 build.gradle 文件中:

buildTypes {
        release {
            minifyEnabled true
            useProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            dexguard {
                config 'dexguard-release.cfg'
            }
        }
    }

这会告诉 Gradle 在发布构建中使用 DexGuard 进行代码混淆。您可以在应用程序的“app”目录中创建一个“dexguard-project.txt”文件来配置 DexGuard 项目,以及一个“dexguard-release.cfg”文件来为发布构建配置混淆。

默认情况下,当您使用 DexGuard 启用代码混淆时,除了 ProGuard 配置文件中指定的任何规则外,它还将使用其自身的混淆规则。但是,您可以通过将 useProguard 选项设置为 false 来禁用 ProGuard 规则的使用。

  • 在运行时通过检查 context.getPackageManager().signature 来验证应用程序签名证书
  • 通过调用 context.getPackageManager().getInstallerPackageName 检查应用程序安装程序以确保其与 Android Market 匹配
  • 在运行时检查运行环境

检查应用程序是否在模拟器上运行

您可以将以下检查添加到您的应用程序中,以检测它是否在模拟器上运行。

private static String getSystemProperty(String name) throws Exception {
    Class systemPropertyClazz = Class.forName("android.os.SystemProperties");
    return (String) systemPropertyClazz.getMethod("get", new Class[] { String.class }).invoke(systemPropertyClazz, new Object[] { name });
}

public static boolean checkEmulator() {

    try {
        boolean goldfish = getSystemProperty("ro.hardware").contains("goldfish");
        boolean qemu = getSystemProperty("ro.kernel.qemu").length() > 0;
        boolean sdk = getSystemProperty("ro.product.model").equals("sdk");

        if (qemu || goldfish || sdk) {
            return true;
        }

    } catch (Exception e) {}

    return false;
}

在运行时检查调试标志

同样,您可以在运行时检查应用程序是否处于调试模式

    context.getApplicationInfo().applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE;

链接

标准

  • OWASP_MASVS_RESILIENCE:
    • MSTG_RESILIENCE_9
    • MSTG_RESILIENCE_12
  • PCI_STANDARDS:
    • REQ_2_2
  • OWASP_MASVS_v2_1:
    • MASVS_RESILIENCE_3
  • HIPAA_CONTROLS:
    • SECURITY212
    • SECURITY213
    • SECURITY255