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

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

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

我们使用Swift的URLSession来捕获和分析这些请求。

swift

import Foundation

let url = URL(string: "https://example.com/verify")!

let task = URLSession.shared.dataTask(with: url) { data, response, error in
    if let error = error {
        print("Error:", error)
        return
    }
    guard let data = data else { return }
    print(String(data: data, encoding: .utf8)!)
}

task.resume()
通过分析响应内容,可以发现所有的verify请求都指向了gcaptcha4.js文件。

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

swift

import Foundation

let path = "gcaptcha4.js"
let content = try String(contentsOfFile: path, encoding: .utf8)

let regex = try NSRegularExpression(pattern: "[.\\'\"]w[.\\'\"]", options: [])
let matches = regex.matches(in: content, options: [], range: NSRange(location: 0, length: content.count))

for match in matches {
    print((content as NSString).substring(with: match.range))
}
通过搜索"w",我们找到了相关代码。在第2527行,我们发现了w的值r在第2525行被定义。

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

swift

import Foundation
import CommonCrypto

func stringify(_ data: Any) -> String {
    let jsonData = try! JSONSerialization.data(withJSONObject: data, options: [])
    return String(data: jsonData, encoding: .utf8)!
}

func md5(_ string: String) -> String {
    let length = Int(CC_MD5_DIGEST_LENGTH)
    var digest = [UInt8](repeating: 0, count: length)
    if let data = string.data(using: String.Encoding.utf8) {
        _ = data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
            CC_MD5(body.baseAddress, CC_LONG(data.count), &digest)
        }
    }
    return digest.map { String(format: "%02x", $0) }.joined()
}

func defaultEncrypt(data: String, key: String) -> String {
    return md5(data + key)
}

// 示例数据
let e: [String: Any] = [
    "device_id": "A8A0",
    "em": [
        "cp": 0,
        "ek": 11,
        "nt": 0,
        "ph": 0,
        "sc": 0,
        "si": 0,
        "wd": 1
    ],
    "ep": "123",
    "geetest": "captcha",
    "fq6a": "1925502591",
    "lang": "zh",
    "lot_number": "7e22264d4f3e4dd8a6ffbf6e82e1122d",
    "passtime": 166,
    "pow_msg": "1|0|md5|2022-03-25T14:23:36.364152+08:00|24f56dc13c40dc4a02fd0318567caef5|7e22264d4f3e4dd8a6ffbf6e82e1122d||29f07cebf938aa4e",
    "pow_sign": "2b47a3a9425dd19dd5abf902c8bb0763",
    "setLeft": 88,
    "track": [[38, 18, 0], [1, 0, 33]],
    "userresponse": 87.47978686742837
]

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

swift

import Foundation
import CommonCrypto

func generateGuid() -> String {
    var result = ""
    for _ in 0..<4 {
        let part = String(format: "%04x", arc4random_uniform(65536))
        result += part
    }
    return result
}

func md5Hash(_ input: String) -> String {
    let length = Int(CC_MD5_DIGEST_LENGTH)
    var digest = [UInt8](repeating: 0, count: length)
    if let data = input.data(using: String.Encoding.utf8) {
        _ = data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
            CC_MD5(body.baseAddress, CC_LONG(data.count), &digest)
        }
    }
    return digest.map { String(format: "%02x", $0) }.joined()
}

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

    let u = "\(n)|\(a)|\(s)|\(o)|\(t)|\(e)|\(r)|"
    let p = generateGuid()
    let g = u + p
    let powMsg = u + p
    let powSign = md5Hash(g)

    print("pow_msg:", powMsg)
    print("pow_sign:", powSign)
}

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

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

    print("set_left:", setLeft)
    print("track:", track)
    print("passtime:", passtime)
    print("userresponse:", userResponse)
}

main()

更多内容联系1436423940

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值