深入解析数美滑块验证码破解:从抓包到实现(Go语言版)


数美滑块验证码是一种常见的安全验证方式,用于防止自动化脚本和机器人进行恶意操作。本文将详细介绍如何通过抓包获取滑块图片信息、分析加密参数、生成滑动轨迹等步骤,成功破解数美滑块验证码。以下是我们要实现的主要步骤:

抓取滑块图片信息并计算滑动距离
分析加密参数
生成滑动轨迹并进行DES加密
验证破解结果
1. 抓取滑块图片信息并计算滑动距离更多内容联系1436423940
首先,进入数美滑块验证码的演示页面,进行抓包操作以获取滑块验证码的前景和背景图片。我们通过net/http从网站获取图片:

go

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "image"
    "image/jpeg"
    "image/png"
    "io/ioutil"
    "net/http"
    "os"
    "strings"

    "gocv.io/x/gocv"
)

type ImageURLs struct {
    Fg string `json:"fg"`
    Bg string `json:"bg"`
}

func downloadImage(url string) (image.Image, error) {
    response, err := http.Get(url)
    if err != nil {
        return nil, err
    }
    defer response.Body.Close()

    img, _, err := image.Decode(response.Body)
    if err != nil {
        return nil, err
    }

    return img, nil
}

func getImages(registerURL string) (image.Image, image.Image, error) {
    resp, err := http.Post(registerURL, "application/json", strings.NewReader("{}"))
    if err != nil {
        return nil, nil, err
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, nil, err
    }

    var urls ImageURLs
    err = json.Unmarshal(body, &urls)
    if err != nil {
        return nil, nil, err
    }

    fgImg, err := downloadImage(urls.Fg)
    if err != nil {
        return nil, nil, err
    }

    bgImg, err := downloadImage(urls.Bg)
    if err != nil {
        return nil, nil, err
    }

    return fgImg, bgImg, nil
}

func getDistance(fgImage, bgImage image.Image) int {
    fgBuffer := new(bytes.Buffer)
    png.Encode(fgBuffer, fgImage)

    bgBuffer := new(bytes.Buffer)
    jpeg.Encode(bgBuffer, bgImage, nil)

    fgMat, _ := gocv.IMDecode(fgBuffer.Bytes(), gocv.IMReadColor)
    bgMat, _ := gocv.IMDecode(bgBuffer.Bytes(), gocv.IMReadColor)

    result := gocv.NewMat()
    gocv.MatchTemplate(fgMat, bgMat, &result, gocv.TmCCoeffNormed, gocv.NewMat())

    _, _, _, maxLoc := gocv.MinMaxLoc(result)
    return maxLoc.X
}

func main() {
    registerURL := "https://www.ishumei.com/trial/captcha.html"
    fgImage, bgImage, err := getImages(registerURL)
    if err != nil {
        fmt.Println("Error fetching images:", err)
        return
    }

    distance := getDistance(fgImage, bgImage)
    fmt.Println("Calculated distance:", distance)
}
2. 分析加密参数
在滑动滑块的过程中,我们需要分析加密参数。抓包查看请求信息,可以看到有一个fverify的验证信息。如果正确的话,riskLevel返回值为PASS,失败为REJECT。

通过在浏览器中设置断点,我们可以找到参数aw等的生成函数,并确定这些参数的加密方式。使用断点调试后,发现是通过DES加密。

以下是通过crypto/des库实现DES加密的示例代码:

go

package main

import (
    "bytes"
    "crypto/cipher"
    "crypto/des"
    "encoding/base64"
    "fmt"
)

func pad(data []byte, blockSize int) []byte {
    paddingSize := blockSize - (len(data) % blockSize)
    padding := bytes.Repeat([]byte{0}, paddingSize)
    return append(data, padding...)
}

func encryptContent(message, key string, flag bool) (string, error) {
    block, err := des.NewCipher([]byte(key))
    if err != nil {
        return "", err
    }

    plainText := []byte(strings.ReplaceAll(message, " ", ""))
    plainText = pad(plainText, block.BlockSize())

    var result []byte
    if flag {
        result = make([]byte, len(plainText))
        mode := cipher.NewECBEncrypter(block)
        mode.CryptBlocks(result, plainText)
    } else {
        result = make([]byte, len(plainText))
        mode := cipher.NewECBDecrypter(block)
        mode.CryptBlocks(result, plainText)
    }

    return base64.StdEncoding.EncodeToString(result), nil
}

