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

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

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

我们使用Scala的akka-http库来捕获和分析这些请求。

scala

import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import scala.concurrent.Future
import scala.util.{Failure, Success}
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import scala.concurrent.ExecutionContext.Implicits.global

object VerifyRequestObserver extends App {
  implicit val system = ActorSystem()
  implicit val materializer = ActorMaterializer()

  val url = "https://example.com/verify"
  val request = HttpRequest(uri = url)

  val responseFuture: Future[HttpResponse] = Http().singleRequest(request)

  responseFuture.onComplete {
    case Success(response) => response.entity.toStrict(10000).onComplete {
      case Success(entity) => println(entity.data.utf8String)
      case Failure(e) => println(s"Error: ${e.getMessage}")
    }
    case Failure(e) => println(s"Error: ${e.getMessage}")
  }
}
通过分析响应内容,可以发现所有的verify请求都指向了gcaptcha4.js文件。

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

scala

import scala.io.Source
import scala.util.matching.Regex

object WParameterLocator extends App {
  val filePath = "gcaptcha4.js"
  val pattern: Regex = """[.'"]w[.'"]""".r

  val fileContents = Source.fromFile(filePath).getLines.mkString("\n")
  pattern.findAllIn(fileContents).foreach(println)
}
通过搜索"w",我们找到了相关代码。在第2527行,我们发现了w的值r在第2525行被定义。

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

scala

import java.security.MessageDigest
import scala.util.parsing.json._

val e = Map(
  "device_id" -> "A8A0",
  "em" -> Map(
    "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" -> List(List(38, 18, 0), List(1, 0, 33)),
  "userresponse" -> 87.47978686742837
)

val a = "your_key"
val jsonString = JSON.toJSONString(e)
val r = MessageDigest.getInstance("MD5").digest((jsonString + a).getBytes).map("%02x".format(_)).mkString

println(r)
4.1 分析pow_msg和pow_sign
通过搜索pow_msg,我们找到相关代码并解析如下:

scala

import scala.util.Random

val n = "example_n"
val a = "example_a"
val s = "example_s"
val o = "example_o"
val t = "example_t"
val e = "example_e"
val r = "example_r"

val u = s"$n|$a|$s|$o|$t|$e|$r|"
val p = Random.alphanumeric.take(32).mkString
val g = u + p
val pow_msg = g
val pow_sign = MessageDigest.getInstance("MD5").digest(g.getBytes).map("%02x".format(_)).mkString

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

val setLeft = 88
val track = List(List(38, 18, 0), List(1, 0, 33))
val passtime = 166
val userresponse = setLeft / (0.8876 * 340 / 300)

println(s"set_left: $setLeft")
println(s"track: $track")
println(s"passtime: $passtime")
println(s"userresponse: $userresponse")
至此,我们已经完成了w参数的明文解析。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值