某网站JS加密、OB混淆与CSS反爬实战分析

news2024/11/16 23:34:19

1. 写在前面

  最近一段时间接触了一些小说网站的业务。发现很多的小说网站,甚至一些小站它们的安全防护措施做的都很到位!例如上次说到的的五秒盾也是存在于一个小说小站。今天要讲的这个网站它集JS加密ob混淆CSS反爬于一体

目标站点

aHR0cHM6Ly93d3cuaG9uZ3NodS5jb20vY29udGVudC8xMTM3NzIvMjA1NDI1LTE0NTU1NzIuaHRtbA==

2. 分析

  

这次主要说的就是小说内容这块,打开这个网站的你会发现内容是不允许复制的。其次页面呈现的内容里面有一部分数据是隐藏的,虽然在页面你看它显示都正常,但在原代码中是没有的,而是由类似span标签代替的

这种反爬虫的手段主要先限制我们对页面的一些操作,然后将某些内容进行加密,最后在网页加载的时候通过解密算法进行解密从而渲染加载到网页

首先,碰到这种情况,我们可以先假设它这个页面的内容是经过二次请求,从接口拿到数据在进行渲染的

所以,我们可以先刷新页面看看XHR下的请求,简单的分析一波

在这里插入图片描述

可以看到某个请求的响应中有一个content字段,一看就知道它是经过加密处理的。这个字段的字面意思倒是可以让我们怀疑它是网页需要呈现的内容数据

在JS逆向中,可以记住大致的主流程,当然主流程里面涉及到的各种技巧与手法又可以开枝散叶,本文不做过多的描述。以后慢慢覆盖讲解:
在这里插入图片描述

3. 定位

  这里我们其实已经知道content字段很有可能是经过加密后的小说内容。所以到这一步我们还是有比较多的方法进行定位,可以直接点击Initiator跟一下请求的调用栈

  同样根据你的经验进行一些预判!如全局搜索一下可疑的关键字。这里我们可以看上面的加密肯定与base64有关,加密的数据也必然会走解密decrypt逻辑,这些可疑的关键词对象都可以是我们入手的点
在这里插入图片描述
上述通过分析定位找到可疑的JS代码,可以看到这里大概率是一个解密函数的调用,我们埋一个断点重新刷新请求一下:

在这里插入图片描述
断点到此处后,我们可以看到content字段,就是一串密文,而这段密文依次调用了utf8to16hs_decryptbase64decode这三个函数。这里我们可以大胆的猜想它们就是解密函数

3. 扣代码

现在我们可以去印证我们最开始的猜想,content字段到底是不是解密后的小说内容,我们将上面几个函数的js代码扣出来

function base64decode(str) {
    var c1, c2, c3, c4, base64DecodeChars = new Array(-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1);
    var i, len, out;
    len = str.length;
    i = 0;
    out = "";
    while (i < len) {
        do {
            c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
        } while (i < len && c1 == -1);if (c1 == -1)
            break;
        do {
            c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
        } while (i < len && c2 == -1);if (c2 == -1)
            break;
        out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
        do {
            c3 = str.charCodeAt(i++) & 0xff;
            if (c3 == 61)
                return out;
            c3 = base64DecodeChars[c3];
        } while (i < len && c3 == -1);if (c3 == -1)
            break;
        out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
        do {
            c4 = str.charCodeAt(i++) & 0xff;
            if (c4 == 61)
                return out;
            c4 = base64DecodeChars[c4];
        } while (i < len && c4 == -1);if (c4 == -1)
            break;
        out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
    }
    return out;
}

function str2long(s, w) {
    var len = s.length;
    var v = [];
    for (var i = 0; i < len; i += 4) {
        v[i >> 2] = s.charCodeAt(i) | s.charCodeAt(i + 1) << 8 | s.charCodeAt(i + 2) << 16 | s.charCodeAt(i + 3) << 24;
    }
    if (w) {
        v[v.length] = len;
    }
    return v;
}