func main() {
    message := "Hello, World!"
    key := "your_key_here"
    flag := true

    encryptedMessage, err := encryptContent(message, key, flag)
    if err != nil {
        fmt.Println("Error encrypting message:", err)
        return
    }

    fmt.Println("Encrypted message:", encryptedMessage)
}
3. 生成滑动轨迹并进行DES加密
滑动轨迹可以通过模拟人的滑动行为来生成,包括一些随机的抖动和速度变化。以下是生成滑动轨迹的示例代码:

go

package main

import (
    "encoding/json"
    "fmt"
    "math/rand"
    "time"
)

func getRandom(distance int) ([][3]int, error) {
    rand.Seed(time.Now().UnixNano())
    track := [][3]int{{0, 0, 0}}

    for i := 0; i < 10; i++ {
        x := 0
        y := rand.Intn(3) - 1
        t := 100*(i+1) + rand.Intn(3)
        track = append(track, [3]int{x, y, t})
    }

    for i := 1; i < len(track)-5; i++ {
        track[i][0] = distance / 2
    }

    for i := len(track) - 5; i < len(track)-1; i++ {
        track[i][0] = distance + rand.Intn(4)
    }

    track[len(track)-1][0] = distance

    trackJSON, err := json.Marshal(track)
    if err != nil {
        return nil, err
    }

    fmt.Println("Slide track:", string(trackJSON))
    return track, nil
}

func main() {
    distance := 100 // 假设滑动距离为100
    track, err := getRandom(distance)
    if err != nil {
        fmt.Println("Error generating track:", err)
        return
    }

    fmt.Println("Generated slide track:", track)
}
4. 验证破解结果
最后,结合前面的步骤,实现滑块破解。以下是完整的示例代码:

go

package main

import (
    "bytes"
    "crypto/cipher"
    "crypto/des"
    "encoding/base64"
    "encoding/json"
    "fmt"
    "image"
    "image/jpeg"
    "image/png"
    "io/ioutil"
    "net/http"
    "strings"

    "gocv.io/x/gocv"
)

type ImageURLs struct {
    Fg string `json:"fg"`
    Bg string `json:"bg"`
}

func downloadImage(url string) (image.Image, error) {
    response, err := http.Get(url)
    if err != nil {
        return nil, err
    }
    defer response.Body.Close()

    img, _, err := image.Decode(response.Body)
    if err != nil {
        return nil, err
    }

    return img, nil
}

func getImages(registerURL string) (image.Image, image.Image, error) {
    resp, err := http.Post(registerURL, "application/json", strings.NewReader("{}"))
    if err != nil {
        return nil, nil, err
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, nil, err
    }

    var urls ImageURLs
    err = json.Unmarshal(body, &urls)
    if err != nil {
        return nil, nil, err
    }

    fgImg, err := downloadImage(urls.Fg)
    if err != nil {
        return nil, nil, err
    }

    bgImg, err := downloadImage(urls.Bg)
    if err != nil {
        return nil, nil, err
    }

    return fgImg, bgImg, nil
}

func getDistance(fgImage, bgImage image.Image) int {
    fgBuffer := new(bytes.Buffer)
    png.Encode(fgBuffer, fgImage)

    bgBuffer := new(bytes.Buffer)
    jpeg.Encode(bgBuffer, bgImage, nil)

    fgMat, _ := gocv.IMDecode(fgBuffer.Bytes(), gocv.IMReadColor)
    bgMat, _ := gocv.IMDecode(bgBuffer.Bytes(), gocv.IMReadColor)

    result := gocv.NewMat()
    gocv.MatchTemplate(fgMat, bgMat, &result, gocv.TmCCoeffNormed, gocv.NewMat())

    _, _, _, maxLoc := gocv.MinMaxLoc(result)
    return maxLoc.X
}

func pad(data []byte, blockSize int) []byte {
    paddingSize := blockSize - (len(data) % blockSize)
    padding := bytes.Repeat([]byte{0}, paddingSize)
    return append(data, padding...)
}

func encryptContent(message, key string, flag bool) (string, error) {
    block, err := des.NewCipher([]byte(key))
    if err != nil {
        return "", err
    }

    plainText := []byte(strings.ReplaceAll(message, " ", ""))
    plainText = pad(plainText, block.BlockSize())

    var result []byte
    if flag {
        result = make([]byte, len(plainText))
        mode := cipher.NewECBEncrypter(block)
        mode.CryptBlocks(result, plainText)
    } else {
        result = make([]byte, len(plainText))
        mode := cipher.NewECBDecrypter(block)
        mode.CryptBlocks(result, plainText)
    }

    return base64.StdEncoding.EncodeToString(result), nil
}

