当前位置: 首页 > news >正文

10-七麦js扣代码

我们来用一个案例来解释js扣代码:qimai数据

寻找加密位置

下xhr断点
打开网站,打开开发者工具,抓取翻页数据包(多取几个,对比数据)

发现**analysis**是加密数据,尝试搜索关键字:

全都没找到数据,很可能是混淆了,别白白费力气了,这个参数也不特殊,本人不知道怎么hook,所以我选择xhr

下面来xhr定位:

粘贴到xhr断点的地方然后关闭开发者工具,因为我们之前为了对比数据包中的参数把翻页翻完了,数据加载过了,没办法重新触发断点,所以要重新刷新网页,再打开开发者工具,触发翻页接口,打上xhr断点

看参数
我们直接看最外层那个函数的传参:

我们所在的栈是作用域跟到的位置(就是后面有黄色字体的地方),而我们看的是所在栈的外层函数,只有调用了外层函数才能进来内层,所以外层也是程序运行经过的地方,自然放入了栈堆,正好是在所在栈的前一栈,所以相当与我们直接看的是前一个栈,而这个栈参数是加密的,所在栈就不用看了。我的意思是,既然这种可以,(栈多的时候)我们也可以在右边直接二分法跳栈分析,前一个栈都是加密的,那后一栈就不用看了,节省时间

然后我们看所在栈的上上一个栈:

然后再继续跟发现跟不过去(作用域不在上个栈了)

这是因为异步调用无法跟栈,异步标志:

跟进异步
我们可以在异步执行之前的代码中打上断点:

然后下拉页面触发断点:

然后看加密参数是否是加密的,结果是正常的,没有加密参数,url也是正常的:

那可能加密逻辑就在这个函数中,但是我们看整个函数的逻辑也没有加密的逻辑,然后异步回调之后的e就有了加密参数:

说明加密逻辑藏在异步中,我们来着重看一下这段代码(在js中这段代码会很常见):

首先是一个for循环,然后看for后面那个括号后一半括号在哪儿,是在t.length之后,然后t.length前面是分号,根据for循环语法:

for (初始化表达式; 条件表达式; 更新表达式) {// 循环体
}

说明t.length才是for循环的条件,然后n.then是循环体

这里有两点说一下:

1.t.shift()是每次删除一个t中的元素然后返回出来删除的元素

2…then异步调用成功执行括号中第一个·t.shift(),失败调用第二个t.shift(),但是不管调不调用某一个,那一个都会取出一个元素然后放在那里等着调用,意思就是每次运行完.then这一行t中都会少两个

所以每次循环一遍就少俩,此循环就循环三次,刚我们说了加密逻辑藏在异步中,一般来说异步都会成功,所以调用的很可能就是第一个t.shift,那么每次取出的就是0,2,4,我们逐个打断点(如果不放心可以每一个都打上断点)然后运行:

断下来了,说明走这条路而且这里数据也是加密的,那说明加密位置很可能就在这里了,为什么?因为你都打上断点了,他走的第一条路就会被断下来,走之前没加密,走过来就加密了,那很可能就在此了,这里混淆了,这里我们从上往下分析(这个图是因为运行到最下面加密完数据了,t就变成了密文):

上面其实就是个拦截器(函数.interceptors.request.use):

axios = require('axios');// 请求拦截器
axios.interceptors.request.use(function (config) {  // 请求成功console.log('success')config.headers['sign'] = '123456'  // 此处可以添加参数加密return config
})// 写要拦截的网站
axios.get('https://httpbin.org/get').then(res=>{console.log(res)})

这不就是把数据拦截下来然后加密在传过去的套路吗

确定加密位置
但是有一个问题,直接运行到return t没法逐步分析了,因为运行到最后所有都成了密文,很难找加密起始的位置,而且这里混淆了也看不出加密关键字,我们重新触发一下断点,上一文我们说尽量不要直接刷新网页,因为接口不同,现在跟我步骤:

这样就过掉了所有断点,然后刷新页面,并关掉’停用断点’(如果停在了xhr断点那里就启用’停用断电’过去然后再重新关闭’停用断点’)现在是这个样子:

然后下拉页面触发断点(之前断点没删就一点一点运行进来就行):

然后逐步运行观察右侧t.url在哪变成密文

往下运行:

点了五次到这里,目前无密文,继续运行:

说明url中的密文在黄线上方产生(在黄线上的是准备运行的代码,黄线上面的是刚运行的代码),然后在刚执行的代码那行打上断点,重复上面步骤重新进入这个函数,然后直接运行,断在刚打断点这里即可,然后再分析这行代码(因为运行完可能会变):

-B == t[qt][O](v) && (t[qt] += (-B != t[qt][O](Bn) ? Nn : Bn) + v + B5 + R[V5](e))

首先有一个逻辑与:&&当左侧代码为true时运行右侧代码,然后后面有一个三元运算符:

t[qt] += (-B != t[qt][O] ? Nn : Bn
当-B != t[qt][O]成立时运行问号后代码,不成立运行冒号后代码,后面就没啥了,然后在浏览器分析:

前面是true,接着运行:

false运行冒号:

现在结果是:“/rank/release?”+… 继续运行:

结果为:“/rank/release?analysis=”+… 继续运行:

R是window,调用window中的encodeURIComponent 方法,我们查一下这个方法:

意思就是转换一种编码,不用管,然后我们发现了:

下面就是确定真正的加密位置了,e肯定是被赋值的,一点一点往上找:

逗号表达式写出来就是这个样子(把零和括号删掉就能变清晰):

e = i[Jt](i[Qt](a, d))

然后i中调用了Jt函数,参数为i[Qt](a, d),然后i中又调用了Qt函数,参数为a和d,d不知道哪儿来的,但是a有来源(找赋值的地方):

在最开头的地方打上断点,重新将代码运行过来:

看看a怎么生成的:

就是和py中的lst.jion(“”)一样,将‘列表’中的字符串拼接在一起,然后经过两行代码将a参数整理出来:

然后和d参数一起传入一个函数然后加密出e,其实到这里我们基本已经知道加密的核心代码了:

那就把它拿下来

扣代码

扣下核心代码
扣下核心代码并整理:

封装函数
将核心代码封装成函数,第一行的a是传入的,封装成函数之后为防止a混乱,将式子中的a换一个名字,然后将参数先写死,var一个变量接收:

然后调用函数运行一下看看:

报错了,说明缺东西,缺环境,下面就要补全这些环境

补环境

补环境就缺啥补啥就行,但是需要耐心和细心,上一幅图缺i,那我们回到浏览器看看i是啥:

为啥Jt是函数呢,记住一句话,括号前面是函数,括号里面是参数(个人总结不一定百分百对)还有一种就是你直接进对象i里找,这里混淆之后是Jt,鼠标放上是cv,你就找i中的cv就行:

打开cv,是个函数,点进去(有函数入口(FunctionLocation)是开发者写出来的函数,用的话要进去cv大法,没有的大概就是内置可以直接拿着函数名用的):

复制这一段:

粘贴下来,并改下函数名:

然后再运行:

我们需要先进入cv函数然后加上断点运行进来看看R是个啥:

发现R是个window对象,接着看:

V5(调用的是encodeURIComponent方法)

R[V5](这里没有FunctionLocation就是内置函数可以直接像我一样用)

t

T

直接把这些方法补进我们的代码中:

继续运行:

回原文继续改:

都打上断点,看看它走哪条路:

再运行:

回浏览器去看:

重新触发断点,都看看吧:

p

qt

T

t[Tt]

N

r(这里不是固定的,看是不是固定的可以过掉断点重新触发看看一不一样)

r生成逻辑(可以局部搜索Ctrl+ F或者先在本函数作用域找):

除了r都是固定值,直接补上(可以在控制台输出这些,到时候报错一个个补)再运行:

运行后会报出i未定义,进入浏览器打上断点,运行看i和i[Jt],i[Qt]:

i[Jt]

是cv欸,我们有救了(不就是我们刚写的改名为func_cv的函数么)

i[Qt]

是函数,进去Ctrl + C

将上面的补入代码:

运行一下:

进入浏览器打上断点,运行进来:

$5

补上:

下面开始参数d

那就只有一种可能,它的上一级作用域这个变量就有了,先看一下全局:

炒鸡多啊,大概看下没有,一般来说赋值其实不会太远,我们Ctrl + F局部搜索一下d =

发现这里挺像,离得很近,而且它所在的作用域在刚那个函数的上一级,下个断点,刷新触发断点(这里的数据是刷新页面时就加载好了的,通过翻页没法断下来,只有再刷新让他再加载一遍才能从这里过从而断下来):

控制台输出一下:

然后记住,重新刷新页面看看是不是固定的:

那就是固定的,把d填上,再运行:

看来还需要补N,找一下:

顺手看下I5

说明是join(“”)方法,补上:

后面就报错哪里就找哪里就行,大多补环境的方法已经讲过,总结一下:

TOP0:缺啥补啥,报错啥回去找到啥

1.显示是函数的就进函数cv大法,但有些是内置函数没有入口就直接复制函数名直接用就行

2.不确定参数变不变就多运行到断点几次看看一不一样

3.对于当前定义域中没有的变量就局部搜索Ctrl+F或者附近找找

4.看起来特殊点的可以全局搜索(和关键字搜索一样)Ctrl+Shift+F

注意:前面有些我是连着找连着补,尽量补一个运行一个,报错之后,再找再补再报错,再找再补再… …

最后代码是这样的:

// 扣核心代码
var params_ = '2025-09-302025-09-302025-09-303364allcn'function func_cv(paramsFromMain) {t = encodeURIComponent(paramsFromMain)['replace'](/%([0-9A-F]{2})/g, function(n, t) {return func_o("0x" + t)});try {return btoa(t)} catch (n) {return R[W5][K5](t)[U5](Z5)}}
function func_o(n) {t = "",["66", "72", "6f", "6d", "43", "68", "61", '72', "43", "6f", "64", "65"].forEach(function(n) {t += unescape("%u00" + n)});var t, e = t;return String[e](n)}
function func_oZ(n, t) {t = t || u();for (var e = (n = n["split"]("")).length, r = t.length, a = "charCodeAt", i = 0; i < e; i++)n[i] = func_o(n[i][a](0) ^ t[(i + 10) % r][a](0));return n.join("")
}
function main(params) {a = func_cv(params) // 调用func_cv函数a = (a += "@#" + "/rank/release".replace("https://api.qimai.cn", "")) + ("@#" + new Date - (-3 || 0) - 1661224081041) + ("@#" + 3)e = func_cv(func_oZ(a, 'xyz517cda96efgh'))return e
}console.log(main(params_))

总结

逆向其实大方向就是:

1.确定加密位置

2.扣关键代码并封装

3.补环境(看着麻烦,实则有时候确实麻烦)

4.若py需要此接口密文,那就调用核心代码函数

这节课挺长,动手实践一下然后理解大方向即可,多做几个案例就会了,之后学习标准算法有时候就不需要这么麻烦了,若本文有哪些地方有误请及时纠正,或者交流讨论,加油加油

http://www.dtcms.com/a/462575.html

相关文章:

  • 做一婚恋网站多少钱医疗网络营销方式
  • golang面经——sync相关
  • wordpress 财经插件wordpress mysql优化
  • 软考中级习题与解答——第十四章_UML建模(5)
  • 万网怎样做网站调试字体怎么装到wordpress
  • 【Open3D】Ch.2:点云体素下采样 | Python
  • 奉贤区做网站wordpress五分钟安装
  • 复杂网络仿真从入门到精通:0 学习路线
  • 怎样创建网站数据库服装租赁 网站 php
  • 礼品工艺品网站建设首页网站模板
  • 福州推广企业网站网站优化助手
  • Playwright MCP 使用归档:让 AI IDE 看懂 API 文档与流程图
  • 网站优化 情况公司注册地址在哪里查询
  • (二)Kafka学习笔记(p13-p23)
  • .net 微信网站开发wordpress 安装 此网页包含重定向循环
  • 【开题答辩过程】以《基于SpringBoot的消防安全应急培训管理平台》为例,不会开题答辩的可以进来看看
  • iis 创建网站o2o有哪些电商平台
  • 南京市环保局官方南京做网站wordpress制作404页面模板
  • python入门到入土---装饰器
  • 自己做网站不推广东莞网站建设哪家专业
  • ubuntu 安装应用
  • 重庆媒体网站建设单价做网站需要登录什么软件
  • 学生管理系统2.0(面向对象)
  • 桐庐建设局网站网络营销方案500字
  • 线段树上二分模板
  • Origin绘制3D坐标下边际直方图
  • 二叉树OJ(三)543. 二叉树的直径 124. 二叉树中的最大路径和 困难
  • 濮阳做公司网站重庆物流最新消息
  • IDEA Maven 仓库配置优先级
  • 手机网站建设网站wordpress 后台登陆 修改