Announcement

👇Official Account👇

图片

Welcome to join the group & private message

Article first/tail QR code

Skip to content

爬虫加密解密算法特征收集 - Python 实战

在爬虫开发过程中,我们经常会遇到各种加密机制的保护。目标网站为了防止数据被轻易抓取,通常会采用 JavaScript 加密、参数签名、数据加密等手段。本文将系统梳理爬虫中常见的加密解密算法特征,并提供 Python 破解实战方案。

一、常见加密类型识别

1.1 编码类加密

Base64 编码

特征识别:

  • 字符串只包含 A-Za-z0-9+/=
  • 长度通常是 4 的倍数
  • 结尾可能有 0-2 个 = 填充符

常见形式:

javascript
// 标准 Base64
"SGVsbG8gV29ybGQ="

// URL 安全的 Base64(替换 +/ 为 -_)
"SGVsbG8gV29ybGQ"

// 去除填充符的 Base64
"SGVsbG8gV29ybGQ"

Python 破解:

python
import base64

# 标准 Base64 解码
data = "SGVsbG8gV29ybGQ="
decoded = base64.b64decode(data).decode('utf-8')
print(decoded)  # Hello World

# URL 安全 Base64
url_safe = "SGVsbG8gV29ybGQ"
decoded = base64.urlsafe_b64decode(url_safe + '=' * (4 - len(url_safe) % 4))

URL 编码

特征识别:

  • % 后跟两位十六进制字符
  • 空格编码为 %20+
  • 中文字符通常被编码

Python 破解:

python
from urllib.parse import unquote, quote

encoded = "%E4%BD%A0%E5%A5%BD"  # 你好
decoded = unquote(encoded)
print(decoded)  # 你好

1.2 哈希类加密

MD5 加密

特征识别:

  • 固定 32 位十六进制字符串
  • 只包含 0-9a-f
  • 相同输入始终产生相同输出
  • 不可逆(但可通过彩虹表破解)

常见形式:

5d41402abc4b2a76b9719d911017c592  # "hello" 的 MD5

Python 识别与破解:

python
import hashlib
import re

def is_md5(text):
    """判断是否为 MD5 格式"""
    return bool(re.match(r'^[a-f0-9]{32}$', text))

# 生成 MD5 对比
text = "hello"
md5_hash = hashlib.md5(text.encode()).hexdigest()
print(f"{text} -> {md5_hash}")

# 简单彩虹表破解(仅适用于简单密码)
def crack_md5(target_hash, wordlist):
    for word in wordlist:
        if hashlib.md5(word.encode()).hexdigest() == target_hash:
            return word
    return None

SHA 系列

特征识别:

算法长度特征
SHA-140 位十六进制,已不安全
SHA-25664 位常用,安全性高
SHA-512128 位更长,更安全

Python 处理:

python
import hashlib

# SHA-256
text = "hello"
sha256_hash = hashlib.sha256(text.encode()).hexdigest()
print(f"SHA-256: {sha256_hash}")

# SHA-1
sha1_hash = hashlib.sha1(text.encode()).hexdigest()
print(f"SHA-1: {sha1_hash}")

1.3 对称加密

AES 加密

特征识别:

  • 密文通常是 Base64 或十六进制格式
  • 需要密钥(Key)和初始向量(IV)
  • 密钥长度通常为 16/24/32 字节(AES-128/192/256)
  • 常见模式:CBC、ECB、GCM

JavaScript 中的常见形式:

javascript
// CryptoJS AES
var encrypted = CryptoJS.AES.encrypt("message", "secret key").toString();

// 通常配合 Base64 输出
// U2FsdGVkX1+Z3zv7X8y+K7zF7X8y+K7zF7X8y+K7zF=

Python 破解(需要找到密钥):

python
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad, pad
import base64

def decrypt_aes(ciphertext, key, iv=None, mode='CBC'):
    """
    AES 解密
    :param ciphertext: Base64 编码的密文
    :param key: 密钥(16/24/32 字节)
    :param iv: 初始向量(CBC 模式需要)
    :param mode: 加密模式 CBC/ECB
    """
    key = key.encode('utf-8')
    
    if mode == 'CBC':
        iv = iv.encode('utf-8') if iv else b'\x00' * 16
        cipher = AES.new(key, AES.MODE_CBC, iv)
    else:  # ECB
        cipher = AES.new(key, AES.MODE_ECB)
    
    ct = base64.b64decode(ciphertext)
    pt = unpad(cipher.decrypt(ct), AES.block_size)
    return pt.decode('utf-8')

