验深知 V2 业务风控逆向分析
字数 1352 2025-08-11 08:36:24

某验深知V2业务风控逆向分析教学文档

一、目标概述

逆向分析某验深知V2业务风控系统,主要目标是理解其验证流程并实现自动化请求。深知V2通过无感采集客户端数据,对用户环境、标识和行为操作进行智能化分析,识别潜在风险用户。

二、完整通讯流程

  1. 访问首页,引入v2.sense.js并提取其中的id
  2. 发起gettype请求,获取动态变化的gct.xxx.js资源路径
  3. 自动发起judge请求,生成并发送加密的Request Payload
  4. 获取session_id后请求业务接口verify-dk-v2

三、关键请求分析

1. gettype请求

  • 返回包含gct.xxx.js路径的JSON
  • gct.xxx.js会生成动态键值对(如{'xnbw': '1158444372'}
  • 该JS名称和内容会定期变化,导致键值对变化

2. judge请求

  • Query String Parameters中包含app_id(即首页获取的id
  • Request Payload为一长串加密字符串
  • 成功验证后返回session_id

四、逆向核心参数

Request Payload由以下代码生成:

var h = o[AUJ_(1156)]();
e = CoUE[ymDv(24)](NFeB);
l = EbF_[ymDv(409)](e, h[ymDv(1194)]);
e = DWYi[ymDv(1137)](l);

1. 获取h值

h值由方法生成一个包含aeskeyrsa的对象:

{
    "aeskey": RwyT(),  // 16位随机值
    "rsa": BPqG(RwyT())  // RSA加密后的结果
}

RSA加密算法需要完整扣取BPqG()方法。

2. 获取e值

e值是对NFeB对象的处理结果,NFeB结构如下:

NFeB = {
    "id": a["id"],
    "page_id": a["page_id"],  // 时间戳
    "lang": a["lang"] || "zh-cn",
    "data": {
        "insights": u || null,  // 浏览器环境信息
        "track_key": c["value"] ? c["key"] : null,
        "track": c["value"] || null,
        "ep": o["KZrg"]("client"),  // 处理后的客户端信息
        "eco": window["GEERANDOMTOKEN"]
    }
}

关键子参数:

insights(u值):

  • 由浏览器环境值以"!!"连接生成
  • 包含屏幕高宽、canvas、UA、插件、时间、时区、语言等

ep值:

  • 传入字符串"client"处理得到
  • 关键部分为window.performance.timing的值,需伪造时间戳

eco值(window.GEERANDOMTOKEN):

  • 可通过Hook获取生成逻辑:
(function() {
    var token = "";
    Object.defineProperty(window, 'GEERANDOMTOKEN', {
        set: function(val) {
            console.log('GEERANDOMTOKEN->', val);
            debugger;
            token = val;
            return val;
        },
        get: function() {
            return token;
        }
    });
})();

生成方法:

  1. 生成32位随机字符串
  2. 加上时间戳
  3. 进行MD5加密

实现代码:

var MD5 = require("md5")
function getToken(){
    var t = MD5(function(e) {
        for (var t = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"], n = "", r = 0; r < e; r++) n += t[parseInt(61 * Math.random(), 10)];
        return n;
    }(32) + new Date().getTime());
    return t;
}

动态键值对(r值):

  • 通过gct.xxx.js生成,如{"xnbw":"1158444372"}
  • 需要动态获取最新JS文件并提取键值对

动态获取示例:

import re
import time
import json
import execjs
import requests

def get_gct():
    url = "https://dkapi.脱敏处理.com/deepknow/v2/gettype"
    params = {
        "callback": "脱敏处理_" + str(int(time.time() * 1000))
    }
    response = requests.get(url, headers=headers, params=params).text
    response = json.loads(re.findall(r"geetest_\d+$(.+)$", response)[0])
    
    # 获取gct.xxx.js地址
    gct_path = "https://static.脱敏处理.com" + response["gct_path"]
    gct_js = requests.get(gct_path, headers=headers).text
    
    # 提取方法名并全局导出
    function_name = re.findall(r"\)\)\{return (.+?)$t$", gct_js)[0]
    break_position = gct_js.find("return function(t){")
    gct_js_new = gct_js[:break_position] + "window.gct=" + function_name + ";" + gct_js[break_position:]
    
    # 添加调用代码
    gct_js_new = "window = global;" + gct_js_new + """
    function getGct(){
        var e = {"lang": "zh", "ep": "test data"};
        window.gct(e);
        delete e["lang"];
        delete e["ep"];
        return e;
    }"""
    
    gct = execjs.compile(gct_js_new).call("getGct")
    return gct

3. 获取l值

使用AES加密算法,以h["aeskey"]为key,e值为待加密字符串:

var CryptoJS = require("crypto-js")
function aesEncrypt(e, i) {
    var key = CryptoJS.enc.Utf8.parse(i),
        iv = CryptoJS.enc.Utf8.parse("0000000000000000"),
        srcs = CryptoJS.enc.Utf8.parse(e),
        encrypted = CryptoJS.AES.encrypt(srcs, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
    
    for (var r = encrypted, o = r.ciphertext.words, i = r.ciphertext.sigBytes, s = [], a = 0; a < i; a++) {
        var c = o[a >>> 2] >>> 24 - a % 4 * 8 & 255;
        s.push(c);
    }
    return s;
}

4. 最终处理

l值经过tc_t方法处理,返回e["res"] + e["end"]格式的结果。注意该方法与某验其他产品中的实现可能有差异,需确保使用正确的常量值。

五、完整流程总结

  1. 获取首页idgct.xxx.js路径
  2. 动态获取并执行gct.xxx.js,提取键值对
  3. 生成GEERANDOMTOKEN
  4. 构建NFeB对象
  5. 生成h值(包含aeskey和rsa)
  6. 将NFeB转为字符串并进行AES加密
  7. 对加密结果进行最终处理
  8. 拼接最终Request Payload:e + h[AUJ_(1173)]

六、注意事项

  1. 不同业务场景下某些参数可能可以固定,但建议保持动态获取以确保稳定性
  2. 浏览器环境信息需要合理伪造,特别是window.performance.timing
  3. gct.xxx.js会定期变化,必须实现动态获取机制
  4. 某验不同产品线的方法实现可能有细微差异,不可直接复用
某验深知V2业务风控逆向分析教学文档 一、目标概述 逆向分析某验深知V2业务风控系统,主要目标是理解其验证流程并实现自动化请求。深知V2通过无感采集客户端数据,对用户环境、标识和行为操作进行智能化分析,识别潜在风险用户。 二、完整通讯流程 访问首页,引入 v2.sense.js 并提取其中的 id 发起 gettype 请求,获取动态变化的 gct.xxx.js 资源路径 自动发起 judge 请求,生成并发送加密的Request Payload 获取 session_id 后请求业务接口 verify-dk-v2 三、关键请求分析 1. gettype请求 返回包含 gct.xxx.js 路径的JSON gct.xxx.js 会生成动态键值对(如 {'xnbw': '1158444372'} ) 该JS名称和内容会定期变化,导致键值对变化 2. judge请求 Query String Parameters中包含 app_id (即首页获取的 id ) Request Payload为一长串加密字符串 成功验证后返回 session_id 四、逆向核心参数 Request Payload由以下代码生成: 1. 获取h值 h值由方法生成一个包含 aeskey 和 rsa 的对象: RSA加密算法需要完整扣取 BPqG() 方法。 2. 获取e值 e值是对NFeB对象的处理结果,NFeB结构如下: 关键子参数: insights(u值): 由浏览器环境值以"! !"连接生成 包含屏幕高宽、canvas、UA、插件、时间、时区、语言等 ep值: 传入字符串"client"处理得到 关键部分为 window.performance.timing 的值,需伪造时间戳 eco值(window.GEERANDOMTOKEN): 可通过Hook获取生成逻辑: 生成方法: 生成32位随机字符串 加上时间戳 进行MD5加密 实现代码: 动态键值对(r值): 通过 gct.xxx.js 生成,如 {"xnbw":"1158444372"} 需要动态获取最新JS文件并提取键值对 动态获取示例: 3. 获取l值 使用AES加密算法,以 h["aeskey"] 为key,e值为待加密字符串: 4. 最终处理 l值经过 tc_t 方法处理,返回 e["res"] + e["end"] 格式的结果。注意该方法与某验其他产品中的实现可能有差异,需确保使用正确的常量值。 五、完整流程总结 获取首页 id 和 gct.xxx.js 路径 动态获取并执行 gct.xxx.js ,提取键值对 生成 GEERANDOMTOKEN 构建NFeB对象 生成h值(包含aeskey和rsa) 将NFeB转为字符串并进行AES加密 对加密结果进行最终处理 拼接最终Request Payload: e + h[AUJ_(1173)] 六、注意事项 不同业务场景下某些参数可能可以固定,但建议保持动态获取以确保稳定性 浏览器环境信息需要合理伪造,特别是 window.performance.timing gct.xxx.js 会定期变化,必须实现动态获取机制 某验不同产品线的方法实现可能有细微差异,不可直接复用