问:等等??这 A+1 站
是什么意思?
答:这……(踱步靠近,又见四下无人,小声说)你对着英文字母表看一看,对!就这个,你看 A
后面是谁。
【2023-11-28】说明
具体见我在评论区的紧急补充……是我想的太复杂了,没有详细测试,咳咳……失误失误,思维惯性误导了。
不过文章还是有可取之处的吧……大概……。
风云又起:接口变化
今天修炼完成后准备看点好看的放松一下,结果我的 A+1 站
小脚本报错了。
猜测是请求的接口有了变化。
爬虫不能爬太狠,开发网站的人会掉头发,做爬虫的人也掉头发,最后大家都掉头发。
随便找一个 up 主页的链接:https://space.A+1站.com/up 的 mid/video
,在无痕浏览器中打开,然后抓包、快速定位到相关请求。
发现接口的确变化了:多了 3 大天王。
为什么上面的 dm_img_list
为 []
,又为什么称它们为 3 大天王
呢??
- 如果不是在无痕浏览器中直接打开网址测试,那么
dm_img_list
的值如下图,咳咳,没必要给自己找麻烦了,就默认 dm_img_list
这样吧。
- 至于另外的两大王,也不简单,具体见后文。
当然啦,A+1站
又不是小网站,大佬肯定早已发现、解决了。
-
先去 A+1哩A+1哩-API收集整理
项目查看 用户空间相关 | BAC Document,发现文档还没有更新,可能网站才刚刚更新那 3 大天王
,文档稍微滞后一些。
-
在其 github 项目的 网页端接口加了新的校验 · Issue #868 中大家有所讨论。
为什么头像、用户名打码?
嗯……参考新闻联播,所以还是打码吧,不过内容是无法打码了。感兴趣可以去对应 issue 查看。
其中一个大佬给出了代码,并且经过测试得到了相同的信息……厉害呀!
还有一位道友给出了本站的链接,不过不知道是什么原因,两天了这个帖子还打不开……(小声说)所以你会看到本文的图片对敏感信息已经打码了。
总之,问题其实已经解决了。不过——因为我自己在用这个接口,自然要了解它的一些变化以便将来应对它的其它变化啦。而在上面的 issues
中大家并没有说分析过程,所以我试着分析一下,发现其中弯弯绕绕 “有点意思”,才有了这篇文章。
诡异身法:找不到的它
直接搜索关键字并没有结果。
如果使用 xhr
断点,哼哼,好长好长的调用栈,并且夹杂了很多异步操作…………我拒绝分析!!
当然,如果全局搜索请求的部分内容,如搜索字符串 wbi/arc/search
倒是能找到几个地方,但还需要分析很久。
以前碰到过这种情况,通常情况下 xhr 断点、搜索请求的 url 这两个方法基本能找到参数的位置,如今遭遇到打击了。
经过在必应搜索关键词:js 逆向搜不到关键字
,查看了一些文章,主要是在JS逆向|加密参数定位的另一种方法及风控的一些思考-CSDN博客受到启发:使用浏览器的内存工具来分析。
仙器 chatGPT
如下,在 xhr 断点处生成内存快照,然后搜索 dm_img_str
参数的值 ,可以确定它是 base64 encode
的字符串。
进行 base64 decode
,得到的是 一个和 webgl
有关的、很像是版本号的字符串。
通过一个名为 openAi
的神秘组织锻造的仙器 chatGPT
,得知 webgl
获取其版本信息的相关函数,从而定位到 dm_img_str
的生成位置!
这比我去 MDN 看 webgl 文档、或者必应搜索好多了,不愧是仙器。
同理,也能定位到 dm_cover_img_str
参数的生成位置!
运气也是实力嘛~
咳咳,上述情况只能说 “凑巧”,谁让它最后多了两个 ==
号呢……不过这样的事情我也有点不满意,下次碰到了没有那两个 ==
号让我辨认该怎么办??而且这种内存分析方式我还是第一次见到,多试一试。
下面再说明一下这种内存分析的方式。
注意,如果关键字的名称很短,比如 "d",那么这种方法也可能失效,就像平时全局搜索关键字时一样,关键字很短时效果就差很多啦。
在本文的番外篇中讨论这个问题。
在内存快照中搜索参数的名字 dm_img_str
(名字越长效果越好,就像普通的全局搜索关键字一样),找到了它的马甲:webglStr
。
然后全局搜索 webglStr:
或者 webglStr=
,统统打上断点,因为我们需要找到对它赋值的地方,那里可能就是 dm_img_str
的来历。
其实打断点调试多处的 webglStr
时,就可以看到一些 weglStr
包含的就是 dm_img_str
的值。
大概是如下这种情况
如下,见到了其来历。
可是,即便知道了 dm_img_str
名字的由来 ,那又如何根据这个名字找到 dm_img_str
参数值生成的地方呢,上述代码中也没见到和它参数值有关的代码呀。
下面就是重点了,仔细观察这个名为 dm_img_str
的字符串,它有几个非常重要的特点:
- 它是一个字符串。(
废话,大家都看不出来吗??)。
- 它是作为名称来使用的,也就是说它将来会作为请求中参数的名字。
- 正因为它会作为 “名字” 使用,反而对它的处理就会非常简单:通常只有取值操作而已,谁还能对一个本该作为名称使用的字符串做些奇奇怪怪的操作,计算机性能强也不是用在这里的嘛。
- 那么将该字符串替换成
Proxy
对象,找到取它的值的地方不就好了!并且那么所有关于该字符串赋值地方都会复制同一个 Proxy
!
所以,准备如下 hook
函数!
// 快速根据字符串创建代{过}{滤}理,从而跟踪它的取值
window.create_str_proxy = function (str) {
let temp = { "v": str };
return new Proxy(temp, {
get(target, property, receiver) {
console.log("访问代{过}{滤}理字符串的属性: ", property);
if (typeof temp["v"][property] === "function") {
if (property === "toString" || property === "valueOf") {
// 到取值的地方就暂停!!!
debugger;
}
// 如果访问底层字符串方法还需要绑定 this 哟
return temp["v"][property].bind(temp["v"]);
}
// 此时就是访问字符串的普通属性啦
return temp["v"][property];
}
})
}
点击运行,找到了~~~!
而上图中 s.webglStr = B(s.webglStr),
的 B
函数如下,嘿!还真把末尾的两个等号去掉了。
根据上面的分析,只要继续找所有 webglStr
就可以找到了!
同理,利用上面的 Proxy
原理,也可以找到 "dm_cover_img_str"
的参数值啦!!
结束了吗??
也就是说:dm_img_str
是当前浏览器的 webgl
的版本(具体我也不清楚,没用过 webgl),dm_cover_img_str
是显卡的信息,这两个值几乎可以认为是固定的,所以直接把浏览器实际请求使用的这两个参数值拿过来添加到以前的代码中即可。
至于 dm_img_list
设置为空就行,它太长了,反正没有它照样可以请求。
另外,经过测试,w_rid
(另一个重要的参数,不在本文讨论范围之类)的生成并没有依赖上面的 3 大天王
。
至此,算是勉强解决了。
试试看 dm_img_list
都到这里了,干脆也就试着分析它吧(虽然它的用处不大……)。
如下,可以确定它是利用 JSON.stringify
转换而来。
全局搜索关键词 JSON.stringify
会有很多结果,这时候就需要通过 hook
了。
let my_json_stringify = JSON.stringify;
JSON.stringify = function (a) {
console.log("========== JSON stringify Start ==========");
// 根据上图的分析,传给 stringify 的是一个数组哟
// 而数组的元素是一个对象,含有 x、y、z 等属性,根据这些特征进行详细地判断
if (Array.isArray(a) && a[0]?.hasOwnProperty("x") && a[0]?.hasOwnProperty("y") && a[0]?.hasOwnProperty("z") && a[0]?.hasOwnProperty("timestamp")) {
debugger;
}
console.log(a);
console.log("========== JSON stringify End ==========");
return my_json_stringify(a);
}
如下,在进行翻页时看到了目标!
上述的 t
其实就是下图中的 s.userLog
,并且意外的看到了其它 2
大王。
所以关键数据来自于上面的 this.getLog(o, i)
方法,最后经过查找,它取了 this.logStack
的值进行处理。
而要往数组添加数据有 .push、unshift
等等,找到了它的代码。此处并没有详细分析,只是看了个大概,毕竟没有它也能访问接口啦,只是好奇。
尾声
修为越高,斗法的对手也越强,就更需要好的灵器、并且熟练运用它们。
其实,利用合适的灵器,今天的 3 大天王
能很快突破。
- 比如有写好的
hook
能直接将各种常用的解密函数的结果输出
- 只要将这些输出和
dm_img_str
的值稍微一对比就能知道其位置的了。
如下,在 v_jstools
中启动这些东西。
然后在控制台搜索相关参数名字是能搜索到的,不过 A+1
站自己定义了 btoa
函数,导致插件没有将其 hook
掉,故无法直接搜索 dm_img_str
的参数值啦,不过知道了 hook
原理也能直接修改网站的 js 文件啦。
番外:搜索的关键字太短
无论是以前的全局搜索关键字,还是今天的在内存分析界面中搜索关键字都有一个缺点:如果关键字太短则搜索结果太多。
此时可以试一试 浏览器内存漫游
的方法,可以理解为它是一种大型的 hook
,据作者所说可以做到 “通杀”,具体见 GitHub - JSREI/ast-hook-for-js-RE: 浏览器内存漫游解决方案(探索中...)。
我并没有尝试,现有的灵器还用不顺手呢,也许当关键字隐藏太深时,可以一试。