JS逆向之补环境过瑞数详解

news2024/11/26 20:28:40

JS逆向之补环境过瑞数详解

“瑞数” 是逆向路上的一座大山,是许多JS逆向者绕不开的一堵围墙,也是跳槽简历上的一个亮点,我们必须得在下次跳槽前攻克它!! 好在现在网上有很多讲解瑞数相关的文章,贴心的一步一步教我们去分析瑞数流程,分析如何去扣瑞数逻辑,企图以此教会我们 (手动狗头)。却鲜有文章详细去讲解如何通过纯补环境的方式过瑞数。今天,它来了!

为了让大家彻底搞定瑞数这个老大哥,本文将从以下四个部分进行描述:

  1. rs的流程逻辑
  2. 浅谈扣代码过rs
  3. 详解补环境过rs
  4. 扣代码与补环境对比
  5. 弯道超车环节

篇幅较长,坐稳发车咯!
注:本文内容均以一个新人友好型 rs4网站: 网上房地产,为例;

一:rs的流程逻辑

我们在做逆向的时候,首先得分析出哪些加密参数是需要逆向的,然后再是去逆向这些参数。当然瑞数也是一样。
所以我们第一步就是明确逆向的目标

  • 现象:上了rs的网站会请求两次page_url,第二次请求page_url时才能得到正确的页面内容;
  • 分析:分析其请求体,发现第二次请求page_url时带上了cookie_s和cookie_t, 而cookies_s是来自第一次请求page_url时其响应头set的;
  • 结论:那么我们的目标就确定了 – 破解cookie_t的生成逻辑;

现在,我们知道了需要逆向的加密参数是cookie_t,那么cookie_t是从何而来呢,我们先分析一下网站的请求

瑞数网站请求流程分析:

