深度剖析ja3指纹及完美突破 js逆向之猿人学第十九题突破ja3指纹验证

前言

 

其实才没几天发过ja3相关的文章:js逆向之猿人学第十九题突破ja3指纹验证  ,原本是没打算写后续的,由于蔡老板很仗义地帮我推了一波(蔡老板这无处安放的魅力啊),使得我写得不太专业的文章被很多大佬关注到了,加上有很多东西没有阐述清楚,同时我由于对写公众号文章经验不足导致出现一些影响阅读体验的问题,本着更深入理解ja3指纹的目的,所以催生出了当前这篇文章。

 

注:本篇文章略长,如果赶时间的朋友,可以直接跳过接下来的理论概念介绍,可以直接从后面的【如何突破ja3】开始看

 

到底什么是ja3

简介

 

git:https://github.com/salesforce/ja3

 

官方解释+谷歌翻译:

JA3 是一种创建 SSL/TLS 客户端指纹的方法,它应该易于在任何平台上生成,并且可以轻松共享以用于威胁情报

 

 

更权威的介绍文章:TLS Fingerprinting with JA3 and JA3S

 

浓缩一下大概意思就是:

JA3 是一种对传输层安全应用程序进行指纹识别的方法。它于 2017 年 6 月首次发布在 GitHub 上,是 Salesforce 研究人员 John Althouse、Jeff Atkinson 和 Josh Atkins 的作品。创建的 JA3 TLS/SSL 指纹可以在应用程序之间重叠,但仍然是一个很好的妥协指标 (IoC)。指纹识别是通过创建客户端问候消息的 5 个十进制字段的哈希来实现的,该消息在 TLS/SSL 会话的初始阶段发送。

 

这.....,2017年就有了,我是今年才通过阅读青南大佬的文章知道有这么个东西。

 

然后我猜,ja3名字的由来,是因为有3个研究人员,且他们的姓名缩写都是ja

 

ja3的由来

 

其实,John Althouse 自己说过,官方解释+谷歌翻译:

