一日一技:Golang 如何突破 JA3?

攝影:產品經理 

小菜上桌

在之前的文章裏面,我們講到了網站通過 JA3 算法,利用一些指紋信息來識別你的請求,無論你是否使用了代理 IP,網站都能識別到你。

今天我們首先講講在 Golang 下面,如何修改這個指紋。

我們先來寫一段代碼,觀察在使用了代理以後, Golang 的 JA3 指紋依然不變:

package main

import (
 "crypto/tls"
 "fmt"
 "io/ioutil"
 "net/http"
 "net/url"
 "time"
)

func req() {
 proxyUrl, err := url.Parse("http://隧道代理IP:PORT")
 client := &http.Client{
  Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl),
   TLSClientConfig: &tls.Config{InsecureSkipVerify: false}},
 }
 resp, err := client.Get("https://httpbin.org/ip")
 if err != nil {
  fmt.Println(err)
 }

 defer resp.Body.Close()
 content, err := ioutil.ReadAll(resp.Body)
 if err != nil {
  fmt.Println(err)
 }
 fmt.Println(string(content))
}

func main() {
 for i := 0; i < 10; i++ {
  req()
  time.Sleep(time.Second)
 }
}

運行效果如下圖所示:

但是,當我要訪問 JA3 測試頁面的時候,發現返回的簽名字符串始終是一樣的:

爲了解決這個問題,我們可以使用一個第三方的包,叫做: ja3transport[1] 。

這個包的使用方法如下面代碼所示:

package main

import (
 "fmt"
 "github.com/CUCyber/ja3transport"
 tls "github.com/refraction-networking/utls"
 "io/ioutil"
 "net/http"
)


type Browser struct {
 Ja3 string
 UserAgent string
}


func req(browser Browser) {
 config := tls.Config{
  InsecureSkipVerify: true,

 }
 tr, _ := ja3transport.NewTransportWithConfig(browser.Ja3, &config)

 client := &http.Client{
  Transport: tr,
 }
 req, _ := http.NewRequest("GET""https://ja3er.com/json", nil)
 req.Header.Set("User-Agent", browser.UserAgent)
 resp, err := client.Do(req)
 if err != nil {
  fmt.Println(err)
 }

 defer resp.Body.Close()
 content, err := ioutil.ReadAll(resp.Body)
 if err != nil {
  fmt.Println(err)
 }
 fmt.Println(string(content))
}

func main() {
 ja3List := []Browser{
  {Ja3: "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53-10,0-23-65281-10-11-35-16-5-13-18-51-45-43-27,29-23-24,0",UserAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15"},
  {Ja3: "771,4865-4866-4867-49196-49195-52393-49200-49199-52392-49188-49187-49162-49161-49192-49191-49172-49171-157-156-61-60-53-47-49160-49170-10,0-23-65281-10-11-16-5-13-18-51-45-43-21,29-23-24-25,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"},
  {Ja3: "771,4865-4866-4867-49196-49195-49188-49187-49162-49161-52393-49200-49199-49192-49191-49172-49171-52392-157-156-61-60-53-47-49160-49170-10,65281-0-23-13-5-18-16-11-51-45-43-10-21,29-23-24-25,0", UserAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Mobile/15E148 Safari/604.1"},
 }
 for _, ja3 := range ja3List{
  req(ja3)
 }
}

運行效果如下圖所示:

這段代碼的關鍵是:tr, _ := ja3transport.NewTransportWithConfig(browser.Ja3, &config),這一行代碼,把我們自定義的 JA3 指紋字符串傳入進去,這個庫在發起請求的時候,修改請求的數據包,用我們自定義的指紋字符串替換原來的默認字符串,從而實現修改 JA3 指紋的目的。大家關注上面圖中我標記的 3 個ja3_hash。他們不同了,說明修改 JA3 指紋成功。

JA3 有自己的生成規則,所以並不能隨便亂改。但確實裏面有一些地方也可以改。大家可以用測試網站進行測試,看改了以後能不能正確返回不同的 ja3_hash。如果能返回,說明改對了。如果報錯了,說明改錯了。

當然,最簡單的方法是收集儘可能多的不同類別不同型號的瀏覽器指紋和對應的 User-Agent,然後隨機選擇一對,輪換使用,這樣就可以有效規避網站對 JA3 字符串頻率的檢查。

關於今天用到的ja3transport,如果大家有興趣可以去看作者寫的文章,介紹了這個包的工作原理: Impersonating JA3 Fingerprints.[2] 。

好了,今天使用 Golang 突破 JA3 的方法就介紹到這裏。請大家期待後面使用 Python 突破 JA3 的方法。

參考文獻

[1]

ja3transport: https://github.com/CUCyber/ja3transport

[2]

Impersonating JA3 Fingerprints.: https://medium.com/cu-cyber/impersonating-ja3-fingerprints-b9f555880e42

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/cX7-kHuIWebDH6r6UQ2I4w