第一次请求: 请求page_url,响应状态码202,响应头中 set了 cookie_s;
在这里插入图片描述
响应体是HTML源码,从上到下可以分为四部分:我先剧透一下它们的作用

  1. 一个meta标签,其content内容很长且是动态的(每次请求会变化),会在eval执行第二层JS代码时使用到;
  2. 一个外链js文件,一般同一页面中其内容是固定的,下面的自执行函数会解密文件内容生成eval执行时需要的JS源码,也就是第二层vm代码;
  3. 一个大自执行函数(每次请求首页都会动态变化),主要是解密外链JS内容,给window添加一些属性如$_ts,会在vm中使用;
  4. 末尾的两个script标签中的函数调用,会更新cookie,使其变长。这里我们可以不用关注这个。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Y95CH4R-1673156546278)(https://note.youdao.com/yws/res/26818/WEBRESOURCE8752b7a5f31959082ecd992b3c0c4ace)]

第二次请求: 请求外链js,一般内容是固定的;
在这里插入图片描述

第三次请求: 请求page_url,返回200,携带cookie_s,cookie_T即可正常请求;
在这里插入图片描述

那么当我们在浏览器中访问该网站时到底发生了什么?其中有什么值得我们关注的?
我们先人工模拟一下浏览器加载page_url源码会发生什么:

  1. 浏览器加载meta ;
  2. 浏览器请求外链js并执行js内容;
  3. 执行page_url源码自执行函数,它内部会将外链js解密成eval需要的万行js字符串,并给window.$_ts添加了很多属性,然后调用eval函数进入VM执行解密后的js,生成cookie,eval执行完毕,继续执行自执行函数;
  4. 执行末尾script标签中的代码,这些代码会更新cookie_t(可以不用管
  5. 执行setTimeout、eventlistener回调函数(可以不用管

瑞数执行流程图解如下:
瑞数执行流程图解

这里我们需要关注eval调用的位置(也就是VM的入口),cookie生成的位置

注:浏览器v8调用eval执行代码时会开启一个虚拟机(VM+数字)去执行JS代码。

我们直接hook eval搜索.call就可以定位到调用eval的位置
在这里插入图片描述
_$Ln就是解密后的js代码字符串;进入vm是一个自执行函数,其中有生成cookie的逻辑,定位cookie可以直接hook或在vm代码中搜索 (5)
在这里插入图片描述

hook cookie代码:

// hook  指定cookie赋值
(function () {
    'use strict';
    Object.defineProperty(document, 'cookie', {
        set: function (cookie) {
            if(cookie.indexOf("FSSBBIl1UgzbN7N80T")!= -1){
                debugger;
            }
            return cookie;
        }
    });
})();

好了,以上就是瑞数的整体流程逻辑,那么我们该如何通过扣代码去生成cookie_t过瑞数呢?

二、浅谈扣代码过瑞数

由于每次请求瑞数page_url,其源码是动态变化的,VM代码也是动态变化的,所以我们要保存一份静态代码方便调试;
直接如图这样,固定page_url响应即可,
在这里插入图片描述

这样请求时,page_url中的 外链JS是固定的,自执行函数是固定的,VM中的代码也是固定的,那么这份固定代码每次生成的cookie_t 是不是也固定呢?
答案:不是,因为cookie_t的生成用到了随机数时间戳,我们将这两个变量也hook固定住,最终生成的cookie_t就是固定的啦。

此时我们就可以开始扣这份静态代码了,扣到node生成的cookie_t与浏览器执行静态代码生成的cookie_t 一致就说明扣成功了。

扣代码需要扣两部分,page_url源码部分和VM中生成cookie_t部分。
按照我们之前的分析,VM中代码会用到window.$_ts,因此我们得先保证从page_url源码中扣下来的代码执行到eval时,能正常生成window.$_ts

我们将page_url的自执行函数外链JS内容先扣下来,meta content也先扣下来,然后根据执行报错简单补一下环境,使得扣下来代码执行到eval时,其window.$_ts和解密出的VM JS代码与本地静态代码生成的一致。
在这里插入图片描述
这就说明我们page_url源码部分扣好了,接下来就可以去扣VM中生成cookie_t的部分。

上面我们分析到cookie的定位,可以知道 _$bO这个函数中生成了二次cookie_t,那这就是我们扣代码的起点,将该函数扣到文件末尾,直接执行,然后缺啥补啥,遇到使用BOM、DOM api的代码时,我们可以使用等价逻辑替换,比如此处原逻辑是获取meta标签中的content内容,然后再删除meta标签,我们可以直接等价替换成 return meta_content。如图:
在这里插入图片描述

如果扣到最后,node生成的cookie_t与本地静态代码生成的不一致,则说明我们扣的代码有些环境检测没过,我们可以根据node与浏览器执行的差异去定位,比如node执行到某个地方的值与浏览器执行静态代码得到的不一样,说明前面逻辑有差异,继续向前定位,如此反复即可找出所有遗漏的环境检测,完成VM部分扣取。

此时我们就完成了这份静态rs代码的扣取并取得成功,但是rs网站的代码是动态的啊,每次请求时 window.$_tsVM js都会变化,难道我们每份都要去扣吗?不,其实我们现在离真正成功只差一个映射,
VM的万行js代码 虽然每次都会变化,但是变化的只是变量名,其他的都不变。
映射就是将动态window.$_ts中的属性名与 我们扣的VM 中JS用到的window.$_ts中的固定属性名一一对应。

所以在扣的过程中我们需要注意VM中哪些地方使用了外部变量,(即一个函数中,哪个变量来自其他作用域,就算外部变量),我们需要关注这些外部变量是从哪来的,如果是VM自执行函数中定义的,那就不用管,如果是来自window.$_ts,则需要记录下来,这就是需要映射传入的。
在这里插入图片描述
这里的计算逻辑使用到了 window.$_ts._$IK,所以我们要做映射时要传入这个值;window.$_ts={_$IK:对应的动态属性名}

解决完映射,也就成功扣代码过rs了。
好了,扣代码到此为止,接下来就是我们本文的重点。

三、详解补环境过rs

不知道补环境原理的同志可以参考我上篇文章:JS逆向之浏览器补环境详解;
其实纯补环境过瑞数原理很简单,我们来观察瑞数执行流程图解,基于浏览器环境执行这些动态JS可以生成可用的 cookie_t。那么只要我们补的浏览器环境足够完美,使得在这些动态JS看来,我们补的环境===浏览器环境,那么我们补的环境执行这些动态JS,同样也能生成可用的 cookie_t,然后我们再通过 document.cookie 将cookie_t 提取出来不就好了。

用伪代码表示就是:

// 补的环境头
window = this;
... 省略大量环境头
// 模拟meta标签及其content
document.createElement('meta');
Meta$content = "{qYnKTJPAw84QfF5jm0I2_1IqhgTvRw8Y0yCBPxIVn6od8AeJE6CBz8ZSU6U...省略";
// 固定的外链js
$_ts=window['$_ts'];if(!$_ts)$_ts={};$_ts.scj=[];$_ts['dfe1675']='þþ+...省略';
// page_url动态自执行函数
(function(){var _$CK=0,_$WI=[[9,3,6,0,4,1; ...ret = _$su.call(_$fr, _$WR); 很长...省略}}}}}}}})();;


