极验验证码是一种常见的防爬虫机制,通过滑动拼图等方式验证用户的人机身份。本文将介绍如何使用Go语言破解极验滑动验证码,模拟验证过程并绕过验证码。
准备工作
首先,确保你已经安装了Go语言开发环境。如果没有,请从Go官方网站下载安装。
分析验证码请求
在破解验证码之前,我们需要分析极验验证码在验证过程中发起的请求。通过观察,可以发现这些请求中的一些关键参数:更多内容联系1436423940
gt 和 challenge:用于标识验证码会话。
w:这是一个加密过的数据,破解的核心就在于解密并伪造这个参数。
获取核心JS文件链接
我们首先获取核心JS文件的链接,以便分析其中的加密逻辑。
go
package main
import (
"fmt"
"net/http"
"regexp"
"io/ioutil"
"log"
)
func getJsLink() (string, error) {
resp, err := http.Get("https://example.com/gettype.php")
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return parseJsLink(string(body)), nil
}
func parseJsLink(body string) string {
re := regexp.MustCompile(`https://.*?\.js`)
match := re.FindString(body)
return match
}
func main() {
jsLink, err := getJsLink()
if err != nil {
log.Fatalf("Failed to get JS link: %v", err)
}
fmt.Println("JS Link:", jsLink)
}
获取无感验证参数
通过请求get.php获取无感验证的参数,包括c和s。
go
package main
import (
"fmt"
"net/http"
"regexp"
"io/ioutil"
"log"
)
func getNoSenseParams() (string, string, error) {
resp, err := http.Get("https://example.com/get.php")
if err != nil {
return "", "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", "", err
}
return parseNoSenseParams(string(body)), nil
}
func parseNoSenseParams(body string) (string, string) {
cRe := regexp.MustCompile(`"c":"(.*?)"`)
sRe := regexp.MustCompile(`"s":"(.*?)"`)
cMatch := cRe.FindStringSubmatch(body)
sMatch := sRe.FindStringSubmatch(body)
c := ""
if len(cMatch) > 1 {
c = cMatch[1]
}
s := ""
if len(sMatch) > 1 {
s = sMatch[1]
}
return c, s
}
func main() {
c, s, err := getNoSenseParams()
if err != nil {
log.Fatalf("Failed to get no-sense params: %v", err)
}
fmt.Printf("c: %s, s: %s\n", c, s)
}
执行无感验证
通过请求ajax.php执行无感验证,如果验证失败,会返回滑块验证等其他类型的验证。
go
package main
import (
"fmt"
"net/http"
"regexp"
"io/ioutil"
"log"
)
func executeNoSenseVerification(c, s string) (string, error) {
url := fmt.Sprintf("https://example.com/ajax.php?c=%s&s=%s", c, s)
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return parseVerificationType(string(body)), nil
}
func parseVerificationType(body string) string {
re := regexp.MustCompile(`"type":"(.*?)"`)
match := re.FindStringSubmatch(body)
if len(match) > 1 {
return match[1]
}
return ""
}
func main() {
c, s, err := getNoSenseParams()
if err != nil {
log.Fatalf("Failed to get no-sense params: %v", err)
}
verificationType, err := executeNoSenseVerification(c, s)
if err != nil {
log.Fatalf("Failed to execute no-sense verification: %v", err)
}
fmt.Println("Verification Type:", verificationType)
}
进行滑动验证
当无感验证失败时,进行滑动验证。通过请求get.php获取滑动验证的基本数据,如bg、fullbg、slice等。
go
package main
import (
"fmt"
"net/http"
"regexp"
"io/ioutil"
"log"
)
func getSlideParams() (map[string]string, error) {
resp, err := http.Get("https://example.com/get.php?slide=true")
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return parseSlideParams(string(body)), nil
}
func parseSlideParams(body string) map[string]string {
re := regexp.MustCompile(`"(\w+)":"(.*?)"`)
matches := re.FindAllStringSubmatch(body, -1)
params := make(map[string]string)
for _, match := range matches {
if len(match) > 2 {
params[match[1]] = match[2]
}
}
return params
}
func main() {
slideParams, err := getSlideParams()
if err != nil {
log.Fatalf("Failed to get slide params: %v", err)
}
for key, value := range slideParams {
fmt.Printf("%s: %s\n", key, value)
}
}
破解w参数
在Go语言中实现w参数的破解过程,包括生成u和h参数。
生成u参数
u参数的生成涉及一个随机数和加密操作。
go
package main
import (
"crypto/rand"
"encoding/hex"
"fmt"
"log"
)
func getU() (string, error) {
bytes := make([]byte, 16)
if _, err := rand.Read(bytes); err != nil {
return "", err
}
return hex.EncodeToString(bytes), nil
}
func main() {
u, err := getU()
if err != nil {
log.Fatalf("Failed to generate U: %v", err)
}
fmt.Println("U:", u)
}
生成h参数
h参数的生成过程复杂一些,需要依赖多个函数。
go
package main
import (
"fmt"
"crypto/sha256"
"encoding/hex"
)
func getH(parameters map[string]string) string {
// 假设生成h参数的逻辑如下
data := parameters["key1"] + parameters["key2"] // 示例拼接
hash := sha256.Sum256([]byte(data))
return hex.EncodeToString(hash[:])
}
func main() {
parameters := map[string]string{
"key1": "value1",
"key2": "value2",
}
h := getH(parameters)
fmt.Println("H:", h)
}
合并u和h参数
最后,将u和h参数合并生成最终的w参数。
go
package main
import (
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"log"
)
func getU() (string, error) {
bytes := make([]byte, 16)
if _, err := rand.Read(bytes); err != nil {
return "", err
}
return hex.EncodeToString(bytes), nil
}
func getH(parameters map[string]string) string {
data := parameters["key1"] + parameters["key2"] // 示例拼接
hash := sha256.Sum256([]byte(data))
return hex.EncodeToString(hash[:])
}
func generateW(parameters map[string]string) (string, error) {
u, err := getU()
if err != nil {
return "", err
}
h := getH(parameters)
return u + h, nil
}
func main() {
parameters := map[string]string{
"key1": "value1",
"key2": "value2",
}
w, err := generateW(parameters)
if err != nil {
log.Fatalf("Failed to generate W: %v", err)
}
fmt.Println("W:", w)
}
发送滑动验证请求
有了w参数后,我们可以构造滑动验证的请求并发送。
go
package main
import (
"fmt"
"net/http"
"regexp"
"io/ioutil"
"log"
)
func executeSlideVerification(w string) (string, error) {
url := fmt.Sprintf("https://example.com/ajax.php?w=%s", w)
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return parseVerificationResult(string(body)), nil
}
func parseVerificationResult(body string) string {
re := regexp.MustCompile(`"result":"(.*?)"`)
match := re.FindStringSubmatch(body)
if len(match) > 1 {
return match[1]
}
return ""
}
func main() {
parameters := map[string]string{
"key1": "value1",
"key2": "value2",
}
w, err := generateW(parameters)
if err != nil {
log.Fatalf("Failed to generate W: %v", err)
}
result, err := executeSlideVerification(w)
if err != nil {
log.Fatalf("Failed to execute slide verification: %v", err)
}
fmt.Println("Verification Result:", result)
}