Android app抓包场景详解

admin 2024年9月9日01:30:01评论14 views字数 17739阅读59分7秒阅读模式

一、未校验:配置证书就能抓

1.这种情况是最简单的情况,Android 7.0之前的设备,直接配置用户证书,就能进行抓包,Android 7.0之后的设备,需要获取root权限1后,把用户证书移到系统证书目录下,或者配置系统强制信任用户证书。对于移动用户证书到系统证书目录下的情况,推荐使用这个插件:https://github.com/ys1231/MoveCertificate,对于强制信任用户证书的这种情况,推荐使用这个插件:https://github.com/NVISOsecurity/MagiskTrustUserCerts。

2.对于这种情况,我们安装完证书后,直接使用代理/vpn的方式进行抓包就可以了,这里我们以via浏览器为例,进行抓包演示,因为我用的设备是Android 7.0以上的,所以我们首先是配置系统强制信任用户证书的插件

Android app抓包场景详解

3.配置完成后,我们在抓包软件上导出证书,然后在设备上进行安装。    

Android app抓包场景详解

4.接下来,我们就可以进行抓包了,抓包成功。

Android app抓包场景详解

二、单向证书认证:客户端校验服务器证书--SSL Pinning

1.这是第二种情况,也就是我们常说的sslpinning,想具体了解sslpining技术,可以去看这2篇文章:https://shunix.com/ssl-pinning/,https://yu-jack.github.io/2020/03/02/ssl-pinning/。    

2.针对这种情况,我们以滴答清单app为例,进行抓包,上面我们已经试过了,用我们的测试设备是可以正常抓到https的数据包的,然后我们再去抓一下滴答清单这个app的包,点击发送验证码按钮后会提示发送失败,请重试 ,说明我们抓包失败了。

Android app抓包场景详解

Android app抓包场景详解

3.这里报错:Client closed the connection before a request was made. Possibly the SSL certificate was rejected,表明在 SSL/TLS 握手阶段,客户端在没有发送 HTTP 请求之前就关闭了连接,客户端拒绝了服务器的证书,也就是上面我们所说的sslpinning技术,还有另外一种报错的情况:SSL handshake with client failed: An unknown issue occurred processing the certificate (certificate_unknown),也是用到了sslpinning技术。那遇到上述这2种情况,我们应该怎么处理呢?使用frida进行hook,我们这里直接用大佬们写好的脚本进行hook    