// 获取cookie
function get_cookie(){
    return document.cookie;
}
// 获取MmEwMD参数
function get_mme(){{
    XMLHttpRequest.prototype.open("GET","http://脱敏/",true);
    return XMLHttpRequest.prototype.uri;
}}

这就是我们最后要补成的文件样子,由于Meta$content 和page_url动态自执行函数是动态变化的,因此我们每次请求page_url 都需要用正则提取出这两个字符串,然后拼接到该文件中,然后python pyexecjs调用get_cookie即可得到可用cookie_t;

在上面的扣代码过瑞数中也提到了,由于有随机数时间戳参与生成cookie_t 运算,导致同一份静态JS代码生成的cookie_t 是变化的,我们可以通过hook使得时间戳和随机数固定,这样同一份静态JS生成的cookie_t就是固定的。

// 固定定随机数和时间戳
Date.prototype.getTime = function(){return 1672931693};
Math.random = function(){return 0.5};

我们也可以通过最终生成的cookie_t 来判断,自己补的环境是不是===浏览器环境
原理很简单,接下来就是如何实践,我们需要补出一份完美的环境头使得这份静态JS执行得到的cookie_t与浏览器执行得到的一致。
因为补环境是一个系统性工作,是有通用套路的,我们可以使用上篇文章提到的补环境框架进行系统性补环境,我们要做的就是根据log输出以及出现的问题不断完善这个框架。

如图,启动框架,上面是我们补的环境头,下面是我们扣的代码,
在这里插入图片描述

继续调试,当我们Proxy拦截器拦截到BOM、DOM api的使用时,就会debugger住,我们可以根据 调用栈 去查看是哪行代码使用的浏览器环境,然后再看到框架中模拟的结果是不是跟浏览器一致,如果不一致,则需要补这个环境。
在这里插入图片描述

如此往复的补环境,直到最后可以生成cookie_t,判断是否与浏览器本地生成的一致,如果不一致则使用二分法去定位,看是哪个浏览器环境没补好,直到 最终得到正确的cookie_t,这里贴一下最后执行效果图:
这是最后打印的一部分环境检测点
在这里插入图片描述

这是取出最终得到的cookie_t
在这里插入图片描述

同理,MmEwMD参数的补环境也是一样的逻辑,当环境头补到完美时,在python中执行最终结果文件,即可得到如下结果:
在这里插入图片描述

四、补环境与扣代码总结:

对于js逆向来说,这是两种常规且实用的手段,也各有优劣势;

不管使用哪种方式,我们都是先从网站中将加密JS代码扣出,然后再选择是继续扣代码,将使用到的浏览器环境api进行逻辑替换;还是使用补环境,让加密JS代码仿佛在浏览器环境中运行。

  • 扣代码与补环境都依赖对JS的熟练度,扣代码更侧重js语法和代码逻辑,补环境更侧重原型链及BOM、DOM对象的模拟。
  • 扣代码熟练度依赖逆向经验,补环境几乎只依赖JS熟练度。
  • 扣代码需要调试跟踪大量逻辑,对于rs,如果不解混淆的话,屁股得坐出痔疮;
  • 扣代码需要替换环境检测逻辑,所以也需要知道哪里使用了浏览器环境; 补环境框架可以只用于监测浏览器环境的使用,可以当做扣代码的一个辅助工具。
  • 由于瑞数是动态的,扣代码只能扣一份静态的,所以需要找到vm中使用到的所有动态属性进行映射。而补环境是通用的,补的越多,可通杀的网站就越多。
  • 扣代码比补环境执行效率高,毕竟补环境的代码数比扣代码多很多,可以通过剔除不需要的环境来缩小差距;
  • 扣代码人工耗时远高于补环境。

总而言之,扣代码侧重js语法和代码逻辑,其熟练度依赖于逆向经验,对不同网站要扣的不一样,难以通用,人工效率低,但是程序执行效率高。
补环境侧重原型链及浏览器环境模拟,熟练度几乎只依赖对JS的原理掌握程度,对于不同网站补的越多可通杀的网站越多,人工效率巨高,但是程序执行效率不高。

五、弯道超车环节

过瑞数几乎是每个新手逆向者的小目标,也是面试官常见的提问点。通过本篇文章,我们已经了解了 瑞数的流程及破解思路,接下来我们可以尝试自己从头实现一个完善的补环境框架,去纯环境黑盒过瑞数,但是这会花费很长一段时间来进行开发,而且其中有很多重复性工作比较无聊(复制粘贴对比等)。