对这个 TLS 客户端进行指纹识别的主要概念来自 Lee Brotherston 2015 年的研究(https://blog.squarelemon.com/tls-fingerprinting/)和他的 DerbyCon 演讲(https://www.youtube.com/watch?v=XX0FRAy2Mec)。如果不是 Lee ,就不会有JA3的出现

 

 

ja3如何工作的

 

原文解释的很好了,官方解释+谷歌翻译:

TLS 及其前身 SSL 用于为常见应用程序和恶意软件加密通信,以确保数据安全,因此可以隐藏在噪音中。要启动 TLS 会话,客户端将在 TCP 3 次握手之后发送 TLS 客户端 Hello 数据包。此数据包及其生成方式取决于构建客户端应用程序时使用的包和方法。服务器如果接受 TLS 连接,将使用基于服务器端库和配置以及 Client Hello 中的详细信息制定的 TLS Server Hello 数据包进行响应。由于 TLS 协商以明文形式传输,因此可以使用 TLS Client Hello 数据包中的详细信息来指纹和识别客户端应用程序

 

更多更专业的,如果很感兴趣,劳烦移步John Althouse发表的文章:Open Sourcing JA3

 

感觉看了上面的话,是不是有点似懂非懂的感觉,没事,听我慢慢说,来个图吧,要来图的话,先来个三次握手的吧,老图了,相信各位朋友也都看烦了,我也看烦了,因为这图都传包浆了

 

 

 详细的三次握手流程解释我就不说了,网上能查到的太多了,我就不献丑解释了,本篇文章的重点也不是它

 

那么按照ja开发者自述,是在三次握手之后,客户端向服务端发起client hello包,这个包里带了客户端这边的一些特征发给服务端,服务端拿来解析数据包,然后回发一个hello给客户端,之后再进行ssl数据交互,下面这个图,就是John Althouse自己画的

 

 

 

 

怎么说?画的很传神很易懂对吧?

 

更多原文解释,请看这里:TLS Fingerprinting with JA3 and JA3S

John Althouse有关ja3的ppt讲义,上面的动图就是ppt文件里的,费了老大劲搞到的:链接: https://pan.baidu.com/s/1pfQwRwg3tbOT2Y2nQZYoAA 提取码: ptj6 (链接失效了可以联系我)

 

 

识别原理

 

以下也都是John Althouse的文章里的+谷歌翻译:

 

1.JA3 不是简单地查看使用的证书,而是解析在 SSL 握手期间发送的 TLS 客户端 hello 数据包中设置的多个字段。然后可以使用生成的指纹来识别、记录、警报和/或阻止特定流量。

2.JA3 在 SSL 握手中查看客户端 hello 数据包以收集 SSL 版本和支持的密码列表。如果客户端支持,它还将使用所有支持的 SSL 扩展、所有支持的椭圆曲线,最后是椭圆曲线点格式。这些字段以逗号分隔,多个值用短划线分隔(例如,每个支持的密码将在它们之间用短划线列出)

 

3. JA3 方法用于收集 Client Hello 数据包中以下字段的字节的十进制值:版本、接受的密码、扩展列表、椭圆曲线和椭圆曲线格式。然后按顺序将这些值连接在一起,使用“,”分隔每个字段,使用“-”分隔每个字段中的每个值

 

其中第一条,也解释了我前一篇请求时尝试提交一个ssl证书为啥没有用的

第二条,服务端会在3次握手之后,收到客户端过来的hello包,然后解包,收集版本、接受的密码、扩展列表、椭圆曲线和椭圆曲线格式,在这时候就可以拿着ja3指纹去比对,哪些是限制了,哪些没有限制的,当确实有在限制名单里,就针对处理,当没有在限制名单里也返回一个hello,接着再继续ssl

 

 

ja3已收录指纹/黑名单

 

 

我猜测,ja3er.com里的十几万ja3指纹,就是所有人访问过该网站的客户端(浏览器或者语言请求库)的指纹,有一条算一条的收集

 

 

案例解释

前面说了一堆理论概念,我们做开发的,如果只有概念没有实操或者例子解释是不够的,所以,来个案例,还是猿人学19题,同时继续祭出wireshark方便分析,先浏览器访问网站,拿到ip,提示一下,你们可别拿着ip去干人网站哈,挺好的一个爬虫练习平台,否则后果自负

 

 

这边wireshark显示:

 

 

 

 

此时你会看到很多的数据数据包,过滤一下,直接在过滤器位置输入ip.,就会有很多指令提示和历史记录

 

全部的命令是啥意思这里就不多说了,更多的可以百度,只介绍几个这里会用到的命令:

 

ip.dst_host就是目标地址,这里你可以理解为就是访问网站的服务端地址

ip.src_host就是源地址,这里你可以理解为就是你正在操作的电脑的ip,这个ip大多是局域网ip

ip.host 跟上面一样,但是不会区分是src还是dst,只要有指定地址的都会过滤出来

 

 

给定过滤指令,回车,此时有可能你输入过滤命令之后,看不到有任何数据包,小问题,可能你打开wireshark完了,没抓到包,重新刷新下网页就行了,此时就看到如下的数据:

 

 

 注意看,最开始的5个数据包就是上面说的流程,前三个是三次握手,第四个开始到第6个就是ja3的hello数据包,个人感觉这段过程也很像三次握手,再后续的数据包就是实质的ssl数据交互了,

 

 

有了这个,看看ja3指纹到底是啥样的,双击这个client hello,然后服务端返回的sever hello就不看了,此时不需要看,忘掉它吧

 

 展开client hello:

 

 

 

 

 

滑倒最后,就能看到ja3指纹了

 

 

然后,看JA3 Fullstring :

771,43690-4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,64250-0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513-51914-21,51914-29-23-24,0

对应:

TLSVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormats

 

以【,】分割,第一个数,771,根据官方解释,就是ssl/tls版本,也就是这个:

 

 python终端跑一下,0x0303就是771,对上了

, 

 

 

 

后续的就不细说了,直接看

 

 

 

 ja3图1

 

 

细心的你发现了,我截图这里是没有第四个数相关的套件, 但是ja自己的文章里是有第四个数EllipticCurves相关的:

 

 

其实不是没有的,是现在第四个参数由EllipticCurves改成了supported_groups

 

ja3图2

注:ja3图1是公司电脑,ja3图2是家里电脑,所以看着ja3字段有点不一样,tls版本也不一样

 

说到版本,纠正下我前一篇给的说明,ja3指纹不是一定在tls1.3上支持的,上面的截图各位朋友应该也看得到,tls1.2也支持的,不过也确实是需要wireshark的最新版才能看到ja3指纹

有关第三个数Extensions扩展列表,感兴趣的可以看看更详细的解释:https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml

所以,实际的案例作为ja3概念解释就到这里了

 

 

如何突破ja3

 

终于到了大家都很感兴趣的环节,怎么破它了

 

python半突破

在上一篇的解决方案里,修改cipher里的加密算法即可,也就是TLSVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormats里的【Ciphers】,

有关ciphers相关套接字的,可以看看openssl的官方解释:https://www.openssl.org/docs/man1.1.1/man1/ciphers.html,并且华为官网的waf介绍里也有不同tls版本对应的套接字:

https://support.huaweicloud.com/bestpractice-waf/waf_06_0012.html

 

 

也就是说,我们要想改,可以直接复制上面的套件覆盖下即可,例如:

 

urllib3.util.ssl_.DEFAULT_CIPHERS = 'EECDH+AESGCMEDH+AESGCM'

 

但是,相信对这个tls有过相关经验的大佬来说,其实在调试requests请求时,调试到这个http/client.py文件库里时,就能看到,在开始connect 时 http版本直接写死成了1.0,还有这个建立连接的tunnel_headers,代码给了个空值

 

 

 

 

 

 

如果你再配上fiddler或者charles抓包看的时候,明显能看到,在python发送实际请求前的CONNECT请求如下:

 

 

而浏览器的这个CONNECT请求是http1.1,且headers是有值的,如下:

 

 

所以,这很明显的差异好吗?是很容易被识别到的

 

而且根据我多方查阅,加上咨询了各位大佬之后,python目前只能改Ciphers里面的算法套件,来生成非默认的ja3指纹,然后可以骗过检测不是太高的反爬机制。

但是其他的Extensions,EllipticCurves,EllipticCurvePointFormats是没法改的,原因是  python跟openssl没有很直接的联系,python发https请求最后还是借助openssl库暴露出来的方法,也就是前面提到的ssl创建context的ssl_create_context),因为openssl库对外提供的方法或者接口是没办法这么高度自定义的,Ciphers部分也最多能改改算法,都不能给个自己定义的算法进去的,而chrome可以访问是因为chrome有自己的ssl,且chrome肯定是不会被禁止的(闹呢,禁止了浏览器正常用户怎么访问?)