# 示例使用
key = "thisisakey123456"  # 16 字节
encrypted = "U2FsdGVkX1+Z3zv7X8y+K7zF7X8y+K7zF7X8y+K7zF="
# decrypted = decrypt_aes(encrypted, key)

如何从 JS 代码中找到 AES 密钥:

python
import re

def extract_aes_key(js_code):
    """从 JS 代码中提取可能的 AES 密钥"""
    patterns = [
        r'key["\']?\s*[:=]\s*["\']([^"\']+)["\']',
        r'encrypt\(["\']([^"\']+)["\']',
        r'password["\']?\s*[:=]\s*["\']([^"\']+)["\']',
    ]
    
    keys = []
    for pattern in patterns:
        matches = re.findall(pattern, js_code)
        keys.extend(matches)
    
    return list(set(keys))

DES/3DES 加密

特征识别:

  • 密钥长度为 8 字节(DES)或 24 字节(3DES)
  • 块大小为 8 字节
  • 密文长度通常是 8 的倍数

Python 破解:

python
from Crypto.Cipher import DES
from Crypto.Util.Padding import unpad
import base64

def decrypt_des(ciphertext, key, iv=None):
    """DES 解密"""
    key = key.encode('utf-8')[:8]  # DES 密钥必须为 8 字节
    iv = iv.encode('utf-8')[:8] if iv else b'\x00' * 8
    
    cipher = DES.new(key, DES.MODE_CBC, iv)
    ct = base64.b64decode(ciphertext)
    pt = unpad(cipher.decrypt(ct), DES.block_size)
    return pt.decode('utf-8')

1.4 非对称加密

RSA 加密

特征识别:

  • 公钥通常以 -----BEGIN PUBLIC KEY----- 开头
  • 私钥通常以 -----BEGIN PRIVATE KEY----------BEGIN RSA PRIVATE KEY----- 开头
  • 密文长度固定,与密钥长度相关
  • 加密数据通常经过 Base64 编码

常见场景:

  • 登录密码加密
  • 敏感数据传输
  • 数字签名验证

Python 处理(需要私钥):

python
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64

def decrypt_rsa(ciphertext, private_key_pem):
    """
    RSA 解密
    :param ciphertext: Base64 编码的密文
    :param private_key_pem: PEM 格式的私钥
    """
    private_key = RSA.import_key(private_key_pem)
    cipher = PKCS1_v1_5.new(private_key)
    
    ct = base64.b64decode(ciphertext)
    pt = cipher.decrypt(ct, None)
    return pt.decode('utf-8')

# 示例私钥格式
private_key = """-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAxgNSPM+TDyx...
-----END RSA PRIVATE KEY-----"""

二、实战:逆向分析加密流程

2.1 分析步骤

  1. 抓包分析

    bash
    # 使用 Chrome DevTools 或 Fiddler 抓包
    # 关注 XHR/Fetch 请求
    # 观察请求参数和响应数据
  2. 定位加密代码

    javascript
    // 在 Chrome DevTools 中搜索关键词
    // encrypt, decrypt, sign, encode, decode
    // CryptoJS, aes, rsa, md5, sha
  3. 断点调试

    javascript
    // 在可疑代码处打断点
    // 观察加密前后的数据变化
    // 提取密钥和算法参数
  4. 编写 Python 破解代码

2.2 实战案例:某网站登录加密

场景描述: 某网站登录接口,密码经过加密后传输。

分析过程:

javascript
// 在页面源码中发现
function encryptPassword(password) {
    var key = CryptoJS.enc.Utf8.parse("1234567890123456");
    var iv = CryptoJS.enc.Utf8.parse("abcdef1234567890");
    var encrypted = CryptoJS.AES.encrypt(password, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    return encrypted.toString();
}

Python 破解:

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

def encrypt_password(password):
    key = "1234567890123456".encode('utf-8')
    iv = "abcdef1234567890".encode('utf-8')
    
    cipher = AES.new(key, AES.MODE_CBC, iv)
    pt = pad(password.encode('utf-8'), AES.block_size)
    ct = cipher.encrypt(pt)
    
    return base64.b64encode(ct).decode('utf-8')

# 使用
encrypted = encrypt_password("mypassword")
print(encrypted)

2.3 实战案例:参数签名破解

场景描述: API 请求需要携带签名参数,防止重放攻击。

常见签名算法:

python
import hashlib
import hmac
import time

def generate_sign(params, secret_key):
    """
    生成签名(常见算法)
    :param params: 请求参数字典
    :param secret_key: 密钥
    """
    # 1. 按键排序
    sorted_params = sorted(params.items())
    
    # 2. 拼接字符串
    param_str = '&'.join([f"{k}={v}" for k, v in sorted_params])
    
    # 3. 添加密钥
    sign_str = f"{param_str}&key={secret_key}"
    
    # 4. MD5 或 HMAC
    sign = hashlib.md5(sign_str.encode()).hexdigest().upper()
    
    return sign

# HMAC 签名
def hmac_sign(message, secret_key):
    return hmac.new(
        secret_key.encode(),
        message.encode(),
        hashlib.sha256
    ).hexdigest()

三、高级技巧

3.1 使用 PyExecJS 执行 JS 代码

python
import execjs

# 读取 JS 文件
with open('encrypt.js', 'r', encoding='utf-8') as f:
    js_code = f.read()

# 编译执行
ctx = execjs.compile(js_code)
result = ctx.call('encryptPassword', 'mypassword')
print(result)

3.2 使用 Playwright 直接调用页面 JS

python
from playwright.sync_api import sync_playwright

def get_encrypted_data(page, data):
    """在浏览器环境中执行加密函数"""
    return page.evaluate(f"""
        () => {{
            return encryptData('{data}');
        }}
    """)

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://target-site.com")
    
    encrypted = get_encrypted_data(page, "sensitive_data")
    print(encrypted)
    
    browser.close()

3.3 WASM 加密处理

某些网站使用 WebAssembly 进行加密,处理更复杂:

python
# 1. 分析 WASM 导出函数
# 2. 使用 wasmtime 或 pywasm 调用
# 3. 或者通过 Playwright 在浏览器中调用

四、反反爬虫策略

4.1 常见防护手段

防护手段识别方法应对策略
字体反爬@font-face 自定义字体下载字体文件,建立映射表
CSS 偏移元素位置与实际显示不符计算真实位置,还原数据
Canvas 指纹检测 Canvas 渲染特征固定随机种子,或使用真实浏览器
WebGL 指纹检测显卡信息使用常见硬件配置
行为检测鼠标轨迹、点击模式模拟人类行为,添加随机延迟

4.2 加密参数动态生成

python
import random
import time

def generate_device_id():
    """生成设备 ID"""
    return ''.join(random.choices('abcdef0123456789', k=32))

def generate_timestamp():
    """生成时间戳"""
    return str(int(time.time() * 1000))

def generate_random_str(length=16):
    """生成随机字符串"""
    return ''.join(random.choices('abcdefghijklmnopqrstuvwxyz0123456789', k=length))

五、工具推荐

5.1 浏览器插件

  • EditThisCookie: Cookie 管理
  • JSON Viewer: JSON 格式化
  • Wappalyzer: 技术栈识别

5.2 抓包工具

  • Fiddler: Windows 平台
  • Charles: 跨平台
  • Proxyman: macOS

5.3 逆向工具

  • Chrome DevTools: 必备
  • PyCharm: Python 开发
  • CyberChef: 在线编码转换

六、总结

加密类型识别特征破解难度常用工具
Base64特定字符集,4的倍数base64 库
MD5/SHA固定长度十六进制⭐⭐hashlib
AES需密钥和 IV⭐⭐⭐pycryptodome
RSA公钥/私钥对⭐⭐⭐⭐pycryptodome
自定义混淆代码⭐⭐⭐⭐⭐JS 逆向

核心原则:

  1. 先识别加密类型,再选择破解方案
  2. 优先寻找密钥,而非硬破解
  3. 复杂加密考虑使用浏览器环境直接执行
  4. 遵守法律法规,仅用于合法爬虫开发

本文持续更新,欢迎交流讨论。

上次更新于: