一、引言
随着移动互联网的迅猛发展,移动 APP 在人们生活中的应用越来越广泛。然而,APP 的安全问题也日益凸显。为了保障 APP 的安全,APP 加固成为了一项重要的技术手段。本文将介绍 APP 加固的概念、原理、作用以及相关的加固平台,并从攻击者和防御者的角度进行分析。
二、APP 加固的概念
APP 加固是指对移动应用进行一系列安全处理,以增强其抵御各种安全威胁的能力。它不仅仅是对源码进行加壳,还包括对客户端本体的各个方面以及业务安全相关的内容进行保护。
三、APP 加固的原理
(一)安卓 APP 加固原理
对于安卓 APP,一般加壳是常见的加固方式。其侧重点是对原始的 dex/so/dll 等进行隐藏、混淆、加花、代码抽离等操作。在程序运行过程中,对隐藏加密的原始 dex 再进行还原,以执行原有逻辑。安卓的加壳技术根据强度分为 4 代:
- 第 1 代:整体的 dex 的加壳隐藏。
- 第 2 代:防调试防 Dump 出现。
- 第 3 代:方法体抽离。
- 第 4 代:Vmp 加壳 /so 加壳(字节码置换虚拟技术)。无论哪一代,运行时解密不会变,所以即使是第 4 代技术也可以在内存中修复,拿到完整的 dex。
(二)iOS APP 加固原理
对于 iOS APP,现在很多安全厂商的做法是通过 Xcode 插件,在编译过程中对逻辑进行混淆、扁平化处理等方式来实现加固。
四、APP 加固的作用
(一)从防御者角度
- 防止被二次打包- 二次打包会带来诸多危害。例如,APP 的原创技术可能被抄袭,界面被模仿,换皮后重新投放市场。而且二次打包后方便黑客调试分析、跟踪关键逻辑,还可能被插入盗号木马,在朋友圈、Q 群、论坛、网盘等传播,严重影响公司形象。
- 保障业务安全- 这是 APP 加固最重要的目的。它可以防止协议被脱端重写,防止业务活动被撸羊毛,确保 APP 的正常业务流程不受安全威胁的干扰。
(二)从攻击者角度(攻击者试图突破加固措施)
- 针对安卓 APP 加壳- 攻击者可能会尝试分析加壳的类型和强度,寻找加壳技术的漏洞。例如,如果是基于第 1 代加壳技术,攻击者可能会尝试寻找方法来绕过整体的 dex 的加壳隐藏。在 Python 中,可以使用一些反编译工具(虽然这可能违反法律和道德规范,仅用于技术分析)来尝试分析加壳后的 APP。例如,使用
apktool
工具(这里只是提及工具的使用可能性,不鼓励非法行为):
import subprocess
def decompile_apk(apk_path):
command = "apktool d " + apk_path
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = process.communicate()
if process.returncode == 0:
return output.decode('utf-8')
else:
return error.decode('utf-8')
- 针对 iOS APP 加固- 攻击者可能会尝试分析 Xcode 插件所做的混淆和扁平化处理,寻找逻辑漏洞。例如,通过对编译后的 APP 进行逆向工程分析(同样可能违反法律和道德规范,仅用于技术分析),使用一些专业的 iOS 逆向工具(如
Hopper
等)来尝试理解 APP 的内部逻辑,寻找可能的攻击点。
五、APP 加固的主要措施及相关代码示例
(一)加壳(dex/so)
这是安卓 APP 加固的常见方式,如前面所述的对 dex/so 进行各种操作。
(二)文件校验
- 签名校验- 对 APP 的签名进行校验可以防止 APP 被篡改。在 Java 中,对于安卓 APP 开发,可以在应用启动时进行签名校验。以下是一个简单的示例代码片段(仅为示意,实际应用中需要更完善的逻辑):
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
PackageManager pm = getPackageManager();
PackageInfo pi = pm.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
Signature[] signatures = pi.getSignatures();
// 这里可以进行签名比对,假设正确的签名已经存储在某个变量中,比如correctSignature
if (signatures[0].equals(correctSignature)) {
Log.i("Signature", "签名正确");
} else {
Log.e("Signature", "签名错误");
}
} catch (Exception e) {
Log.e("Signature", "获取签名信息失败");
}
}
}
- dex / 包体 / 特殊文件等校验- 除了签名校验,还可以对 dex 文件、包体以及特殊文件等进行校验,确保 APP 的完整性。
(三)不返回多余信息
在 APP 的开发过程中,要注意避免返回多余的信息,防止信息泄露给攻击者。例如,在处理 API 请求时,只返回必要的数据,避免返回敏感的调试信息或不必要的内部状态信息。
(四)不打印多余信息
同样,在代码中要避免打印多余的信息,特别是在调试模式下,要确保不会因为打印的信息而泄露敏感信息。
(五)封包验签
对 APP 发送和接收的数据包进行验签,确保数据的完整性和真实性。在 Python 中,可以使用一些加密库(如
cryptography
)来实现封包验签的相关功能(这里仅为示意,实际应用中需要更复杂的逻辑):
from cryptography.highlevelcrypto import HMAC, hashes
def verify_package_signature(package_data, signature):
key = "your_secret_key" # 这里应该使用安全的密钥
hmac = HMAC(key, hashes.SHA255())
hmac.update(package_data)
expected_signature = hmac.finalize()
return signature == expected_signature
(六)时间戳验证
对 APP 中的时间戳进行验证,确保数据的时效性和真实性。例如,在处理一些时效性较强的业务数据时,通过验证时间戳来判断数据是否有效。
(六)https 校验 SSL 证书
在 APP 与服务器之间的通信中,如果使用 https 协议,要对 SSL 证书进行校验,确保通信的安全性。在 Java 中,可以使用
javax.net.ssl
包中的相关类来实现 SSL 证书的校验(这里仅为示意,实际应用中需要更完善的逻辑):
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class SSLValidator {
public static boolean validateSSLContext(String host) throws KeyManagementException, NoSuchAlgorithmException, CertificateException, IOException {
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
X509TrustManager x509TrustManager = (X509TrustManager) trustManagers[0];
sslContext.init(null, new TrustManager[] {x509TrustManager}, null);
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(HostnameVerifiersession.hostname, SSLSession.hostnameVerifier) {
return hostname.equals(session.hostnameVerifier);
}
};
return hostnameVerifier.verify(host, sslContext.getSSLSession(host)) && ssl.open(Session.hostnameVerifier, sslContext.getSSLSession(host));
}
}
(七)敏感数据不落地
在 APP 中,要尽量避免敏感数据在本地设备上留存。如果必须留存,要进行加密处理。例如,对于用户的登录密码,不要直接存储在本地,而是进行加密存储,并且在使用后及时清除相关数据。
(八)对用户做好安全提示
在 APP 中要对用户进行必要的安全提示,例如提示用户设置强密码、不要在公共网络上使用 APP 等。
(九)敏感操作进行环境清场
在 APP 进行一些敏感操作时,如登录、转账等,要对环境进行清场,确保没有恶意程序在后台运行,影响操作的安全性。
(十)敏感操作进行用户状态二次校验
在 APP 进行一些敏感操作时,如登录、转账等,要对用户状态进行二次校验,确保操作的合法性和安全性。
(十一)手势密码做全局 FLAG
对于 APP 中的手势密码,要将其作为一个全局的标志,在 APP 的各个相关模块中进行统一的管理和验证。
(十二)设备绑定信息糅合多个因子
将设备绑定信息与多个因子进行糅合,如设备 ID、MAC 地址、IP 地址等,增强设备识别的准确性和安全性。
六、APP 加固平台推荐
市面目前有很多 APP 加固平台,各大厂商也有免费的,像 360、百度、腾讯乐固、网易盾、阿里聚安全。收费的有爱加密、梆梆、娜迦、几维、顶象科技。个人应用一般可以使用 360 的加固。对于实实在运营的企业 app 建议大家使用爱加密的收费版本,收费与免费的区别就是兼容性、应急响应、售后服务的有力支持。爱加密目前技术已经发展到双 VMP (dex+SO) 多重加密,支持多种自定义加固,如防止模拟器运行、防止界面截 图、防止界面劫持、本地数据强加密 (sharedPerence/SQI 数据)、防止内存 Dump 等,并且现在已应支持强大的协议加密。
七、结论
APP 加固是保障移动应用安全的重要手段。无论是从防御者的角度防止 APP 被攻击,还是从攻击者的角度尝试突破加固措施,都体现了 APP 加固在移动安全领域的重要性。通过合理选择加固平台和采取有效的加固措施,可以大大提高 APP 的安全性,保护用户和企业的利益。
版权归原作者 阿贾克斯的黎明 所有, 如有侵权,请联系我们删除。