【干货分享】uniapp做的安卓App如何加固

2023年了,uniapp还有人用吗?

对于这个问题,只能说,2023年了,使用uniapp去开发APP的人越来越多了。

一方面在于全平台兼容确实很香,对于一些小项目或者时间要求比较高的项目来说,可以节省大量的时间与精力,也为公司节约了成本;另一方面,开发速度非常快。就像前面说的,对于一些小项目来说,几天就可以搞定,而对于一些大项目来说,性能和原生大差不差,而且全平台兼容的特性也可以弥补这点;最后就是社区,里面有很多优质的框架和插件,节约了大量的时间(时间就是发量!!!),更重要的是,社区出人才,总能找到人和你一起吐槽(bushi)睿智的官方…

总而言之,虽然uniapp文档一般好,bug一般多,更新像拆炸弹,但是,对于很多人来说,还是很有意义的。所以用的人还是很多。

但是目前随着各种商城上架政策的严格审查,对于加固等需求也慢慢起来了,所以今天我们来讲讲uniapp开发的安卓APP要如何加固。

加固原理

先来看看一般加固会从哪几个方向进行加固

image.png

而我们如果把uniapp制作的安卓APP在加固上其实大同小异–只要是apk或者aab格式都可以,所以我们就基于这个原理来进行加固。

加固流程

01 代码混淆

按照一般的思路,先给他混淆一下子。使用代码混淆工具来混淆 JavaScript 代码,以使其难以被逆向工程和破解。常用的混淆工具包括 ProGuard 和 DexGuard。在 UniApp 中,你可以在打包安卓应用时配置 ProGuard 来进行代码混淆。示例代码如下所示,在项目根目录下的 uniapp.pro 文件中添加以下配置:

-keep class com.dcloud.** { *; }
-keep public class * extends io.dcloud.* {
    *;
}

02 加固资源文件 & 防止调试和反调试

加固资源文件: 将敏感资源文件(如证书、配置文件等)进行加密或混淆,以防止被攻击者获取。可以使用第三方工具对资源文件进行加密,或者自定义加密算法来保护资源文件的安全

防止调试和反调试: 这一步可以使用第三方库或自定义代码来实现这些保护措施。比如说,可以检测应用程序是否在调试模式下运行,并在调试模式下采取相应的措施,例如关闭应用程序或隐藏敏感信息。

import android.os.Debug;

public class DebugUtils {
    public static boolean isDebugMode() {
        return Debug.isDebuggerConnected();
    }
}

就是说,在应用程序中调用 DebugUtils.isDebugMode() 方法,可以根据返回值来判断应用程序是否在调试模式下运行,并采取相应的措施。

03 加密敏感数据

我们直接使用PBEWithMD5AndDES 算法对数据进行加密和解密。使用的时候,你可以调用 EncryptionUtils.encrypt(data) 方法来加密敏感数据,并调用 EncryptionUtils.decrypt(encryptedData) 方法来解密数据。记得将 PASSWORDSALT 替换为你自己的密码和盐值(重要!!!)。

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.security.spec.KeySpec;
import java.util.Base64;

public class EncryptionUtils {
    private static final String ALGORITHM = "PBEWithMD5AndDES";
    private static final String PASSWORD = "your_secret_password"; // 自定义密码,请更换为自己的密码
    private static final byte[] SALT = {
        (byte) 0x4b, (byte) 0x6d, (byte) 0x7d, (byte) 0x15,
        (byte) 0x78, (byte) 0x56, (byte) 0x34, (byte) 0x22
    }; // 自定义盐值,请更换为自己的盐值

