第17章 Day20-Day21 逆向爬虫之瑞数6

news/2025/9/25 15:32:17/文章来源:https://www.cnblogs.com/fuminer/p/19111311

逆向爬虫之补环境专题

一、补环境的原理

浏览器环境和node环境对比:

image-20250113下午70540645

浏览器下:

image-20250113下午93341880

node.js

image-20250113下午93621748

当我们辛苦将浏览器环境的加密或者解密入口找到,把加密或者解密的JS的代码拷贝到本地,由node解释器驱动执行的时候,会因为拷贝的JS代码中包括只能由浏览器调用的API,现在被node执行就会报错,为了解决这个问题,我们需要在拷贝的代码环境中模拟补充需要的前端对象,所以我们就非常有必要掌握浏览器接口对象常用的八大前端对象

二、Window对象

  • window:窗口对象,也是最重要的一个对象

    addEventListener:f
    setInterval:f
    setTimeout:f
    name
    selfdocument
    navigator
    location
    screen
    historytoString:f
    

    window是顶级变量,在浏览器中,任何在全局作用域中声明的变量或函数都会成为 window 对象的属性。例如,如果你声明一个全局变量 var yuan = 10;,你可以通过 window.yuan。window 仅在浏览器环境中存在。在 Node.js 等其他环境中,顶级对象是 global

  • document:文档对象:第二重要对象

    body
    documentElement
    cookiegetElementById:f
    getElementByTagName:f
    getElementByClassName:f
    createElement:ftoString:f
    
  • navigator:导航对象

    userAgent
    toString:f
    
  • location:地址栏对象

    href
    toString:f
    
  • screen:屏幕对象

    availHeight
    availLeft
    availTop
    availWidth
    toString:f
    
  • history:历史对象

    back
    forward
    go
    toString:f
    
  • localStorage和sessionStorage:本地存储对象

    getItem:f
    setItem:f
    removeItem:f
    toString:f
    
  • element:泛指,标签对象

    # 常用标签对象
    h1-h6标签
    p标签
    input标签
    div和span标签
    img标签
    table标签
    form标签
    canvas标签:toDataURL:f# 标签对象常用属性和方法
    ele.style
    ele.innerHtml
    ele.getAttribute()
    ele:ele.getElementById:fele.getElementByTagName:fele.getElementByClassName:f
    

image-20250114下午90709036

为了更好的让大家理解我们接下来的实战补环境案例,我先给大家模拟了一套简单的JS逆向代码

function get_sign() {// 黑匣子,省略很多代码// (1) BOM和DOM正常的前端动作window.addEventListener("test")// 搜索框let kw = document.getElementById("kw")let _class = kw.getAttribute("class")// 创建画布let canvas = document.createElement("canvas")let ctx = canvas.getContext("2d");ctx.fillRect(10, 10, 100, 100);// (2) 基于DOM和BOM进行环境校验if (navigator.toString() === '[object Navigator]') {let navLength = navigator.userAgent.lengthreturn "u82d1660a" + navLength // Yuan老师的微信,想深入学逆向爬虫的联系我,结一段善缘!} else {return false}
}console.log(get_sign())

在这里,整层的JS加密代码对于我们而言就是一个黑匣子,有千千万万行代码,甚至做了混淆处理,我们不能去一行行读,看看整个过程到底用到了哪些对象以及对应的属性和方法的。所以这里就涉及到了到了补环境最终的一件事情:代理监控

三、Proxy代理

JavaScript中的Proxy是一种内置对象,它允许你在访问或操作对象之前拦截和自定义底层操作的行为。通过使用Proxy,你可以修改对象的默认行为,添加额外的逻辑或进行验证,以实现更高级的操作和控制。

Proxy对象包装了另一个对象(目标对象),并允许你定义一个处理程序(handler)来拦截对目标对象的操作。处理程序是一个带有特定方法的对象,这些方法被称为"捕获器"(traps),它们会在执行相应的操作时被调用。

