首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【JS逆向百例】某坤行 1101,雪球 1038,新 acw_sc__v2 逆向分析

【JS逆向百例】某坤行 1101,雪球 1038,新 acw_sc__v2 逆向分析

原创
作者头像
K哥爬虫
发布2025-10-09 16:10:08
发布2025-10-09 16:10:08
600
代码可运行
举报
文章被收录于专栏:Python 爬虫Python 爬虫
运行总次数:0
代码可运行
pV5GxQP.png
pV5GxQP.png

声明

本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!

本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责,若有侵权,请在公众号【K哥爬虫】联系作者立即删除!

前言

最近有小伙伴博客留言,询问关于雪球 1038 长串的相关逆向思路,该参数整体难度中等,有些细节地方会导致最后生成的参数无法使用,在了解长串之前先分析一下基础的短串(某坤行),由简到繁。非业务项目,本文仅对该参数进行逆向分析,仅供学习交流。

逆向目标

  • 目标:某坤行/某雪球/acw_sc__v2
  • 网址:
    • aHR0cHM6Ly93d3cuemtoLmNvbS9pdGVtL0FBNjI0MjI5MS5odG1s
    • aHR0cHM6Ly94dWVxaXUuY29tLw==
    • aHR0cHM6Ly93d3cudGhmdW5kLmNvbS5jbi8=

抓包分析

某坤行

首先访问详情页,发现他会请求 2 次,第一次返回带混淆的 js 代码:

EJ91BY.png
EJ91BY.png

第二次请求,携带 md5__1101 参数即可返回正常的 html 内容:

EJ9PgH.png
EJ9PgH.png

某雪球

某雪球长串短串随机触发(大部分是长串),我们这里点击评论列表的小气泡图标,发起数据请求,其中载荷参数为主要分析对象:

EJ9YZU.png
EJ9YZU.png

本文由易到难,从短串到长串依次进行分析。

逆向分析

某坤行

首先我们访问详情页,下脚本断点,发现他在 VMxxx.html 里成功断下,这里发现 href 暂未生成相关参数:

EJ9zDs.png
EJ9zDs.png

单步跟栈,最终发现在末尾调用 m[l1(Gh.GI)](j, m[l1(Gh.GV)](H, m[l1(Gh.GO)](T, b[l1(Gh.Gp)][l1(Gh.GT)]))) 方法,生成了新的 href 参数:

EJ9Jl7.png
EJ9Jl7.png

进入 j 函数,首先通过 sig 函数生成值后,再拼接时间戳等生成新参数,1482973743|0|1757665216486|1,将对应的 sig 算法扣下即可:

代码语言:javascript
代码运行次数:0
运行
复制
'sig': function(I) {
            var lU = l1;
            for (var V = -0x51b * -0x1 + 0x2051 * -0x1 + 0x1b36, O = m[lU(Go.l)](encodeURIComponent, I), W = 0x1 * 0x102d + -0x1 * -0x1b0f + 0x4 * -0xacf; m[lU(Go.m)](W, O[lU(Go.G)]); W++)
                V = m[lU(Go.k)](m[lU(Go.Q)](m[lU(Go.t)](m[lU(Go.b)](V, 0xa78 + -0x662 * 0x2 + 0x1 * 0x253), V), 0x1647 + -0x32e * 0x8 + 0x11 * 0x47), O[lU(Go.Y)](W)),
                V |= -0xfe1 * 0x2 + -0x1c9d + 0x3c5f;
            return V;
        }
EJ9XAI.png
EJ9XAI.png

随后将拼接好的参数经过 F['ua'](V, !(-0x1c67 + 0x544 + 0x1723)) 方法生成最终的参数:

EJ9jJV.png
EJ9jJV.png

进入 ua 函数,是个平坦流,发现其主要生成逻辑为 uu,D 为固定值:

EJX6Ec.png
EJX6Ec.png

最终经过 z['uu'] 将 I 值与匿名函数传入,生成 1101 值,只需将 uu 模块整体扣下即可:

EJXFc3.png
EJXFc3.png

最后,携带正确的 1101 参数即可完成请求:

EJXZjj.png
EJXZjj.png

某雪球

无限 debugger

