当前位置: 首页 > news >正文

初始爬虫13(js逆向)

为了解决网页端的动态加载,加密设置等,所以需要js逆向操作。

JavaScript逆向可以分为三大部分:寻找入口,调试分析和模拟执行。 

1.chrome在爬虫中的作用

        1.1preserve log的使用

默认情况下,页面发生跳转之后,之前的请求url地址等信息都会消失,勾选perserve log后之前的请求都会被保留

        1.2filter过滤

在url地址很多的时候,可以在filter中输入部分url地址,对所有的url地址起到一定的过滤效果

        1.3观察特定种类的请求

常见的选项:

XHR:大部分情况表示ajax请求
JS:js请求
CSS:css请求
但是很多时候我们并不能保证我们需要的请求是什么类型,特别是我们不清楚一个请求是否为ajax请求的时候,直接选择all,从前往后观察即可,其中js,css,图片等不去观察即可

不要被浏览器中的一堆请求吓到了,这些请求中除了js,css,图片的请求外,其他的请求并没有多少个

        1.4寻找入口

这是非常关键的一步,逆向在大部分情况下就是找一些加密参数到底是怎么来的,比如请求中的 token ,sign 等参数到底在哪里构造的, 这个关键逻辑可能写在某个关键的方法里面或者隐藏在某个关键的变量里面。一个网站加载了很多 JS 文件,那么怎么从这么多 JS 代码里面找到关键的位置,那就是一个关键的问题,这就是寻找入口

在network进行搜索,一般来说,请求带有加密参数,常见有 sign 或者 token;要构造请求首先需要获取加密参数,最简单有效的方法就是通过全局搜索,参数名大多数情况下就是一个普通的字符串,如 token 我们可以通过搜索 tokentoken:token :"token" 等等;   

        1.5断点操作

另外我们还可以通过断点进行入口查找,比如 XHR 断点, DOM 断点,事件断点等。我们可以在开发者工具中的 Sources 面板里面添加设置; 

2.调式分析 

        2.1格式化操作

一般来说,许多的 JavaScript 代码都是经过打包和压缩的,多数情况下,我们可以使用 Sources 面板下 JavaScript 窗口左下角的格式化按钮对代码进行格式化;

除此之外,有一些网站的 HTML 和 JavaScript 是混杂在一起的,我们可以使用一些工具 ,可以得到格式化后的代码;

推荐工具:在线代码格式化 (oschina.net)

        2.2断点调试 

代码格式化后,我们就进入了正式的调试流程,基本操作是给想要调试的代码添加断点,同时在对应的面板里观察对应变量的值 

3.模拟执行 

        3.1python改写实现模拟执行

由于 Python 简单易用,同时也能够模拟调用执行 JS ,如果整体逻辑不复杂的话,我们可以尝试使用 Python 来把整个加密流程完整的实现一遍。如果整体流程相对复杂,我们可以尝试使用 Python 来模拟调用 JS 来执行

        3.2JS模拟执行+API

由于整个逻辑是 JS 实现的,使用 Python 来执行 JS难免会有一些不太方便的地方。而 Node.js 天生就有对 JS 的支持。为了更通用的实现 JS 的模拟调用, 我们可以用 express 来模拟调用 JS, 同时将其暴露成一个 API , 从而可以实现跨语言调用

        3.3浏览器模拟执行

由于整个逻辑是运行在浏览器里面的,我们当然也可以将浏览器当做整个执行环境。比如使用 Selenium ,PlayWright 等来尝试执行一些 JS 代码,得到一些返回结果 

4.JavaScript 逆向爬取实战 

我们在爬取网站的时候,会遇到一些需要分析接口或URL信息的情况,这时会有各种各样的类似加密的情形

目标网站:Scrape | Movie
目标:获取列表页和详细页信息

        4.1 列表页

                4.1.1寻找入口,调试分析,得到解密内容:

第一步,查看XHR文件,也就是ajax请求(动态页面的原因)。

第二步观察payload(指在 HTTP 请求中实际发送给服务器的数据 ),我们需要通过分析 payload,爬虫可以模拟用户提交数据、获取动态内容或破解反爬机制。

列表页请求构造中有三个参数,只有 token 需要获取;

不断查找到目标代码(解密内容部分)

                 4.1.2 python代码模拟执行加密