func getRandom(distance int) ([][3]int, error) {
    track := [][3]int{{0, 0, 0}}

    for i := 0; i < 10; i++ {
        x := 0
        y := rand.Intn(3) - 1
        t := 100*(i+1) + rand.Intn(3)
        track = append(track, [3]int{x, y, t})
    }

    for i := 1; i < len(track)-5; i++ {
        track[i][0] = distance / 2
    }

    for i := len(track) - 5; i < len(track)-1; i++ {
        track[i][0] = distance + rand.Intn(4)
    }

    track[len(track)-1][0] = distance

    trackJSON, err := json.Marshal(track)
    if err != nil {
        return nil, err
    }

    fmt.Println("Slide track:", string(trackJSON))
    return track, nil
}

func main() {
    registerURL := "https://www.ishumei.com/trial/captcha.html"
    fgImage, bgImage, err := getImages(registerURL)
    if err != nil {
        fmt.Println("Error fetching images:", err)
        return
    }

    distance := getDistance(fgImage, bgImage)
    fmt.Println("Calculated distance:", distance)

    track, err := getRandom(distance)
    if err != nil {
        fmt.Println("Error generating track:", err)
        return
    }

    nm, err := json.Marshal(track)
    if err != nil {
        fmt.Println("Error marshalling track:", err)
        return
    }

    dy := track[len(track)-1][2]

    key := "your_key_here"
    flag := true

    encryptedNM, err := encryptContent(string(nm), key, flag)
    if err != nil {
        fmt.Println("Error encrypting nm:", err)
        return
    }

    encryptedDY, err := encryptContent(fmt.Sprint(dy), key, flag)
    if err != nil {
        fmt.Println("Error encrypting dy:", err)
        return
    }

    verifyData := map[string]string{
        "nm": encryptedNM,
        "dy": encryptedDY,
        "rid": "register_id_here",
        "dl": fmt.Sprint(distance),
    }

    verifyDataJSON, err := json.Marshal(verifyData)
    if err != nil {
        fmt.Println("Error marshalling verify data:", err)
        return
    }

    resp, err := http.Post("https://www.ishumei.com/trial/fverify", "application/json", bytes.NewBuffer(verifyDataJSON))
    if err != nil {
        fmt.Println("Error verifying:", err)
        return
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error reading response:", err)
        return
    }

    var result map[string]string
    err = json.Unmarshal(body, &result)
    if err != nil {
        fmt.Println("Error unmarshalling response:", err)
        return
    }

    if result["riskLevel"] == "PASS" {
        fmt.Println("验证成功")
    } else {
        fmt.Println("验证失败")
    }
}

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要解决Lua语言中的滑块验证码问题,可以参考以下几个方案: 1. 分析滑块验证码的页面结构和逻辑:首先,通过分析滑块验证码的HTML页面和相关的JavaScript代码,了解验证码的验证机制,找到相关的接口和算法。 2. 使用模拟鼠标操作:在Lua中,可以使用相关的库或者框架来模拟鼠标的移动和点击操作。通过计算验证码滑块与背景图的偏移量,模拟鼠标移动到正确位置,并且模拟点击滑块实现滑动。 3. 验证滑块位置的准确性:在滑块移动后,通常需要验证滑块的位置是否正确。可以将滑块的位置信息和验证结果发送到后台服务器进行验证,得到验证结果后再进行相关的操作。 4. 使用图像识别技术:如果滑块验证码的算法或者验证机制较为复杂,可以使用图像识别技术来解决。通过对验证码图片进行分析和处理,识别滑块位置和相关参数,然后模拟鼠标操作实现滑块的验证。 5. 考虑反爬虫机制:为了防止机器人或者爬虫程序的自动化操作,在滑块验证码中可能还存在一些反爬虫的机制。需要分析验证码的验证请求和返回结果,根据结果进行相应的处理,例如设置适当的等待时间、添加随机的操作等。 总之,解决Lua语言中的滑块验证码问题需要结合相关的网络和图像处理技术,通过分析验证码的页面结构和逻辑,模拟鼠标操作或者使用图像识别技术来实现验证码的自动验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值