乐于分享
好东西不私藏

安卓app绕过技巧及抓包实战指南

安卓app绕过技巧及抓包实战指南

点击上方蓝字关注我们

一.代理抓包

1.工作协议层:

    代理抓包主要工作在应用层,本质是:

App → 本地代理 → 远端服务器

2.代理抓包弊端:

  1. 只支持 HTTP/HTTPS,不支持 TCP/UDP 自定义协议。
  2. 很多原生 SDK、Socket 通信不走系统代理,抓不到。
  3. 容易被 App 检测 :代理地址、代理端口、CA 证

3.代理抓包常用方法:Charles、Fiddler

Postern + Charles + Burp Suite
  1. 下载postern到移动端,并让移动端与电脑在同一网络下。

  2. 开启Charles,关闭windows代理:

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

  4. 在charles中添加移动端的ip:

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

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

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

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

  9. 添加代理转发,就可以转发流量到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 == nullreturn 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抓包特点

  1. 可以抓取全局流量

  2. 不依赖系统代理设置

  3. 可捕获非 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 == nullreturn 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 == nullreturn false;    Network active = cm.getActiveNetwork();    if (active == nullreturn 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 = 4            return 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.缺点:

  1. 容易被检测(环境异常),需要 root, Android 10+ 限制更严格。

  2. 会改变网络行为特征。

  3. 对系统稳定性有影响。

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 -F

6.常见检测方式:

(1)系统层检测

  • 检查 iptables 规则是否异常

  • 检测 NAT 表是否被修改

  • 判断设备是否 Root

(2)证书与加密检测

  • SSL Pinning(证书绑定)

  • 检测中间人证书

  • 校验公钥哈希

四.Frida 协议 Hook 抓包

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 {    @Override    public 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("证书不匹配!可能被抓包!");        }    }    @Override    public void checkClientTrusted(X509Certificate[] chain, String authType) {}    @Override    public X509Certificate[] getAcceptedIssuers() {        return new X509Certificate[0];    }}

      4.绕过方法:

      (1)LSposed+JustTrustMe模块绕过SSL Pinning:

      1. 下载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: {                checkClientTrustedfunction (chain, authType) {},                checkServerTrustedfunction (chain, authType) {},                getAcceptedIssuersfunction () {                    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信任模型以及应用安全机制。

        往期推荐

        JWT认证漏洞实战解析(一)

        继续干货输出!JWT认证漏洞实战解析(二)

        云存储实战挖掘思路与演示

        AI编程助手“说瞎话”,背后隐藏的攻击手段

        新思路!支付漏洞实战案例分享:低价薅高价商品

        话题征集
        Today’s News
        NEWS
            哈喽,感谢看到这里的你!

            如果有什么想要了解的话题、想看的内容也可添加下方小助手联系我们,或留言评论区,选中话题会整理写成完整文章噢~

            也可加入我们交流群,参与话题讨论,群里也不定时分享干货、答疑解惑,第一时间同步新文章和小惊喜,添加下方小助手,备注【公众号,进群】即可。

        备注【公众号,进群】加入交流群

        一起交流,相互学习

        点点赞
        点分享
        点推荐
        写留言