走快车道:
本文该版本 补环境框架 是基于上篇文章框架进行系统性完善的,目前可以过瑞数这种级别网站,可以说是相当完善了,补了相当多的环境,如果你想省下大量时间、极大提高效率、直接弯道超车的话,可以 微信联系我:dengshengfeng666 付费源码借鉴;
春节优惠价199(节后恢复统一固定价 233),付完直接发框架项目源码(有最新图文readme可直接小白上手),后续有疑问可以直接问我。
或者直接在CSDN私信我。

该版本与上版本改进点:

  1. 优化Proxy13种拦截器,做到了Proxy的极限,并使其能递归代理,支持a.b.c.d.e…级别的深度检测;
  2. 完善最终结果文件.js的调用机制,使其无需改动,能直接用于V8和node调用;
  3. 新增部分BOM、DOM对象,如:XMLHttpRequest,XMLHttpRequestEventTarget等等;
  4. 补全rs用到的所有浏览器环境方法,使其可以黑盒过rs;
  5. 优化调试方式,可以在想断的时候断点,不想断的时候跳过检测;
  6. 增加py直接调用结果文件案例,可以使用python以v8和node方式调用;
  7. 优化readme,图文介绍环境配置及使用方式。

弯道超车,从我做起
该版本框架目录:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167140.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

英伟达Flex-unity插件