var yuan = {username: "yuan",age: 22,wx: "u82d1660a"
}
yuan = new Proxy(yuan, {get(target, p, receiver) {console.log(target, "查询了属性", p)// return window['username'];/// 这里如果这样写. 有递归风险的...// return Reflect.get(...arguments);return Reflect.get(target, p);},set(target, p, value, receiver) {console.log(target, "设置了属性", p, "值为:", value)Reflect.set(target, p, value);}
});yuan.username;
yuan.age;
yuan.username = "rain"
yuan.age = 18

image-20250113下午94526816

基于Proxy的特性,衍生了基本补环境思路:在本地,用Proxy代理监控浏览器所有的BOM、DOM对象,相当于在node.js中,对整个浏览器环境对象进行了代理,拷贝的加密JS代码使用任何浏览器 api都能被我们所拦截。然后我们针对拦截到的环境检测点去补对应属性和方法。

因为接下来的补环境中,涉及到需要监控的前端对象还是比较多的 ,如果每一个都按着上面对yuan的Proxy代理,就会导致监控代码大量重复不简洁。所以,在这里,爬虫工程师都需要一个简单的功能函数,对需要监控的数组对象循环监控:

function setProxyArr(proxyObjArr) {for (let i = 0; i < proxyObjArr.length; i++) {const objName = proxyObjArr[i];const handler = {get(target, property, receiver) {console.log("方法:", "get", "对象:", objName, "属性:", property, "属性类型:", typeof property, "属性值:", target[property], "属性值类型:", typeof target[property]);return target[property];},set(target, property, value, receiver) {console.log("方法:", "set", "对象:", objName, "属性:", property, "属性类型:", typeof property, "属性值:", value, "属性值类型:", typeof target[property]);return Reflect.set(target, property, value, receiver);}};// 检查并初始化对象let targetObject = global[objName] || {};  // 在 Node.js 环境中使用 globalglobal[objName] = new Proxy(targetObject, handler);  // 在 Node.js 中使用 global}
}

接下来,我们就将这段Proxy监控函数注入到刚才我们的案例中:

window = global
window.addEventListener = function () {
}
kw = {getAttribute() {}
}
ctx = {fillRect: function () {}
}
canvas = {getContext() {return ctx}
}
document = {getElementById(id) {console.log("document getElementById by:", id)if (id === "kw") {return kw}},createElement(ele) {console.log("document createElement ", ele)return canvas}
}
navigator = {userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',toString: function () {return '[object Navigator]'}
}function setProxyArr(proxyObjArr) {for (let i = 0; i < proxyObjArr.length; i++) {const objName = proxyObjArr[i];const handler = {get(target, property, receiver) {console.log("方法:", "get", "对象:", objName, "属性:", property, "属性类型:", typeof property, "属性值:", target[property], "属性值类型:", typeof target[property]);return target[property];},set(target, property, value, receiver) {console.log("方法:", "set", "对象:", objName, "属性:", property, "属性类型:", typeof property, "属性值:", value, "属性值类型:", typeof target[property]);return Reflect.set(target, property, value, receiver);}};// 检查并初始化对象let targetObject = global[objName] || {};  // 在 Node.js 环境中使用 globalglobal[objName] = new Proxy(targetObject, handler);  // 在 Node.js 中使用 global}
}setProxyArr(["window", "document", "navigator"])function get_sign() {// 黑匣子,省略很多代码// (1) BOM和DOM正常的前端动作window.addEventListener("test")// 搜索框let kw = document.getElementById("kw")let _class = kw.getAttribute("class")// 创建画布let canvas = document.createElement("canvas")let ctx = canvas.getContext("2d");ctx.fillRect(10, 10, 100, 100);// (2) 基于DOM和BOM进行环境校验if (navigator.toString() === '[object Navigator]') {let navLength = navigator.userAgent.lengthreturn "u82d1660a" + navLength // Yuan老师的微信,想深入学逆向爬虫的联系我,结一段善缘!} else {return false}
}console.log(get_sign())

环境验证的JS代码其实一共有两个思路,思路一是基于当前环境是不是浏览器环境,是的话正常执行。思路二是当前环境是不是node环境,如果不是,则正常执行,扩展案例:

window = globaldelete global
delete process
delete Buffer
delete __dirname
delete __filenamewindow.addEventListener = function () {
}
kw = {getAttribute() {}
}
ctx = {fillRect: function () {}
}
canvas = {getContext() {return ctx}
}
document = {getElementById(id) {console.log("document getElementById by:", id)if (id === "kw") {return kw}},createElement(ele) {console.log("document createElement ", ele)return canvas}
}
navigator = {userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',toString: function () {return '[object Navigator]'}
}function setProxyArr(proxyObjArr) {for (let i = 0; i < proxyObjArr.length; i++) {const objName = proxyObjArr[i];const handler = {get(target, property, receiver) {console.log("方法:", "get", "对象:", objName, "属性:", property, "属性类型:", typeof property, "属性值:", target[property], "属性值类型:", typeof target[property]);return target[property];},set(target, property, value, receiver) {console.log("方法:", "set", "对象:", objName, "属性:", property, "属性类型:", typeof property, "属性值:", value, "属性值类型:", typeof target[property]);return Reflect.set(target, property, value, receiver);}};// 检查并初始化对象// let targetObject = global[objName] || {};  // 在 Node.js 环境中使用 global// global[objName] = new Proxy(targetObject, handler);  // 在 Node.js 中使用 globallet targetObject = window[objName] || {};  // 在 Node.js 环境中使用 globalwindow[objName] = new Proxy(targetObject, handler);  // 在 Node.js 中使用 global}
}setProxyArr(["window", "document", "navigator"])function get_sign() {// 黑匣子,省略很多代码// (1) BOM和DOM正常的前端动作window.addEventListener("test")// 搜索框let kw = document.getElementById("kw")let _class = kw.getAttribute("class")// 创建画布let canvas = document.createElement("canvas")let ctx = canvas.getContext("2d");ctx.fillRect(10, 10, 100, 100);let navLength = navigator.userAgent.length// (2) 基于DOM和BOM进行环境校验if (navigator.toString() === '[object Navigator]') {// (3) 基于node关键字判断是不是浏览器环境const isNode = typeof process !== 'undefined' && typeof global !== 'undefined';if (isNode) {console.log("当前环境是 Node.js");return false} else {console.log("当前环境不是 Node.js");return "u82d1660a".toUpperCase() + navLength // Yuan老师的微信,想深入学逆向爬虫的联系我,结一段善缘!}} else {return false}
}console.log(get_sign())

四、瑞数案例

yuan老师微信u82d1660a

1、瑞数介绍

image-20240910下午74639085

‌瑞数信息是一家专注于提供互联网动态业务应用安全防护解决方案的公司

瑞数动态安全 Botgate(机器人防火墙)以“动态安全”技术为核心,通过动态封装、动态验证、动态混淆、动态令牌等技术对服务器网页底层代码持续动态变换,增加服务器行为的“不可预测性”,实现了从用户端到服务器端的全方位“主动防护”,为各类 Web、HTML5 提供强大的安全保护。

瑞数可以理解为是我们进入到JS逆向世界的标志

过瑞数的方法基本上有以下几种

  • 自动化工具
  • 补环境
  • 纯算

2、瑞数流程

  1. rs的网站会请求两次page_url(文档请求),第1次page_url(文档请求)会返回一个cookie1,和一个响应体(HTML源码),以及请求响应码是202或者 412

image-20240726下午54233924

  1. 响应体(HTML源码)包括3个部分:
  • 一个meta标签,其content内容很长且是动态的(每次请求会变化),会在eval执行第二层JS代码时使用到;
  • 一个ts代码,下面的自执行函数会解密文件内容生成eval执行时需要的JS源码,也就是第二层vm代码;
  • 一个大自执行函数(每次请求首页都会动态变化),给window添加一些属性如$_ts,会在vm中使用;
  • 这三个要素用于在本地生成一个cookie2,用于第2次请求
  1. 第2次page_url(文档请求)携带cookie1和ncookie2,获取真正的页面内容!

image-20250215下午75633183

image-20250215下午75755613

瑞数 3、4 代有以 S 和 T 结尾的两个 Cookie,其中以 S 结尾的 Cookie 是第一次的 那个请求返回的,以 T 结尾的 Cookie 是由 JS 生成的,动态变化的,T 和 S 前面一般会跟 80 或 443 的数字,Cookie 值第一个数字为瑞数的版本。

瑞数 5 、6代也有以 S 和 T 结尾的两个 Cookie,但有些特殊的 5 代瑞数也有以 O 和 P 结尾的,同样的,以 O 结尾的是第一次的 412 那个请求返回的,以 P 结尾的是由 JS 生成的,Cookie 值第一个数字同样为瑞数的版本。

3、瑞数案例解析

【1】基本结构与流程

image-20250607下午15919782

【2】VM环境与入口

先定位入口,这里涉及一个VM环境

  • “VM”表示的是Virtual Machine(虚拟机),这些文件通常表示由浏览器生成和执行的虚拟机脚本环境中的临时脚本。这些脚本并不是项目源代码的一部分,也不是实际存在的物理文件。 它们在浏览器的内存中创建并执行

  • 比如说,当你在调试一个网页时,如果在某些动态生成并执行的JS代码上设定了断点,Chrome调试器会在一个以"VM"开头的文件中显示这些代码,例如"VM111.js"。这个"VM"文件的存在只是为了调试目的,它并不存在于服务器端,也不会被存储在本地,而是存在于浏览器内存中。一般情况下,这类文件的出现是因为浏览器对JavaScript代码的处理方式,如动态编译或者JavaScript堆栈跟踪。

  • 通过eval函数或者new Function方法,Chrome浏览器会创建一个"VM"文件来展示这段临时执行的代码

通过脚本断点可以断住ts和自执行函数,因为第一次响应的index.html是动态的,所以为了后面调试,我们先试用文件替换本地化。

接下来在index.html中直接使用正则快速定位入口函数:

# 搜索.call

image-20250607下午15352371

这个位置通常在分析瑞数的时候作为入口,图中 _\(jL== 实际上是 ==eval== 方法,传入的第一个参数 ==_\)iCWindow 对象,第二个对象 _$eB 是我们前面看到的 VM 虚拟机中的 IIFE 自执行代码。

最后在入口位置单步调试,即可进入到VM环境!

image-20250607下午15638063

后面的断点调试就在这个环境中。

【3】补环境

初始化补环境文件

metaContent = "pDcfDN8f3jz1r7XPqFGsPL6q9rSYtQFpgNsbPWxFArYi81IxUjQqVJWLCSbyMjvmpPyvkJOGoZQizOfI8SGYRSg.ZWDc2MpBkbeiYeTC0T2n07RtcD7cCyQ_xeajMYzzU28381JavZM7FlN4Pz3whmOha766Uu_TEYu3H4pK.j6M9UQzVj.Y2G"self = top = window = global;
window.setTimeout = function () {
}
window.setInterval = function () {
}
window.clearInterval = function () {
}
window.addEventListener = function () {
}
window.XMLHttpRequest = function () {
}
window.HTMLFormElement = function () {}window.ActiveXObject = function ActiveXObject() {
}div = {getElementsByTagName() {return []}
}
script = {getAttribute(attr) {if (attr === "r") {return "m"}},parentElement: {removeChild: function () {}}
}meta = {content: metaContent,getAttribute(attr) {if (attr === "r") {return "m"}},parentNode: {removeChild: function () {}}}document = {createElement: function (ele) {console.log("document createElement", ele)if (ele === "div") {return div} else if (ele === "form") {return {getElementsByTagName: function () {return []}}} else {return {}}},getElementsByTagName(ele) {console.log("document getElementsByTagName", ele)if (ele === "script") {return [script, script]}if (ele === "meta") {return [meta, meta]} else {return []}},appendChild: function () {},removeChild: function () {},documentElement: {addEventListener: function () {}},getElementById() {return {}}
}location = {"ancestorOrigins": {},"href": "https://www.ouyeel.com/search-ng/queryResource/index","origin": "https://www.ouyeel.com","protocol": "https:","host": "www.ouyeel.com","hostname": "www.ouyeel.com","port": "","pathname": "/search-ng/queryResource/index","search": "","hash": ""
}navigator = {appCodeName: "Mozilla",appName: "Netscape",appVersion: "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",webdriver: false
}

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

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

相关文章

建一个网站大概需要多少钱同城购物网站建设成本

【&#x1f40b;和鲸冬令营】通过数据打造爆款社交APP用户行为分析报告 文章目录 【&#x1f40b;和鲸冬令营】通过数据打造爆款社交APP用户行为分析报告1 业务背景2 数据说明3 数据探索性分析4 用户行为分析4.1 用户属性与行为关系分析4.2 转化行为在不同用户属性群体中的分布…

做网站 域名如何要回android编程

1.同步解释 1.1 同步基础概念 触发器&#xff1a;触发器是控制采集的命令。您可以使用触发器来启动、停止或暂停采集。触发信号可以源自软件或硬件源。 时钟&#xff1a;时钟是用于对数据采集计时的周期性数字信号。根据具体情况&#xff0c;您可以使用时钟信号直接控制数据采…

基于多假设跟踪(MHT)算法的MATLAB实现

一、核心代码 %% MHT多假设跟踪主函数 function mht_demo()% 参数设置num_targets = 3; % 真实目标数量num_scans = 50; % 总扫描次数detection_prob = 0.9; % 检测概率clutter_rate = 0.1; % 杂波密度(…

ROS2之消息接口

ROS2 的三大消息接口 1. 消息(Message, msg)定义文件后缀:.msg作用:用于 话题 (Topic) 通信,节点之间以“流”的方式交换数据。特点:一对多(一个话题可以有多个订阅者/发布者)单向通信(发布 → 订阅)异步(发…

Linux grep cut tomcat logs

截取当天catalina.out日志 grep "2025-09-25" catalina.out > 20250925.log截取指定时间段(2025年9月24日到2025年9月25日)的日志grep "2025-09-2[4-5]" catalina.out >20250924-25.log截取…

软件工程课程第一次团队作业

软件工程课程第一次团队作业这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/202501SoftwareEngineering这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/202501SoftwareEngineering/homework/13546…

Vona ORM分表全攻略

针对高并发、数据量大的场景,通常会考虑采用分表机制进行优化。下面以 Model User/Order 为例,通过查询用户的订单列表,来演示分表的使用方法分表 针对高并发、数据量大的场景,通常会考虑采用分表机制进行优化。下…

对网站建设展望网站域名申请程序

一 问题的引入 约瑟夫问题的源头完全可以命名为“自杀游戏”。本着和谐友爱和追求本质的目的&#xff0c;可以把问题描述如下&#xff1a; 现有n个人围成一桌坐下&#xff0c;编号从1到n&#xff0c;从编号为1的人开始报数。报数也从1开始&#xff0c;报到m人离席&#xff0c…

如何在预算与风险之间做选择 iOS 混淆(源码混淆 vs IPA 混淆)的成本-收益分析与实战决策框架

本文从成本-收益和工程决策角度,提供 iOS 混淆(源码混淆 vs IPA 混淆) 的 ROI 评估模型、实战案例与 5 步决策流程,帮助团队在有限预算下科学选择混淆策略并工程化落地(含映射表、灰度与测试建议)。在现实工程里…

【兰州大学主办|EI稳定检索】第二届信息光学与光电技术国际学术会议(CIOT 2025)

第二届信息光学与光电技术国际学术会议(CIOT 2025)将于2025年10月24-26日于昆明召开。会议将围绕信息光学、光电技术等在光学领域中的最新研究成果,为来自国内外高等院校、科学研究所、企事业单位的专家、教授、学者…

深入解析:设计模式-状态模式详解

深入解析:设计模式-状态模式详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&q…

【IEEE出版】第五届网络通信与信息安全国际学术会议(ICNCIS 2025)

2025年第五届网络通信与信息安全国际学术会议(ICNCIS2025)将于2025年10月17-19日于哈尔滨召开。【连续四届EI、Scopus双检索 | 快至会后4个月EI检索】 【已签约IEEE出版申请,已上线IEEE官方列表会议!EI检索稳定有保…

第16章 Day19 Charles安装和使用---微信小程序逆向

Charles安装(三方抓包工具) Charles客户端下载: 官网地址:https://www.charlesproxy.com/download/ 选择适合自己的系统版本下载下载安装完成后激活 激活网站地址:https://www.zzzmode.com/mytools/charles/打开安…

定制网站 北京服务器上怎么搭建网站

一,工具简介 tcpconnect工具追踪执行活动TCP连接的内核函数(例如,通过connect()系统调用;accept()是被动连接)。 详细地说,tcpconnect通过钩住内核中的tcp_v4_connect和/或tcp_v6_connect函数来工作,这些函数是在尝试建立TCP连接时被调用的。当这些函数被调用时,tcpc…

如何让百度快速收录网页如何让百度快捷收录网页的方法

如何让百度快速收录网页如何让百度快捷收录网页的方法2025-09-25 15:15 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; di…

061_尚硅谷_算术运算符课堂练习

061_尚硅谷_算术运算符课堂练习1.练习1:97天假期,有xx个星期零xx天 2.练习2:华氏温度134.2转为摄氏度

DBLINK的创建和使用(总结)

DBLINK的创建和使用(总结) 目录DBLINK的创建和使用(总结)一、什么是 DBLINK?二、创建 DBLINK 的三种主要方式方式一:使用 tnsnames.ora 文件(最常用、最推荐)步骤 1:配置 tnsnames.ora 文件步骤 2:创建 DBLI…

Could not resolve host: mirrorlist.centos.org

执行 [root@localhost yum.repos.d]# yum install bind-utils时,报centos-release-scl-rh Could not resolve host: mirrorlist.centos.org; Unknown error解决上面问题[root@localhost ~]# cd /etc/yum.repos.d [roo…

axi 4k边界检测

在AXI4协议中,一个突发传输(burst transfer)不能跨越4KB的边界,为啥呢,因为我们认为每个slave设备通常是4KB对齐的,为了避免一次burst的传输可能越过目的slave这个风险,所以就定了这个规矩 更深的说,确保数据传…

GOSIM 开源出海工作坊:给开源创业者的忠告

“出海”两个字,在开源语境里不是浪漫叙事,而是生死抉择。在这个数字机遇无限的时代,开源不仅是技术创新的象征,更是全球商业扩张的关键驱动力。本次分享将带你走过开源项目从诞生到跨越国界、进入全球市场的完整历…