也就是可以说这是python自身的缺陷了?所以,我之前测试时不管用requests,httpx,还是aiohttp都不行,因为这三个库底层都借助了openssl库发请求。

假如这种反爬手段满天飞的时候,python层面还没有成型的方案解决怎么办?

 

python的业务方向中引以为傲的爬虫居然有缺陷?而且这个问题非常致命啊,感觉被降维打击了,伤心的是目前还没法改变局面,你说焦虑不焦虑?

 

那有朋友估计会想问,“那为啥之前猿人学19题可以过?” ,那是因为19题检测的不严,只要ja3指纹长度小于等于浏览器的指纹长度都可以过,但其实还有很多特征的可以检测到的,来,看图,还是上次的图,看最后一个数有很大区别的,这个我在上一篇的结尾里也把这个问题抛出来了

 

 

这么明显的特征,如果是一个实际的网站案例,你觉得他会放过你吗?

 

说到这里,有朋友可能不信,口说无凭,这次来个实际的案例,一个大佬给我的,由于他给我的嘱咐,这个接口设计到了很多商业层面的问题,我就不能直接给接口地址了,你们也别问我了,看出来了的朋友也劳烦你不要说出去,自己知道就行了,主要是这个影响有点大,另外此时也没找到一个合适的网站作为案例举证,所以得用一下子

 

浏览器打开(抱歉,我必须马赛克马到位),正常访问是这样的

 

 

 

 

