初始爬虫13(js逆向)

news2024/11/30 0:45:21

为了解决网页端的动态加载,加密设置等,所以需要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 base64

def 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 final

def 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 resp

if __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 = KEY
    iv = secret_key
    k = 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 = KEY
    iv = secret_key
    k = 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', '')  # 执行解密密并转码返回str
    return 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)

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

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

相关文章

基于html的大模型调试页面

效果1 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>API Call Example</title><st…

C++面向对象--------继承篇

目录 一.继承&#xff08;重点&#xff09; 1.1 概念 1.2 构造函数 1.2.1 派生类与基类的构造函数关系 1.2.2 解决方案 1.2.2.1 补充基类的无参构造函数 1.2.2.2 手动在派生类中调用基类构造函数 1.2.2.2.1 透传构造 1.2.2.2.2 委托构造 1.2.2.2.3 继承构造 1.3 对象…

为什么SEO是一个不断学习和适应的过程?

SEO并不是一成不变的&#xff0c;它是一个需要不断学习和适应的过程。谷歌的算法经常更新&#xff0c;用户的搜索行为也在不断变化&#xff0c;这使得SEO策略必须与时俱进&#xff0c;才能保持有效性。企业需要认识到&#xff0c;SEO是一项长期的投资&#xff0c;需要持续的关注…

Spring WebFlux 响应式概述(1)

1、响应式编程概述 1.1、响应式编程介绍 1.1.1、为什么需要响应式 传统的命令式编程在面对当前的需求时的一些限制。在应用负载较高时&#xff0c;要求应用需要有更高的可用性&#xff0c;并提供低的延迟时间。 1、Thread per Request 模型 比如使用Servlet开发的单体应用&a…

PostgreSQL学习笔记十:锁机制详解

一、PostgreSQL 的锁机制 PostgreSQL中的锁机制是确保数据一致性和完整性的关键。它通过不同级别的锁来控制对数据对象的并发访问&#xff0c;主要包括表级锁、行级锁、页级锁、咨询锁&#xff08;Advisory Locks&#xff09;以及死锁&#xff08;Deadlocks&#xff09;。 1. …

基于Java+Springboot+Vue开发的大学竞赛报名管理系统

项目简介 该项目是基于JavaSpringbootVue开发的大学竞赛报名管理系统&#xff08;前后端分离&#xff09;&#xff0c;这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能&#xff0c;同时锻炼他们的项目设计与开发能力。通过学习基于Java…

# linux从入门到精通-从基础学起,逐步提升,探索linux奥秘(九)--网络设置与文件上传下载

linux从入门到精通-从基础学起&#xff0c;逐步提升&#xff0c;探索linux奥秘&#xff08;九&#xff09;–网络设置与文件上传下载 一、网络设置 1、首先知道网卡配置文件位置&#xff1a;/etc/sysconfig/network-scripts [rootlocalhost test1]# ls /etc/sysconfig/netwo…

JSON 格式化工具:快速便捷地格式化和查看 JSON 数据

JSON 格式化工具&#xff1a;快速便捷地格式化和查看 JSON 数据 为什么需要 JSON 格式化工具&#xff1f; 在日常开发和调试中&#xff0c;JSON 是非常常见的数据交换格式。无论是前端与后端的接口调用&#xff0c;还是数据存储和处理&#xff0c;JSON 格式都扮演着重要角色。…

【HarmonyOS开发笔记 2 】 -- ArkTS语法中的变量与常量

ArkTS是HarmonyOS开发的编程语言 ArkTS语法中的变量 【语法格式】&#xff1a; let 变量名: 类型 值 let&#xff1a;是定义变量的关键字类型&#xff1a; 值数据类型&#xff0c; 常用的数据类型 字符型&#xff08;string&#xff09;、数字型&#xff08;number&#xf…

PG 17 增量备份功能介绍

背景 PG 17 新增了增量备份功能&#xff0c;可以通过 pg_basebackup --incrementalPATH_TO_MANIFEST 命令进行增量备份。 官方文档&#xff1a;https://www.postgresql.org/docs/current/app-pgbasebackup.html 使用方法 全量备份 启动实例后&#xff0c;首先配置参数 sum…

【北京迅为】《STM32MP157开发板嵌入式开发指南》- 第三十五章 嵌入式开发概述及环境构建

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

数据库表使用方法:

数据库表&#xff1a; 提供四种类型的约束保证完整性&#xff1a; 1.域完整性&#xff0c;2.实体完整性 3.自定义完整性 4.引用完整性 实体完整性&#xff1a; 约束方法&#xff1a;唯一约束&#xff0c;主键约束&#xff0c;标识列 域完整性&#xff1a; 约束方法&#x…

基于depth anything模型理解深度估计运行机理

文章目录 前言一、概念说明1、深度概念2、绝对深度概念3、相对深度概念4、深度估计表示方法二、相对深度估计与绝对(即度量)深度估计1、模型预测绝对深度劣势与应用优势2、模型预测相对深度必然性3、小结三、深度估计模型loss方法四、深度估计模型评估方法1、绝对相对误差2、…

Python:方法的链式调用

相关阅读 Pythonhttps://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 在Python编程中&#xff0c;方法的链式调用是一种简洁且优雅的编程风格&#xff0c;它允许你在一行代码中连续调用多个方法&#xff0c;这种编程模式在简化代码、提升可…

22.安卓逆向-frida基础-objection工具1-安装和简单使用(Python的pip指令安装完提示不是内部命令解决办法)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;图灵Python学院 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要盲目相信。 工…

java4~~~

日期 第一代 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.logging.SimpleFormatter;public class Main {public static void main(String[] args) throws ParseException {//两种构造器的使用//1、获取当…

OpenCV高级图形用户界面(1)创建滑动条函数createTrackbar()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 创建一个滑动条并将其附加到指定的窗口。 该函数 createTrackbar 创建一个具有指定名称和范围的滑动条&#xff08;滑块或范围控制&#xff09;…

Flexbox 弹性盒子布局

Flexbox&#xff0c;全称弹性盒子布局&#xff0c;提供更精细的控制&#xff0c;能轻松解决困扰我们许久的垂直居中和登高列问题。 1 display: flex 将容器设置为弹性容器&#xff0c;容器会占据100%的可用宽度&#xff0c;高度则由自身的内容来决定&#xff0c;即使改变主轴…

基于SSM的“企业人事管理系统”的设计与实现(源码+数据库+文档)

基于SSM的“企业人事管理系统”的设计与实现&#xff08;源码数据库文档) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 登陆页面 部门管理页面 加班页面 考勤页面 请假页面 工资页面 …

leetcode链表(三)-反转链表

题目 . - 力扣&#xff08;LeetCode&#xff09; 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 思路 首先定义一个cur指针&#xff0c;指向头结点&#xff0c;再定义一个pre指针&#xff0c;初始化为None。 然后就要开始反转了&…