安全矩阵

 找回密码
 立即注册
搜索
查看: 1914|回复: 0

APP抓包大法(最全总结)

[复制链接]

65

主题

65

帖子

241

积分

中级会员

Rank: 3Rank: 3

积分
241
发表于 2022-7-21 12:36:04 | 显示全部楼层 |阅读模式
APP抓包大法(最全总结) (qq.com)
​ 0x01 不走代理的App
如何判断:连接Fiddler代理-->抓不到包-->关闭Fiddler后正常通信。
解决方法:PC端模拟器+如下全局代理抓包工具,筛选出模拟器进程无需配置可以直接解密https流量

1. HTTPAnalyserv7


2. HTTPDebuggerpro


0x02 常规App抓包
1. 普通代理 Fiddler
PS:fiddler 抓app仍是http代理抓包,容易被检测限制
可以在FiddlerScript 中的handle下配置 抓取websocket (多是明文)

static function OnWebSocketMessage(oMsg: WebSocketMessage) {     // Log Message to the LOG tab     FiddlerApplication.Log.LogString(oMsg.ToString());}  2. Charles + postern 可以新建一个VPN配置socks5代理
从而绕过更多抓包限制,Charles处理https包更优秀,配置如下简图,也可自行百度高级用法。



去掉本地windows代理,只抓取移动端的流量手机端Postern左侧配置代理—添加代理服务器输入上图设置好的socks代理8889端口,代理类型选择socks5,再返回配置规则删除其他规则,添加匹配所有通过刚刚设置好的代理保存。如图:



开启postern,允许连接vpn,浏览器输入chls.pro这个网址下载安装证书。
Charles点击图中的第二步解密按钮,可解密https流量(8.0以上系统可以将证书放到系统证书目录下)

3. VPN手机端使用Httpcanary抓包
使用VPN,流量会强制走VPN通道,可以抓到更多的包。
配置安装证书,有root权限可以把证书安装到系统证书下(7.1及以下系统默认信任用户证书)
点击右下的小飞机即可抓包,右上角有过滤选项可以只抓http tcp等
左边设置目标应用可以指定进程,方便只抓取想要的数据包
PS:安卓7.1及以上,抓取https流量,需要root后把fiddler、burp、charles等工具的的证书安装到系统根证书下
openssl x509 -inform PEM -subject_hash_old -in Desktop.pem |head -1  #获取hash值用hash值.0重命名证书adb push 重命名后证书 /sdcard/mount -o rw,remount /      #挂载为可读写mv /sdcard/证书 /etc/security/cacerts/      #系统证书路径chmod 644 /etc/security/cacerts/证书  #修改权限644# /data/misc/user/0/cacerts-added   #用户证书路径
0x03代理证书检测绕过
如何判断:0x02抓不到的有可能就是代理检测,更直观的判断就是App可以正常使用,打开httpcanary抓不到或者网络连接失败
说到代理检测:先简单介绍下数字证书常见的检测机制
一般来说主要检测证书中{证书链 签发关系 公钥 指纹}等这些内容,所以我们绕过代理检测也要从这些方面入手。
所以实际抓包测试中hook掉系统自带的检测api和常见框架中的检测api即可。然后再利用0x02中的抓包姿势就O了。

下介绍两种方式:
1. Xposed框架+JustTrustMe (0.3)



安装xp框架后直接安装justtrustme的apk,在模块里勾选中开启,然后一定!!重启模拟器/手机,打开关闭xp框架和模块一定要重启手机才能生效。
JustTrustMe的源码<可自行编译>(文末有编译好的apk等本文工具打包下载)
项目地址:https://github.com/Fuzion24/JustTrustMe

从项目代码中可以看到作者hook了很多常见的系统函数、常见框架(okhttp等)HttpsURLConnection 下的API X509TrustManager、HostnameVerifier(域名验证),setSSLSocketFactory()中的sslcontext里的checksevercertificate(),setHostnameVerifier() 方法;okhttp/okhttp3框架中证书Pinner,certificatePinner 下的 check 方法, 设置通信组件中的setSSLSocketFactory() 方法等。

2. Frida + Hook.js
Frida请自行安装,可以参考https://www.jianshu.com/p/c349471bdef7
Frida:hook中常用的两个命令:
frida -UF -l .\hook.js   #注入最前端的进程(当前的app)frida -U --no-pause -f com.xxx.xxx(包名) -l .\Hook.js  #启动前注入
下面的JS代码类似于frida下的增强版的justtrustme ,Hook了下述的一些系统api和框架
1.SSLcontext
2.okhttp
3.webview
4.XUtils
5.httpclientandroidlib
6.JSSE
7.network_security_config (android 7.0+)
8.Apache Http client (support partly)
9.OpenSSLSocketImpl
10.TrustKit
11.Cronet
  1. <p>Java.perform(function () {</p><p>    /*
  2.     hook list:
  3.     1.SSLcontext
  4.     2.okhttp
  5.     3.webview
  6.     4.XUtils
  7.     5.httpclientandroidlib
  8.     6.JSSE
  9.     7.network\_security\_config (android 7.0+)
  10.     8.Apache Http client (support partly)
  11.     9.OpenSSLSocketImpl
  12.     10.TrustKit
  13.     11.Cronet
  14.     */</p><p>    // Attempts to bypass SSL pinning implementations in a number of
  15.     // ways. These include implementing a new TrustManager that will
  16.     // accept any SSL certificate, overriding OkHTTP v3 check()
  17.     // method etc.
  18.     var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
  19.     var HostnameVerifier = Java.use('javax.net.ssl.HostnameVerifier');
  20.     var SSLContext = Java.use('javax.net.ssl.SSLContext');
  21.     var quiet_output = false;</p><p>    // Helper method to honor the quiet flag.</p><p>    function quiet_send(data) {</p><p>        if (quiet_output) {</p><p>            return;
  22.         }</p><p>        send(data)
  23.     }</p><p>
  24.     // Implement a new TrustManager
  25.     // ref: https://gist.github.com/oleavr/3ca67a173ff7d207c6b8c3b0ca65a9d8
  26.     // Java.registerClass() is only supported on ART for now(201803). 所以android 4.4以下不兼容,4.4要切换成ART使用.
  27.     /*
  28. 06-07 16:15:38.541 27021-27073/mi.sslpinningdemo W/System.err: java.lang.IllegalArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing
  29. 06-07 16:15:38.542 27021-27073/mi.sslpinningdemo W/System.err:     at android.net.http.X509TrustManagerExtensions.<init>(X509TrustManagerExtensions.java:73)
  30.         at mi.ssl.MiPinningTrustManger.<init>(MiPinningTrustManger.java:61)
  31. 06-07 16:15:38.543 27021-27073/mi.sslpinningdemo W/System.err:     at mi.sslpinningdemo.OkHttpUtil.getSecPinningClient(OkHttpUtil.java:112)
  32.         at mi.sslpinningdemo.OkHttpUtil.get(OkHttpUtil.java:62)
  33.         at mi.sslpinningdemo.MainActivity$1$1.run(MainActivity.java:36)
  34. */
  35.     var X509Certificate = Java.use("java.security.cert.X509Certificate");
  36.     var TrustManager;
  37.     try {
  38.         TrustManager = Java.registerClass({
  39.             name: 'org.wooyun.TrustManager',
  40.             implements: [X509TrustManager],
  41.             methods: {
  42.                 checkClientTrusted: function (chain, authType) { },
  43.                 checkServerTrusted: function (chain, authType) { },
  44.                 getAcceptedIssuers: function () {
  45.                     // var certs = [X509Certificate.$new()];
  46.                     // return certs;
  47.                     return [];
  48.                 }
  49.             }
  50.         });
  51.     } catch (e) {
  52.         quiet_send("registerClass from X509TrustManager >>>>>>>> " + e.message);
  53.     }</p><p>    // Prepare the TrustManagers array to pass to SSLContext.init()
  54.     var TrustManagers = [TrustManager.$new()];</p><p>    try {
  55.         // Prepare a Empty SSLFactory
  56.         var TLS_SSLContext = SSLContext.getInstance("TLS");
  57.         TLS_SSLContext.init(null, TrustManagers, null);
  58.         var EmptySSLFactory = TLS_SSLContext.getSocketFactory();
  59.     } catch (e) {
  60.         quiet_send(e.message);
  61.     }</p><p>    send('Custom, Empty TrustManager ready');</p><p>    // Get a handle on the init() on the SSLContext class
  62.     var SSLContext_init = SSLContext.init.overload(
  63.         '[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom');</p><p>    // Override the init method, specifying our new TrustManager
  64.     SSLContext_init.implementation = function (keyManager, trustManager, secureRandom) {</p><p>        quiet_send('Overriding SSLContext.init() with the custom TrustManager');</p><p>        SSLContext_init.call(this, null, TrustManagers, null);
  65.     };</p><p>    /*** okhttp3.x unpinning ***/</p><p>
  66.     // Wrap the logic in a try/catch as not all applications will have
  67.     // okhttp as part of the app.
  68.     try {</p><p>        var CertificatePinner = Java.use('okhttp3.CertificatePinner');</p><p>        quiet_send('OkHTTP 3.x Found');</p><p>        CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function () {</p><p>            quiet_send('OkHTTP 3.x check() called. Not throwing an exception.');
  69.         }</p><p>    } catch (err) {</p><p>        // If we dont have a ClassNotFoundException exception, raise the
  70.         // problem encountered.
  71.         if (err.message.indexOf('ClassNotFoundException') === 0) {</p><p>            throw new Error(err);
  72.         }
  73.     }</p><p>    // Appcelerator Titanium PinningTrustManager</p><p>    // Wrap the logic in a try/catch as not all applications will have
  74.     // appcelerator as part of the app.
  75.     try {</p><p>        var PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager');</p><p>        send('Appcelerator Titanium Found');</p><p>        PinningTrustManager.checkServerTrusted.implementation = function () {</p><p>            quiet_send('Appcelerator checkServerTrusted() called. Not throwing an exception.');
  76.         }</p><p>    } catch (err) {</p><p>        // If we dont have a ClassNotFoundException exception, raise the
  77.         // problem encountered.
  78.         if (err.message.indexOf('ClassNotFoundException') === 0) {</p><p>            throw new Error(err);
  79.         }
  80.     }</p><p>    /*** okhttp unpinning ***/</p><p>
  81.     try {
  82.         var OkHttpClient = Java.use("com.squareup.okhttp.OkHttpClient");
  83.         OkHttpClient.setCertificatePinner.implementation = function (certificatePinner) {
  84.             // do nothing
  85.             quiet_send("OkHttpClient.setCertificatePinner Called!");
  86.             return this;
  87.         };</p><p>        // Invalidate the certificate pinnet checks (if "setCertificatePinner" was called before the previous invalidation)
  88.         var CertificatePinner = Java.use("com.squareup.okhttp.CertificatePinner");
  89.         CertificatePinner.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function (p0, p1) {
  90.             // do nothing
  91.             quiet_send("okhttp Called! [Certificate]");
  92.             return;
  93.         };
  94.         CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function (p0, p1) {
  95.             // do nothing
  96.             quiet_send("okhttp Called! [List]");
  97.             return;
  98.         };
  99.     } catch (e) {
  100.         quiet_send("com.squareup.okhttp not found");
  101.     }</p><p>    /*** WebView Hooks ***/</p><p>    /* frameworks/base/core/java/android/webkit/WebViewClient.java */
  102.     /* public void onReceivedSslError(Webview, SslErrorHandler, SslError) */
  103.     var WebViewClient = Java.use("android.webkit.WebViewClient");</p><p>    WebViewClient.onReceivedSslError.implementation = function (webView, sslErrorHandler, sslError) {
  104.         quiet_send("WebViewClient onReceivedSslError invoke");
  105.         //执行proceed方法
  106.         sslErrorHandler.proceed();
  107.         return;
  108.     };</p><p>    WebViewClient.onReceivedError.overload('android.webkit.WebView', 'int', 'java.lang.String', 'java.lang.String').implementation = function (a, b, c, d) {
  109.         quiet_send("WebViewClient onReceivedError invoked");
  110.         return;
  111.     };</p><p>    WebViewClient.onReceivedError.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest', 'android.webkit.WebResourceError').implementation = function () {
  112.         quiet_send("WebViewClient onReceivedError invoked");
  113.         return;
  114.     };</p><p>    /*** JSSE Hooks ***/</p><p>    /* libcore/luni/src/main/java/javax/net/ssl/TrustManagerFactory.java */
  115.     /* public final TrustManager[] getTrustManager() */
  116.     /* TrustManagerFactory.getTrustManagers maybe cause X509TrustManagerExtensions error  */
  117.     var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");
  118.     TrustManagerFactory.getTrustManagers.implementation = function(){
  119.         quiet_send("TrustManagerFactory getTrustManagers invoked");
  120.         return TrustManagers;
  121.     }</p><p>    var HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection");
  122.     /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */
  123.     /* public void setDefaultHostnameVerifier(HostnameVerifier) */
  124.     HttpsURLConnection.setDefaultHostnameVerifier.implementation = function (hostnameVerifier) {
  125.         quiet_send("HttpsURLConnection.setDefaultHostnameVerifier invoked");
  126.         return null;
  127.     };
  128.     /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */
  129.     /* public void setSSLSocketFactory(SSLSocketFactory) */
  130.     HttpsURLConnection.setSSLSocketFactory.implementation = function (SSLSocketFactory) {
  131.         quiet_send("HttpsURLConnection.setSSLSocketFactory invoked");
  132.         return null;
  133.     };
  134.     /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */
  135.     /* public void setHostnameVerifier(HostnameVerifier) */
  136.     HttpsURLConnection.setHostnameVerifier.implementation = function (hostnameVerifier) {
  137.         quiet_send("HttpsURLConnection.setHostnameVerifier invoked");
  138.         return null;
  139.     };</p><p>    /*** Xutils3.x hooks ***/
  140.     //Implement a new HostnameVerifier
  141.     var TrustHostnameVerifier;
  142.     try {
  143.         TrustHostnameVerifier = Java.registerClass({
  144.             name: 'org.wooyun.TrustHostnameVerifier',
  145.             implements: [HostnameVerifier],
  146.             method: {
  147.                 verify: function (hostname, session) {
  148.                     return true;
  149.                 }
  150.             }
  151.         });</p><p>    } catch (e) {
  152.         //java.lang.ClassNotFoundException: Didn't find class "org.wooyun.TrustHostnameVerifier"
  153.         quiet_send("registerClass from hostnameVerifier >>>>>>>> " + e.message);
  154.     }</p><p>    try {
  155.         var RequestParams = Java.use('org.xutils.http.RequestParams');
  156.         RequestParams.setSslSocketFactory.implementation = function (sslSocketFactory) {
  157.             sslSocketFactory = EmptySSLFactory;
  158.             return null;
  159.         }</p><p>        RequestParams.setHostnameVerifier.implementation = function (hostnameVerifier) {
  160.             hostnameVerifier = TrustHostnameVerifier.$new();
  161.             return null;
  162.         }</p><p>    } catch (e) {
  163.         quiet_send("Xutils hooks not Found");
  164.     }</p><p>    /*** httpclientandroidlib Hooks ***/
  165.     try {
  166.         var AbstractVerifier = Java.use("ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier");
  167.         AbstractVerifier.verify.overload('java.lang.String', '[Ljava.lang.String', '[Ljava.lang.String', 'boolean').implementation = function () {
  168.             quiet_send("httpclientandroidlib Hooks");
  169.             return null;
  170.         }
  171.     } catch (e) {
  172.         quiet_send("httpclientandroidlib Hooks not found");
  173.     }</p><p>    /***
  174. android 7.0+ network_security_config TrustManagerImpl hook
  175. apache httpclient partly
  176. ***/
  177.     var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl");
  178.     // try {
  179.     //     var Arrays = Java.use("java.util.Arrays");
  180.     //     //apache http client pinning maybe baypass
  181.     //     //https://github.com/google/conscrypt/blob/c88f9f55a523f128f0e4dace76a34724bfa1e88c/platform/src/main/java/org/conscrypt/TrustManagerImpl.java#471
  182.     //     TrustManagerImpl.checkTrusted.implementation = function (chain, authType, session, parameters, authType) {
  183.     //         quiet_send("TrustManagerImpl checkTrusted called");
  184.     //         //Generics currently result in java.lang.Object
  185.     //         return Arrays.asList(chain);
  186.     //     }</p><p>    // } catch (e) {
  187.     //     quiet_send("TrustManagerImpl checkTrusted nout found");
  188.     // }</p><p>    try {
  189.         // Android 7+ TrustManagerImpl
  190.         TrustManagerImpl.verifyChain.implementation = function (untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {
  191.             quiet_send("TrustManagerImpl verifyChain called");
  192.             // Skip all the logic and just return the chain again :P
  193.             //https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2017/november/bypassing-androids-network-security-configuration/
  194.             // https://github.com/google/conscrypt/blob/c88f9f55a523f128f0e4dace76a34724bfa1e88c/platform/src/main/java/org/conscrypt/TrustManagerImpl.java#L650
  195.             return untrustedChain;
  196.         }
  197.     } catch (e) {
  198.         quiet_send("TrustManagerImpl verifyChain nout found below 7.0");
  199.     }
  200.     // OpenSSLSocketImpl
  201.     try {
  202.         var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl');
  203.         OpenSSLSocketImpl.verifyCertificateChain.implementation = function (certRefs, authMethod) {
  204.             quiet_send('OpenSSLSocketImpl.verifyCertificateChain');
  205.         }</p><p>        quiet_send('OpenSSLSocketImpl pinning')
  206.     } catch (err) {
  207.         quiet_send('OpenSSLSocketImpl pinner not found');
  208.     }
  209.     // Trustkit
  210.     try {
  211.         var Activity = Java.use("com.datatheorem.android.trustkit.pinning.OkHostnameVerifier");
  212.         Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (str) {
  213.             quiet_send('Trustkit.verify1: ' + str);
  214.             return true;
  215.         };
  216.         Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (str) {
  217.             quiet_send('Trustkit.verify2: ' + str);
  218.             return true;
  219.         };</p><p>        quiet_send('Trustkit pinning')
  220.     } catch (err) {
  221.         quiet_send('Trustkit pinner not found')
  222.     }</p><p>    try {
  223.         //cronet pinner hook
  224.         //weibo don't invoke</p><p>        var netBuilder = Java.use("org.chromium.net.CronetEngine$Builder");</p><p>        //https://developer.android.com/guide/topics/connectivity/cronet/reference/org/chromium/net/CronetEngine.Builder.html#enablePublicKeyPinningBypassForLocalTrustAnchors(boolean)
  225.         netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.implementation = function (arg) {</p><p>            //weibo not invoke
  226.             console.log("Enables or disables public key pinning bypass for local trust anchors = " + arg);</p><p>            //true to enable the bypass, false to disable.
  227.             var ret = netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.call(this, true);
  228.             return ret;
  229.         };</p><p>        netBuilder.addPublicKeyPins.implementation = function (hostName, pinsSha256, includeSubdomains, expirationDate) {
  230.             console.log("cronet addPublicKeyPins hostName = " + hostName);</p><p>            //var ret = netBuilder.addPublicKeyPins.call(this,hostName, pinsSha256,includeSubdomains, expirationDate);
  231.             //this 是调用 addPublicKeyPins 前的对象吗? Yes,CronetEngine.Builder
  232.             return this;
  233.         };</p><p>    } catch (err) {
  234.         console.log('[-] Cronet pinner not found')
  235.     }
  236. });</p>
复制代码


0x04 总结
常见的App抓包姿势差不多就这些了,基本可以抓到未加固的或者debug版的App的数据包。代码混淆,入口加固,资源加固等App,混淆类的需要通过匹配函数的参数类型找到修改后的函数名自己重写方法、加固类的需要jadx-guif反编译后分析加固的的逻辑找到App的函数入口让其初始化解密后再重写相关函数等。后期再找案例分析。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2025-4-26 09:52 , Processed in 0.016846 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表