JS逆向之某头条jsvmp逻辑层算法分析
今天我们来研究下,某头条的jsvmp逻辑层加密算法,其主要的目的是想在大家在接触此类算法时,给出点实质性的建议和思路。
0x01 分析加密
进入到目标网站通过分析请求会发现一个动态的 _signature 加密参数
0x02 定位加密
不同于以往,我们这次使用 ajax 请求拦截方式,来对这个参数进行拦截
通过堆栈的调用信息,得出以下结果
打上断点实现最终定位
换一种形式调用
0x03 window被赋予的属性
我们分析得知: _signature 参数由 window.byted_arawler.sign 方法实现,然而这个方法指向 acrawler.js 文件中一个莫名其妙的位置
所以我们目的也有了初步的明确:只要让 window 对象拥有 byted_acrawler 属性,那么整套算法就会被我们完全击破
0x04 惯用的方法
我们在本地新建一个 HTML 文件把代码整体拷贝过来,然后用浏览器打开
我们惊奇的发现,这个 byted_acrawler 属性已经存在于 window 对象之中,但是当我们借用 node 去执行它的时候,却秒被现实打脸
0x05 如何分析
我们先整体看下代码,除了 if-else 就是 else-if 活活的一个无限套娃形式,而且里面的逻辑,只用单一的字母表示,根本没有任何阅读性
虽然通篇都是 if-else 但它肯定也符合一定的逻辑规律,如若不然,它一定会报错。只不过官方这样做的目的,让它失去可读性,从而导致我们无法对分析。试想,我们可不可以,把它换一种形式进行表示出来,从而恢复它的可读性呢?
0x06 平坦化流程
这是一个全新的概念,也是对抗 jsvmp 算法必会的概念,虽然方式比较简单,但工程量比较庞大。我们需要将代码中所有的 if-else 替换成 switch-case 但问题在于 switch 哪个变量 case 那种情况?
观察一下这段代码:
var j = parseInt("" + b[O] + b[O + 1], 16);
验证一下,整体流程会不会因为j 变量的动态变化,进入到不同的逻辑分支?
不妨我们通过开篇所讲的条件断点试一下,每次 j=16 时会不会进入同一个逻辑分支中,如果能,说明 j 所有 if-else 的动态参数。如果不能,那就再去验证其他参数。
经验证,我们可以确定 j=16 时都会进入到上述的分支,所以我们不妨可以这样将它表示出来
switch (j) {case 0:// todo somethindbreak;case 16:q = S[R--],w = S[R--],(A = S[R--]).x === G ? A.y >= 1 ? S[++R] = K(b, A.c, A.l, q, A.z, w, null, 1) : (S[++R] = K(b, A.c, A.l, q, A.z, w, null, 0),A.y++) : S[++R] = A.apply(w, q);break;default://todo somethingreturn; }
最终我们梳理的结果是这样的
这里注意一下:x 会有一个偏移量计算,每次运行都会 x>>4 并且 x 和 A 的值相等
0x07 环境对比
等我们对代码平坦化流程之后,我们需要考虑之前的一个问题,为什么浏览器环境就可以拥有byted_acrawler 而 node 环境却是 undefined 呢?可能的原因是,它肯定存在某种环境的检测,导致 node 环境失效
我们先从运行的开端分析一下(这也是很多人会忽略的细节)
glb = "undefined" == typeof window ? global : window
这段代码放到浏览器运行,代表的是 window 对象
如果把它放到 node 环境运行,它代表却是 global 对象
所以我们需要改变下 node 环境,这里我采用的是 jsdom 来对环境进行一下伪装,这样的话,我们就改变了初始的环境
0x08 逻辑对比
修改完环境之后,我们再次运行我们本地文件,我们会发现抛出一个错误
这是 case 26 流程所抛出的,所以我们直接在官方打条件断点进行比对
这是官方的结果
经过对比,官方 S 中拥有Object 函数而本地却是 undefined 所以我们要给它添加这种属性
window.Object = function (){return ["native code"];
}
添加完之后自然有了这种属性
0x09 环境补全
鉴于这个对比过程太过漫长,我这里主要列出几个重要的属性,其他的请自行校验:
1.补齐 canvas 属性
window.HTMLCanvasElement.prototype.getContext = function () {return {fillText(text, x, y, maxWidth) {return ["native code"];},arc(x, y, radius, startAngle, endAngle, anticlockwise) {return ["native code"];},stroke() {return ["native code"]},getExtension() {return ["native code"]},getParameter() {return ["native code"]}}
}
2.补齐 localStorage(这个会影响 _signature 生成的长度)
(function () {let localStorage = {"__tea_cache_tokens_2018": "{"user_unique_id":"verify_kut5p98i_BUC0aRbH_QZ5B_4lu4_BQzz_F22NI2z6snKh","web_id":"7018918857491351074","timestamp":1634353853331}","__tea_cache_tokens_24": "{"web_id":"7018898163830441479","ssid":"522d279c-ba4b-4c85-a61c-98b7f1a05b71","user_unique_id":"7018898163830441479","timestamp":1634219409505}","__tea_cache_first_24": "1","tt_scid": "z1OscwP3.P6dJQt3WyFHyZ65WZCoGUYARVlW9x0SAYAXAN.mmr9m1v6FlmpA1M98f94d","__tea_cache_first_2018": "1","_byted_param_sw": "lmr6SespEoX9rv9+V/8="}for (var p in localStorage) {window.localStorage.setItem(p, localStorage[p])}
})()
修改 jsdom User-Agent (必须跟请求中保持一致)
resourceLoader = new jsdom.ResourceLoader({
strictSSL: false,
userAgent: “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36”,
});
const jsdomConfig = {
resources: resourceLoader,
url: “https://www.toutiao.com/”,
}
0x10 简洁化处理
如果细心的话会发现,每个分支的代码,只运行了一小部分就跳出了所在的分支,剩下的代码形同虚设般存在。之所以会这样,是因为分支内部的 A 值会影响代码的整体走势,所以我们只需要判断满足 A的代码就可以,其他的都是在尸位素餐
精简之前
case 25:(A = x) > 8 ? (C = S[R--],S[R] = typeof C) : A > 6 ? S[R] = --S[R] : A > 4 ? S[R -= 1] = S[R][S[R + 1]] : A > 2 && (q = S[R--],(A = S[R]).x === G ? A.y >= 1 ? S[R] = K(b, A.c, A.l, [q], A.z, w, null, 1) : (S[R] = K(b, A.c, A.l, [q], A.z, w, null, 0),A.y++) : S[R] = A(q));break;
精简之后
case 25:S[R -= 1] = S[R][S[R + 1]]break;
0x11 总结
1.对于这种混淆的代码而言,流程平坦化是首选,但如何进行才是关键
2.代码不仅想知道你的运行环境,它更想知道这种环境是否真的适合它
最终效果:
最后声明:
本片文章只用于学习交流,切勿用于商业用途,如果有侵权行为,请与作者联系,本人会在第一时间将其删除。
欢迎关注:
JS逆向之某头条jsvmp逻辑层算法分析相关推荐
- 【JavaScript 逆向】今日头条 jsvmp,_signature 参数分析
前言 现在一些网站对 JavaScript 代码采取了一定的保护措施,比如变量名混淆.执行逻辑混淆.反调试.核心逻辑加密等,有的还对数据接口进行了加密,这次案例是通过补环境过 jsvmp. 声明 本文 ...
- 【JS逆向系列】某乎x96参数3.0版本与jsvmp进阶
[JS逆向系列]某乎x96参数3.0版本与jsvmp进阶 前言 初看js代码 补环境方案 修改字节码方案(反混淆与反汇编) 算法还原 后记 前言 距离上一次的某乎jsvmp也过了好一段时间,现在也从2 ...
- 【JS逆向系列】某乎x96参数与jsvmp初体验
[JS逆向系列]某乎x96参数与jsvmp初体验 js分析 jsvmp分析 第一种解决方案-补环境 第二种解决方案-修改操作码 第三种解决方案-算法还原 参考文章 样品网址:aHR0cHM6Ly93d ...
- Js逆向教程17-极验滑块 实现加密算法的逻辑
Js逆向教程17-极验滑块 实现加密算法的逻辑 还是和上节课一样,针对这个网址 https://www.geetest.com/demo/slide-float.html 一.加密算法的结果查看 计算 ...
- 微信小程序学习笔记 ( 小程序主体学习 二 逻辑层 app.js 扩展 高级食用方法)
目录结构 上图是我建立的的微信小程序的目录结构 主体学习 逻辑层(App Service) 小程序开发框架的逻辑层由 JavaScript 编写. 逻辑层将数据进行处理后发送给视图层,同时接受视 ...
- js逆向案例-rus4逻辑学习
目录 一.RS4特点 二.网站请求流程特点 三.网站加载js的顺序 四.正式逻辑的研究 1.cookie如何定位? 2.扣函数缺啥补啥注意事项? 3.如何获取`$_ts动态变量`值? 4.如何定位`M ...
- 爬虫逆向 js逆向常用工具简单介绍
古语有云:工欲善其事,必先利其器. 作为逆向的开始,这个自然是无法避免的,毕竟js逆向的环境是浏览器,而浏览器自然为开发做了很多工具,方便再开发的时候检测开发过程中是否有问题,就像开发过程中debug ...
- python爬虫 慢慢买历史低价爬取 js逆向入门
[本文仅供学习,请勿用于非法用途,若非法使用概不负责] 前话: 最近计划从Java转向爬虫,假期闲来无事想着找点事情做,于是就想着能不能把慢慢买的商品历史价格爬下来.(PS:作者平时购物喜欢使用慢慢买 ...
- 微信小程序学习笔记(4)--------框架之逻辑层
逻辑层 逻辑层(App Service):小程序框架的逻辑层是由JavaScript编写的,逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈. App进行程序注册,Page进行页面注册 g ...
最新文章
- 在C#中应用哈希表(Hashtable)
- python 类的执行中保部存值_python函数名称空间与作用域、闭包
- POJ-2635 The Embarrassed Cryptographer 大数取模
- 2015-03-06——正则表达式基础
- react native redux 梳理
- 【Cocosd2d实例教程六】Cocos2d实现屏幕背景的自动滚动
- Linux 系统应用编程——出错处理(errno)
- mysql类 php100_php mysql 类
- Centos 6.5部署nginx+uwsgi+django
- 在网上搜到的有用的资料
- 最新版python如何安装qt5_Python3 搭建Qt5 环境的方法示例
- 爬虫项目——xpath练手(1)
- 海思使用HiTool下载程序
- 三星2610打印机故障INTERNAL ERROR - Incomplete Session by time out
- 计算机无法读取智能卡,电脑智能卡读卡器驱动程序丢失怎么办?如何重新安装智能卡服务?...
- oracle+sql+groupby,oracle学习笔记2:SQL执行
- 多重背包二进制优化(wzk吃小鸡腿)
- 4.2w字,详细的带你认识基础I/O【Linux--基础IO】
- 微信公众号服务器端脑图,微信公众号中隐藏的思维导图工具,帮你随时随地高效思考...
- 布袋除尘器过滤风速多少_布袋除尘器过滤风速的选择!