文章日期:2025.2.4
使用工具:Node.js
本章知识:分析易盾滑块的 fp 参数生成
version:2.28.0
v:v1.1
文章难度:简单
文章全程已做去敏处理!!! 【需要做的可联系我】
AES解密处理(直接解密即可)(crypto-js.js 标准算法):在线AES加解密工具
声明:为了保护本作者可以持续的更新知识,此次逆向出的网站源码代码不予分享,有需要可以直接找我。但作者所写出的代码(非网页源代码)会在网站最低部公示。
注意:仅供学习!!仅供交流!!仅供测试!!
随着某网站的滑块更新,我的文章也要紧跟步伐,抽出时间进行更新教学,无论之前逆向的代码是否还能继续使用,我都要随着版本更新再次逆向一下,都是为了更好的了解某网站的规则。
废话不多说,先看小视频。这个是测试 fp 是否有效的方法,我本地生成fp参数值,利用油猴把fp参数值替换到网站的cookie里,使其生效,然后滑动滑块进行测试我生成的 fp 参数是否有效,如果fp没有问题,则滑块会正常通过,反之则通不过而且滑块会变红。
提示:不要在官网测试fp参数,因为官网是不会验证你的网址,无论你网址是什么,都会给你通过。
案例一(滑块):
案例二(无感):
1、打开某某网站(使用文章开头的AES在线工具解密):
eumnTMBK1YX1yHa2YPIzznz0lllcK4OHdbDHkOTYuvQ=
2、我们打开网站后,选择嵌入式会比较方便一点,然后单独刷新一下滑块验证码,可以在控制台看到今天要逆向分析的参数,fp参数。
注意:fp参数可以用于滑块的任何请求载荷,都是通用的,只要是关于当前滑块的请求,那么fp都是可以相互使用,无需重复逆向。包括不限于无感验证。
3、开始之前别忘了先替换一下这个文件,如果不替换,在逆向分析的过程中会影响你打的断点。如果不知道替换流程的,可以看一下这个文章【【web js逆向分析易盾滑块cb参数】逆向分析网易易盾滑块的cb参数,仅供学习交流】,里面有替换文件的过程。
4、接下来我们看一下这个参数怎么逆向分析,其实这个【fp】参数是和cookie的【gdxidpyhxdE】有关联,他先生成了参数,然后把参数赋值到了cookie里,然后再从cookie里取这个值作为fp,所有我们直接用hook,hook一下cookie的【gdxidpyhxdE】值。
5、直接上油猴插件,记得hook前线清除一下cookie,这样才能使他触发生成fp参数,我们才能hook住。油猴过程就省略了,直接把代码给你们。
javascript
// ==UserScript==
// @name cookie 函数 - HOOOK大法
// @version 0.1
// @description 控制台追踪 cookie 函数运行时的日志信息并断住
// @author 小木_.
// @match *://*/*
// @grant none
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAABkCAYAAAA7Ska5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAs9JREFUeNrsneFtwjAQhQ8myAjZADYgI7BB2aCMwAa0EzAC3SAwQcIEdIOwQZtI7h9EqJ5Jcs8+P8lqUVNkPt1d7nyOmcl0WrYje/L3Qog0G/n9i7ufCweHCoIGmGfKnRWtHKilJPWC2rbj2o4fgkGpNQEgah2UoFxnAbhYOXKwvrWjbsfZve5+/w4l9oxhFQfnskGrGhhIHssdqxwiboSQP00N5vhP1m0SzCHm5K96wVKilg+UKlb3eRVM9LVX4QFlZ6G4XINQmiFcaB4AGNQlPl2aH73QW3UmRtRo3J7nAbgRYgEXS2AQnay4EbpQJcliRrYWZjAZCKa2AgaNL2crYArw+lqMCEnsrmJIqotRrK6ExpeLFTBofDlZAbMArr1ZCrxI37ocYwKMFtMldrlW/sIMRj2+sIJZMSR2jGDQ+sjEMiaa2O3HmgSbxaDx5WIFTFqx69FRsP6RGal0BNhdKResI3C2AgYNvLUVMAvwejOBF9kcVI49GRaLUe0IMINR7Qgwg6GoqBmVOgIDFI6TbE9lcCW6+MIChiqxYwKTOgI9Uu8IMFpMLgQdAUYwaWGqR3uJ6AFOrcKxmnJimq6EFo4nK2DUt3qwgkmFYyocxyscJ3+ET8uVKAtHBjCUhSODjpISu4dCOo6lxgQ1XCkXoo4jE5gUX3qEPoNk5hlHZGGq0prk1K6UC7YwVVsBg8aXsxUwFFtVQ48vZraSLSWgs1+mdKW3UOILsxuZOP/Fx43UF6amcqV38PovC9aSgdV0N9YWwGwEPzHIhNCj2vYWoBSSTiN7KHQJs7QAJfewlk2yFqNNtSJZyzB3osoClJ2HtRSpJjKYt/ik/pUFKGhcaSSiQ8373KfxgBJ1husTaK8xQ9mI33eTlBJhZ7GLB77fZtO4/w1GM/eBOwu4f4DhL7dYONP3CZTde3YHD39IoKd2vGINfXFkG7Lb/AowAEq4SC9qqUT/AAAAAElFTkSuQmCC
// @run-at document-start
// ==/UserScript==
// hook cookie 函数
// 保存原始的 document.cookie
var cookie_cache = document.cookie;
// 使用 Object.defineProperty 来劫持 document.cookie
Object.defineProperty(document, 'cookie', {
get: function () {
return cookie_cache;
},
set: function (val) {
console.log(`[J] - cookie设置内容 -> ${val}`);
// ****************** 查找特定的 cookie 对象值
if (val.indexOf('gdxidpyhxdE') !== -1) {
console.log(`[J] - cookie捕获到设置 已断点 -> ${val}`);
debugger;
}
// 提取出 cookie 名和值
const cookie = val.split(";")[0];
const ncookie = cookie.split("=");
console.log(`[J] - cookie设置 -> [${ncookie[0]}]==[${ncookie[1]}]`);
// ****************** 处理是否更新或添加 cookie
let flag = false;
// 更新 cookie_cache,避免重复添加同一个 cookie
const cache = cookie_cache.split("; ").map((item) => {
const [key] = item.split("=");
if (key === ncookie[0]) {
flag = true;
return cookie; // 替换已有的 cookie
}
return item; // 保持原有的 cookie
});
// 如果没有找到该 cookie,就将其添加到 cookie_cache
if (!flag) {
cache.push(cookie);
}
// 更新 cookie_cache,并合并所有 cookies
cookie_cache = cache.join("; ");
return cookie_cache;
}
});
6、用hook脚本断住后,我们直接看堆栈,在堆栈里找一下他怎么生成的这个参数
7、随便找一下就找到了,直接找到他生成fp的函数位置,我们直接把代码全部扣到本地,注意不要扣我黄色圈起来的代码,哪些代码是和生成fp参数没有任何关系的,扣了也没什么用
8、扣下来后,我们直接运行,发现缺少【v】,我们直接在官网打断点,跟栈进去
9、我们跟进来后,把这些代码都扣下来,注意黄色圈起来的逗号,扣到本地的时候,记得替换为【)】括号
10、扣代码都很简单,我就不带大家一个一个演示了,我接下来就直接讲比较重要的内容。
11、问题一
11.1、注意一下要填写网站的域名,这个一定要填写对,如果你生成的fp参数要用于【https://n3.xxx.com/....】,那你就必须填写【n3.xxx.com】,否则是无法使用的,而且这个值是不能固定,如果你想要把这个fp参数用到其他的网站,那你这个网址也要进行更换
12、问题二
这个可以了解一下,他是将你浏览器的环境经过一系列的处理,生成了一个列表,存储着两个值。这个无论是选择方法一,还是方法二,都是可以正常运行的,但我建议大家选择方法二
12.1、指纹代码展示图,没办法,不能给你们直接发源代码,大家看着理解一下,原理都很简单,如果里面也可以添加一下随机值,让他的指纹可以随机生成,毕竟服务器是不会去验证你的指纹信息是否是正确的,但他会验证你的指纹效验,如果效验失败就会导致你的fp参数用不了,所以大家尽可能使用源代码去生成这个参数
13、问题三
遇到这种try一定要注意,多去分析他,看下面的图,有的时候try是不能随便删除的,但如果他只执行一次,那你可以先在官网多测试几次,看看他到底会不会执行catch,如果不会,那我们就把try删除掉,他的存在只会影响我们逆向分析
14、问题四
依然是try,这个是有for循环的,而且他这个try里的函数也很少,很明显,不能删除这个try,如果随便删除,是会导致最终的结果有变化,服务器就不会接受你的结果
15、问题五
最终生成的结果需要经过JSON转一下字符串,可以处理一下反斜杠
16、总结一下
16.1、一定要注意【try】,多测试一下,调试一下,防止流程和官网不一样而导致最终结果用不了
16.2、要注意网站域名的添加,这个东西如果添加错误或没有添加,那么得出的结果就会用不了
16.3、【指纹】这个是我测试的比较少,无论是写死还是动态生成多少可行的(本人采用动态生成)
17、好了,本文到此结束,别忘了三连,下次继续更新
【测试fp参数的脚本 - Hook脚本】 需要结合油猴插件
javascript
// ==UserScript==
// @name 通用修改添加Cookie
// @version 2025-02-03
// @description 修改cookie
// @author 小木_.
// @match *://*/*
// @grant none
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAABkCAYAAAA7Ska5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAs9JREFUeNrsneFtwjAQhQ8myAjZADYgI7BB2aCMwAa0EzAC3SAwQcIEdIOwQZtI7h9EqJ5Jcs8+P8lqUVNkPt1d7nyOmcl0WrYje/L3Qog0G/n9i7ufCweHCoIGmGfKnRWtHKilJPWC2rbj2o4fgkGpNQEgah2UoFxnAbhYOXKwvrWjbsfZve5+/w4l9oxhFQfnskGrGhhIHssdqxwiboSQP00N5vhP1m0SzCHm5K96wVKilg+UKlb3eRVM9LVX4QFlZ6G4XINQmiFcaB4AGNQlPl2aH73QW3UmRtRo3J7nAbgRYgEXS2AQnay4EbpQJcliRrYWZjAZCKa2AgaNL2crYArw+lqMCEnsrmJIqotRrK6ExpeLFTBofDlZAbMArr1ZCrxI37ocYwKMFtMldrlW/sIMRj2+sIJZMSR2jGDQ+sjEMiaa2O3HmgSbxaDx5WIFTFqx69FRsP6RGal0BNhdKResI3C2AgYNvLUVMAvwejOBF9kcVI49GRaLUe0IMINR7Qgwg6GoqBmVOgIDFI6TbE9lcCW6+MIChiqxYwKTOgI9Uu8IMFpMLgQdAUYwaWGqR3uJ6AFOrcKxmnJimq6EFo4nK2DUt3qwgkmFYyocxyscJ3+ET8uVKAtHBjCUhSODjpISu4dCOo6lxgQ1XCkXoo4jE5gUX3qEPoNk5hlHZGGq0prk1K6UC7YwVVsBg8aXsxUwFFtVQ48vZraSLSWgs1+mdKW3UOILsxuZOP/Fx43UF6amcqV38PovC9aSgdV0N9YWwGwEPzHIhNCj2vYWoBSSTiN7KHQJs7QAJfewlk2yFqNNtSJZyzB3osoClJ2HtRSpJjKYt/ik/pUFKGhcaSSiQ8373KfxgBJ1husTaK8xQ9mI33eTlBJhZ7GLB77fZtO4/w1GM/eBOwu4f4DhL7dYONP3CZTde3YHD39IoKd2vGINfXFkG7Lb/AowAEq4SC9qqUT/AAAAAElFTkSuQmCC
// @run-at document-start
// ==/UserScript==
(function() {
'use strict'
var gdxidpyhxdE = 'ht+mq\\XAn7r2JUoxqSxQotRXCtqPjqyiHNHWqkUm9O+PuBuv2mR/ZbiKokllp12LMyRoAf6nJCnGJH9jySnbqkKiD3YYjrbINq9GzgU931cW0uLkIRM0QrnmCo\\fJYYaIDr30cJptQszznNrA\\Z0nCpklcgcXHKQYMgNaM1fx\\9mp4lQ:1738677906156'
var d = new Date;
d.setTime(d.getTime() + 1e3 * 60 * 60 * 24 * 5000000);
document.cookie = "gdxidpyhxdE=" + gdxidpyhxdE + ";expires=" + d.toGMTString() + ";path=/"
})();