使用Go语言破解gcaptcha4.js中的w参数加密算法

在本文中,我们将介绍如何使用Go语言来逆向工程gcaptcha4.js文件,找到并破解w参数的加密算法。整个过程包括观察verify请求,定位加密位置,分析加密算法,并最终还原w参数的明文。

一. 观察verify请求
首先,我们需要观察verify请求的发起者。通过网络请求分析工具,我们可以看到所有verify请求都来自于gcaptcha4.js文件。因此,这个文件成为我们分析的重点。

我们使用Go语言的http包来捕获和分析这些请求。

go

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    resp, err := http.Get("https://example.com/verify")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(string(body))
}
通过分析响应内容,可以发现所有的verify请求都指向了gcaptcha4.js文件。

二. 定位w参数加密位置
为了找到w参数的加密位置,我们需要解析gcaptcha4.js文件。我们可以下载并格式化这个文件,然后使用正则表达式搜索关键词:w、.w、'w'或"w"。

go

package main

import (
    "fmt"
    "io/ioutil"
    "regexp"
)

func main() {
    data, err := ioutil.ReadFile("gcaptcha4.js")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    re := regexp.MustCompile(`[.\'"]w[.\'"]`)
    matches := re.FindAllString(string(data), -1)
    fmt.Println(matches)
}
通过搜索"w",我们找到了相关代码。在第2527行,我们发现了w的值r在第2525行被定义。

三. 分析w参数加密算法
接下来,我们需要简化代码中w的定义。假设我们已经提取了相关的JavaScript代码,我们可以使用Go语言来模拟这个过程。

go

package main

import (
    "crypto/md5"
    "encoding/hex"
    "encoding/json"
    "fmt"
)

func stringify(data interface{}) string {
    jsonData, err := json.Marshal(data)
    if err != nil {
        fmt.Println("Error:", err)
    }
    return string(jsonData)
}

func defaultEncrypt(data, key string) string {
    hash := md5.New()
    hash.Write([]byte(data + key))
    return hex.EncodeToString(hash.Sum(nil))
}

// 示例数据
type Data struct {
    DeviceID string                 `json:"device_id"`
    Em       map[string]int         `json:"em"`
    Ep       string                 `json:"ep"`
    Geetest  string                 `json:"geetest"`
    Fq6a     string                 `json:"fq6a"`
    Lang     string                 `json:"lang"`
    LotNum   string                 `json:"lot_number"`
    Passtime int                    `json:"passtime"`
    PowMsg   string                 `json:"pow_msg"`
    PowSign  string                 `json:"pow_sign"`
    SetLeft  int                    `json:"setLeft"`
    Track    [][]int                `json:"track"`
    UserResp float64                `json:"userresponse"`
}

func main() {
    e := Data{
        DeviceID: "A8A0",
        Em: map[string]int{
            "cp": 0,
            "ek": 11,
            "nt": 0,
            "ph": 0,
            "sc": 0,
            "si": 0,
            "wd": 1,
        },
        Ep:       "123",
        Geetest:  "captcha",
        Fq6a:     "1925502591",
        Lang:     "zh",
        LotNum:   "7e22264d4f3e4dd8a6ffbf6e82e1122d",
        Passtime: 166,
        PowMsg:   "1|0|md5|2022-03-25T14:23:36.364152+08:00|24f56dc13c40dc4a02fd0318567caef5|7e22264d4f3e4dd8a6ffbf6e82e1122d||29f07cebf938aa4e",
        PowSign:  "2b47a3a9425dd19dd5abf902c8bb0763",
        SetLeft:  88,
        Track:    [][]int{{38, 18, 0}, {1, 0, 33}},
        UserResp: 87.47978686742837,
    }

    a := "your_key"
    r := defaultEncrypt(stringify(e), a)
    fmt.Println(r)
}
4.1 分析pow_msg和pow_sign
通过搜索pow_msg,我们找到相关代码并解析如下:

go

package main

import (
    "crypto/md5"
    "encoding/hex"
    "fmt"
    "math/rand"
    "time"
)

func generateGuid() string {
    rand.Seed(time.Now().UnixNano())
    guid := fmt.Sprintf("%x%x%x%x", rand.Int31(), rand.Int31(), rand.Int31(), rand.Int31())
    return guid
}

func md5Hash(input string) string {
    hash := md5.New()
    hash.Write([]byte(input))
    return hex.EncodeToString(hash.Sum(nil))
}

func main() {
    n := "example_n"
    a := "example_a"
    s := "example_s"
    o := "example_o"
    t := "example_t"
    e := "example_e"
    r := "example_r"

    u := fmt.Sprintf("%s|%s|%s|%s|%s|%s|%s|", n, a, s, o, t, e, r)
    p := generateGuid()
    g := u + p
    powMsg := u + p
    powSign := md5Hash(g)

    fmt.Println("pow_msg:", powMsg)
    fmt.Println("pow_sign:", powSign)
}
4.2 分析set_left、track、passtime、userresponse
set_left:滑块移动距离的整数值
track:移动轨迹,从第二步开始,是相对上一步的相对移动距离(x, y, t)
passtime:总移动时间
userresponse:计算公式为set_left / (0.8876 * 340 / 300)
go

package main

import (
    "fmt"
)

func main() {
    setLeft := 88
    track := [][]int{{38, 18, 0}, {1, 0, 33}}
    passtime := 166
    userResponse := float64(setLeft) / (0.8876 * 340 / 300)

    fmt.Println("set_left:", setLeft)
    fmt.Println("track:", track)
    fmt.Println("passtime:", passtime)
    fmt.Println("userresponse:", userResponse)
}
至此,我们已经完成了w参数的明文解析。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值