【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