import hashlib
import time
import requests
import base64def get_token(encrypt_url):timestamp = str(int(time.time()))str1 = f'/api/movie/{encrypt_url},{timestamp}'.encode('utf-8')str2 = (hashlib.sha1(str1).hexdigest() + f',{timestamp}').encode('utf-8')final = base64.b64encode(str2).decode('utf-8')return finaldef get_url(id):encrypt_url = ('ef34#teuq0btua#(-57w1q5o5--j@98xygimlyfxs*-!i-0-mb' + str(id)).encode('utf-8')encrypt_url = base64.b64encode(encrypt_url).decode('utf-8')url = f"https://spa6.scrape.center/api/movie/{encrypt_url}/?token={get_token(encrypt_url)}"resp = requests.get(url)return respif __name__ == '__main__':response = get_url(1)print(response.json())

 

        4.2 常见加密方式

                4.2.1 base64 

import base64
​
print(base64.b64encode('msb'.encode()))
print(base64.b64decode('bXNi'.encode()))var str1 = "msb";

                4.2.2 MD5

MD5消息摘要算法(英文:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5加密算法是不可逆的,所以解密一般都是通过暴力穷举方法,以及网站的接口实现解密。

解密工具:md5在线解密破解,md5解密加密 (cmd5.com) 

import hashlib
pwd = "123"
# 生成MD5对象
m = hashlib.md5()
# 对数据进行加密
m.update(pwd.encode('utf-8'))
# 获取密文
pwd = m.hexdigest()
print(pwd)

                4.2.3 SHA1

 SHA1(Secure Hash Algorithm)安全哈希算法主要适用于数字签名标准里面定义的数字签名算法,SHA1比MD5的安全性更强。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。

一般在没有高度混淆的Js代码中,SHA1加密的关键词就是sha1。

解密工具:哈希在线加密|MD5在线解密加密|SHA1在线解密加密|SHA256在线解密加密|SHA512在线加密|GEEKAPP开发者在线工具

import hashlib
sha1 = hashlib.sha1()
data1 = "msb"
data2 = "kkk"
sha1.update(data1.encode("utf-8"))
sha1_data1 = sha1.hexdigest()
print(sha1_data1)
sha1.update(data2.encode("utf-8"))
sha1_data2 = sha1.hexdigest()
print(sha1_data2)

运行结果:

                4.2.4 HMAC

 HMAC全称:散列消息鉴别码。HMAC加密算法是一种安全的基于加密hash函数和共享密钥的消息认证协议。实现原理是用公开函数和密钥产生一个固定长度的值作为认证标识,用这个标识鉴别消息的完整性。

python实现代码:

new(key,msg=None,digestmod)方法

创建哈希对象

key和digestmod参数必须指定,key和msg(需要加密的内容)均为bytes类型,digestmod指定加密算法,比如‘md5’,'sha1'等

对象digest()方法:返回bytes类型哈希值

对象hexdigest()方法:返回十六进制哈希值

import hmac
import hashlib
key = "key".encode()
text = "msb".encode()
m = hmac.new(key, text, hashlib.sha256)
print(m.digest())
print(m.hexdigest())

                4.2.5 DES

DES全称:数据加密标准(Data Encryption Standard),属于对称加密算法。DES是一个分组加密算法,典型的DES以64位为分组对数据加密,加密和解密用的是同一个算法。它的密钥长度是56位(因为每个第8位都用作奇偶校验),密钥可以是任意的56位数,而且可以任意时候改变。

Js逆向时,DES加密的搜索关键词有DES、mode、padding等。

# pyDes需要安装
from pyDes import des, CBC, PAD_PKCS5
import binascii
# 秘钥
KEY = 'dsj2020q'
def des_encrypt(s):"""DES 加密:param s: 原始字符串:return: 加密后字符串,16进制"""secret_key = KEYiv = secret_keyk = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)en = k.encrypt(s, padmode=PAD_PKCS5)return binascii.b2a_hex(en).decode()
​
​
def des_decrypt(s):"""DES 解密:param s: 加密后的字符串,16进制:return:  解密后的字符串"""secret_key = KEYiv = secret_keyk = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)de = k.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5)return de.decode()
​
​
text = 'msb'
secret_str = des_encrypt(text)
print(secret_str)
​
clear_str = des_decrypt(secret_str)
print(clear_str)

                4.2.6 AES

