安卓app绕过技巧及抓包实战指南
点击上方蓝字关注我们


1.工作协议层:
代理抓包主要工作在应用层,本质是:
App → 本地代理 → 远端服务器
2.代理抓包弊端:
-
只支持 HTTP/HTTPS,不支持 TCP/UDP 自定义协议。 -
很多原生 SDK、Socket 通信不走系统代理,抓不到。 -
容易被 App 检测 :代理地址、代理端口、CA 证书
3.代理抓包常用方法:Charles、Fiddler
-
下载postern到移动端,并让移动端与电脑在同一网络下。
-
开启Charles,关闭windows代理:

-
设置代理,设置socks5端口默认16666,可修改为其他端口:

-
在charles中添加移动端的ip:

-
导入证书到移动端,可以手动导入,注意android7.0以上默认只对系统证书信任,需要使用Magisk中添加MoveCertificate ,重启后,用户证书即可在系统中生效

-
配置postern,添加socks5连接,服务器地址为主机地址,端口为charles开启的socks端口

-
配置代理规则,代理选择刚刚添加的代理


-
打开vpn就可以抓取到数据包


-
添加代理转发,就可以转发流量到burp上面

4.app如何检测代理抓包:
检测 1:获取系统代理(最核心检测)
public static boolean isProxyOpen() {try {String proxyHost = System.getProperty("http.proxyHost");String proxyPort = System.getProperty("http.proxyPort");return proxyHost != null && proxyPort != null;} catch (Exception e) {return false;}}
检测 2:OkHttp 显式禁止代理后,依然检测系统代理
public static boolean checkSystemProxy() {try {ProxySelector selector = ProxySelector.getDefault();List<Proxy> proxyList = selector.select(new URI("http://www.baidu.com"));return proxyList != null && !proxyList.isEmpty() && proxyList.get(0).type() != Proxy.Type.DIRECT;} catch (Exception e) {return false;}}
检测 3:检测常见抓包端口(8888/8080/9999)
publicstatic boolean checkProxyPort() {String port = System.getProperty("http.proxyPort");if (port == null) return false;return port.equals("8888") || port.equals("8080") || port.equals("9999");}5.如何绕过代理检测:
(1)frida:将java层检查代理直接返回为空,绕过检测
Java.perform(function() {const System = Java.use('java.lang.System');System.getProperty.overload('java.lang.String').implementation = function(key) {if (key === "http.proxyHost" || key === "https.proxyHost" || key === "socksProxyHost") {return null;}return this.getProperty(key);};});
(2)使用vpn抓包
二.vpn抓包 1.工作协议层:
vpn抓包主要工作在网路层+传输层,原理主要是通过创建一个本地 VPN,将所有流量导入分析程序。
工作流程:
App → 虚拟 VPN → 抓包程序 → 网络
2.vpn抓包特点
可以抓取全局流量
不依赖系统代理设置
可捕获非 HTTP 流量
3.vpn抓包常见方式:Reqable、HttpCanary
Reqable:
Reqable 可以在移动端通过创建一个本地 VPN,将设备的所有网络流量导入自身进行分析。
App → 本地 VPN(Reqable)→ Reqable解析 → 目标服务器
Reqable使用方法:
(1)在移动端下载Reqable客户端
(2)让移动端与电脑在同一网络下
(3)选择协同配置:
(4)使用移动端扫描该二维码:
(5)连接成功(注意一定要在同一网络下):
(6)安装证书:
如果手机已经root,可以选择一键安装系统证书:
注意:该方法在Android 7.0以上不一定生效,需要在Magisk/APatch中添加
MoveCertificate,重启后,用户证书即可在系统中生效下载地址:ys1231/MoveCertificate: 支持Android7-16移动证书,兼容magiskv20.4+/kernelsu/APatch, Support Android7-16, compatible with magiskv20.4+/kernelsu/APatch
(7)安装证书后即可抓取到数据包:
4.app如何检测vpn抓包:
主要判断设备是否存在 VPN 通道 / 虚拟网卡 / 异常网络路径
(1)检测vpn是否开启:
public static boolean isVpnActive(Context context) {ConnectivityManager cm =(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);if (cm == null) return false;Network[] networks = cm.getAllNetworks();for (Network network : networks) {NetworkCapabilities caps = cm.getNetworkCapabilities(network);if (caps != null &&caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {return true;}}return false;}
(2) 检测网络接口(tun0 等)
public static boolean detectVpnInterface() {try {Enumeration<NetworkInterface> interfaces =NetworkInterface.getNetworkInterfaces();while (interfaces.hasMoreElements()) {NetworkInterface ni = interfaces.nextElement();String name = ni.getName();if (name != null &&(name.contains("tun") || name.contains("ppp"))) {return true;}}} catch (Exception ignored) {}return false;}
(3) 检测默认网络类型
public static boolean isVpnDefaultNetwork(Context context) {ConnectivityManager cm =(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);if (cm == null) return false;Network active = cm.getActiveNetwork();if (active == null) return false;NetworkCapabilities caps = cm.getNetworkCapabilities(active);return caps != null &&caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN);}5.如何绕过vpn抓包检测:
Java.perform(function() {// 1. 绕过 VPN 网络状态检测const NetworkCapabilities = Java.use('android.net.NetworkCapabilities');NetworkCapabilities.hasTransport.implementation = function(transport) {if (transport === 4) { // TRANSPORT_VPN = 4return false; // 欺骗App:没有开启VPN}return this.hasTransport(transport);};// 2. 绕过 tun 虚拟网卡检测const FileReader = Java.use('java.io.FileReader');const BufferedReader = Java.use('java.io.BufferedReader');BufferedReader.readLine.implementation = function() {const line = this.readLine();if (line != null && (line.includes("tun") || line.includes("utun") || line.includes("ppp"))) {return "tt"; // 过滤 tun 网卡信息}return line;};});三.iptables 透明代理抓包 1.iptables 透明代理本质:
在网络层拦截流量,并强制重定向到本地代理程序。
2.核心流程:
App → TCP/IP → iptables 重定向 → 本地代理 → 目标服务器
3.主要流程:
开启 IP 转发–》配置 NAT 重定向 –》使用代理工具接管流量
1.重定向 HTTP
iptables -t nat -A OUTPUT -p tcp –dport 80 -j REDIRECT –to-port 8080
2.重定向 HTTPS
iptables -t nat -A OUTPUT -p tcp –dport 443 -j REDIRECT –to-port 8080
4.缺点:
容易被检测(环境异常),需要 root, Android 10+ 限制更严格。
会改变网络行为特征。
对系统稳定性有影响。
5.iptables 命令:
# 清空规则iptables -t nat -Fiptables -t nat -X# 重定向 TCP 80/443 到本地 8080iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 8080iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-port 8080# 抓取完成后清空iptables -t nat -F6.常见检测方式:
(1)系统层检测
-
检查 iptables 规则是否异常
-
检测 NAT 表是否被修改
-
判断设备是否 Root
(2)证书与加密检测
-
SSL Pinning(证书绑定)
-
检测中间人证书
-
校验公钥哈希


SSL Pinning
1.什么是SSL Pinning:
我们在正常https抓包时,虽然也需要证书,但那个是伪造的CA证书,很多app只要服务器证书由这些根证书签发,App 就信任,所以当我们装证书后,就可以中间人抓包。
但SSL Pinning是App 不相信系统证书,会将服务器证书的公钥哈希写入到app中,即使我们配置了CA证书也无法抓包。
2.SSL Pinning常见写法:
(1) 绑定证书公钥(常见):
提取服务器证书的公钥哈希,App 内置这个哈希字符串,握手时对比服务器返回的证书公钥哈希是否一致
(2)绑定证书文件:
直接把服务器的 .cer / .pem 证书打包进 App,握手时对比整个证书
3.app常见SSL Pinning 实现方法:
(1)OKHttp官方实现:
OkHttpClient client = new OkHttpClient.Builder().certificatePinner(new CertificatePinner.Builder().add("api.xxx.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=").add("api.xxx.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=").build()).build();(2)Android 官方 NetworkSecurityConfig(Android 7+):
<?xml version="1.0" encoding="utf-8"?><network-security-config><domain-config><domainincludeSubdomains="true">api.xxx.com</domain><pin-setexpiration="2028-01-01"><pindigest="SHA-256">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</pin><pindigest="SHA-256">BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=</pin></pin-set></domain-config></network-security-config>(3)自定义 TrustManager:
X509TrustManager是 Java / Android 标准接口,大部分证书校验都会走这 3 个函数:public interface X509TrustManager {// 1. 校验服务器证书voidcheckServerTrusted(X509Certificate[] chain, String authType);// 2. 校验客户端证书voidcheckClientTrusted(X509Certificate[] chain, String authType);// 3. 返回可信任的CA列表X509Certificate[] getAcceptedIssuers();}具体实现方法(单向认证):
// 自定义 TrustManager,强制只信任指定证书public class MyPinningTrustManager implements X509TrustManager {@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {// 这里做 SSL Pinning 校验if (chain == null || chain.length == 0) {throw new CertificateException("证书为空");}X509Certificate cert = chain[0];String pubKeyHash = getPublicKeyHash(cert);// 只认内置的公钥(SSL Pinning)if (!pubKeyHash.equals("abcd1234xxxxxx")) {throw new CertificateException("证书不匹配!可能被抓包!");}}@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType) {}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}}
4.绕过方法:
(1)LSposed+JustTrustMe模块绕过SSL Pinning:
下载LSposed和JustTrustMe
下载地址:
LSposed:https://github.com/LSPosed/LSPosed
JustTrustMe:https://github.com/Fuzion24/JustTrustMe
下载后,先在Magisk导入LSposed模块:
导入成功后重启,会显示LSposed已加载: 将下载的JustTrustMe的apk导入到手机中,进入LSPosed就可以看到已经导入成功:
可以选择应用去启用该模块:
(2)Frida 绕过 OkHttp CertificatePinner:
Java.perform(function(){const CertificatePinner = Java.use('okhttp3.CertificatePinner');CertificatePinner.check.implementation = function(host, certificates) {// 直接跳过校验,不抛异常return;};});(3)Frida绕过自定义 TrustManage(仅适用于简单场景):
1、Frida 注入通常做的是:
-
Hook
SSLContext.init(...) -
把原本的
TrustManager[]替换成你自己的 -
或者 Hook 某些证书校验函数,让它们直接返回成功
2、正常的 TrustManager 会做这些事:
-
校验证书链
-
校验证书是否被信任 CA 签发
-
校验域名
而置空 TrustManager的逻辑就是:不做任何校验,直接信任所有证书
// 绕过 SSL 证书校验 - 空 TrustManager 实现function bypassSSL() {console.log("[+] 开始注入空 TrustManager 绕过证书校验");try {const TrustManager = Java.use('javax.net.ssl.TrustManager');const X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');const SSLContext = Java.use('javax.net.ssl.SSLContext');// 实现空的 X509TrustManager(不校验任何证书)const EmptyTrustManager = Java.registerClass({name: 'com.example.EmptyTrustManager',implements: [X509TrustManager],methods: {checkClientTrusted: function (chain, authType) {},checkServerTrusted: function (chain, authType) {},getAcceptedIssuers: function () {return [];}}});const trustManagers = Java.array('javax.net.ssl.TrustManager', [EmptyTrustManager.$new()]);SSLContext.init.overload('[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom').implementation = function (keyManagers, tms, random) {console.log("全局替换 SSL 信任管理器成功");return this.init(keyManagers, trustManagers, random);};} catch (e) {console.log("证书绕过失败: " + e.message);}}Java.perform(function () {bypassSSL();console.log("Frida 证书绕过脚本加载完成");});五.总结 在实际对抗中,抓包与App之间本质是一场“检测与绕过”的博弈:应用会通过代理检测、VPN检测、证书校验甚至Native层校验来阻止分析,而安全研究人员则通过Hook、证书注入、环境伪装等方式进行绕过。因此,单一工具往往无法解决所有问题,必须根据目标App的实现选择合适的抓包层级和对抗策略。
需要特别注意的是,现代移动应用已经大量采用 TLS 1.3、HTTP/2、QUIC(HTTP/3)以及Native加密逻辑,这些都会显著提高抓包难度,使传统代理方式逐渐失效。因此,抓包能力的提升不在于掌握更多工具,而在于理解网络分层、TLS信任模型以及应用安全机制。
往期推荐
话题征集 Today’s News NEWS 哈喽,感谢看到这里的你! 如果有什么想要了解的话题、想看的内容也可添加下方小助手联系我们,或留言评论区,选中话题会整理写成完整文章噢~
也可加入我们交流群,参与话题讨论,群里也不定时分享干货、答疑解惑,第一时间同步新文章和小惊喜,添加下方小助手,备注【公众号,进群】即可。
备注【公众号,进群】加入交流群
一起交流,相互学习
点点赞 点分享 点推荐 写留言
夜雨聆风




