进入评论列表,打开 F12 触发了无限 debugger,这个 debugger,之前也有粉丝问过,类型如下:

EJnVAq.jpg
EJnVAq.jpg

向上查看堆栈,发现是进入了大 Function,主要逻辑就是 s['charCodeAt'](0);,在其中插入 debugger 导致字符转 Unicode 编码时断下:

EJnWCs.jpg
EJnWCs.jpg

将 js 修改为 (Xg = M['E'][XD(j4.A)][XD(j4.h)][XD(j4.m) + 'r']('s', 'i', R[XD(j4.V)](R[XD(j4.b)](R[XD(j4.Q)](H), XR), R[XD(j4.w)])),Xi[XR]["charCodeAt"](0)) 利用逗号表达式的特性将这个 debugger 过掉。

随后我们就要找到这个 js 是在哪里动态注入的,同 1101 参数思路一样,下脚本断点后刷新页面,将我们修改后的 js 文本替换到 Gq.text 中:

EJnDRI.jpg
EJnDRI.jpg

再次刷新,发现 js 没有触发 debugger,但是浏览器卡死了,说明发现 js 被我们手动修改了。

向上排查,可疑位置如下:

EJnag7.jpg
EJnag7.jpg

修改后会导致 js 发生改变,导致这里 ME 不等于 997,我们将这里也一并修改,让 ME 恒等于 997,返回正常逻辑。再次替换,刷新页面即可正常调试(首页第一次请求 html 中 script 里也会携带 js,同理替换,换汤不换药,这里不做区分。后续评论接口可按上述方法替换分析)。

这个属于代码执行过程中产生的 debugger,也可以直接用魔改浏览器过掉,可以参考:

浏览器魔改-从根本上通杀所有的无限debugger:https://mp.weixin.qq.com/s/up0frzR2Fl9ijtHikkfs7Q

逆向分析

按抓包分析中的步骤,我们点击评论按钮,进入到下图 send 堆栈处:

EJnOZV.jpg
EJnOZV.jpg

经过 GE 方法后,openArgs 中携带了 1038 参数,继续跟进,发现进入到了类似 1101 参数的生成逻辑,但是比其更为复杂:

EjmHSJ.jpg
EjmHSJ.jpg

进入到加密函数 XY 中,发现是 switch 与 case 重重嵌套:

EjmKsG.jpg
EjmKsG.jpg

这里不做解混淆,利用 1101 的思路去慢慢跟进,首先是对 params 进行了拼接然后编码了一下:

EjmgEB.jpg
EjmgEB.jpg

其中 _waf_bd8ce2ce37 是前置接口返回的:

EjmhWt.jpg
EjmhWt.jpg

随后继续单步跟进,发现它魔改了 Math 函数:

Ejm8jb.jpg
Ejm8jb.jpg

经过研究发现,类似固定随机因子到自写函数,使得 Math.random 可以得到自己想要的,进入 p 函数,发现每次置入随机因子的时候,F 都会初始化一个值(这个可以用做观察点,可以下断点看看走完全程需要置入多少次随机因子):

Ejm58P.jpg
Ejm58P.jpg

同时,发现在 F 值重置的时候,会调用 z 函数来生成 XR 值,在 z 函数内则是 Error 堆栈检测,它会检测你是哪个函数调用报错的:

EjmAtw.jpg
EjmAtw.jpg

堆栈不同则最后生成的 XR 不同(随机因子与 F 值初始化有关系,同时又与 XR 值有关系,XR 为错误堆栈检测)。最终在这些值的加成下,让 random 可以返回想要的值,如下图:

EjmVe6.jpg
EjmVe6.jpg

随后调用 X8 函数生成 Xb 值:

EjmcyO.jpg
EjmcyO.jpg

然后调用 XQ = R[ZJ(M4.H)](X8, Xm)) 方法,继续由 x8 生成 XQ,这里 random 还是一直轮着的,前面出现错误,那么后面生成的参数都是错的。

最终调用 XX, X0 完成 xb 值的拼接:

代码语言:javascript
代码运行次数:0
运行
复制
Xb = [R[ZJ(M4.v)](XX, Xb), R[ZJ(M4.F)](XX, XQ), R[ZJ(M4.p)](X0), R[ZJ(M4.e)](new M['E'][(ZJ(M4.k))]()[ZJ(M4.G)](), ''), XV[ZJ(M4.J) + ZJ(M4.d)], XV[ZJ(M4.n) + ZJ(M4.S)], R[ZJ(M4.c)](f)][ZJ(M4.W)]('|');

主要讲的就 X0,里面检测居多,其中最经典的就是调试或篡改检测,进入 X0 函数,首先到了检测函数 L:

EjmvUQ.jpg
EjmvUQ.jpg

第一个便是反调试检测,如下:

Ejmasf.jpg
Ejmasf.jpg

检测代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
Xg = 0

var Xj = new Error()
    , XR = {};
XR["configurable"] = !(-0x2ed * -0xa + -0x1 * -0x647 + -0x2388);
XR["enumerable"] = !(0x833 + 0x1e9 + -0xa1b * 0x1);
XR["get"] = function () {
    console.log("触发")
    return Xg = -0x1 * -0x791 + -0x775 + -0x10 * 0x40 + 997,
        '';
}
    ,
    (Object["defineProperty"](Xj, "stack", XR), console.debug(Xj))


console.log(Xg)

正常运行这段代码会将 Xg 的值设置为 1,即被检测,过掉这个检测且不影响原代码的情况下,只需加一行 console.debug=function (){} 即可过掉,如果不加,你最后扣下来的 1038 是用不了的。

随后进入到了一系列 node 的环境检测:

EjmOEc.jpg
EjmOEc.jpg

因为我们是扣代码,所以只要照着浏览器去改就行了,全部弄好后,最终生成的 X0 值才是可用的。

最后调用 J 函数,将拼接后的 Xb 传入即可生成最终的值,但是这里还有一个小坑,正常加密的时候,码表应该是 T 开头的,但是如果没有处理码表,加密出来的参数会对应不上:

EjmUjj.jpg
EjmUjj.jpg

最终溯源发现码表经过了修改,先修改随机因子:

EjmPp5.jpg
EjmPp5.jpg

然后 G 函数通过已随机的因子将码表打乱,重新排序,得到正确的码表:

EjmRGm.jpg
EjmRGm.jpg

结果:

EjmYt4.jpg
EjmYt4.jpg

acw_sc__v2

acw_sc__v2 的难度在 1101 与 1038 之间,能搞定 1038 那么新 v2 自然也是可以的,还是熟悉 debugger,这也是粉丝提问的:

EjmzH9.png
EjmzH9.png

还是老办法,进行 js 替换:

Ejmroh.jpg
Ejmroh.jpg

替换后用 Hook 进行堆栈追踪,发现最终的生成位置如下:

Ejm4UY.jpg
Ejm4UY.jpg

向上分析逻辑,发现还是先进行随机设置(分析到后文不难看出这又是另一种混淆,让它返回想返回的随机数,与固定参数组合生成想要的值),T 的话,分析可知,仍然还是由 arg1 按照指定规则生成的,T = arg1[yX(oK.p)](-0x1640 + 0x701 * 0x2 + 0x1 * 0x5ec + oO, -0x9e4 + -0x53 * 0x35 + -0x38f * -0x7 + oO)[yX(oK.X)]('')

EjmjcU.jpg
EjmjcU.jpg

首先进入魔改后的 fiil 函数,将数组进行规则打乱后返回:

EjmeQG.jpg
EjmeQG.jpg

随后利用设置好的随机数再次将打乱后的数据按照指定规则排序(这里可以记录随机数):

EjpTGe.jpg
EjpTGe.jpg

再拼接随机文本数字,最终转小写后拼接生成,不管是 1101 还是 1038 亦或者 acw_sc__v2 参数,最终算法也都仅几十行不过百行:

Ejpl6Q.jpg
Ejpl6Q.jpg

结果验证

EjpgP9.jpg
EjpgP9.jpg

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 声明
  • 前言
  • 逆向目标
  • 抓包分析
    • 某坤行
    • 某雪球
  • 逆向分析
    • 某坤行
    • 某雪球
      • 无限 debugger
      • 逆向分析
    • acw_sc__v2
  • 结果验证
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档