好像有这么个库,可以用来流体仿真 官网是这个:NVIDIA FleX | NVIDIA 开发者 问题 但是现在好像没了: NVIDIA FleX for Unity (1.0 BETA) | 物理 | Unity Asset Store 百度 Unity 8.Oct.2021 Unfortunately, NVIDIA FleX for Unity (1.0 …

完美Crack:Froala Editor 4.0.16 Patch

基于 Web 的 JavaScript/HTML WYSIWYG 文本编辑器。 Froala Editor 是一个用 JavaScript 编写的轻量级 WYSIWYG HTML 编辑器,可为您的应用程序启用富文本编辑功能。使用简单,许多功能不必用数百个按钮让用户不知所措。编辑器的智能工具栏可以在一个简单的…

ESP-IDF:基于企业链表实现的循环链表实例,实现了初始,插入,循环打印的功能

例程: /* circle链表基于企业链表*/ // 链表节点 typedef struct CIRCLENODE { CIRCLENODE *next; } circleNode; typedef struct CIRCLELIST { circleNode head; int size; } circleList; circleList *Inital_CircleList() { circleList *cp (circleList *)mal…

LeakCanary简要原理

首先需要知道ReferenceQueue&#xff08;引用队列&#xff09;&#xff1a;public static void main(String[] args) {Activity activity new Activity(); // 模拟ActivityReferenceQueue<Activity> queue new ReferenceQueue<>(); // 引用队列WeakReference<…

从汇编的角度了解C++原理——new和malloc的区别

文章目录1、new和malloc的区别1.1、例程1.2、总结本文用到的反汇编工具是objconv&#xff0c;使用方法可以看我另一篇文章https://blog.csdn.net/weixin_45001971/article/details/128660642。 其它文章&#xff1a; 从汇编的角度了解C原理——类的储存结构和函数调用 从汇编的…

【索引】引用A survey on pickup and delivery problems的文章

1. Dynamic container drayage with uncertain request arrival times and service time windows⭐️ 具有不确定请求到达时间和服务时间窗口的动态集装箱运输 Container drayage plays a critical role in intermodal global container transportation, as it accomplishes th…

hud 1846巴什博弈(简单的解法 或 Sprague-Grundy解法)

各位勇敢者要玩的第一个游戏是什么呢&#xff1f;很简单&#xff0c;它是这样定义的&#xff1a; 1、 本游戏是一个二人游戏; 2、 有一堆石子一共有n个&#xff1b; 3、 两人轮流进行; 4、 每走一步可以取走1…m个石子&#xff1b; 5、 最先取光石子的一方为胜&#xff1b; 如…

不懂Token,就是别说自己是中级测试工程师

官方回答&#xff1a; Token 是在服务端产生的。如果前端使用用户名/密码向服务端请求认证&#xff0c;服务端认证成功&#xff0c;那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位。 基于工程师的理解&#xff1a; token就相当于客户…

Go语言初始

"当我回头&#xff0c;妄想找到幸福的线索&#xff0c;那束光拉长我的影子&#xff0c;逃离我。"一、Go简介Go&#xff08;又称 Golang&#xff09;是 Google 的 Robert Griesemer&#xff0c;Rob Pike 及 Ken Thompson 开发的一种静态强乐西、编译型语言。Go 语言语…

Unicorn反混淆:恢复被OLLVM保护的程序(一)

一、目标 现在很多程序利用ollvm的控制流平坦化来增加逆向分析的难度。 控制流平坦化 (control flow flattening)的基本思想主要是通过一个主分发器来控制程序基本块的执行流程&#xff0c;例如下图是正常的执行流程 1:show1 经过控制流平坦化后的执行流程就如下图: 1:show2 …

RT-Thread系列--启动过程

一、目的RT-Thread是一个小而美的RTOS&#xff0c;所有的RTOS的都有一个特点&#xff0c;那就是存在调度器&#xff0c;像RT-Thread的调度器是一个实时抢占式调度器&#xff08;同优先级任务使用时间片调度方式&#xff09;。本篇不讲调度器相关的内容&#xff0c;着重讲解调度…

【博客591】LVS的DR和NAT模式下要注意的缺陷

LVS的DR和NAT模式下要注意的缺陷 1、DR模式和NAT模式的转发原理 2、LVS的DR和NAT模式下要注意的缺陷 缺陷1&#xff1a;DR模式下的realserver和 lvs的vip提供服务的端口必须一致。 例如vip的端口对外端口为 80&#xff0c;但后端服务的真实端口为8080&#xff0c;通过lvs的D…

SpringBoot快速上手

SpringBoot 概述 Spring Boot 可以轻松创建独立的、生产级的基于 Spring 的应用程序&#xff0c;您可以“直接运行”。 特征 创建独立的 Spring 应用程序 直接嵌入Tomcat&#xff0c;Jetty或Undertow&#xff08;无需部署WAR文件&#xff09; 提供固执己见的“入门”依赖项…

初始C语言 - 函数(2)

目录 1.函数的嵌套调用和链式访问 1&#xff09;函数嵌套调用 2&#xff09;函数的链式访问 - 函数的返回值作为另一个函数的参数 2. 函数的声明和定义 1&#xff09;变量的声明和定义 2&#xff09;函数的声明和定义 //函数必须先声明后使用//函数的声明写在头文件里 3.…

集成学习、Bagging集成原理、随机森林构造过程、随机森林api与案例、boosting集成原理、梯度提升决策树(GBDT)、XGBoost与泰勒展开式

一、集成学习 集成学习&#xff1a;通过建立几个模型来解决单一预测问题&#xff0c;工作原理是生成多个分类器/模型&#xff0c;各自独立地学习和作出预测。这些预测最后结合成组合预测&#xff0c;因此优于任何一个单分类的做出预测 机器学习的两个核心任务 集成学习中boost…

【UE4 第一人称射击游戏】51-制作手榴弹

上一篇&#xff1a;【UE4 第一人称射击游戏】50-用另一种方法实现僵尸随机漫游 僵尸攻击玩家时造成伤害本篇效果&#xff1a;按G键投掷出手榴弹&#xff0c;产生爆炸效果步骤&#xff1a;新建一个蓝图类&#xff08;父类为Actor&#xff09;&#xff0c;命名为“GrenadeActor”…

水声功率放大器模块在圆柱壳结构声源辐射研究中的应用

客户需求&#xff1a;实验需要在消声水池中对圆柱壳声源振动和远场声压进行实验测量&#xff0c;圆柱壳内部尺寸为&#xff1a;高0.5m(不含盖板)&#xff0c;壳外径0.5&#xff0c;内径0.497m&#xff0c;上下盖板高0.014m&#xff0c;所以对圆柱壳内功率放大模块的尺寸以及供电…

Qt图表操作(QCustomPlot 与 QtCharts的介绍与使用)

一、QCustomPlot简介 QCustomPlot是QT下一个方便易用的绘图工具&#xff0c;该绘图库专注于制作美观&#xff0c;出版品质的2D图表&#xff0c;图表和图表&#xff0c;以及为实时可视化应用程序提供高性能。它可以导出为各种格式&#xff0c;如矢量化的PDF文件和光栅化图像&…

Task12 数据缘何而来数据格式

目录1 常见的格式1.1 Excel文件的格式1.2 Excel数据的格式1.3 基本知识2 Excel数据格式2.1 数据类型转换3 练习1 常见的格式 1.1 Excel文件的格式 Excel文件的常见格式&#xff1a;.xls和.xlsx 1.2 Excel数据的格式 Excel数据的存储不同格式&#xff1a;xlsx、csv、txt cs…

mysql快速生成100W条测试数据(8)全球各城市人口及经济增长速度并存入mysql数据库

这是之前的文章里面包含一些以前的一些操作流程可以进行参考学习 更加详细操作步骤在第一篇文章里面 mysql快速生成100W条测试数据&#xff08;1&#xff09;&#xff1a;游戏人物数据 mysql快速生成100W条测试数据&#xff08;2&#xff09;公司员工信息 mysql快速生成100W条测…