    public static String encrypt(String data) {
        try {
            KeySpec keySpec = new PBEKeySpec(PASSWORD.toCharArray(), SALT, 65536);
            SecretKey secretKey = SecretKeyFactory.getInstance(ALGORITHM).generateSecret(keySpec);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            PBEParameterSpec parameterSpec = new PBEParameterSpec(SALT, 100);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
            byte[] encryptedBytes = cipher.doFinal(data.getBytes("UTF-8"));
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String decrypt(String encryptedData) {
        try {
            KeySpec keySpec = new PBEKeySpec(PASSWORD.toCharArray(), SALT, 65536);
            SecretKey secretKey = SecretKeyFactory.getInstance(ALGORITHM).generateSecret(keySpec);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            PBEParameterSpec parameterSpec = new PBEParameterSpec(SALT, 100);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, parameterSpec);
            byte[] decodedBytes = Base64.getDecoder().decode(encryptedData);
            byte[] decryptedBytes = cipher.doFinal(decodedBytes);
            return new String(decryptedBytes, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

04 防止篡改

我们使用 SHA-256 哈希算法计算数据的哈希值。使用的时候,可以调用 IntegrityUtils.calculateHash(data) 方法来计算数据的哈希值,并将其与原始的哈希值进行比较,以验证数据的完整性。例如:

String data = "Hello, world!";
String originalHash = "2ef7bde608ce5404e97d5f042f95f89f1c232871";
String calculatedHash = IntegrityUtils.calculateHash(data);

boolean isIntegrityVerified = IntegrityUtils.verifyIntegrity(data, originalHash);
if (isIntegrityVerified) {
    System.out.println("Data integrity verified.");
} else {
    System.out.println("Data has been tampered with!");
}

05 签名功能

补充一个Android签名。

1)简介

本工具用于对android加固后的apk进行重新签名。

版本 文件 备注
Windows版 apk签名工具压缩包.exe 该版本包含Java运行环境,不需要额外安装。
通用版 dx-signer-v1.9r.jar 该版本需要Java 8+的运行环境,请依照操作系统进行安装:Adoptium

本工具依照Apache 2.0 协议开源,可以在这里查看源码https://github.com/dingxiangtech/dx-signer

使用说明

  1. 下载签名工具dx-signer.jar,双击运行。
  2. 选择输入apk、aab文件。
  3. 选择签名的key文件,并输入key密码。
  4. 选择重签后apk、aab的路径,以apk结束。如:D:\sign.apk
  5. 点击“签名”按钮,等待即可签名完成。

ps:如果有alias(证书别名)密钥的或者有多个证书的,请在高级tab中选择alias并输入alias密码

2)多渠道功能简介

多渠道工具兼容友盟和美团walle风格的多渠道包,方便客户把APP发布到不同的应用平台,进行渠道统计。

使用说明

  1. 在app中预留读取渠道信息的入口,具体见5.2.2读取渠道信息
  2. 在5.1.1的签名使用基础上,点击选择渠道清单
  3. 选择清单文件channel.txt。具体文件格式见5.2.3
  4. 点击签名,等待生成多个带签名的渠道app

读取渠道信息

顶象多渠道工具兼容友盟和美团walle风格的多渠道包,下面是两种不同风格的渠道信息读取方法。选其中之一即可

读取渠道信息:UMENG_CHANNEL

输出的Apk中将会包含UMENG_CHANNELmata-data

<application ... >
    <meta-data
        android:name="UMENG_CHANNEL"
        android:value="XXX" />
</application>

可以读取这个字段。

public static String getChannel(Context ctx) {
    String channel = "";
    try {
        ApplicationInfo appInfo = ctx.getPackageManager().getApplicationInfo(ctx.getPackageName(),
                PackageManager.GET_META_DATA);
        channel = appInfo.metaData.getString("UMENG_CHANNEL");
    } catch (PackageManager.NameNotFoundException ignore) {
    }
    return channel;
}
读取渠道信息:Walle

输出的Apk也包含Walle风格的渠道信息

可以在使用Walle的方式进行读取。

implementation 'com.meituan.android.walle:library:1.1.7'

String channel = WalleChannelReader.getChannel(this.getApplicationContext());

渠道文件格式说明

请准备渠道清单文件channel.txt, 格式为每一行一个渠道, 例如:

0001_my
0003_baidu
0004_huawei
0005_oppo
0006_vivo

结语

以上就是基于uniapp制作的Android APP的加固方式,仅供参考~ 欢迎一起交流学习~

免费加固>>>uniapp 安卓APP加固

猜你喜欢

转载自blog.csdn.net/dingxiang234/article/details/131767635