Android 抓包相关 SSL相关

news2024/11/18 7:39:05

https无法明文抓包

Android P版本开始强制App使用Https协议,否则访问崩溃如下所示错误:

java.lang.ClassCastException: 
com.android.okhttp.internal.huc.HttpURLConnectionImpl cannot be cast to javax.net.ssl.HttpsURLConnection

可参阅:
Android 9.0强制使用https,会阻塞http请求,如果app使用的第三方sdk有http,将全部被阻塞

因此在Android P基本很少能能抓取http请求,多数以https为主。

但是你在参考网上https抓包配置后发现还是无法解密内容:
在这里插入图片描述

Android 7 以上系统默认会让App不信任默认用户证书,只信用系统证书。
默认情况我们只能导入用户证书,系统证书导入需要一些root权限。如下图所示导入的charles证书。
在这里插入图片描述
如果你是App所有用户可以参阅下面文章操作:

Android 7及以上信任用户证书

如果你有root权限直接导入系统证书即可:

(1) 首先安装代理的证书(此时会将会自动将证书转化为特定格式),用户证书安装目录:
/data/misc/user/0/cacerts-added
如笔者次目录下的用户证书
在这里插入图片描述
(2) 将证书文件拷贝到系统证书目录/system/etc/security/cacerts
举例命令

cp 97fa6c80.0  /system/etc/security/cacerts  

如果出现 Read-only file system ,重新挂载分区(android 8以上版本请关闭dm-verity以及avb在尝试网上重新挂载命令)。

//针对ROM是userdebug版本可以使用下面的命令
adb disable-verity
adb reboot
adb root
adb remount

对于root手机可以考虑使用mask的一个模块:
movecert_iyue
这个模块原理非常简单,和新源码如下

