初始爬虫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)

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

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

相关文章

【SPIE出版,EI检索稳定】2024年人机交互与虚拟现实国际会议(HCIVR 2024,11月15-17日)

2024年人机交互与虚拟现实国际会议(HCIVR 2024) 2024 International Conference on Human-Computer Interaction and Virtual Reality 官方信息 会议官网:www.hcivr.org 2024 International Conference on Human-Computer Interaction and …

Cuda By Example - 7 (光线追踪)

第6章以实现简单的光线追踪为例子,引入了Constant Memory和性能测量方法。 Constant Memory NVIDIA的硬件提供了64K的constant只读内存。定义constant内存的变量,使用关键字__constant__。从constant内存里读取出来的数据,可以缓存起来&…

【Ubuntu18.04命令行code打不开】可能的解决方法

目录 问题:命令行code打不开文件尝试① kimi是这么说的② sudo apt-get install apparmor apparmor_utils③ 在混沌的操作完以上一通后,sudo apt-get install snapd 我试了将近一个小时 : ( so depressed 我只是想用vscode打开个文件夹,我甚至…

Leetcode 1129. 颜色交替的最短路径

1.题目基本信息 1.1.题目描述 给定一个整数 n,即有向图中的节点数,其中节点标记为 0 到 n – 1。图中的每条边为红色或者蓝色,并且可能存在自环或平行边。 给定两个数组 redEdges 和 blueEdges,其中: redEdges[i] …

从零入门AI篡改图片检测(金融场景)#Datawhale十月组队学习

1.大赛背景 在全球人工智能发展和治理广受关注的大趋势下,由中国图象图形学学会、蚂蚁集团、云安全联盟CSA大中华区主办,广泛联合学界、机构共同组织发起全球AI攻防挑战赛。本次比赛包含攻防两大赛道,分别聚焦大模型自身安全和大模型生成内容…

安装好的 Nginx 增加 nginx-module-vts 模块

目录 1. nginx-module-vts 准备 2.查看已安装的的 nginx 编译参数 3. 重新编译 nginx 添加 nginx-module-vts 模块 4. 验证 1. nginx-module-vts 准备 # 解压 unzip nginx-module-vts-master.zip # 将解压包移动到/usr/local/目录 mv nginx-module-vts-master /usr/local/ …

jmeter响应断言放进csv文件遇到的问题

用Jmeter的json 断言去测试http请求响应结果,发现遇到中文时出现乱码,导致无法正常进行响应断言,很影响工作。于是,察看了其他测试人员的解决方案,发现是jmeter本身对编码格式的设置导致了这一问题。解决方案是在jmete…

轻松应对PDF编辑难题:四款免费pdf编辑器实测体验

作为一名办公室文员,每天处理各种文件是家常便饭。而PDF文档因其格式稳定、不易篡改的特性,在工作中扮演着重要角色。但编辑PDF文件却不像编辑Word文档那样简单,这就需要一款得心应手的PDF编辑器。今天,我就来分享一下我使用过的几…

如何利用解析器绕过访问控制

0x01 前言 每年blackhat总是会有一些新奇的攻击思路值得大家学习,在2024年blackhat的议题中发现一篇很有意思的文章,作者提出了一套基于邮箱的欺骗攻击思路,利用RFC标准中对SMTP协议中邮箱地址的特性,提供一系列绕过技巧&#xf…

揭秘Map与Set的键值奥秘与集合魅力,解锁高效数据魔法

文章目录 前言➰一、关联式容器1.1 关联式容器的概述1.2 关联式容器的工作原理1.3 关联式容器的核心特性 ➰二、键值对2.1 键值对的基本概念2.2 键值对在C中的实现 ➰三、树形结构的关联式容器3.1 树形结构的特点3.2 使用场景 ➰四、set的使用与定义4.1 set的基本特性4.2 set的…

Flutter UI组件库(JUI)

Flutter UI组件库 (JUI) 介绍 您是否正在寻找一种方法来简化Flutter开发过程,并创建美观、一致的用户界面?您的搜索到此为止!我们的Flutter UI组件库(JUI)提供了广泛的预构建、可自定义组件,帮助您快速构建…

RHCE--ntp客户端,时间服务器服务端

NTP 是网络时间协议( Network Time Protocol )的简称,通过 udp 123 端口进行网络时钟同步。 Chrony 是一个开源自由的网络时间协议 NTP 的客户端和服务器软件。它能让计算机保持系统时钟与时钟服务器( NTP )同步&#…

计算机网络:数据链路层 —— 以太网(Ethernet)

文章目录 局域网局域网的主要特征 以太网以太网的发展100BASE-T 以太网物理层标准 吉比特以太网载波延伸物理层标准 10吉比特以太网汇聚层交换机物理层标准 40/100吉比特以太网传输媒体 局域网 局域网(Local Area Network, LAN)是一种计算机网络&#x…

基于SSM果蔬经营系统的设计

管理员账户功能包括:系统首页,个人中心,用户管理,商品信息管理,类型管理,系统管理,订单管理 前台账号功能包括:系统首页,个人中心,商品信息,广告…

爬虫+数据保存

爬虫以及数据保存 这篇文章, 分享如何将爬虫爬到的数据, 保存到excel表格当中。 文章目录 1.安装保存数据的第三方库openpyxl并使用 2.爬虫加单表数据保存 3.爬虫加多表数据保存 4.实战 一、安装保存数据的第三方库openpyxl并使用 我们需要安装openpyxl的第三方库 安装…

Qt第十三天:网络编程:TCP和UDP的使用

我发现了有些人喜欢静静看博客不聊天呐, 但是ta会点赞。 这样的人呢帅气低调有内涵, 美丽大方很优雅。 说的就是你, 不用再怀疑哦 ❤️TCP: 一、创建项目,命名为Server,继承QWidget 二、添加Qt设计师…

CentOS7安装RabbitMQ-3.13.7、修改端口号

本文安装版本: Erlang:26.0 官网下载地址 Erlang RabbitMQ:3.13.7 官网下载地址 RabbitMQ RabbitMQ和Erlang对应关系查看:https://www.rabbitmq.com/which-erlang.html 注:安装erlang之前先安装下依赖文件&#xff0…

云黑系统全解无后门 +搭建教程

这套系统呢是玖逸之前南逸写的一套云黑系统,功能带有卡密生成和添加黑名单等,源码放在我的网盘里已经两年之久,由于玖逸现在已经跑路了所以现在发出来分享给大家,需要的可以自己拿去而开,反正功能也不是很多具体的自己…

Teledyne LeCroy:800G高速以太网一站式自动化测试解决方案(网络打流测试+物理层加压干扰+协议分析)

LinkExpert一站式测试解决方案 LinkExpert 是一款软件应用程序,可对Teledyne LeCroy的协议分析仪和训练器进行自动化硬件控制和管理。除了作为合规性、一致性和验证测试的便捷接口外,它还能轻松地将这些测试添加到自动回归测试流程中。 现在,…

WPF基础权限系统

一.开发环境 VisualStudio 2022NET SDK 8.0Prism 版本 8.1.97Sqlite 二. 功能介绍 WPF 基础权限系统,是一个支持前后端分离设计的 客户端(C/S)项目,该示例项目前端xaml使用UI库 ,Material Design Themes UI 来构建用户界面,确保…