概述
【瑞数5】浅谈某普期刊JS逆向的环境检测点
- 前言
- JS加载流程
- 第一个JS
- 第二个JS
- 第三个JS
- AST简单解混淆
- 环境检测
- 前奏
- 异步执行JS流程
- 高潮
- 运行结果
- 总结
- 鸣谢
前言
这几天把某期刊的rs5环境检测看差不多了,所以写篇文章简单聊下rs5会检测到的一些环境。我所用的方法基于浏览器“沙箱”的,可以做到边调试边补环境。
如果有想看算法运行逻辑的同学,出门左转看十一姐的文章。
RPC方案可以看看这个视频(陈不不大佬出品)。
https://www.bilibili.com/video/BV1PS4y127Mn
PS:我菜所以不会分析算法逻辑…
本文以某普期刊的高级检索接口作为示例,地址:aHR0cDovL3Fpa2FuLmNxdmlwLmNvbS9RaWthbi9TZWFyY2gvQWR2YW5jZT9mcm9tPWluZGV4
JS加载流程
第一步当然是,输入网址,F12,打上script断点调试,回车!
访问网页先是返回一个这样的html代码,而不是维普首页的内容。并返回给我们一个Cookie,GW1gelwM5YZuS=xxxxxx。玩过某数都知道,我们需要在这个页面得到一个GW1gelwM5YZuT参数,然后写在cookie中,再次访问网址,即可得到首页的内容。
第一个JS
第一个JS是生成$_ts参数。我建议大家先copy一份源代码以供后续本地调试。
然后这个JS的链接是在html页面里的,用正则可以很快的匹配到。
第二个JS
我们点击跳过断点,进入第二个JS。JS在$_ts里push很多参数,供后续使用。这个JS也是比较重要的,然后这个JS是在html页面里的,是一个闭包函数。JS运行结束时会用eval函数进入第三个JS。
然后html标签的meta,它的content参数,后续也是有使用到的。
第三个JS
这里就是eval函数入口。我们直接搜索]](_$ 字符串就能很快定位到这里了。打上断点看一下。没做过的同学可以自己试试各种方法去找到这里哈,博主用了hook cookie的方式找到了这里,贴上hook代码(直接从v神插件里偷代码,大佬的代码用起来就是舒服,嘿嘿~)。
init_cookie(document.cookie)
function init_cookie(cookie){
var cache = (cookie || "").trim();
if (!cache){
cache = ''
}else if (cache.charAt(cache.length-1) != ';'){
cache += '; '
}else{
cache += ' '
}
Object.defineProperty(Document.prototype, 'cookie', {
get: function() {
var r = cache.slice(0,cache.length-2);
v_console_log(' [*] document -> cookie[get]', r)
return r
},
set: function(c) {
v_console_log(' [*] document -> cookie[set]', c)
var ncookie = c.split(";")[0].split("=");
if (!ncookie[1]){
return c
}
var key = ncookie[0].trim()
var val = ncookie[1].trim()
var newc = key+'='+val
var flag = false;
var temp = cache.split("; ").map(function(a) {
if (a.split("=")[0] === key) {
flag = true;
return newc;
}
return a;
})
cache = temp.join("; ");
if (!flag) {
cache += newc + "; ";
}
return cache;
}
});
}
- 可以看到_$ya就是第三个JS了,并且这里的 $_ts已经init完成了。
- 这时候,我把3份JS都保存到本地了,供后续本地调试。
- 本地调试的时候,可以把入口注释掉,然后手动eval 格式化好的代码,这样调试会更轻松一些。
- 博主这边不依赖Node环境,使用vm2模块构建沙箱进行调试,然后Promise需要手写,否则V8运行会报错。
AST简单解混淆
第三份JS是重点需要调试并且查看代码是如何检测环境的。我们可以用AST简单的脱个混淆。我是直接在调试的时候把这个数组值的拿出来,然后用AST直接匹配替换(这个混淆数组是由一个函数得到的,这里就不放出来了,很好找到)。效果如图~
环境检测
前奏
前奏是指上述3个js执行完毕之后,会得到一个比较短的cookie(是可以直接访问的首页,检测比较松),以及三个环境值,在localStorage里,分别是 nd、cDro、YWTU
这部分的dom检测比较松,没什么坑,很容易补出来。
这里它创建了一个div节点,并使用了div.getElementsByTagName(“i”)方法获取了一个值。不懂的同学可以去菜鸟教程里看看,或者在浏览器里输入这些代码查看返回值等。 并且还检测了msCrypto以及ActiveObject。
每次调用xhr的open方法时,都会走向这里。他创建了一个a 标签,并对a标签href进行赋值。这里有做参数值校验,并和location里的参数进行比对,但是是有差异的,如果有问题会导致后面搜索接口里的得到的拼接url错误。
我们去浏览器hook下 createElement 这个方法,然后进到这个地方的代码看下a标签下的 href、pathname 等参数,将环境补的一模一样即可。
document.hookCreateElement = document.createElement;
document.createElement = function(tagName){
if(tagName === "a"){
debugger;
}
return document.hookCreateElement(tagName);
}
用 dir(标签a) 就能得到标签下的值了,下图是a标签下的值
与 location下的值还是有差异的,这里是有用的,对应的值必须要补的完全一样,然后这里其实有个小细节,通过对a标签的href进行赋值,a标签下的host hostname 等一些参数也会根据href的值来进行赋值,然后rs6也是有检测这个标签的。
这里就是使用了document.getElementsByTagName方法获取到了html页面里 meta 节点,得到了content参数,然后把这个节点删除掉了。
这里是把页面上 head下的所有script节点全部删除
检测了document.documentElement.style
页面上还有2个这样的函数,是在script节点下的,别漏掉了。这里的方法会再页面write一个节点出来,并删除所有script节点。
write了一个节点,若没有body节点,则会创建body节点并在body节点下加入一个子节点。
在这里获取他的名字 and 值
rs5 检测了location document navigator 等重要环境值,以及原型链toString检测。当我们使用代理(proxy)的时候(自行百度,不做介绍),就能监测到他使用了哪些环境变量。这里就不一一列举了,偏多~ 但是必须一致,否则会导致运行轨迹变化。
异步执行JS流程
前奏部分执行完毕后,开始异步执行最后的JS。这部分是得到localStorage里的 ff、f0 、f1 、fh1 环境变量,最后得到完整的cookie, 长度位279位。
下面是前奏的JS代码中,添加的一些异步方法(巨坑!!)
这里检测了navigator.getBattery方法,然后navigator.getBattery()后异步执行_$mg方法。
这里就是_$mg方法执行过程中会调用的一个地方,这里的 sy 再后续会用到,这里的level是一个环境值。Ap是BatteryManager。
然后是window.addEventListener 添加类型为 load 的监听事件,一共7个,在这过程中就有用到上面提到的 sy 参数, 若为undefined,就会导致JS运行轨迹变化。 异步执行方法的顺序需要注意!
然后再执行监听事件JS中,再次添加setTimeout 来实现异步执行JS。
_$_w就是setTimeout , 后面则是要执行的方法。
高潮
这部分尤其残暴。检测了各种节点操作,添加删除,寻找子节点 等等
这部分关系到 fh1 参数的形成。_$UC 是后续进行加密时会用到的数组。 创建div节点,通过设置innerHTML添加子节点,然后将div 加入到 body节点下。通过不断修改style来改变节点的高度、宽度,若修改style后的 宽、高 与一开始的宽高不一致,就把style样式的名称存入数组。
检测了 window 下的 matchMedia
这里是个小细节,window instanceof Window 结果是true。
这里就是webgl指纹了
还有很多坑,需要同学们自己去踩了才知道。博主这篇文章只放了一些踩到的坑~ 并不是全部。再多说一点,就不礼貌了~
运行结果
附上运行结果
其中ff是动态的(环境检测)。f0,f1在不同浏览器下会不一样,2个值的变化取决于 canvas指纹、webgl指纹,fh1可能在别的浏览器中不存在。YWTU(每份JS生成的不同),cDro都是静态的。
2022.7.7 补充
目前鼠标事件分析的七七八八了,比较重要的是move、leave、enter、down。至于事件流程,大家先在代码中找到赋值数组的位置,然后在浏览器上进行断点,查看是哪个鼠标事件触发之后会走到这。最后经过一系列的鼠标事件过后,cookie的xxxT参数以及url的后缀长度都会和浏览器一致。下面是运行结果测试,大致已经算是完结了,撒花~
2022.7.21 补充
由于沙箱是v8环境,我之前用execjs库运行js,无法动态缓存一些环境,所以是手动在v8环境中调用获取值来进行访问测试。然后就在今天,群里的泰迪佬告诉我py_mini_racer这个库是可以执行js并缓存环境的(在这里感谢下泰迪佬,爱你么么)。测试下来,执行速度还不错,连续访问了20次都返回了200状态码。安利一波~
2022.8.29 补充
用了v神的插件之后,就自己写了个hook 浏览器dom节点的脚本,能实现dom节点自吐调用了哪些函数和值,写的还不是很好。然后顺带hook了鼠标事件之后我才发现,这样去定位js代码调用鼠标事件的位置会更快一点。当然如果用控制流去判断,也能定位到位置,这样去查看调用堆栈会更清晰些。hook 脚本代码已经放在新出的文章里了~
总结
-
补环境当中,若遇到执行时的参数有问题,导致的运行轨迹变化,需要去浏览器上定位相同代码位置查找问题、或翻JS代码找到参数赋值的地方。
-
补环境的话,主要在意的就是在控制流循环下运行的顺序是否与浏览器上的一致。
PS:博主主要就是在这里比对浏览器的运行顺序,进行问题排查(可以排查大部分,还有一些需要自己去想办法找)。
-
博主文章写的少,可能排版看起来不舒服,还请见谅~
-
本篇文章仅供学习参考,如有侵权,请立即联系博主删除。未经博主允许请勿私自转发文章~
鸣谢
在这里感谢陈不不大佬,在JS逆向之路上提供了不少帮助~
有兴趣的小伙伴们可以看看他在B站上发的视频,对JS逆向提升有一定的帮助~
我、陈不不、泰迪合作的星球:https://t.zsxq.com/06bIUvBEM
最后
以上就是落寞铃铛为你收集整理的【瑞数5】浅谈某普期刊JS逆向的环境检测点前言JS加载流程AST简单解混淆环境检测运行结果总结鸣谢的全部内容,希望文章能够帮你解决【瑞数5】浅谈某普期刊JS逆向的环境检测点前言JS加载流程AST简单解混淆环境检测运行结果总结鸣谢所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复