AES全程:高级加密标准,在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。

AES也是对称加密算法,如果能够获取到密钥,那么就能对密文解密。

Js逆向时,AES加密的搜索关键词有AES、mode、padding等。

import base64
from Crypto.Cipher import AES
​
# AES
# 需要补位,str不是16的倍数那就补足为16的倍数
def add_to_16(value):while len(value) % 16 != 0:value += '\0'return str.encode(value)  # 返回bytes
​
# 加密方法
def encrypt(key, text):aes = AES.new(add_to_16(key), AES.MODE_ECB)  # 初始化加密器encrypt_aes = aes.encrypt(add_to_16(text))  # 先进行aes加密encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8')return encrypted_text
​
# 解密方法
def decrypt(key, text):aes = AES.new(add_to_16(key), AES.MODE_ECB)  # 初始化加密器base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8'))decrypted_text = str(aes.decrypt(base64_decrypted), encoding='utf-8').replace('\0', '')  # 执行解密密并转码返回strreturn decrypted_text

                4.2.7 RSA

RSA全称:Rivest-Shamir-Adleman, RSA加密算法是一种非对称加密算法,在公开密钥加密和电子商业中RSA被广泛使用,它被普遍认为是目前最优秀的公钥方案之一。RSA是第一个能同时用于加密和数字签名的算法,它能够抵抗目前为止已知的所有密码攻击。

注意Js代码中的RSA常见标志setPublickey。

算法原理参考:https://www.yht7.com/news/184380

import base64
from Crypto.Cipher import PKCS1_v1_5
from Crypto import Random
from Crypto.PublicKey import RSA
​
​
# ------------------------生成密钥对------------------------
def create_rsa_pair(is_save=False):"""创建rsa公钥私钥对:param is_save: default:False:return: public_key, private_key"""f = RSA.generate(2048)private_key = f.exportKey("PEM")  # 生成私钥public_key = f.publickey().exportKey()  # 生成公钥if is_save:with open("crypto_private_key.pem", "wb") as f:f.write(private_key)with open("crypto_public_key.pem", "wb") as f:f.write(public_key)return public_key, private_key
​
​
def read_public_key(file_path="crypto_public_key.pem") -> bytes:with open(file_path, "rb") as x:b = x.read()return b
​
​
def read_private_key(file_path="crypto_private_key.pem") -> bytes:with open(file_path, "rb") as x:b = x.read()return b
​
​
# ------------------------加密------------------------
def encryption(text: str, public_key: bytes):# 字符串指定编码(转为bytes)text = text.encode("utf-8")# 构建公钥对象cipher_public = PKCS1_v1_5.new(RSA.importKey(public_key))# 加密(bytes)text_encrypted = cipher_public.encrypt(text)# base64编码,并转为字符串text_encrypted_base64 = base64.b64encode(text_encrypted).decode()return text_encrypted_base64
​
​
# ------------------------解密------------------------
def decryption(text_encrypted_base64: str, private_key: bytes):# 字符串指定编码(转为bytes)text_encrypted_base64 = text_encrypted_base64.encode("utf-8")# base64解码text_encrypted = base64.b64decode(text_encrypted_base64)# 构建私钥对象cipher_private = PKCS1_v1_5.new(RSA.importKey(private_key))# 解密(bytes)text_decrypted = cipher_private.decrypt(text_encrypted, Random.new().read)# 解码为字符串text_decrypted = text_decrypted.decode()return text_decrypted
​
​
if __name__ == "__main__":# 生成密钥对# create_rsa_pair(is_save=True)# public_key = read_public_key()# private_key = read_private_key()public_key, private_key = create_rsa_pair(is_save=False)
​# 加密text = "msb"text_encrypted_base64 = encryption(text, public_key)print("密文:", text_encrypted_base64)
​# 解密text_decrypted = decryption(text_encrypted_base64, private_key)print("明文:", text_decrypted)

相关文章:

初始爬虫13(js逆向)

为了解决网页端的动态加载,加密设置等,所以需要js逆向操作。 JavaScript逆向可以分为三大部分:寻找入口,调试分析和模拟执行。 1.chrome在爬虫中的作用 1.1preserve log的使用 默认情况下,页面发生跳转之后&#xf…...