python代码,这里我用之前介绍的简写形式了,只加这两行,其他地方不用改就行的

 

 

 

 

眼尖的朋友应该看到cookies有_abck字段了,别激动,什么axxai的,没听过,不知道哈,我真不知道,而且这里的场景我也没有涉及相关的对抗的哈。

 

运行时发现程序卡住且一直没有响应的状态,测试得知原因是这个网站强制验证了http2.0的问题,requests暂不支持http2被该服务器识别一直不响应结果导致卡住。

 

那换成httpx,(有关httpx详细的代码如何突破ja3的,可以看我之前写的这篇:python爬虫- requests、httpx、aiohttp、scrapy突破ja3指纹识别 里的httpx)

 

发现运行还是不行的。

 

 

怎么改都不成功的,这个就是实际例子说明了,这是python语言层面的问题啊,难道python真的有缺陷?

 

golang 之ja3transport库突破ja3

 

之后在蔡老板朋友圈里,青南大佬评论中说了是可以替换ja3指纹的,我请教青南大佬之后,他给了我一个方案,用golang突破,原文链接:一日一技:Golang 如何突破 JA3?

核心就是,代码里加了第三方库,ja3transport,这个库可以直接伪造ja3,刺不刺激?

 

一执行,一看,就发现真的改变了ja3指纹,惊呆!激动!刺激!兴奋!

 

大概的看了下ja3transport的介绍,它在发起请求的时候,会将请求的client hello数据包里的ja3指纹修改为我们自己的给定的,这样就达到了修改 JA3指纹的目的,妙啊

 

ja3transport简介

 

这个大佬给了一段解释+谷歌翻译:

JA3 的问题在于它仅比基于用户代理字符串的指纹识别客户端好一点。到目前为止,用户代理字符串比 TLS ClientHello 数据包更容易更改。JA3 签名的参数仍由 TLS 客户端控制,因此不能作为可信的信息来源。在 Jeff 和 John 的 ShmooCon 谈话中,他们提到 JA3 不是灵丹妙药他们提出的颠覆 JA3 检测的方法是使用操作系统的 HTTPS 客户端绕过 TLS 客户端特定的 JA3 签名。我们提出了另一种通过制作与其他 TLS 客户端(如浏览器)匹配的 ClientHello 数据包来破坏 JA3 检测的方法

 

 

ja3transport突破原理

官方解释+谷歌翻译:

要想颠覆JA3,需要修改5个JA3参数,可以在Refraction Networking的utls项目ClientHelloSpec提供的struct中修改。该包允许用户构建和执行 ClientHello 握手。第一个参数,TLS 版本,可以用和成员修改。第二个参数,可用密码套件,可以通过更新成员来更改。第三个参数 TLS 扩展可以通过更新成员来更改。参数的一个问题是所有参数都必须遵循 TLSVersionMinTLSVersionMaxCipherSuitesExtensionsExtensionsTLSExtension界面。第四个和第五个参数,椭圆曲线和椭圆曲线点格式,分别是 TLS 扩展SupportedCurvesExtension和 的一部分SupportedPointsExtension


我们不是根据 JA3 字符串创建客户端,而是可以生成与 Web 浏览器等良性签名匹配的 JA3 签名。有一些预设允许 JA3 签名匹配 Chrome 或 Firefox,甚至更多。我们仅限于屏蔽使用 Go 可用的相同扩展的应用程序。例如,如果 Chrome 使用 Go 不支持的扩展程序,我们无法屏蔽它。屏蔽密码套件比较棘手,因为任何密码套件都可以进行广告,即使它没有实现。如果执行握手的服务器接受客户端通告但实际上并不支持的密码套件,则会出现问题。只要服务器接受实际支持的密码套件,虚假宣传比可用密码套件多的密码套件就不是问题

 

Go 的net/http库有一个名为Transport. 传输结构负责编写如何将数据包发送到目标服务器。由于 JA3 的签名是基于 ClientHello 数据包的,我们可以进行 TLS 握手,让 Go 完成剩下的工作。该Transport对象是一个参数http.Client结构其中大部分进入开发人员都很熟悉。通过生成Transport结构体,我们的库应该可以与任何现有的 Go 项目无缝协作

 

浓缩下梗概,意思就是在go构建请求,三次握手之后,到实际要发起client hello包之前,ja3transport把数据包拦截了,然后把原来的ja3指纹修改成了自传递的ja3字段发出client hello,服务端就认了,然后就通过了。

 

太牛逼了,他不是直接修改的tls里的那五个数组套件,因为ja3transport作者自己也说了,要想突破ja3,他认为的方法和选择的方法也是避开了直接改5个JA3参数,而是在5个JA3参数创建好之后进行拦截替换

 

那么也就是说,其实golang跟python比也并没有在语言上占有很大优势,唯一就是golang多了这么一群人提前就研究并写好了这个第三方库,而python没法解决只是还没有人写出能够拦截数据包并替换ja3指纹的库,也就是这个并不是python的缺陷啊。当然,如果你急于求得结果,我建议你还是学一下golang来解决问题。

 

 

更多的解释请看原文:https://medium.com/cu-cyber/impersonating-ja3-fingerprints-b9f555880e42

 

 

ja3transport后续问题

 

作者也说了,如果你随意地伪造ja3,假如服务端通过一些方式得知你客户端访问进程跟实际的ja3不匹配,那应该也会屏蔽你

我们能想到的最简单的检测改进是将 JA3 签名与生成 TLS ClientHello 数据包的进程映像配对。如果有客户端生成与 Firefox 匹配的 JA3 签名,但该进程不是 Firefox,则可能会发生一些奇怪的事情

 

ja3transport缺陷

 

但是,用这个库ja3transport执行的刚才那个案例网站的时候发现报了如下错,提示就是说这个服务器不支持版本304的协议

 

tls: server selected unsupported protocol version 304

 

 

一搜这个报错,就看到有个大佬说是因为不支持http2.0导致的:

 

对啊,这个网站上面它强制http2了,那也就是说,ja3transport不支持http2.0,这就是他的缺陷啊

 

golang之CycleTLS库http2.0+ja3指纹完美突破

 

那只要能解决http2这个问题,是不是就破了这个站呢?再看上面这个大佬发的日期:

 

 

 

7 May,那现在已经过去这么久了,大胆猜测一下,是不是这个大佬已经解决了呢?此时估计有朋友应该回想,“你这个人怎么这么不严谨,什么都靠猜吗?上一篇解决猿人学19题删一大片cipher加密算法解决问题也是猜的”

 

哈哈哈,是啊,因为我个人觉得,爬虫跟前后端开发还是有点区别的,前后端开发,按照我的理解,讲究的逻辑严密,事先考虑各个层面的问题,尽量少bug然后服务能够长期稳定运行,但是爬虫的话,有时候没思路的情况下真的是大胆猜测出来的,我现在的思维已经转向这个方面了,虽然以前也干过后端开发,但是思维已经回不去了。

 

 

我开始尝试了这个库:git地址:https://github.com/Danny-Dasilva/CycleTLS,真的就是抱着试一试的心态,执行,结果真的跟浏览器访问一样的,搞定,牛逼!

 

 

 

 

所以,也就是说,之前用的库github.com/CUCyber/ja3transport,不够适合当下场景 http2+ja3双重验证

 

 

go代码:

 

package main

import (
	"github.com/Danny-Dasilva/CycleTLS/cycletls"
	"log"
)

func main() {

	client := cycletls.Init()

	response, err := client.Do("(保密)", cycletls.Options{
		Body : "",
		Ja3: "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-21,29-23-24,0",
		UserAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.67",
	}, "GET");
	if err != nil {
		log.Print("Request Failed: " + err.Error())
	}
	log.Println(response)
}

  

 

是不是感觉代码量也少很多

 

 

nodejs

 

还是用上面大佬Danny-Dasilva的CycleTLS库即可,他也开发了node的库:https://github.com/Danny-Dasilva/CycleTLS#example-cycletls-request-jsts

 

直接npm install cycletls,然后照着案例的代码来就行了,可能对于大部分爬虫开发来说,node相对golang来说会更熟悉一点的,

const initCycleTLS = require('cycletls');
// Typescript: import initCycleTLS from 'cycletls';

(async () => {
  // Initiate CycleTLS
  const cycleTLS = await initCycleTLS();

  // Send request
  const response = await cycleTLS('https://ja3er.com/json', {
    body: '',
    ja3: '771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-51-57-47-53-10,0-23-65281-10-11-35-16-5-51-43-13-45-28-21,29-23-24-25-256-257,0',
    userAgent: 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0',
    proxy: 'http://username:[email protected]:443'
  }, 'get');

  console.log(response);

  // Cleanly exit CycleTLS
  cycleTLS.exit();

})();

 

验证python指纹

既然已经可以随意改了对吧,那我改成python默认的指纹访问下这个网站看看呢?我下面只改了ja3指纹,看运行结果,果然是被拉黑了,哈哈哈哈

 

 

 

换接口验证

 

为了验证真的成功了,哈哈,该严谨的地方确实得严谨一点,还是用的golang,我换了另一个接口地址执行,确实有结果了。

 

 

用wireshark做最后的验证

 

那边go程序在执行,还是这个被马死的目标,这边wireshark抓包看结果,是的,相信你也看出猫腻了,它居然发了两次client hello包

 

 

 

而之前我们看到的,比如猿人学的那个,实际只会发一次的,这里发两次就很奇怪,然后,这两次发出去的ja3指纹还不一样:

 

 

 

哪里不一样,以逗号作为分割,除了第一个数和最后一个数,其他的字段的开头一个数组都不一样(以【-】作为分割)

 

 

然后,此时此刻,我们先去ja3官网看看浏览器本来的指纹呢?

 

 

chrome访问ja3官网返回得到的:
    771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-21,29-23-24,0

chrome访问目标网站用wireshark抓包得到:

  第一个:
    771,43690-4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,60138-0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513-51914-41,14906-29-23-24,0

  第二个:
    771,10794-4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,14906-0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513-2570-21,60138-29-23-24,0

 

仔细对比之后,也就刚好多了标记的


 

去掉上面标记出来的,其实第一个和第二个是一样的,仅仅是这个被我马赛克马死的平台是这样,我猜应该是这个平台自己多加了一层握手流程,所以会有2个client hello,具体为啥有两个不纠结了,我也不是该平台的开发,也没法得知具体原因,不重要了,能获取数据就行了。

 

不过等等,突然有个疑问?为啥wireshark的ja3指纹,同一个golang脚本啊,就算两个client hello,也应该是两个一样的ja3指纹啊,为了进一步分析,先用浏览器访问ja3后,同时看看wireshark抓包的是啥,这?我该信哪个?怎么wireshark多了点其他的东西

 

 

 

 

这引出了一个新的问题,哪个才是对的

 

ja3到底存在吗? 

 

按理来说,应该信ja3官方,因为这玩意儿就是别人搞出来的,那既然如此,是wireshark在搞事咯?(此时此刻突然想起了学生时代的一个数学逻辑题,假如你是侦探,现在有几个嫌疑人,已知里面有个人说了谎,从几个嫌疑人的供词里找出真凶。。。扯远了)

 

为了进一步确认这个问题,根据青南大佬给文章的方案,可以伪造ja3指纹,那此时此刻,试下吧,现在的逻辑就是,我用一个我已知的指纹去请求ja3,然后看看ja3官方的返回,再看wireshark的ja3指纹对比,如果wireshark里的ja3不全等于我们自定义的ja3,那就确认是wireshark在他喵的搞事了

 

 

首先澄清,没作弊哈,我用的第一个,跟我浏览器里的ja3是不一样的

 

 

 

这里我用的ja3transport库了,因为ja3官网没有强制HTTP2了,运行下面的代码,发现返回的确实改变了的,且值正是我们给定的

 

 

 

再看wireshark这边:

 

 

发现也是自定义的那个值,没有奇怪的数组了

 

 

相信有朋友会问,这就奇怪了,为啥这里又一样了?难道wireshark没有骗我们?啊这。。。,不是吧,忘了吗?ja3transport这个库会在在三次握手后,即将发起client hello数据包时,拦截这个包,然后把自定义的ja3指纹替换原有的啊,这是ja3transport库的原理,所以,这里wireshark能跟我们给定的ja3指纹对应上

 

 

