什么是Android应用加固?
应用加固(App Hardening)是一种保护Android应用免受逆向工程、篡改和攻击的技术,主要包括:
- 代码混淆(ProGuard/R8)
- 反调试/反Hook检测
- 完整性校验
- 加壳/脱壳保护
- so文件加密
1. 基础加固:代码混淆(必做)
配置 build.gradle (Module: app)
gradle
复制
android {
buildTypes {
release {
minifyEnabled true // 启用代码压缩
shrinkResources true // 移除无用资源
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
配置 proguard-rules.pro
proguard
复制
# 基础混淆规则
-optimizationpasses 5 # 优化次数
-dontusemixedcaseclassnames # 不使用混合大小写
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# 保留入口点
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
# 保留Native方法
-keepclasseswithmembernames class * {
native <methods>;
}
# 保留注解
-keepattributes *Annotation*
# 混淆类名
-repackageclasses 'a' # 将所有类移到'a'包下
-allowaccessmodification # 允许修改访问修饰符
2. 中级加固:签名校验 + 完整性检查
在 MainActivity.java 或 Application 中添加自检代码
java
复制
public class SecurityUtils {
// 签名校验(防止二次打包)
public static boolean checkSignature(Context context) {
try {
String packageName = context.getPackageName();
PackageManager pm = context.getPackageManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
pm.getPackageInfo(packageName,
PackageManager.GET_SIGNING_CERTIFICATES);
}
// 对比签名hash(你需要提前计算好正确签名的hash)
String correctHash = "你的正确签名SHA-256值";
// 实际获取当前签名并对比...
return true; // 校验通过
} catch (Exception e) {
return false;
}
}
// APK完整性校验(校验classes.dex CRC)
public static boolean checkDexIntegrity(Context context) {
try {
String apkPath = context.getPackageCodePath();
File apkFile = new File(apkPath);
// 计算关键文件的CRC或MD5
long crc = getFileCRC32(apkFile);
long expectedCRC = 123456789L; // 预存的正确值
return crc == expectedCRC;
} catch (Exception e) {
return false;
}
}
// CRC32计算
private static long getFileCRC32(File file) throws Exception {
CRC32 crc32 = new CRC32();
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[8192];
int len;
while ((len = fis.read(buffer)) != -1) {
crc32.update(buffer, 0, len);
}
}
return crc32.getValue();
}
}
在 Application.onCreate() 中调用
java
复制
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
// 安全检测
if (!SecurityUtils.checkSignature(this)) {
Toast.makeText(this, "应用签名异常,请从官方渠道下载", Toast.LENGTH_LONG).show();
System.exit(0);
}
if (!SecurityUtils.checkDexIntegrity(this)) {
Toast.makeText(this, "应用已被篡改", Toast.LENGTH_LONG).show();
System.exit(0);
}
// 反调试检测
if (isDebugged()) {
System.exit(0);
}
}
private boolean isDebugged() {
return Debug.isDebuggerConnected() || Debug.waitingForDebugger();
}
}
3. 高级加固:加壳保护(DEX加密)
基本原理
复制
原始APK: classes.dex (明文)
↓
加固后APK:
- classes.dex (壳程序,很小)
- assets/encrypted.dex (加密后的原dex)
- libs/libdecoder.so (解密so)
简单加壳实现思路
步骤1:加密原始DEX
java
复制
// 加密工具(独立程序)
public class DexEncryptor {
public static void encrypt(String dexPath, String outPath, String key) {
try {
byte[] dexData = Files.readAllBytes(Paths.get(dexPath));
// AES加密
byte[] encrypted = aesEncrypt(dexData, key);
Files.write(Paths.get(outPath), encrypted);
} catch (Exception e) {
e.printStackTrace();
}
}
}
步骤2:壳程序(ProxyApplication)
java
复制
public class ProxyApplication extends Application {
private Application realApp;
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// 1. 解密assets中的加密dex
byte[] encryptedDex = loadEncryptedDex();
byte[] decryptedDex = decrypt(encryptedDex, "密钥");
// 2. 写入临时文件
File tempDex = new File(getCacheDir(), " decrypted.dex");
FileUtils.writeByteArrayToFile(tempDex, decryptedDex);
// 3. 使用DexClassLoader加载解密后的dex
DexClassLoader dcl = new DexClassLoader(
tempDex.getAbsolutePath(),
getCacheDir().getAbsolutePath(),
null,
base.getClassLoader()
);
// 4. 替换ClassLoader(反射)
replaceClassLoader(dcl);
// 5. 加载原Application
realApp = (Application) dcl.loadClass("com.example.RealApp").newInstance();
realApp.attachBaseContext(base);
}
@Override
public void onCreate() {
super.onCreate();
realApp.onCreate();
}
}
步骤3:AndroidManifest.xml 修改
xml
复制
<application
android:name=".ProxyApplication" <!-- 改为壳Application -->
android:label="@string/app_name">
<!-- 原Application配置移到meta-data -->
<meta-data
android:name="REAL_APPLICATION"
android:value="com.example.MyRealApp" />
</application>
4. Native层加固(SO加密)
反调试检测(C代码)
c
复制
// anti_debug.c
#include <sys/ptrace.h>
#include <unistd.h>
#include <jni.h>
// Ptrace反调试
void anti_ptrace() {
ptrace(PTRACE_TRACEME, 0, 0, 0);
}
// 检测调试器
int is_being_debugged() {
// 检查TracerPid
FILE* fp = fopen("/proc/self/status", "r");
char line[256];
while (fgets(line, sizeof(line), fp)) {
if (strstr(line, "TracerPid:")) {
int pid = atoi(line + 10);
fclose(fp);
return pid != 0;
}
}
fclose(fp);
return 0;
}
JNIEXPORT void JNICALL
Java_com_example_security_SecurityUtils_initSecurity(JNIEnv* env, jclass clazz) {
anti_ptrace();
if (is_being_debugged()) {
// 检测到调试,退出或崩溃
_exit(0);
}
}
5. 使用第三方加固服务(推荐)
对于商业应用,建议使用成熟的加固方案:
表格
复制
| 服务商 | 特点 | 官网 |
|---|---|---|
| 腾讯乐固 | 免费额度,兼容性好 | legu.qcloud.com |
| 阿里聚安全 | 与阿里云生态整合 | jaq.alibaba.com |
| 360加固保 | 老牌方案,企业版强 | jiagu.360.cn |
| 网易云加固 | 游戏应用优化 | nos.netease.com |
| 百度移动安全 | 深度保护方案 | mtc.baidu.com |
使用腾讯乐固示例(Gradle插件)
gradle
复制
// build.gradle (Project)
buildscript {
dependencies {
classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.21'
}
}
// build.gradle (Module)
apply plugin: 'AndResGuard'
andResGuard {
mappingFile = null
use7zip = true
useSign = true
keepRoot = false
whiteList = [
"R.drawable.icon",
"R.string.app_name"
]
}
加固等级总结
表格
复制
| 级别 | 方法 | 难度 | 防护效果 |
|---|---|---|---|
| 基础 | ProGuard混淆 + 移除Log | ⭐ | 防小白 |
| 中级 | 签名校验 + 完整性检测 | ⭐⭐ | 防初级破解 |
| 高级 | DEX加壳 + SO加密 | ⭐⭐⭐ | 防中级逆向 |
| 商业 | 第三方专业加固 | ⭐ | 防高级攻击 |