首页 论坛 基于CDP协议绕过前端加密的Python爆破脚本实现
2025年12月17日 发帖:
63 浏览
回帖 点赞 0 状态帖子有人回复啦,看看Ta 们说了啥~
帖子详情

 

一、CDP协议与前端加密绕过原理
Chrome DevTools Protocol(CDP)是谷歌提供的一种基于WebSocket的调试协议,允许外部工具与Chrome浏览器进行深度交互。通过CDP,可以实时监控和修改页面行为,包括拦截网络请求、动态修改JavaScript代码以及监听执行流程。

🔍 CDP工作原理与加密绕过机制
CDP的核心优势在于它能在三个关键阶段对JS代码进行动态修改:

网络连接阶段:在脚本文件到达浏览器但尚未解析前修改内容
代码解析阶段:在V8引擎解析脚本时进行代码替换
代码执行阶段:在运行时通过断点干预执行流程
加密绕过原理的核心是利用CDP的Debugger.evaluateOnCallFrame命令,该命令允许在指定的调试调用栈帧中执行JavaScript表达式。这意味着无需逆向分析复杂的加密算法,而是直接利用浏览器自身的运行环境执行加密函数。

🎯 技术实现框架
关键CDP命令应用:

断点设置:在加密函数被调用位置设置断点,获取执行上下文
动态调用:通过Debugger.evaluateOnCallFrame注入参数并获取加密结果
实时干预:在代码执行阶段修改加密逻辑或获取中间值
三种主要修改方式对比:

方法        适用阶段        实现方式        优势
网络拦截        网络连接阶段        Network.setRequestInterception拦截响应后修改脚本        修改效率高
脚本解析替换        代码解析阶段        监听Debugger.scriptParsed事件进行代码替换        执行效率高
运行时修改        代码执行阶段        设置条件断点修改变量或执行流程        灵活性最高
💡 实际应用场景
在密码爆破场景中,CDP绕过加密的技术流程为:

环境准备:启动带远程调试端口的Chrome浏览器
断点定位:在加密函数调用位置设置断点,获取callFrameId
动态加密:通过CDP命令调用加密函数对测试密码进行加密
集成爆破:将加密结果用于构造登录请求,实现自动化测试
这种方法将复杂的JS逆向问题转化为可控的浏览器自动化操作,特别适用于加密算法复杂或混淆严重的场景,能够显著提高测试效率和成功率。

二、Python库选型与环境准备
🔧 核心库选择与技术路线对比
基于CDP协议绕过前端加密的Python实现,主要有三种技术路线,各具特色:

技术方案        核心库        适用场景        优势        局限性
原生CDP协议        websocket-client + requests        需要精细控制CDP命令的复杂场景        完全控制CDP流程,灵活性最高        需要手动处理所有CDP命令和事件
高层封装库        PyChromeDevTools        快速原型开发,简化CDP交互        封装了常用CDP命令,开发效率高        对底层控制能力相对有限
浏览器自动化        selenium-wire + CDP扩展        需要结合请求拦截的场景        集成请求捕获和CDP功能        性能开销较大

# 基础调试模式启动
chrome –remote-debugging-port=9222 –user-data-dir=/tmp/chrome-profile

# 增强版启动参数(推荐)
chrome –remote-debugging-port=9222 \
–user-data-dir=/tmp/chrome-profile \
–no-first-run \
–no-default-browser-check \
–disable-extensions \
–disable-plugins \
–disable-translate
验证调试接口可用性:

import requests