那么,也就是说,wireshark有一套的自己的ja3指纹解析套件解析并显示了,但是这个解析套件跟ja3官网是不一样的,所以显示不一样。当然这是我经过多次分析推理得出来的结论,查了wireshark的文档,暂时没找到相关的介绍和解释,姑且这么理解吧,肯定信ja3官方不能信wireshark啊,毕竟这ja3是别人搞出来的。

 

而且仔细看下面这个图,我鼠标放到ja3上面的时候,下面的进制数据并不会对应显示

 

 

 

用微信好友chao的话,"所有真实的信息都有二进制的数据,而wireshark的ja3都没有对应的二进制数据"

 

所以我跟chao讨论之后,认为ja3其实并不存在(上一次这么醍醐灌顶还是读到《三体》里的那句台词"物理学不存在",不好意思又扯远了。。。),或者说ja3并不是实质性存在的字符,而是通过TLSVersion,Ciphers,Extensions,EllipticCurves,EllipticCurvePointFormats这五个tls组件根据自己的加密算法另类存在的,因为wireshark都能通过自己的解析逻辑解析显示啊。以上推论仅代表个人观点,有误请指正

 

 

需要注意的点

1.有没有发现,其实ja3在2017年就有了,为啥国内到现在这么久了,而之前不是有句话,国内的互联网行情领先国外几十年,因为国内各种安全防护,安全盾之类的确实太前沿,而国外这方面的防护很少,就cloudflare,akamai等的云防护,以及谷歌的行为检测,能数下来的就几个,但是国内相关的安全防御手段就太多了。

在我查阅ja3相关的问题时,发现国外好多开发者在2018,2019年就有人在问怎么修改ja3指纹了,那为啥这个ja3指纹没有大规模用到呢?很奇怪,之前在蔡老板的知识星球里跟某大佬也有过简单的探讨,表示了国内对于的ja3为啥国内没普及的看法,我倒是觉得很可能在明年会有大批普及的,但它确实也有自己的问题,确实会导致访问速度稍微的变慢一点点(对于不用太在意秒级响应的来说其实可以忽略不计),牺牲零点几秒到一两秒的响应时间就能阻挡一大片爬虫,我觉得是值得的,国内开发大佬这么多,肯定可以优化时间这个问题的。

 

2.有了一个ja3,那我觉得后续肯定会出现升级版或者替代版了,红蓝对抗,反爬与反反爬,一直在对抗中进步,是好是坏,只能用时间来判定了。而且其实这个ja3有关的方法和介绍,我完全可以自己搞懂憋着不说,用来作为自己的绝技的,但是我个人是一个乐于分享的人,我觉得一些值得记录的东西就应该记录下来或者公开出来,很多新东西靠自己一个人摸索是没法走到更远的,好比这个ja3,如果一开始没有Lee Brotherston大佬在2015公开讲解,也就不会有这么牛逼的ja3指纹出现了,好东西确实是要留着自己用,不过哪些东西可以分享那些东西可以保留我还是有分寸的。很喜欢微信好友Regionover在一篇文章里的一句话:【故事要留给过去,但成长要用于分享

3.另外,希望国内外能有大神可以仿照这个ja3transport库或者CycleTLS库写一个python的库出来,唉,我自己也想写出来啊,在写这篇文章的时期,我也在看原理,对于在这之前对golang仅限于字面上了解的我来说,真的有点吃力,要写个python库出来,还是需要花很多时间研究的。

 

 

结语

1.这次的解析个人觉得终于算是深入理解ja3了

2.以上都是个人见解,如果有误还望指正,有任何问题,我很乐意跟各位大佬们交流,我微信id:geekbyte

3.最近通过蔡老板的群,认识了很多大佬,学到很多技术,受益匪浅。蔡老板的群大佬太多了,各种大厂的人,多到简直舔不过来,如果你也想进群,可以加蔡老板的星球,没错就是文章开头提到那个有着无处安放的魅力的男人 :

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章