前端发送了请求头的参数,经debug发现后端请求对象请求头中没有该参数

debug测试,发现前端发来请求头中确实没有找到添加的请求头参数,但是 Network 中却显示请求头中有该参数信息。 原因是RequestHeaders中设置的请求参数含有下划线,NGINX将静默地丢弃带有下划线的HTTP标头,这样做是为了防止在将头映…...

雷池社区版如何使用静态资源的方式建立站点

介绍: SafeLine,中文名 “雷池”,是一款简单好用, 效果突出的 Web 应用防火墙(WAF),可以保护 Web 服务不受黑客攻击。 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、X…...

车载电源OBC+DC/DC

文章目录 1. 车载DC/DC应用场景2. PFC2.1 简介2.2 专业名词2.3 常见拓扑结构2.3.1 传统桥式PFC2.3.2 普通无桥型PFC2.3.3 双Boost无桥PFC2.3.4 图腾柱PFC2.3.5 参考资料 2.4 功率因数2.4.1 简介2.4.2 计算 3. DC/DC3.1 Boost升压电路3.1.1 简介3.1.2 电路框图3.1.3 工作原理3.1…...

【朝花夕拾】免费个人网页搭建:免费托管、CDN加速、个人域名、现代化网页模板一网打尽

现代化网页设计的免费宝藏:GitHub PagesCodePenCloudflareUS.KG 前言 在当今数字化时代,个人和企业越来越重视在线形象的建立。GitHub Pages 提供了一个免费且便捷的平台,允许用户托管静态网站。然而,GitHub Pages 默认的域名可…...

Spring Boot知识管理系统:用户体验设计

6系统测试 6.1概念和意义 测试的定义:程序测试是为了发现错误而执行程序的过程。测试(Testing)的任务与目的可以描述为: 目的:发现程序的错误; 任务:通过在计算机上执行程序,暴露程序中潜在的错误。 另一个…...

《数字信号处理》学习08-围线积分法(留数法)计算z 逆变换

目录 一,z逆变换相关概念 二,留数定理相关概念 三,习题 一,z逆变换相关概念 接下来开始学习z变换的反变换-z逆变换(z反变化)。 由象函数 求它的原序列 的过程就称为 逆变换。即 。 求z逆变换…...

vue3中的computed属性

模板界面&#xff1a; <template><div class"person"><h2>姓&#xff1a; <input type"text" v-model"person.firstName" /></h2><h2>名&#xff1a; <input type"text" v-model"person…...

C++学习笔记之vector容器

天上月&#xff0c;人间月&#xff0c;负笈求学肩上月&#xff0c;登高凭栏眼中月&#xff0c;竹篮打水碎又圆。 山间风&#xff0c;水边风&#xff0c;御剑远游脚下风&#xff0c;圣贤书斋翻书风&#xff0c;风吹浮萍又相逢。 STL(Standard Template Library,标准模板库 ) 从…...

LeNet-5(论文复现)

LeNet-5&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 文章目录 LeNet-5&#xff08;论文复现&#xff09;概述LeNet-5网络架构介绍训练过程测试过程使用方式说明 概述 LeNet是最早的卷积神经网络之一。1998年&#xff0c;Yann LeCun第一次将LeN…...

基于SpringBoot+Vue+Uniapp汽车保养系统小程序的设计与实现

详细视频演示 请联系我获取更详细的演示视频 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而…...

【问题实战】Jmeter中jtl格式转换图片后如何分开展示各个性能指标?

【问题实战】Jmeter中jtl格式转换图片后如何分开展示各个性能指标&#xff1f; 遇到的问题解决方法查看修改效果 遇到的问题 JMeter测试计划中只设置了一个性能监控器jpgc - PerfMon Metrics Collector&#xff1b;在这个监控器中设置几个性能监控指标&#xff0c;比如CPU、Di…...

解决 MySQL 连接数过多导致的 SQLNonTransientConnectionException 问题

这里写目录标题 解决 MySQL 连接数过多导致的 SQLNonTransientConnectionException 问题1. 概述2. 问题描述异常日志的关键部分&#xff1a; 3. 原因分析3.1. MySQL 连接数配置3.2. 连接池配置问题3.3. 代码中未正确关闭连接3.4. 高并发导致连接需求激增 4. 解决方案4.1. 增加 …...