def check_chrome_debugger():
“””检查Chrome调试接口是否正常”””
try:
response = requests.get(‘ http://127.0.0.1:9222/json’)
if response.status_code == 200:
tabs = response.json()
print(f”[+] 发现 {len(tabs)} 个调试标签页”)
return True
else:
print(“[-] 调试接口不可用”)
return False
except Exception as e:
print(f”[-] 连接失败: {e}”)
return False
💻 开发环境搭建示例
基础CDP连接测试:

import websocket
import json
import requests

class CDPEnvironment:
def __init__(self, host=’127.0.0.1′, port=9222):
self.debug_url = f’http://{host}:{port}’
self.ws_conn = None

def setup_connection(self):
“””建立CDP WebSocket连接”””
try:
# 获取WebSocket调试地址
resp = requests.get(f'{self.debug_url}/json’)
ws_url = resp.json()[0][‘webSocketDebuggerUrl’]

# 创建WebSocket连接
self.ws_conn = websocket.create_connection(ws_url)
print(“[+] CDP连接建立成功”)
return True
except Exception as e:
print(f”[-] 连接失败: {e}”)
return False

def enable_debug_domains(self):
“””启用必要的调试域”””
domains = [‘Runtime’, ‘Debugger’, ‘Network’, ‘Page’]
for domain in domains:
cmd = {‘id’: 1, ‘method’: f'{domain}.enable’}
self.ws_conn.send(json.dumps(cmd))
response = self.ws_conn.recv()
print(f”[+] {domain}域启用: {response}”)

def test_environment(self):
“””测试环境完整性”””
# 测试Runtime执行能力
test_cmd = {
‘id’: 2,
‘method’: ‘Runtime.evaluate’,
‘params’: {‘expression’: ‘1 + 1’}
}
self.ws_conn.send(json.dumps(test_cmd))
result = json.loads(self.ws_conn.recv())
print(f”

  • 环境测试结果: {result}”)

    # 环境验证示例
    def validate_environment():
    env = CDPEnvironment()
    if env.setup_connection():
    env.enable_debug_domains()
    env.test_environment()
    🔒 安全与合规配置
    必要的安全措施:

    # 请求频率控制 – 避免触发防护机制
    import time
    import random

    def safe_delay(min_delay=1, max_delay=3):
    “””添加随机延迟避免检测”””
    delay = random.uniform(min_delay, max_delay)
    time.sleep(delay)

    # 错误处理与日志记录
    import logging

    logging.basicConfig(
    level=logging.INFO,
    format=’%(asctime)s – %(levelname)s – %(message)s’
    )
    📋 环境准备检查清单
    ✅ Chrome浏览器已安装并配置调试端口
    ✅ Python 3.7+ 环境已就绪
    ✅ 必需依赖库已安装(websocket-client, requests)
    ✅ 调试接口可正常访问( http://127.0.0.1:9222/json )
    ✅ WebSocket连接测试通过
    ✅ 基础CDP命令执行正常
    此环境配置为后续的加密函数定位和爆破流程实现奠定了坚实的技术基础。

    三、加密函数动态定位与密钥提取
    🔍 动态定位加密函数的核心方法
    1. 断点调试定位法

    关键步骤:通过Chrome开发者工具手动设置断点,获取加密函数执行上下文
    CDP实现流程:
    # 设置断点监听加密函数调用
    breakpoint_cmd = {
    “id”: 2,
    “method”: “Debugger.setBreakpoint”,
    “params”: {
    “location”: {“scriptId”: “<实际脚本ID>”, “lineNumber”: <加密函数行号>}
    }
    }
    ws.send(json.dumps(breakpoint_cmd))

    # 等待断点触发并提取callFrameId
    while True:
    msg = json.loads(ws.recv())
    if msg.get(“method”) == “Debugger.paused”:
    call_frame_id = msg[“params”][“callFrames”][0][“callFrameId”]
    break
    2. 全局函数扫描法

    使用CDP命令扫描window对象中的加密函数:
    scan_cmd = {
    “id”: 4,
    “method”: “Runtime.evaluate”,
    “params”: {
    “expression”: “Object.keys(window).filter(k => k.includes(‘encrypt’) || k.includes(‘sign’))”,
    “returnByValue”: True
    }
    }
    ws.send(json.dumps(scan_cmd))
    resp = json.loads(ws.recv())
    encrypt_functions = resp[“result”][“result”][“value”]
    🗝️ 动态密钥提取策略
    1. 实时密钥捕获

    在加密函数执行时捕获动态生成的密钥参数:
    def capture_dynamic_key(ws, call_frame_id):
    # 执行表达式获取当前加密密钥
    key_cmd = {
    “id”: 5,
    “method”: “Debugger.evaluateOnCallFrame”,
    “params”: {
    “callFrameId”: call_frame_id,
    “expression”: “window.currentKey || cryptoKey || encryptionKey”,
    “objectGroup”: “console”
    }
    }
    ws.send(json.dumps(key_cmd))
    key_resp = json.loads(ws.recv())
    return key_resp[“result”][“result”][“value”]
    2. 密钥生命周期管理

    会话密钥:在同一个浏览器会话中保持有效
    请求级密钥:每次请求重新生成,需要实时捕获
    时间戳密钥:基于时间动态变化,需同步时间参数
    🛡️ 反调试环境下的定位技巧
    1. 隐蔽式断点设置

    避免在明显位置设置断点,选择函数内部或异步回调中
    使用条件断点减少触发频率:
    conditional_bp = {
    “params”: {
    “location”: {“scriptId”: script_id, “lineNumber”: line_num},
    “condition”: “password.length > 0”  # 仅当有密码输入时触发
    }
    }
    2. 环境检测绕过

    在定位前先执行反检测脚本:
    anti_detect_script = “””
    Object.defineProperty(navigator, ‘webdriver’, {get: () => undefined});
    window.debuggerDetected = false;
    “””
    ws.send(json.dumps({
    “method”: “Runtime.evaluate”,
    “params”: {“expression”: anti_detect_script}
    }))
    📊 动态参数追踪表
    参数类型        提取方法        更新频率        CDP命令
    静态密钥        页面加载后一次性提取        会话级        Runtime.evaluate
    动态令牌        请求前实时捕获        请求级        Debugger.evaluateOnCallFrame
    时间戳参数        同步浏览器时间        秒级        Runtime.evaluate(Date.now())
    随机数种子        跟踪随机函数调用        每次加密        条件断点监控
    🔧 实战代码:完整的动态定位流程
    class EncryptionLocator:
    def __init__(self, ws_connection):
    self.ws = ws_connection
    self.call_frame_id = None
    self.current_key = None

    def setup_encryption_monitoring(self):
    “””设置加密函数监控”””
    # 启用必要域
    self.ws.send(json.dumps({“id”:1,”method”:”Debugger.enable”}))
    self.ws.send(json.dumps({“id”:2,”method”:”Runtime.enable”}))

    # 搜索加密相关函数
    encrypt_funcs = self.scan_encryption_functions()
    print(f”[+] 发现加密函数: {encrypt_funcs}”)

    # 设置断点监控
    for func_name in encrypt_funcs:
    self.set_function_breakpoint(func_name)

    def wait_for_encryption_call(self, timeout=30):
    “””等待加密函数被调用”””
    start_time = time.time()
    while time.time() – start_time < timeout:
    msg = json.loads(self.ws.recv())
    if msg.get(“method”) == “Debugger.paused”:
    # 检查是否在加密函数中断
    call_frame = msg[“params”][“callFrames”][0]
    if any(keyword in call_frame[“functionName”] for keyword in [‘encrypt’, ‘sign’]):
    self.call_frame_id = call_frame[“callFrameId”]
    self.extract_dynamic_parameters()
    return True
    # 非加密断点,继续执行
    self.ws.send(json.dumps({“id”:10,”method”:”Debugger.resume”}))
    return False

    def extract_dynamic_parameters(self):
    “””提取动态加密参数”””
    # 获取当前加密密钥
    key_expr = “window.currentKey || cryptoKey || encryptionKey || ””
    key_cmd = {
    “id”: 20,
    “method”: “Debugger.evaluateOnCallFrame”,
    “params”: {
    “callFrameId”: self.call_frame_id,
    “expression”: key_expr
    }
    }
    self.ws.send(json.dumps(key_cmd))
    key_resp = json.loads(self.ws.recv())
    self.current_key = key_resp[“result”][“result”][“value”]

    print(f”[+] 动态密钥已捕获: {self.current_key}”)

版权:言论仅代表个人观点,不代表官方立场。转载请注明出处:https://www.zuozi.net/forum/37263.html

发表评论
1 条评论
2026年1月3日 下午4:03 回复

123