mv -f /data/misc/user/0/cacerts-added/* $MODDIR/system/etc/security/cacerts/

就是将用户证书移动mask规范下的system目录(会被映射到真实的/system)
在这里插入图片描述

安装后重启即可看到系统证书:

在这里插入图片描述
抓包效果图可以明显看到成功解析了数据:
在这里插入图片描述

app不走代理

很多网络框架可以自主选择是否选择路由代理。如下代码:

//
  val httpHost = System.getProperties().getProperty("http.proxyHost");
  val httpPort = System.getProperties().getProperty("http.proxyPort");
  val httpsHost = System.getProperties().getProperty("https.proxyHost");
  val httpsPort = System.getProperties().getProperty("https.proxyPort");
  //输出代理信息
  Log.e( "test", "httpHost ${httpHost} httpPort ${httpPort} \r\n httpsHost ${httpsHost} httpsPort ${httpsPort} ")

  System.getProperties().remove("http.proxyHost");
  System.getProperties().remove("http.proxyPort");
  System.getProperties().remove("https.proxyHost");
  System.getProperties().remove("https.proxyPort");

  val url = URL("https://www.google.com")
  val urlConnection = url.openConnection() as HttpsURLConnection
  urlConnection.connect()
  val readBytes = urlConnection.inputStream.readBytes()
  Log.e("test", "${String(readBytes)}")

上面的这种方式会迫使wifi手动设置代理抓包方式失效

解决方案:

  1. 电脑开个热点,然后抓电脑无线网卡即可(软路由差不多,比较简单不做举例)
  2. 手机开代理软件转发流量到代理
  3. 手机刷Nethunter 直接当电脑玩,抓手机网卡即可(我现在还想不到不走网卡上网的app)

举例代理流量 (2)

VPN方式转发流量可以通杀市面大多数的APP,但是部分app会检测,但是免root。proxydroid需要root但基本可以做到市面上百分之99%的应用无感知透明代理

我们以charles+proxydroid举例

charles 开启socks代理
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

流量转发VPN
Charles+postern抓包教程 转载
流量转发 proxydroid

举例(3) 刷入Nethunter内核
在这里插入图片描述
刷入后你将是一个完整linux系统,通过vnc链接手机桌面,然后开启wireshark解析数据包

在这里插入图片描述
当然wireshare比较适合做自定义协议的分析,https还是建议在新的内核系统再装一个charles在通过iptable转发流量。

SSL Pinning(客户端固定证书)

客户端可以强制只信任某一证书,那么代理抓包的中间人证书将失效并且可以风控异常设备进行上报。

我们首先用keytool生产一个PKCS12文件(里面包含密钥以及证书)

keytool -genkeypair --ext SAN=IP:192.168.38.70  -alias baeldung -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore baeldung.p12 -validity 3650

其中注意上面需要改成自己的IP

生产的文件会交付给我们的Demo服务端使用,然后我们需要再提起里面的证书给客户端

//生产处一个证书,但是这个证书不是我们需要的格式
openssl pkcs12 -in   baeldung.p12 -out your-cert.pem  -nokeys
//将证书转化成Android 客户端证书格式
openssl x509 -outform der -in your-cert.pem  -out your-cert.crt

我们服务端使用spring boot作为案例:

//UserControl.kt
//接口如下:
@Controller
@RequestMapping("test")
class UserControl {
    @RequestMapping("xx")
    @ResponseBody
    fun myout(): String {
        return "hello"
    }
}

最后是我们的ssl配置如下(即可拷贝证书到工程的keystore/baeldung.p12)

#application.properties 文件
# The format used for the keystore. It could be set to JKS in case it is a JKS file
server.ssl.key-store-type=PKCS12
# The path to the keystore containing the certificate
server.ssl.key-store=classpath:keystore/baeldung.p12
# The password used to generate the certificate
server.ssl.key-store-password=123456
# The alias mapped to the certificate
server.ssl.key-alias=   baeldung


最后就是我们的客户端案例:

 fun test(){
         val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
         val caInput: InputStream = BufferedInputStream(this.resources.assets.open("your-cert.crt"))
         val ca: X509Certificate = caInput.use {
             cf.generateCertificate(it) as X509Certificate
         }
         System.out.println("ca=" + ca.subjectDN)

         // Create a KeyStore containing our trusted CAs
         val keyStoreType = KeyStore.getDefaultType()
         val keyStore = KeyStore.getInstance(keyStoreType).apply {
             load(null, null)
             setCertificateEntry("baeldung", ca)
         }

         // Create a TrustManager that trusts the CAs inputStream our KeyStore
         val tmfAlgorithm: String = TrustManagerFactory.getDefaultAlgorithm()
         val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm).apply {
             init(keyStore)
         }

         // Create an SSLContext that uses our TrustManager
         val context: SSLContext = SSLContext.getInstance("TLS").apply {
             init(null, tmf.trustManagers, null)
         }

         // Tell the URLConnection to use a SocketFactory from our SSLContext
         val url = URL("https://192.168.38.70:8080/test/xx")
         val urlConnection = url.openConnection() as HttpsURLConnection
         urlConnection.sslSocketFactory = context.socketFactory
         urlConnection.connect()
         val inputStream: InputStream = urlConnection.inputStream

        Log.e("test", "${String(inputStream.readBytes())}")
     }

开启代理抓包后:
在这里插入图片描述
在这里插入图片描述

解决方案1:

对于客户端固定证书个人推荐推荐frida hook方式进行解绑
这里给出一个开源的解决脚本
frida-android-unpinning

举例clone 上面的脚本执行后
frida -U  -f com.example.learnssldemo   -l frida-script.js 

输出:
JackdeMacBook-Pro:frida-android-unpinning-main jack$ frida -U  -f com.example.learnssldemo   -l frida-script.js 
     ____
    / _  |   Frida 16.0.8 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Pixel 6 (id=19291FDF6006PD)
Spawned `com.example.learnssldemo`. Resuming main thread!               
[Pixel 6::com.example.learnssldemo ]-> ---
Unpinning Android app...
[+] SSLPeerUnverifiedException auto-patcher
[+] HttpsURLConnection (setDefaultHostnameVerifier)
[+] HttpsURLConnection (setSSLSocketFactory)
[+] HttpsURLConnection (setHostnameVerifier)
[+] SSLContext
[+] TrustManagerImpl
[ ] OkHTTPv3 (list)
[ ] OkHTTPv3 (cert)
[ ] OkHTTPv3 (cert array)
[ ] OkHTTPv3 ($okhttp)
[ ] Trustkit OkHostnameVerifier(SSLSession)
[ ] Trustkit OkHostnameVerifier(cert)
[ ] Trustkit PinningTrustManager
[ ] Appcelerator PinningTrustManager
[ ] OpenSSLSocketImpl Conscrypt
[ ] OpenSSLEngineSocketImpl Conscrypt
[ ] OpenSSLSocketImpl Apache Harmony
[ ] PhoneGap sslCertificateChecker
[ ] IBM MobileFirst pinTrustedCertificatePublicKey (string)
[ ] IBM MobileFirst pinTrustedCertificatePublicKey (string array)
[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (SSLSocket)
[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (cert)
[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (string string)
[ ] IBM WorkLight HostNameVerifierWithCertificatePinning (SSLSession)
[ ] Conscrypt CertPinManager
[ ] CWAC-Netsecurity CertPinManager
[ ] Worklight Androidgap WLCertificatePinningPlugin
[ ] Netty FingerprintTrustManagerFactory
[ ] Squareup CertificatePinner (cert)
[ ] Squareup CertificatePinner (list)
[ ] Squareup OkHostnameVerifier (cert)
[ ] Squareup OkHostnameVerifier (SSLSession)
[+] Android WebViewClient (SslErrorHandler)
[ ] Android WebViewClient (WebResourceError)
[ ] Apache Cordova WebViewClient
[ ] Boye AbstractVerifier
[ ] Appmattus (Transparency)
Unpinning setup completed
---

在这里插入图片描述

解决方案2:

如果你是App所有者那么你只需要在如下地方配置即可
在这里插入图片描述
在这里插入图片描述

HTTPS using Self-Signed Certificate in Spring Boot
通过 HTTPS 和 SSL 确保安全

mutual authentication

如法炮制,首先是生产一个客户端使用的证书

keytool -genkeypair   -alias baeldung -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore cbaeldung.p12 -validity 3650

生产的p12文件格式Android 无法直接使用需要转化为bks格式,这里使用portecle 进行转化。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

此时我们还需要导出一个jks给服务端使用,教程如下:
首先执行命令导出客户端p12的证书

openssl pkcs12 -in cbaeldung.p12 -out OUTFILE.crt -nodes

然后重新打开portecle然后执行如下操作将证书放入jks格式的一个封装文件中,
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

首先我们编写服务端代码,只需要将上文证书固定代码稍微增加即可

# application.properties
# The format used for the keystore. It could be set to JKS in case it is a JKS file
server.ssl.key-store-type=PKCS12
# The path to the keystore containing the certificate
server.ssl.key-store=classpath:keystore/baeldung.p12
# The password used to generate the certificate
server.ssl.key-store-password=123456
# The alias mapped to the certificate
server.ssl.key-alias=  baeldung
spring.rsocket.server.ssl.key-store-type=PKCS12
#开启验证客户端证书
server.ssl.client-auth=need
server.ssl.trust-store=classpath:keystore/clienttrus.jks
server.ssl.trust-store-password=123456
server.ssl.trust-store-type=JKS


在这里插入图片描述

客户端代码:

 fun test() {
        
        
        //服务端证书固定代码
        val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
        val caInput: InputStream = BufferedInputStream(this.resources.assets.open("your-cert.crt"))
        val ca: X509Certificate = caInput.use {
            cf.generateCertificate(it) as X509Certificate
        }
        System.out.println("ca=" + ca.subjectDN)

        // Create a KeyStore containing our trusted CAs
        val keyStoreType = KeyStore.getDefaultType()
        val keyStore = KeyStore.getInstance(keyStoreType).apply {
            load(null, null)
            setCertificateEntry("baeldung", ca)
        }

        // Create a TrustManager that trusts the CAs inputStream our KeyStore
        val tmfAlgorithm: String = TrustManagerFactory.getDefaultAlgorithm()
        val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm).apply {
            init(keyStore)
        }


        
        //客户端证书导入
        val keyStore2 = KeyStore.getInstance("BKS");
        val ksIn = this.resources.getAssets().open("cbaeldung.bks");
        ksIn.use {ksIn->
            keyStore2.load(ksIn, KEY_STORE_PASSWORD.toCharArray())
        }
        val keyManagerFactory = KeyManagerFactory.getInstance("X509");
        keyManagerFactory.init(keyStore2, KEY_STORE_PASSWORD.toCharArray());


        // Create an SSLContext that uses our TrustManager
        val context: SSLContext = SSLContext.getInstance("TLS").apply {
            init(
                keyManagerFactory.keyManagers,//开启客户端证书
                tmf.trustManagers, //服务端证书固定
                null)
        }

        // Tell the URLConnection to use a SocketFactory from our SSLContext
        val url = URL("https://192.168.38.70:8080/test/xx")
        val urlConnection = url.openConnection() as HttpsURLConnection
        urlConnection.sslSocketFactory = context.socketFactory
        urlConnection.connect()
        val inputStream: InputStream = urlConnection.inputStream

        Log.e("test", "${String(inputStream.readBytes())}")
    }

不要忘记将bks文件拷贝到Android工程哦

当你开启抓包软件后你会发现链接失败。。.。

解决方案:
如果你不是app拥有者,首先先用上网的Frida解绑,然后再逆向App取出客户端bks文件以及密码,然后导入chales。
在这里插入图片描述

本节服务端代码
本节客户端

参阅文章1 开源app-从0到1实现(四)Android端自制https证书实现双向认证.md

🍶 为什么你的 Charles 会抓包失败?

Hook通用抓包

= =无视所谓的证书绑定,双向认证1232
一个firda 脚本

在这里插入图片描述

原理看了下非常简单,可参阅我的另一篇博文Android hook方式抓包

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/192005.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C 语言零基础入门教程(二十三)

C 可变参数 有时,您可能会碰到这样的情况,您希望函数带有可变数量的参数,而不是预定义数量的参数。C 语言为这种情况提供了一个解决方案,它允许您定义一个函数,能根据具体的需求接受可变数量的参数。下面的实例演示了…

Centos8中安装配置php

一、问题描述Centos8中我们在使用Apache部署配置网站的时候,发现Apache服务已经正常启动且网站也配置完成到Apache主目录中,但是访问时网站却不能正常运行【即:只能够以列表的方式列出所有网站的资源文件,而不是以网页的形式展现】…

关于荧光素76863-28-0,FITC-5-thiosemicarbazide,荧光素-5-氨基硫脲 相关知识分享

荧光素-5-氨基硫脲,Fluorescein-5-thiosemicarbazide,FITC-5-thiosemicarbazide荧光素-5-氨基硫脲是一种含胺的荧光探针,可用于标记糖和蛋白质羰基衍生物Product specifications:1.CAS No:76863-28-02.Molecular formu…

超越OCR的富文档内容解析神器LayoutParser

论文题目:《A unified toolkit for Deep Learning Based Document Image Analysis》 论文链接:https://arxiv.org/abs/2103.15348 论文官方网站:https://layout-parser.github.io/ 论文开源项目:https://github.com/Layout-Par…

Ubuntu 18.04安装配置MySQL数据库

文章目录1. 安装MySQL数据库2. 配置MySQL数据库3. 远程访问设置4. Navicat连接MySQL数据库1. 安装MySQL数据库 这里可以通过包管理工具apt安装MySQL数据库,在ubuntu18.04下mysql版本默认为5.7。 安装命令如下: sudo apt-get install mysql-server安装…

【Echarts雪花宝典特殊示例100+】 目录

目前已发表2篇示例文章vueecharts系列教程旨在为开发者提供简单快捷的代码示例,复制即可用。在每一个示例中,解释相应的API知识点,做到简易实现,轻松学会。 通常一个Echarts图表通常由title(标题)、legend(图例)、grid&#xff0…

ESP-IDF:插入排序和希尔排序测试

代码&#xff1a; /插入排序和希尔排序测试/ void printArray14(int arr[], int len) { for (int i 0; i < len; i) { cout << arr[i] << " "; } cout << endl; } void insertSort(int arr[], int start, int end) { // 无序插入有序队列&am…

BM19 寻找峰值

目录 描述 示例1 思路&#xff1a; 代码&#xff1a; 描述 给定一个长度为n的数组nums&#xff0c;请你找到峰值并返回其索引。数组可能包含多个峰值&#xff0c;在这种情况下&#xff0c;返回任何一个所在位置即可。 1.峰值元素是指其值严格大于左右相邻值的元素。严格…

专访三维空间雷成老师 | 原来水墨画风格的3D建筑动画可以如此惊艳……

CGarchitect 是业界赫赫有名的国际3D建筑赛事&#xff0c;2005年首次举办至今已成功举办了17届大赛&#xff0c;每年都吸引了全球许多知名的建筑设计工作室、动画工作室、艺术家及学生参赛。2021年的CGarchitect奖项类别包括图像组、影片组和交互组&#xff0c;其中图像组和影片…

【Rust】17. Rust 中的并发

17.1 线程 17.1.1 spawn&#xff1a;创建新线程 thread::spawn&#xff1a;创建一个新线程&#xff0c;需要传递一个闭包&#xff0c;并在其中包含希望在新线程运行的代码thread::sleep&#xff1a;调用强制线程停止执行一小段时间。比如&#xff1a;thread::sleep(Duration::…

深入理解MySql(一)MySql视图、存储过程、预处理语句、触发器、定时器

MySql视图、存储过程、预处理语句、触发器、定时器 1、视图 视图&#xff08;View&#xff09;是一种虚拟存在的表。视图中的数据并不在数据库中实际存在&#xff0c;行和列数据来自定义视图的查询中使用的表&#xff0c;并且是在使用视图时动态生成的。 视图只保存了查询的…

iOS面试- 0x02 WebView

有了UIWebView&#xff0c;为什么还需要WKWebView&#xff1f; UIWebVieW的缺点&#xff1a; 笨重难用、内存泄露、内存消耗大&#xff0c;性能差 —— WKWebView提高性能 WKWebView 拥有60fps滚动刷新率和safari相同的js引擎等优势。 1、WKWebView 白屏问题 WKWebView是一个多…

ElasticSearch6.x版本的Scroll滚动查询讲解及Kibana和SpringBoot实操演示

文章目录一、Scroll滚动查询介绍二、Kibana上操作三、SpringBoot中操作四、总结一、Scroll滚动查询介绍 ElasticSearch中在进行普通的查询时&#xff0c;默认只会查询出来10条数据。我们通过设置ElasticSearch中的size可以将最终的查询结果从10增加到10000。但这时候如果我们需…

Sensor曝光和帧率基础知识

Sensor曝光和帧率基础知识1. 简介2. H_BLANK和V_BLANK3. 曝光原理3.1 Sensor逐行曝光基本原理3.2 Sensor全局曝光基本原理4. 曝光时间计算公式4.1 曝光一行的时间line_timeline\_timeline_time4.2 曝光一帧的时间exposure_timeexposure\_timeexposure_time4.3 帧率(fps)的计算1…

2023,“蔚小理”真的经不起更多“事故”了

历史总是惊人的相似。2013年&#xff0c;哈弗品牌独立出来&#xff0c;与长城品牌并行运营&#xff0c;当时推出两年的哈弗H6正卖得火热&#xff0c;推动SUV这个细分品类在中国快速成长&#xff0c;中国自主品牌也借SUV开始攻占被合资品牌占领的市场。时移势易。十年后的2023年…

浅析TSINGSEE车载监控平台助力城市公交智能监管的方案设计

道路运输已成为铁路以外最重要的地面运输方式&#xff0c;在国民经济和社会发展中发挥着举足轻重的作用。然而&#xff0c;随着汽车的普及和交通需求的快速增长&#xff0c;道路运输带来的交通拥堵、交通事故和环境污染等负面影响日益突出&#xff0c;逐渐成为全球经济社会发展…

Baklib支招 ——如何帮助企业创建内部维基(wiki)?

企业维基&#xff08;wiki&#xff09;的重要的好处就是&#xff1a;可以按照个性化的理解和需求进行编辑&#xff0c;而不担心被别人修改。这个个人维基可以作为自己的外挂大脑使用&#xff0c;但是不要成为一个垃圾筐&#xff0c;什么都往里装&#xff0c;扔进去就再也不看了…

计算机SCI论文重复率需要控制在多少? - 易智编译EaseEditing

SCI论文的重复率一般在20%左右&#xff0c;一般是没有没问题的。 SCI期刊在检查论文重复率时&#xff0c;并不是简单的只看总重复率&#xff0c;还有单篇重复率。 目前有很多SCI期刊都会先查重&#xff0c;看重复率&#xff0c;但也会看内容。 而且&#xff0c;重复率高也不一定…

lio-sam学习笔记(一)

前言&#xff1a; 对于lio-sam框架的安装配置。 每一回不同框架的配置真是要了老命了。。。 一、安装依赖 官方github&#xff1a; GitHub - TixiaoShan/LIO-SAM: LIO-SAM: Tightly-coupled Lidar Inertial Odometry via Smoothing and Mapping lio-sam主要有两个依赖&am…

6.深度学习和计算

6.深度学习和计算 目录 层和块 自定义块顺序块在前向传播函数中执行代码 参数管理 参数访问 目标参数一次性访问所有参数从嵌套块收集参数 参数初始化 内置初始化自定义初始化 参数绑定 自定义层 不带参数的层带参数的层 读写文件 加载和保存张量加载和保存模型参数使用GPU 计…