猫头虎分享:什么是 ChatGPT 4o Canvas?

猫头虎是谁&#xff1f; 大家好&#xff0c;我是 猫头虎&#xff0c;猫头虎技术团队创始人&#xff0c;也被大家称为猫哥。我目前是COC北京城市开发者社区主理人、COC西安城市开发者社区主理人&#xff0c;以及云原生开发者社区主理人&#xff0c;在多个技术领域如云原生、前端…...

qiankun 主项目和子项目都是 vue2,部署在同一台服务器上,nginx 配置

1、主项目配置 1.1 micro.vue 组件 <template><div id"container-sub-app"></div> </template><script> import { loadMicroApp } from qiankun; import actions from /utils/actions.js;export default {name: microApp,mixins: [ac…...

深入浅出MongoDB(七)

深入浅出MongoDB&#xff08;七&#xff09; 文章目录 深入浅出MongoDB&#xff08;七&#xff09;查询优化创建索引以支持读取操作查询选择性覆盖查询 分析性能使用数据库分析器评估对数据库的操作使用db.currentOp()评估mongod操作使用explain评估查询性能 优化查询性能创建索…...

【华为】配置NAT访问互联网

1.AR1&#xff1a; int g0/0/0 ip ad 64.1.1.2 255.255.255.0 int g0/0/1 ip ad 110.242.68.1 255.255.255.02.AR2: (1)配置端口ip: int g0/0/1 ip ad 10.3.1.2 255.255.255.0 int g0/0/0 ip ad 64.1.1.1 255.255.255.0(2)配置默认路由&#xff1a; ip route-static 0.0.0.0 0.…...

Spring Boot项目使用多线程执行定时任务

我在一个Spring Boot项目中&#xff0c;采用定时器执行一些操作&#xff0c;比如10秒就发送一次数据。这些操作有2个&#xff0c;如下所示。我就想&#xff0c;虽然这两个操作各自指定了时间频率&#xff0c;但如果其中一个操作非常耗时&#xff0c;会不会影响其他操作呢&#…...

【安装JDK和Android SDK】

安装JDK和Android SDK 1 前言2 下载2.1 下载途径2.2 JDK下载和安装2.2.1 下载2.2.2 安装并配置环境变量2.2.3 验证 2.3 SDK下载和安装2.3.1 下载2.3.2 安装2.3.3 环境变量配置2.3.4 验证 1 前言 在软件开发中&#xff0c;Android应用开发通常使用Android Studio&#xff0c;但…...

汇总10个AI免费一键生成PPT的网站

一、前言 PPT幻灯片是现代办公和学习中的重要组成部分。它在工作、研究或培训中扮演着重要角色&#xff0c;并能够让观众更好地理解信息。随着当今人工智能技术的快速发展&#xff0c;现在有很多免费的AI PPT生成器可供选择&#xff0c;帮助用户更加便捷地制作出高效且具有较强…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践

在电商行业蓬勃发展的当下&#xff0c;多平台运营已成为众多商家的必然选择。然而&#xff0c;不同电商平台在商品数据接口方面存在差异&#xff0c;导致商家在跨平台运营时面临诸多挑战&#xff0c;如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...

如何通过git命令查看项目连接的仓库地址?

要通过 Git 命令查看项目连接的仓库地址&#xff0c;您可以使用以下几种方法&#xff1a; 1. 查看所有远程仓库地址 使用 git remote -v 命令&#xff0c;它会显示项目中配置的所有远程仓库及其对应的 URL&#xff1a; git remote -v输出示例&#xff1a; origin https://…...

数据分析六部曲?

引言 上一章我们说到了数据分析六部曲&#xff0c;何谓六部曲呢&#xff1f; 其实啊&#xff0c;数据分析没那么难&#xff0c;只要掌握了下面这六个步骤&#xff0c;也就是数据分析六部曲&#xff0c;就算你是个啥都不懂的小白&#xff0c;也能慢慢上手做数据分析啦。 第一…...

如何做好一份技术文档?从规划到实践的完整指南

如何做好一份技术文档&#xff1f;从规划到实践的完整指南 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 总有一行代码&#xff0c;能点亮万千星辰。 &#x1f50d; 在技术的宇宙中&#xff0c;我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...