某看视频hk_sign参数逆向实战全记录

某看视频hk_sign参数逆向实战全记录

在完成《某茄小说a_bogus参数逆向实战》后,我们继续深入JS逆向领域,这次的目标是某看视频hk_sign参数逆向。相比之前案例中相对直接的加密逻辑,某看视频的防护手段更为棘手:核心代码被深度混淆,并通过动态执行的方式运行,使得全局搜索和静态分析几乎失效。

面对这种通过动态调用调试和深度混淆构建的复杂环境,常规的逆向思路难以奏效。本文将分享如何运用高阶调试技巧,在这种“混沌”中精准定位加密核心,完整解析其输入参数拼接规则和MD5签名流程。

本文目录

  1. 抓包分析:锁定hk_sign参数位置
  2. 搜索遇阻:加密参数被混淆处理
  3. XHR断点:精准拦截请求生成点
  4. 堆栈追踪:在动态调用中寻找线索
  5. 关键突破:日志断点揭示加密函数
  6. 算法还原:控制台验证加密逻辑
  7. 在线验证:MD5加密算法确认
  8. 技术总结:复杂环境逆向方法论

1. 抓包分析:锁定hk_sign参数位置

打开某看视频首页,随意点击一个视频播放,滑动到页面下方的”猜你喜欢”区域。点击旁边的”换一换”按钮,同时在浏览器开发者工具的Network面板中进行抓包。

目标接口:/haokan/ui-web/video/feed
关键参数:hk_sign(用于签名验证)

某看视频hk_sign参数逆向抓包界面
图1: 某看视频推荐接口抓包结果

2. 搜索遇阻:加密参数被混淆处理

按照常规逆向思路,首先在源代码中全局搜索hk_sign关键词。但搜索结果为空,这表明参数名在代码中被深度混淆,无法直接定位生成位置。

全局搜索无结果

3. XHR断点:精准拦截请求生成点

在Sources面板添加XHR断点,URL片段设置为:/haokan/ui-web/video/feed。点击”换一换”后,代码执行暂停在:

var s = BOOMR.orig_fetch.apply(this, arguments);

此时观察请求参数,hk_sign已经生成。这说明我们需要在调用堆栈中向上追踪,找到参数的生成源头。

XHR断点拦截

4. 堆栈追踪:在动态调用中寻找线索

通过堆栈面板逐个分析调用栈帧,重点关注每个栈帧作用域中的hk_sign值变化。当追踪到栈帧a时,发现hk_sign尚未生成,关键代码为:

return { type: "normal", arg: t.call(n, r) }

此处的t.call(n, r)是一个动态函数调用,存在以下特征:

  • 函数引用t是动态的,无法静态分析
  • 没有明显的参数特征,难以通过数据流追踪
  • 调用链被故意打乱,增加逆向难度
调用堆栈分析

5. 关键突破:日志断点揭示加密函数

面对动态函数调用t.call(n, r)的困境,常规的单步调试难以奏效。此时我们采用日志断点(Logpoint)技术,在断点处添加日志表达式t,这样每次执行到此都会在控制台输出函数t的实际内容,而不会中断代码执行。

日志断点在控制台输出t
图5: 日志断点配置与控制台输出效果

通过多次点击”换一换”触发调用,我们观察到在第二次call时控制台输出了关键信息:

ƒ (e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,u.fetch.get({url:"/haokan/ui-web/video/feed",data:Object(p.appendCryptoParams)

这段代码明确显示了加密逻辑的入口:Object(p.appendCryptoParams)({time:+new Date})。这表明:

  • 加密函数p.appendCryptoParams
  • 输入参数:包含时间戳的对象
  • 调用位置:在u.fetch.get请求的data参数中
  • 请求地址/haokan/ui-web/video/feed

我们在data: Object(p.appendCryptoParams)({time: +new Date})这一行设置条件断点,当代码执行到此位置时暂停。跟进p.appendCryptoParams函数调用,发现它跳转到了n[a(526)]函数:

p.appendCryptoParams 位置下断点
图6: 跟进p.appendCryptoParams函数调用
 n[a(526)] = function(e) {
                    var t = (0,
                    n[a(529)])(e);
                    return s(s({}, e), t)
                }

这个函数实际上是一个包装器,真正的加密逻辑在n[a(529)]函数中。我们继续跟进n[a(529)],终于找到了完整的加密实现:

 n[a(529)] = function(e) {
                    var t = a;
                    e = e || {};
                    for (var r = Math[t(656)](Date[t(841)]() / 1e3), n = (0,
                    l[t(573)])(16), i = t(698) != typeof window ? 1 : 0, s = window[t(598)][t(832)] ? 1 : 0, u = [], f = [], d = 0; o[t(831)](d, 3); d++) {
                        var h = o[t(882)](Math[t(656)](1e3 * Math[t(839)]()) % 48, 43)
                          , p = Math[t(656)](1e3 * Math[t(839)]()) % 48 + 43;
                        u[t(724)](String[t(599)](h)),
                        f[t(724)](String[t(599)](p))
                    }
                    var m = [u[t(554)](""), i, s, 1, r, f[t(554)]("")][t(554)]("")
                      , g = (0,
                    l[t(782)])(m, t(836))
                      , v = {};
                    v[t(639)] = n,
                    v[t(736)] = r;
                    var y = Object[t(873)](e)[t(756)]()[t(638)]((function(r) {
                        var n = t;
                        return ""[n(776)](r, "=")[n(776)](e[r])
                    }
                    ))[t(554)]("")
                      , b = c[t(866)](n + y + t(734) + r)[t(472)]();
                    return v[t(773)] = b,
                    v[t(488)] = (0,
                    l[t(455)])((0,
                    l[t(559)])(g)),
                    v
                }

这个突破的关键在于:日志断点让我们在不中断程序执行的情况下,观察到了动态函数的真实面貌,从而找到了加密逻辑的准确入口。这种方法在应对混淆和动态调用时特别有效。

通过分析n[a(529)]函数,我们可以看出加密过程包含以下几个关键步骤:

  • 时间戳生成r = Math.floor(Date.now() / 1000)
  • 随机数生成n = 生成16位随机字符串
  • 环境检测:检测window对象和某些属性
  • 字符数组构建:通过循环生成u和f两个字符数组
  • 参数序列化:将输入参数e转换为URL查询字符串格式
  • MD5加密:对拼接后的字符串进行MD5哈希计算

6. 算法还原:控制台验证加密逻辑

在加密函数return语句处设置断点,当代码执行暂停时,我们在控制台中还原关键参数并验证加密逻辑。

参数函数名在控制台还原
图7: 控制台验证加密逻辑

通过控制台还原出加密代码:

c.MD5('04573d4d1aa6b9a6time=1761111056033guanghui1231761111056').toString()

在控制台执行后得到下面的值,与原始生成的hk_sign值完全一致。

2ecb4e1c3cbcf9888647ce5cd1e8e315

7. 在线验证:MD5加密确认

这明显是MD5加密,我们打开MD5在线加密网站进行验证。

在线MD5工具验证加密结果
图8: 在线MD5工具验证加密结果

将相同字符串输入在线MD5工具,得到的哈希值与控制台结果一致,确认是标准MD5加密算法。

8. 技术思考:动态调用的逆向策略

回顾本次某看视频hk_sign参数逆向过程,当遇到t.call(n, r)这类动态调用时,最大的挑战在于其缺乏明显的参数特征,且处于循环调用中。这种情况下,传统的静态分析方法往往失效。核心的突破思路在于:通过日志断点实时捕获函数实体,结合堆栈分析定位加密逻辑的准确入口。这种”动态追踪+实时分析”的策略,在处理深度混淆的代码时显得尤为重要。

下期预告
小红薯X-S签名逆向解析(上篇):突破自定义Base64与算法轮廓》本文详细记录了如何定位seccore_signv2加密函数,分析其外层算法逻辑,并成功扣取自定义Base64代码实现本地复现。

Comments

No comments yet. Why don’t you start the discussion?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注