加解密,编解码,js逆向

加密与编码流程详解

为什么要加密与编码?

在现代 Web 应用中,为了防止数据被非法获取或篡改,服务器与客户端之间的通信通常会使用加密和编码的方式进行保护。尤其是在电商、金融、社交等敏感场景下,这种做法尤为重要。

当你第一次访问某个网站时,服务器会下发一段 JavaScript 代码(通常是通过 <script src="xxx.js"> 引入),这段 JS 中可能包含了加密算法逻辑以及密钥生成规则。浏览器执行这些脚本后,后续发送的请求参数(如搜索词、分页、用户行为)都会经过加密处理,并通过 Base64 等方式进行编码后再发送给服务器。

对爬虫的影响:

  • 无法直接构造请求参数:如果你不知道加密方式和密钥,就无法构造出合法的请求体。
  • 无法解析返回结果:即使你成功发出请求,服务器返回的数据也可能是加密过的,你需要有对应的解密逻辑才能提取有效信息。
  • 需要逆向分析 JS 脚本:要破解加密逻辑,必须定位并提取 JS 中的加密函数、密钥生成方式,甚至模拟执行环境(如使用 PyppeteerSelenium)。

举例说明
假设你想批量爬取某网站第1到第10页的内容,但每一页的请求参数都经过 AES 加密。你如果不掌握加密逻辑,只能手动点击页面按钮,复制加密后的参数,再逐个请求,效率极低且容易被封 IP。


流程概述

发送方(客户端/爬虫):

1. 加密

使用对称加密算法(如 AES、DES、3DES)对明文数据进行加密。以 AES 为例:

  • 密钥(key):用于加密和解密,长度必须符合要求(如 AES-128 为 16 字节)
  • 初始化向量(IV):用于 CBC 模式,增加加密数据的随机性
  • 填充方式:如 PKCS7,确保数据长度是块大小的整数倍

2. 编码

加密后的数据通常是二进制格式,不适合直接传输。因此常使用 Base64 编码,将其转换为 ASCII 可打印字符。

  • Base64 编码特点
    • 使用 64 个字符表示数据:A-Z、a-z、0-9、+、/
    • 数据末尾可能会出现 = 进行补位

接收方(服务端/爬虫):

1. 解码

将接收到的 Base64 字符串还原成原始的二进制加密数据。

2. 解密

使用相同的密钥和 IV 对数据进行解密,恢复原始明文。


Python 示例代码

AES 加密 + Base64 编码

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import base64

data = "hello world".encode()
data_padded = pad(data, 16)  # PKCS7 填充

key = b"1234567890abcdef"
iv = b"0987654321zxcvbn"

cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted_data = cipher.encrypt(data_padded)

base64_encrypted = base64.b64encode(encrypted_data).decode()
print("加密并Base64编码后的结果:", base64_encrypted)

Base64 解码 + AES 解密

from Crypto.Util.Padding import unpad

encrypted_bytes = base64.b64decode(base64_encrypted)
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_padded = cipher.decrypt(encrypted_bytes)
original_data = unpad(decrypted_padded, 16)

print("解密后的原始数据:", original_data.decode())

MD5 散列算法简介

MD5 是一种常用的散列算法,用于生成固定长度的摘要(128位)。虽然不适用于加密,但常用于验证文件完整性。

Python 示例

import hashlib

data = "hello world".encode()
md5_hash = hashlib.md5(data).hexdigest()
print("MD5摘要:", md5_hash)

RSA 非对称加密简介

RSA 是一种非对称加密算法,使用公钥加密、私钥解密。适用于安全传输密钥、数字签名等场景。

Python 示例

生成密钥对

from Crypto.PublicKey import RSA

key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()

with open("private.pem", "wb") as f:
    f.write(private_key)

with open("public.pem", "wb") as f:
    f.write(public_key)

加密

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

key = RSA.import_key(open("public.pem").read())
cipher_rsa = PKCS1_OAEP.new(key)
data = "hello world".encode()
encrypted_data = cipher_rsa.encrypt(data)
print("RSA加密结果:", encrypted_data)

解密

key = RSA.import_key(open("private.pem").read())
cipher_rsa = PKCS1_OAEP.new(key)
decrypted_data = cipher_rsa.decrypt(encrypted_data)
print("RSA解密结果:", decrypted_data.decode())

JS逆向分析技巧

为什么要js逆向

在第一次访问某网站时,网站服务器会发给你的浏览器一套js代码,这套代码中包含了加密的方式和密钥,你和服务器之间的通信要按照这套js代码,进行加密和编码,这样就可以防止爬虫进行批量爬取了,举例来说,我想批量爬取1到10页的内容,如果我不知道加密方式和密钥,我只能手动点击一到10页的按钮,一个个去拷贝加密后的请求参数,然后复制过来再去请求,同时,我在收到加密的回复后,我得不到有用的信息,所以我必须想个办法拿到那套Js代码中的加密和密钥部分,这样我才能使用脚本

当你在处理前端 JavaScript 代码时,如果遇到加密逻辑,可以通过以下步骤来逆向分析:

常用方法

  1. 全局搜索:查找可能用于加密的函数或变量名,如 decryptencryptkeyiv 等。
  2. 调试工具:利用浏览器开发者工具设置断点,逐步跟踪代码执行过程,观察参数传递情况。
  3. 确定关键信息:通过调试找到加密过程中使用的具体密钥(key)、初始向量(IV)和其他相关参数。

案例分析

  • 案例一:AES 加密

    • 在 JavaScript 中查找类似 CryptoJS.AES.encrypt 的调用。
    • 设置断点并查看传入的密钥和 IV。
  • 案例二:RSA 加密

    • 查找使用 window.crypto.subtle.encrypt 或第三方库(如 forge)的加密逻辑。
    • 调试获取公钥和加密数据。
  • 案例三:Base64 编码

    • 查找 btoa()Buffer.from(...).toString('base64') 的使用。
    • 观察输入和输出是否与预期一致。

关键步骤

  1. 全局搜索关键词

    • 搜索 encrypt, decrypt, key, iv, CryptoJS, forge, btoa, atob
    • 查找调用加密函数的位置,例如 CryptoJS.AES.encrypt(...) 或自定义函数
  2. 设置断点调试

    • 在浏览器开发者工具中打开 Sources 面板
    • 找到包含加密逻辑的 JS 文件
    • 在加密函数前后设置断点,观察输入输出值
  3. 提取关键信息

    • 密钥(key)、初始化向量(IV)可能硬编码,也可能动态生成
    • 有时会使用时间戳、随机数等作为种子生成密钥
    • 注意是否有混淆或压缩,必要时可使用在线反混淆工具
  4. 模拟执行环境

    • 如果 JS 依赖浏览器上下文(如 window、document),可以使用 PyppeteerPlaywright 控制真实浏览器
    • 如果只是纯函数,可以提取 JS 函数并在 Node.js 或 PyExecJS 中运行

总结笔记建议

编写加密相关的笔记时,建议记录以下内容:

项目 内容
加密算法类型 如 AES、RSA、MD5
加密模式 如 CBC、ECB
填充方式 如 PKCS7、ZeroPadding
密钥来源 固定值?动态生成?来自 cookie?
IV 来源 同上
编码方式 Base64、Hex、URL Encode 等
JS 调试方法 断点位置、变量名、函数调用栈
逆向难点 是否有混淆、是否依赖浏览器环境
posted @ 2025-05-30 16:34  玉米面手雷王  阅读(47)  评论(0)    收藏  举报