function hs_decrypt(str, key) {
    if (str == "") {
        return "";
    }
    var v = str2long(str, false);
    var k = str2long(key, false);
    var n = v.length - 1;
    var z = v[n - 1]
      , y = v[0]
      , delta = 0x9E3779B9;
    var mx, e, q = Math.floor(6 + 52 / (n + 1)), sum = q * delta & 0xffffffff;
    while (sum != 0) {
        e = sum >>> 2 & 3;
        for (var p = n; p > 0; p--) {
            z = v[p - 1];
            mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
            y = v[p] = v[p] - mx & 0xffffffff;
        }
        z = v[n];
        mx = (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
        y = v[0] = v[0] - mx & 0xffffffff;
        sum = sum - delta & 0xffffffff;
    }
    return long2str(v, true);
}


function long2str(v, w) {
    var vl = v.length;
    var sl = v[vl - 1] & 0xffffffff;
    for (var i = 0; i < vl; i++) {
        v[i] = String.fromCharCode(v[i] & 0xff, v[i] >>> 8 & 0xff, v[i] >>> 16 & 0xff, v[i] >>> 24 & 0xff);
    }
    if (w) {
        return v.join('').substring(0, sl);
    } else {
        return v.join('');
    }
}


function utf8to16(str) {
    var out, i, len, c;
    var char2, char3;
    out = "";
    len = str.length;
    i = 0;
    while (i < len) {
        c = str.charCodeAt(i++);
        switch (c >> 4) {
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
            out += str.charAt(i - 1);
            break;
        case 12:
        case 13:
            char2 = str.charCodeAt(i++);
            out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
            break;
        case 14:
            char2 = str.charCodeAt(i++);
            char3 = str.charCodeAt(i++);
            out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
            break;
        }
    }
    return out;
}

function decrypt(content,key){
    return utf8to16(hs_decrypt(base64decode(content), key))
}

decrypt函数是自己定义的,为了更好的调用上面的解密函数。同时可以看到,解密函数调用的时候不光是传了content参数,还有一个key,那么我们现在需要分析key这个值是什么

回到接口请求分析那一步,之前第一次分析的时候,就把所有的请求都看了一遍,自然有发现这个key也是在XHR请求响应中的
在这里插入图片描述
现在,我们只需要从这两个接口当中请求拿到contentkey值就能调用我们的JS解密算法进行解密

这里我们可以在Console控制台把js代码放进去再构造一下contentkey即可验证,得到的结果正如我们猜想,它就是加密后的内容,如下是解密后的数据:

在这里插入图片描述

4. CSS反爬绕过

  现在我们已经得到了页面加密的内容、解密算法。但是可以看到解密出来后的数据是不完整的,被隐藏了。现在要做的就是拿到被隐藏的那些文字内容,这样整个页面的内容才是全的

我们再回过头看之前的请求分析,这个图里面除了content字段还有一个ohter字段的值貌似也是经过加密处理的
在这里插入图片描述
不要考虑那么多,现在为止我们只要这么想,所有的数据在呈现到前端页面时,必定是有迹可循的。不管是后端加密还是前端加密,都是一样,我们直接用解密函数在控制台看看,如下:
在这里插入图片描述
很可惜这并不是所缺失的那些内容,倒像是一段JS代码,不过好像也并不是正常的JS代码,显然经过了混淆。但是好在结构还算清晰

我们不用管这里面的具体加密与解密算法是怎样的,只需要分析它的加密跟解密的逻辑最后调用即可

ob混淆里面有一个大数组

var _0x09d1 = ['uJtRs', 'RyzMW', 'wkLRG', 'prototype', 'endWith', 'GIvaF', 'test', 'enc', '0767CD2FAAF99E58', 'window', 'location', 'href', 'Latin1', 'parse', 'D063F0602455077D', '146385F634C9CB00', 'ZeroPadding', 'toString', 'Utf8', 'split', 'createElement', 'style', 'setAttribute', 'type', 'async', 'head', 'cqrvw', 'link', 'nNyBj', 'length', 'parentNode', 'insertBefore', 'appendChild', '4|1|5|3|2|0', 'fromCharCode', 'tMLmi', 'OAWFf', 'KUtvo', 'KgGRl', 'qBUPd', 'addRule', '.context_kw', '::before', 'styleSheets', 'cssRules', 'pad', 'ZFebI', 'clamp', 'qVUkH', 'sigBytes', 'words', 'xsbdD', 'ouYQw']

这个数组基本是明文的,很多大厂网站这个数组全是跟变量_0x09d1一样全是十六进制的,其实经过分析就能发现words就是被打散隐藏的缺失内容

在这里插入图片描述
到了这一步,我们第一种方案则可以根据span标签里的class的数字索引去取words数组里面的值了
在这里插入图片描述

5. 内容还原

当然还有另外一种还原内容的方案,这里我建议使用JS注入然后渲染

html = '<!DOCTYPE html><html><head><meta charset="UTF-8"><script>'+js+'</script></head><body>'+content+'</body></html>'
    r = HTML(html=html)
    script_code = '''
        var span_list = document.getElementsByTagName("span");
        for (var i=0; i<span_list.length; i++) {
            var content = window.getComputedStyle(
                span_list[i], ':before'
            ).getPropertyValue('content');
            span_list[i].innerText = content.replace('"', '').replace('"', '');
        }
    '''
    r.render(script=script_code, reload=False)
    print(r.find('body', first=True).text)

上面的font color=#ff0033 size=3>ohter就是我们解密出来的那段js混淆代码,也就是用来还原缺失内容的关键函数,它就是我们上面的js参数,然后content就是我们上面还原的第一阶段解密出来的content

解密后的网页内容
在这里插入图片描述

解密后的JS混淆代码
在这里插入图片描述

注入后拿到的页面完整内容
在这里插入图片描述

  好了,到这里又到了跟大家说再见的时候了。创作不易,帮忙点个赞再走吧。你的支持是我创作的动力,希望能带给大家更多优质的文章

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

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

相关文章

用真人模型制作3D虚拟人物,岂不是更真实?

3D虚拟人物是指利用计算机技术和图形学技术创建的一种能够模拟真实人体形态、行为和语言的虚拟实体。与传统的平面图像或视频不同&#xff0c;3D虚拟人物具有立体感和真实感&#xff0c;能够在虚拟环境中实现人机交互和情感交流&#xff0c;给用户带来全新的沉浸式体验。 随着…

文件批量改名新技巧:轻松将日期插入到文件名中,整理更有序!

在数字化时代&#xff0c;我们每天都面临着大量的文件&#xff0c;而合理整理和命名这些文件对于我们的工作和生活至关重要。特别是在需要存档或分享文件时&#xff0c;具有清晰的命名规则可以极大地提升工作效率和组织性。 首先&#xff0c;进入文件批量改名高手的文件批量重…

表征材料表面性质​的第一性原理计算方法:功函数

功函数计算是指通过计算材料表面或界面上的电子结构能量差来确定材料的界面特性的方法。在材料科学和表面科学领域&#xff0c;界面的性质对于材料的功能和性能具有重要影响。通过理解和控制界面&#xff0c;可以优化材料的电子传输、光学性能、催化活性等关键特性。 功函数表示…

网络协议【图解TCP/IP(笔记二)】

文章目录 网络协议随处可见的协议协议的必要性生活中的协议计算机中的协议分组交换协议协议的标准化 网络协议 随处可见的协议 在计算机网络与信息通信领域里&#xff0c;人们经常提及“协议”一词。互联网中常用的具有代表性的协议有IP、TCP、HTTP等。而LAN&#xff08;局域…

企业元宇宙虚拟场景开发公司广州华锐互动

元宇宙是一个虚拟的世界&#xff0c;可以模拟现实世界中的场景和交互方式。利用元宇宙搭建线上元宇宙互动展厅可以让企业在虚拟环境中展示产品、服务和品牌形象&#xff0c;与客户进行互动交流&#xff0c;提高企业的知名度和影响力。 通过搭建线上元宇宙互动展厅&#xff0c;利…

【python学习】matplotlib绘制仅有y轴的数值条码图/台阶图(隐藏特定坐标轴)

matplotlib绘制仅有y轴的数值条码图/台阶图 图形来源图形绘制思路绘图代码 图形来源 今天看文章&#xff0c;文章中有一幅图&#xff0c;图的表达形式很适合我目前的数据展示&#xff0c;于是想要用python画出来。 文章来源&#xff1a;Yun-Hua Cheng_2017_Scientific Report…

web学习笔记1

计算机&#xff1a; 课程大纲&#xff1a;html&#xff08;五条猫结构&#xff09; 结构 css 表现 JavaScript 行为 html&#xff1a;超文本标记语言 超&#xff1a;超链接&#xff0c;能从一个网页跳转到另一个网页 标记&#xff1a;文本要变成超文本&#xff0c;就需要各…

pwn05(应对简单栈溢出的常规套路)

目录 一、常规检查&#xff08;nc、file、checksec&#xff09; 二、IDA反编译&#xff0c;只找两个东西即可 1、寻找造成栈溢出的函数的地址到ebp的距离 2、 寻找我们所要利用的函数的地址&#xff08;即我们希望程序最后返回到哪里&#xff09; 三、编写并运行exp脚本 一…

eNSP-NAT网络地址转换服务

NAT网络地址转换服务 文章目录 NAT网络地址转换服务一、题目要求二、题目分析三、拓扑结构四、基础配置五、测试验证 一、题目要求 1.私网地址使用192.168.1.0/24进行子网划分 2.Telnet Server设备启动Telnet服务 3.isp设备仅配置IP地址 4.PC6,PC7,PC8均可以访问PC9 5.内网…

python 第十章 函数

系列文章目录 第一章 初识python 第二章 变量 第三章 基础语句 第四章 字符串str 第五章 列表list [] 第六章 元组tuple ( ) 第七章 字典dict {} 第八章 集合set {} 第九章 常用操作 文章目录 系列文章目录10.1函数的作用10.2函数的使用步骤定义函数调用函数函数的注意事项 10…

Linux 内存泄漏检测的实现原理与实现

在使用没有垃圾回收的语言时&#xff08;如 C/C&#xff09;&#xff0c;可能由于忘记释放内存而导致内存被耗尽&#xff0c;这叫 内存泄漏。由于内核也需要自己管理内存&#xff0c;所以也可能出现内存泄漏的情况。为了能够找出导致内存泄漏的地方&#xff0c;Linux 内核开发者…

抖音seo矩阵系统源码开发部署--开发文档分享

目录 一、抖音seo矩阵系统源码自研概况分析 二、 技术开发语言及功能框架 技术要求&#xff1a; 功能框架&#xff1a; 三、 抖音seo矩阵系统开发原则 四、 抖音seo矩阵系统源码开发示例 一、抖音seo矩阵系统源码自研概况分析 关于抖音seo矩阵系统源码自研&#xff0c;在开…

零零信安-DD数据泄露报警日报【第202期】

2023.07.07共发现匿名网络资讯信息79,948条&#xff1b;最近7天同比增长-20.6%&#xff1b;最近30天共发现匿名网络资讯信息2,587,590条。 北京零零信安科技有限公司成立于2020年&#xff0c;是国内首家专注于外部攻击面管理&#xff08;EASM&#xff09;的网络安全公司。基于…

Python3,10行代码竟然让URL变短了,没想到还可以这么玩。

让URL变短的方法 1、引言2、代码实战2.1 安装2.2 示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c;有没有什么方法&#xff0c;能让url变短一点 小鱼&#xff1a;我去~ url怎么惹你了&#xff0c; 你让它变短。&#xff1f; 小屌丝&#xff1a;没有了&#xff0c; 我…

python scrapy爬取网站数据(一)

框架介绍 scrapy中文文档 scrapy是用python实现的一个框架&#xff0c;用于爬取网站数据&#xff0c;使用了twisted异步网络框架&#xff0c;可以加快下载的速度。 scrapy的架构图&#xff0c;可以看到主要包括scheduler、Downloader、Spiders、pipline、Scrapy Engine和中间…

你如何准备测试数据?

目录 前言&#xff1a; 一、基于 GUI 操作生成 二、调用 API 生成 三、通过数据库操作生成 四、综合运用 API 和数据库的方式生成 前言&#xff1a; 在进行自动化测试时&#xff0c;准备好合适的测试数据是十分重要的。 准备测试数据是我们测试过程中非常重要的一环&…

RocketMQ5.0--顺序消息

RocketMQ5.0–顺序消息 一、顺序消息概览 RocketMQ支持局部消息顺序消费&#xff0c;可以确保同一个消费队列中的消息被顺序消费&#xff0c;如果做到全局顺序消费则可以将主题配置成一个消费队列。并发&#xff08;默认&#xff09;消息消费参考​ 《RocketMQ5.0.0消息消费&…

java中对象字段转换

文章目录 前言一、对象属性转换问题二、如何处理转换?三 、处理办法1 利用 JsonProperty 改变转出属性2 利用 JsonAlias 增加接收的属性 总结 前言 在java中,有时候会涉及到一些对象的转换,为什么转换呢? 由于接受参数和用的时候对应不上由于经历过一些修改,为了兼容 一、对…

mac上 如何批量在文件名后加相同的文字?

mac上如何批量在文件名后加相同的文字&#xff1f;不管你是使用windows电脑还是使用mac电脑&#xff0c;很多小伙伴都会在电脑上进行文件批量重命名的操作&#xff0c;不过这项操作对于使用windows系统电脑的小伙伴来说会简单一些&#xff0c;因为在网上可以搜索到很多这样的教…

Python基础:错误与异常

文章目录 错误和异常程序错误异常处理断言处理程序调试 错误和异常 程序错误 程序的错误 ​ python程序中错误通常分为3种类型&#xff0c;即语法错误、运行错误和逻辑错误。 语法错误&#xff1a;源代码中的拼写语法错误&#xff0c;这些错误导致Python编译器无法把Python…