Java.perform(function() {/*hook list:1.SSLcontext2.okhttp3.webview4.XUtils5.httpclientandroidlib6.JSSE7.network_security_config (android 7.0+)8.Apache Http client (support partly)9.OpenSSLSocketImpl10.TrustKit11.Cronet*/       // Attempts to bypass SSL pinning implementations in a number of       // ways. These include implementing a new TrustManager that will       // accept any SSL certificate, overriding OkHTTP v3 check()       // method etc.       var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');       var HostnameVerifier = Java.use('javax.net.ssl.HostnameVerifier');       var SSLContext = Java.use('javax.net.ssl.SSLContext');       var quiet_output = false;       // Helper method to honor the quiet flag.       function quiet_send(data) {              if (quiet_output) {                     return;              }              send(data)       }       // Implement a new TrustManager       // ref: https://gist.github.com/oleavr/3ca67a173ff7d207c6b8c3b0ca65a9d8       // Java.registerClass() is only supported on ART for now(201803). 所以android 4.4以下不兼容,4.4要切换成ART使用.       /*06-07 16:15:38.541 27021-27073/mi.sslpinningdemo W/System.err: java.lang.IllegalArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing    06-07 16:15:38.542 27021-27073/mi.sslpinningdemo W/System.err:     at android.net.http.X509TrustManagerExtensions.(X509TrustManagerExtensions.java:73)        at mi.ssl.MiPinningTrustManger.(MiPinningTrustManger.java:61)06-07 16:15:38.543 27021-27073/mi.sslpinningdemo W/System.err:     at mi.sslpinningdemo.OkHttpUtil.getSecPinningClient(OkHttpUtil.java:112)        at mi.sslpinningdemo.OkHttpUtil.get(OkHttpUtil.java:62)        at mi.sslpinningdemo.MainActivity$1$1.run(MainActivity.java:36)*/       var X509Certificate = Java.use("java.security.cert.X509Certificate");       var TrustManager;       try {              TrustManager = Java.registerClass({                     name: 'org.wooyun.TrustManager',                     implements: [X509TrustManager],                     methods: {                            checkClientTrusted: function(chain, authType) {},                            checkServerTrusted: function(chain, authType) {},                            getAcceptedIssuers: function() {                                   // var certs = [X509Certificate.$new()];                                   // return certs;                                   return [];                            }                     }              });       } catch (e) {              quiet_send("registerClass from X509TrustManager >>>>>>>> " + e.message);       }       // Prepare the TrustManagers array to pass to SSLContext.init()       var TrustManagers = [TrustManager.$new()];       try {              // Prepare a Empty SSLFactory              var TLS_SSLContext = SSLContext.getInstance("TLS");              TLS_SSLContext.init(null, TrustManagers, null);              var EmptySSLFactory = TLS_SSLContext.getSocketFactory();       } catch (e) {              quiet_send(e.message);       }       send('Custom, Empty TrustManager ready');       // Get a handle on the init() on the SSLContext class       var SSLContext_init = SSLContext.init.overload(              '[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom');       // Override the init method, specifying our new TrustManager       SSLContext_init.implementation = function(keyManager, trustManager, secureRandom) {                  quiet_send('Overriding SSLContext.init() with the custom TrustManager');              SSLContext_init.call(this, null, TrustManagers, null);       };       /*** okhttp3.x unpinning ***/       // Wrap the logic in a try/catch as not all applications will have       // okhttp as part of the app.       try {              var CertificatePinner = Java.use('okhttp3.CertificatePinner');              quiet_send('OkHTTP 3.x Found');              CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {                     quiet_send('OkHTTP 3.x check() called. Not throwing an exception.');              }       } catch (err) {              // If we dont have a ClassNotFoundException exception, raise the              // problem encountered.              if (err.message.indexOf('ClassNotFoundException') === 0) {                     throw new Error(err);              }       }       // Appcelerator Titanium PinningTrustManager       // Wrap the logic in a try/catch as not all applications will have       // appcelerator as part of the app.       try {              var PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager');              send('Appcelerator Titanium Found');              PinningTrustManager.checkServerTrusted.implementation = function() {                     quiet_send('Appcelerator checkServerTrusted() called. Not throwing an exception.');              }       } catch (err) {              // If we dont have a ClassNotFoundException exception, raise the              // problem encountered.              if (err.message.indexOf('ClassNotFoundException') === 0) {                     throw new Error(err);              }       }       /*** okhttp unpinning ***/       try {              var OkHttpClient = Java.use("com.squareup.okhttp.OkHttpClient");              OkHttpClient.setCertificatePinner.implementation = function(certificatePinner) {                     // do nothing                     quiet_send("OkHttpClient.setCertificatePinner Called!");                     return this;              };              // Invalidate the certificate pinnet checks (if "setCertificatePinner" was called before the previous invalidation)              var CertificatePinner = Java.use("com.squareup.okhttp.CertificatePinner");              CertificatePinner.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(p0, p1) {                     // do nothing                     quiet_send("okhttp Called! [Certificate]");                     return;              };              CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(p0, p1) {                     // do nothing                     quiet_send("okhttp Called! [List]");                     return;              };       } catch (e) {              quiet_send("com.squareup.okhttp not found");       }       /*** WebView Hooks ***/       /* frameworks/base/core/java/android/webkit/WebViewClient.java */       /* public void onReceivedSslError(Webview, SslErrorHandler, SslError) */       var WebViewClient = Java.use("android.webkit.WebViewClient");       WebViewClient.onReceivedSslError.implementation = function(webView, sslErrorHandler, sslError) {              quiet_send("WebViewClient onReceivedSslError invoke");              //执行proceed方法              sslErrorHandler.proceed();              return;       };       WebViewClient.onReceivedError.overload('android.webkit.WebView', 'int', 'java.lang.String', 'java.lang.String').implementation = function(a, b, c, d) {              quiet_send("WebViewClient onReceivedError invoked");              return;       };       WebViewClient.onReceivedError.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest', 'android.webkit.WebResourceError').implementation = function() {              quiet_send("WebViewClient onReceivedError invoked");              return;       };       /*** JSSE Hooks ***/       /* libcore/luni/src/main/java/javax/net/ssl/TrustManagerFactory.java */       /* public final TrustManager[] getTrustManager() */       /* TrustManagerFactory.getTrustManagers maybe cause X509TrustManagerExtensions error  */       // var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");       // TrustManagerFactory.getTrustManagers.implementation = function(){       //     quiet_send("TrustManagerFactory getTrustManagers invoked");       //     return TrustManagers;       // }       var HttpsURLConnection = Java.use("javax.net.ssl.HttpsURLConnection");       /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */       /* public void setDefaultHostnameVerifier(HostnameVerifier) */       HttpsURLConnection.setDefaultHostnameVerifier.implementation = function(hostnameVerifier) {              quiet_send("HttpsURLConnection.setDefaultHostnameVerifier invoked");              return null;       };       /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */       /* public void setSSLSocketFactory(SSLSocketFactory) */       HttpsURLConnection.setSSLSocketFactory.implementation = function(SSLSocketFactory) {              quiet_send("HttpsURLConnection.setSSLSocketFactory invoked");              return null;       };       /* libcore/luni/src/main/java/javax/net/ssl/HttpsURLConnection.java */       /* public void setHostnameVerifier(HostnameVerifier) */       HttpsURLConnection.setHostnameVerifier.implementation = function(hostnameVerifier) {              quiet_send("HttpsURLConnection.setHostnameVerifier invoked");              return null;       };       /*** Xutils3.x hooks ***/       //Implement a new HostnameVerifier       var TrustHostnameVerifier;       try {              TrustHostnameVerifier = Java.registerClass({                     name: 'org.wooyun.TrustHostnameVerifier',                     implements: [HostnameVerifier],                     method: {                            verify: function(hostname, session) {                                   return true;                            }                     }              });       } catch (e) {              //java.lang.ClassNotFoundException: Didn't find class "org.wooyun.TrustHostnameVerifier"                  quiet_send("registerClass from hostnameVerifier >>>>>>>> " + e.message);       }       try {              var RequestParams = Java.use('org.xutils.http.RequestParams');              RequestParams.setSslSocketFactory.implementation = function(sslSocketFactory) {                     sslSocketFactory = EmptySSLFactory;                     return null;              }              RequestParams.setHostnameVerifier.implementation = function(hostnameVerifier) {                     hostnameVerifier = TrustHostnameVerifier.$new();                     return null;              }       } catch (e) {              quiet_send("Xutils hooks not Found");       }       /*** httpclientandroidlib Hooks ***/       try {              var AbstractVerifier = Java.use("ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier");              AbstractVerifier.verify.overload('java.lang.String', '[Ljava.lang.String', '[Ljava.lang.String', 'boolean').implementation = function() {                     quiet_send("httpclientandroidlib Hooks");                     return null;              }       } catch (e) {              quiet_send("httpclientandroidlib Hooks not found");       }       /***android 7.0+ network_security_config TrustManagerImpl hookapache httpclient partly***/       var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl");       // try {       //     var Arrays = Java.use("java.util.Arrays");       //     //apache http client pinning maybe baypass       //     //https://github.com/google/conscrypt/blob/c88f9f55a523f128f0e4dace76a34724bfa1e88c/platform/src/main/java/org/conscrypt/TrustManagerImpl.java#471       //     TrustManagerImpl.checkTrusted.implementation = function (chain, authType, session, parameters, authType) {       //         quiet_send("TrustManagerImpl checkTrusted called");       //         //Generics currently result in java.lang.Object       //         return Arrays.asList(chain);       //     }       //       // } catch (e) {       //     quiet_send("TrustManagerImpl checkTrusted nout found");       // }       try {              // Android 7+ TrustManagerImpl              TrustManagerImpl.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {                     quiet_send("TrustManagerImpl verifyChain called");                     // Skip all the logic and just return the chain again :P                     //https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2017/november/bypassing-androids-network-security-configuration/                     // https://github.com/google/conscrypt/blob/c88f9f55a523f128f0e4dace76a34724bfa1e88c/platform/src/main/java/org/conscrypt/TrustManagerImpl.java#L650                     return untrustedChain;              }       } catch (e) {              quiet_send("TrustManagerImpl verifyChain nout found below 7.0");       }       // OpenSSLSocketImpl       try {              var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl');              OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certRefs, authMethod) {                     quiet_send('OpenSSLSocketImpl.verifyCertificateChain');              }              quiet_send('OpenSSLSocketImpl pinning')       } catch (err) {              quiet_send('OpenSSLSocketImpl pinner not found');       }       // Trustkit       try {              var Activity = Java.use("com.datatheorem.android.trustkit.pinning.OkHostnameVerifier");              Activity.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(str) {                     quiet_send('Trustkit.verify1: ' + str);                     return true;              };              Activity.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(str) {                     quiet_send('Trustkit.verify2: ' + str);                     return true;              };              quiet_send('Trustkit pinning')       } catch (err) {              quiet_send('Trustkit pinner not found')       }       try {              //cronet pinner hook              //weibo don't invoke              var netBuilder = Java.use("org.chromium.net.CronetEngine$Builder");              //https://developer.android.com/guide/topics/connectivity/cronet/reference/org/chromium/net/CronetEngine.Builder.html#enablePublicKeyPinningBypassForLocalTrustAnchors(boolean)                  netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.implementation = function(arg) {                     //weibo not invoke                     console.log("Enables or disables public key pinning bypass for local trust anchors = " + arg);                     //true to enable the bypass, false to disable.                     var ret = netBuilder.enablePublicKeyPinningBypassForLocalTrustAnchors.call(this, true);                     return ret;              };              netBuilder.addPublicKeyPins.implementation = function(hostName, pinsSha256, includeSubdomains, expirationDate) {                     console.log("cronet addPublicKeyPins hostName = " + hostName);                     //var ret = netBuilder.addPublicKeyPins.call(this,hostName, pinsSha256,includeSubdomains, expirationDate);                     //this 是调用 addPublicKeyPins 前的对象吗? Yes,CronetEngine.Builder                     return this;              };       } catch (err) {              console.log('[-] Cronet pinner not found')       }});

4.用了大佬的脚本后,发现还是不行,还是失败了,只能换一个再试试了,又尝试了justtrustme,地址:https://github.com/Fuzion24/JustTrustMe,结果还是不行。

Android app抓包场景详解

5.在辗转反侧之时,我想起之前用算法助手时,里面带着一个justtruatme的升级版,于是就拿来试了试,结果成功拿下。可以正常进行抓包了。    

Android app抓包场景详解

6.经过上述尝试,我们针对sslpinning这种,可以先用市面上已有的sslunpinning工具进行尝试,如果遇到都无法进行成功的情况,那就需要我们去手工进行hook了,大致有两种思路,一是对所有HTTP字符串相关类进行Hook,二是考虑到App在验证证书时会打开证书文件判断是否是App自身所信任的,因此一定会使用File类的构造函数打开证书文件获得文件的句柄,所以我们在测试时可以Hook上所有File类的构造函数,即对File.$init函数进行hook。这里我用了objection进行hook的:objection -N -h 127.0.0.1 -p 26666-g cn.ticktick.task explore -P ~/.objection/plugins -s "android hooking watch class_method java.io.File.$init --dump-args --dump-backtrace --dump-return",这里因为$在命令行中有特殊含义,所以用对它进行转义,避免被当成命令行变量。hook之后,我们在得到的数据里面搜索/system/etc/security/cacerts    

Android app抓包场景详解

7.我们在搜到的数据里面,找到了一个关于证书的堆栈信息,我们用jadx反编译后,找到这个方法    

Android app抓包场景详解

8.复制一下,丢给chatgpt分析一下,得出结论,这段代码是关于处理 SSL 证书验证的逻辑,是基于域名和证书的哈希值进行匹配,检查传入的证书是否符合某些预期的标准,那我们尝试hook它,并让它返回空,这样不就能绕过证书校验了嘛。

function main() {    Java.perform(function () {        console.log("启动");        let f = Java.use("ll.f");        f["a"].implementation = function (str, list) {            console.log(`f.a is called: str=${str}, list=${list}`);            return;        };    });}setTimeout(main, 500)    

Android app抓包场景详解

9.非常幸运,经过hook后,我们成功抓到了这个数据包,至此完成。

三、双向证书认证:服务器校验客户端证书。

1.这是第三种情况,我们以便利蜂app为例,进行抓包尝试,经过尝试,还是和之前一样报错:SSL handshake with client failed: An unknown issue occurred processing the certificate (certificate_unknown)

Android app抓包场景详解

2.我们先使用objection的android sslpinning disable把这个sslpinning过掉,过掉之后,我们再抓包,发现请求正常发出,响应返回报错:400 No required SSL certificate was sent。判断为服务器校验客户端证书。    

Android app抓包场景详解

3.当我们遇到这种情况,需要我们从app中找到内置的客户端证书,导入到抓包工具中,才能正常进行抓包,那怎么才能找到客户端的证书呢?通常是有二种方法,第一种是用r0ysue大佬写的r0capture进行hook导出,第二种是去hook Keystore,找到加载证书的地方,手动分析源码去找到证书和密码。我们先用一下第一种方案:直接上r0capture,有枣没枣打一杆子试试。

Android app抓包场景详解

4.运气不错,证书找到了,我们直接在dowload目录下把证书拿出来,安装到Charles里    

Android app抓包场景详解

5.然后,再次进行抓包,可以看到,我们成功绕过了双向证书认证。

Android app抓包场景详解

6.我们去看一下r0ysue大佬的脚本,简单来解释一下原理,在安卓开发中,系统包是无法混淆的,例如java.security.KeyStore不会被混淆,所以可以去hook这个类,并且在 Java 中,KeyStore$PrivateKeyEntry 是存储在 KeyStore 中,包含私鑰和相關的證書,即getPrivateKey() 和 getCertificateChain() 這兩個方法,也就是说当應用程序調用 getPrivateKey() 或 getCertificateChain() 方法來獲取私鑰和證書時,会被脚本拦截并提取返回的私钥和证书数据,然后storeP12() 函數,將提取的私鑰和證書組合起來,存儲為一個 .p12 文件,并使用密码r0ysue進行加密並寫入到指定的文件路徑。    

Java.perform(function () {    function uuid(len, radix) {        var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');        var uuid = [], i;        radix = radix || chars.length;        if (len) {            // Compact form            for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];        } else {            // rfc4122, version 4 form            var r;            // rfc4122 requires these characters            uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';            uuid[14] = '4';            // Fill in random data. At i==19 set the high bits of clock sequence as            // per rfc4122, sec. 4.1.5            for (i = 0; i < 36; i++) {                if (!uuid[i]) {                    r = 0 | Math.random() * 16;                    uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];                }            }        }        return uuid.join('');    }    function storeP12(pri, p7, p12Path, p12Password) {        var X509Certificate = Java.use("java.security.cert.X509Certificate")        var p7X509 = Java.cast(p7, X509Certificate);        var chain = Java.array("java.security.cert.X509Certificate", [p7X509])        var ks = Java.use("java.security.KeyStore").getInstance("PKCS12", "BC");        ks.load(null, null);        ks.setKeyEntry("client", pri, Java.use('java.lang.String').$new(p12Password).toCharArray(), chain);        try {            var out = Java.use("java.io.FileOutputStream").$new(p12Path);            ks.store(out, Java.use('java.lang.String').$new(p12Password).toCharArray())        } catch (exp) {            console.log(exp)        }    }    // 在服务器校验客户端的情形下,帮助dump客户端证书,并保存为p12的格式,证书密码为r0ysue    Java.use("java.security.KeyStore$PrivateKeyEntry").getPrivateKey.implementation = function () {        var result = this.getPrivateKey()        var packageName = Java.use("android.app.ActivityThread").currentApplication().getApplicationContext().getPackageName();        storeP12(this.getPrivateKey(), this.getCertificate(), '/sdcard/Download/' + packageName + uuid(10, 16) + '.p12', 'r0ysue');            return result;    }    Java.use("java.security.KeyStore$PrivateKeyEntry").getCertificateChain.implementation = function () {        var result = this.getCertificateChain()        var packageName = Java.use("android.app.ActivityThread").currentApplication().getApplicationContext().getPackageName();        storeP12(this.getPrivateKey(), this.getCertificate(), '/sdcard/Download/' + packageName + uuid(10, 16) + '.p12', 'r0ysue');        return result;    }});

7.这个便利蜂的例子到此为止,我们再拿出上次我们折腾过的Fake Location,它也是双向证书认证,这次我们自己去找一下证书,还是一样启动charles进行抓包。

Android app抓包场景详解

8.可以看到,报错和之前是一样的,我们之前说过了,这种是sslpinning的情况,我们用objection的android sslpinning disable把它过掉,过掉之后,再重新抓包,发现报错变了,请求包正常,响应包400的情况。    

Android app抓包场景详解

9.这种情况就是双向证书校验了,我们需要去解包找证书搜索.p12,.bks,.pem,还是一样没找到,我们只能去脱壳反编译代码,这次脱壳我用的是大佬给分享的一个脱壳网站:https://nop.gs/

Android app抓包场景详解

10.然后我们去代码里找找看,这里我们直接搜索keystore,发现就这几个,而且就这俩货带着BKS的关键字样。    

Android app抓包场景详解

11.点进去看看,终于知道为啥我解包后,搜索常见证书后缀搜不着的原因了,原来是用了图片做证书。md

Android app抓包场景详解

12.证书找到了,接下来就是找密码了,怎么找呢?当然是hook了,上脚本。之前也说过了,因为java.security.KeyStore是系统的类是不会被混淆的,所以我们hook它就行了。

function hook_KeyStore_load() {    Java.perform(function () {        var StringClass = Java.use("java.lang.String");        var KeyStore = Java.use("java.security.KeyStore");        KeyStore.load.overload('java.security.KeyStore$LoadStoreParameter').implementation = function (arg0) {            // printStack("KeyStore.load1");            // 输出调用栈                console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));            console.log("KeyStore.load1:", arg0);            this.load(arg0);        };        KeyStore.load.overload('java.io.InputStream', '[C').implementation = function (arg0, arg1) {            // printStack("KeyStore.load2");            console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));            console.log("KeyStore.load2:", arg0, arg1 ? StringClass.$new(arg1) : null);            this.load(arg0, arg1);        };        console.log("hook_KeyStore_load...");    });}hook_KeyStore_load()

13.来,让我们来看看hook的效果如何?hook出来了,密码是lerist.key.2021

Android app抓包场景详解

14.然后我们把证书拿出来

Android app抓包场景详解

15.这里我用了keystore explorer对证书进行格式的转换    

Android app抓包场景详解

16.我们得把证书转成p12格式,才能在charles里安装,安装完成后,虽然是加密得,但是可以正常抓包了。    

Android app抓包场景详解

四、总结

在Android应用的抓包过程中,处理不同类型的证书验证机制的方法有所不同:

无证书校验:如果应用没有进行证书验证,我们只需配置抓包工具的证书即可进行抓包。

单向证书认证(SSL Pinning):对于SSL Pinning的应用,我们通常需要使用Frida等工具进行hook,以绕过SSL Pinning机制。在某些情况下,可能需要尝试多种方法,如使用JustTrustMe脚本,才能成功进行抓包。

双向证书认证:对于双向证书认证,我们可以使用r0capture直接dump证书。此外,也可以通过代码中找到证书和密码,然后将其转换为.p12证书,并导入到抓包工具中进行抓包。

原文始发于微信公众号(Flower Sec):Android app抓包场景详解

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月9日01:30:01
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Android app抓包场景详解https://cn-sec.com/archives/3144418.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息