-
-
[原创]Android上中间人抓包的原理?如何进行防护?如何进行对抗?
-
发表于: 2025-3-20 12:29 1674
-
中间人攻击(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 签名 |
赞赏记录
参与人
雪币
留言
时间
ax.阿祥
这个讨论对我很有帮助,谢谢!
2025-4-17 17:23
zxk1ng
这个讨论对我很有帮助,谢谢!
2025-3-27 23:28
kanxue14
非常支持你的观点!
2025-3-26 08:15
JaniQuiz
+1
谢谢你的细致分析,受益匪浅!
2025-3-24 13:59
赞赏
他的文章
赞赏
雪币:
留言: