【Android安全-Android上中间人抓包的原理?如何进行防护?如何进行对抗?】此文章归类为:Android安全。
中间人攻击(MITM)是怎么抓包的?
MITM 攻击一般有几种方式,都是围绕着让应用“误信”伪造的服务器或证书。
代理劫持流量(Burp Suite / Charles)
攻击者在手机上安装一个代理工具(比如 Burp Suite、Charles),然后手动安装伪造 CA 证书,让 HTTPS 流量经过代理。这样一来,所有数据就可以被解密、查看、甚至篡改。
对抗方案:
- SSL Pinning(证书固定),让应用只信任指定的证书,而不是系统 CA。
- 检测系统代理,如果发现有代理工具在运行,直接阻断网络请求。
代码检测代理:
1 2 3 4 | private boolean isUsingProxy() {
String proxyHost = System.getProperty("http.proxyHost");
return proxyHost != null;
}
|
篡改系统证书(Root + Magisk)
如果手机已经 Root,攻击者可以修改 /system/etc/security/cacerts/,加入自己的伪造 CA 证书,让整个系统都信任它。这样,哪怕应用开启了 SSL Pinning,流量还是会被解密。
对抗方案:
- 应用内部存储证书哈希值,避免使用系统 CA。
- 检测 Root 状态,如果发现设备被 Root,直接提醒用户或禁止某些功能。
代码检测 Root:
1 2 3 4 5 6 7 | private boolean isDeviceRooted() {
String[] paths = { "/system/bin/su", "/system/xbin/su", "/sbin/su" };
for (String path : paths) {
if (new File(path).exists()) return true;
}
return false;
}
|
Hook SSL 相关 API(Frida / Xposed)
更高级的攻击方式是 Hook SSLSocketFactory 或 OkHttp 相关的 SSL 方法,把 checkServerTrusted() 直接改成 始终返回 true,这样 SSL Pinning 形同虚设。
Frida 绕过 SSL Pinning 的代码(攻击者用的):
1 2 3 4 5 6 7 8 | Java.perform(function () {
var SSLContext = Java.use("javax.net.ssl.SSLContext");
SSLContext.init.implementation = function (key, trust, secure) {
console.log("[Bypassed] SSL Pinning check");
return this.init.overload('java.security.KeyManager[]', 'java.security.TrustManager[]', 'java.security.SecureRandom')
.call(this, key, null, secure);
};
});
|
对抗方案:
- 检测 Frida Hook 进程,如果发现 Frida 在运行,直接终止应用。
- 使用 Native 层(C/C++)实现 SSL 逻辑,让 Hook 更困难。
- 在 SSL Pinning 逻辑里加时间验证,防止攻击者随便改逻辑。
代码检测 Frida:
1 2 3 4 5 6 7 8 9 | public static boolean detectFrida() {
String[] fridaLibs = { "frida-agent", "libfrida" };
for (String lib : fridaLibs) {
if (new File("/system/lib/" + lib).exists() || new File("/system/lib64/" + lib).exists()) {
return true;
}
}
return false;
}
|
对抗方案(多层防御)
光靠 SSL Pinning 其实不够,因为 Hook 可以绕过它。所以我一般会用多层防护,提高攻击难度。
1. 启用 SSL Pinning
让应用只信任固定的证书,防止伪造 CA。
代码(OkHttp 实现 SSL Pinning):
1 2 3 4 5 6 7 | CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAA=")
.build();
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();
|
2. 检测代理和 VPN
避免流量被导入 Burp Suite/Fiddler 之类的工具。
代码检测 VPN:
1 2 3 4 | private boolean isUsingVPN() {
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_VPN;
}
|
3. 反 Hook 保护
防止 Frida/Xposed Hook 关键 API。
代码检测 Xposed:
1 2 3 4 5 6 7 8 | public static boolean isXposedActive() {
try {
Class.forName("de.robv.android.xposed.XposedBridge");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
|
4. 数据层加密(即使被抓包,也无法解密)
即使 TLS 失效,攻击者拿到的数据仍然是加密的。
AES 加密数据
1 2 3 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, aesKey, new IvParameterSpec(ivBytes));
byte[] encryptedData = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
|
5. 服务器端 HMAC 校验
防止攻击者篡改数据或重放请求。
服务器端 HMAC 签名校验
1 2 3 | Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"));
byte[] signature = mac.doFinal(data.getBytes());
|
最后简洁版如下:
| 防护措施 |
目的 |
实现方式 |
| SSL Pinning |
防止伪造证书 |
OkHttp CertificatePinner |
| 检测代理/VPN |
防止 Burp/Fiddler 抓包 |
isUsingProxy() / isUsingVPN() |
| 反 Hook |
防止 Frida/Xposed 绕过 SSL Pinning |
进程检测 |
| 应用层加密 |
即使 TLS 失效,数据也无法解密 |
AES + HMAC |
| 服务器端 HMAC 校验 |
防止数据篡改 |
HMAC-SHA256 签名 |
更多【Android安全-Android上中间人抓包的原理?如何进行防护?如何进行对抗?】相关视频教程:www.yxfzedu.com