首页
社区
课程
招聘
从 Web 到小程序:用 AI-First 思维重构逆向调试工具
发表于: 6天前 1185

从 Web 到小程序:用 AI-First 思维重构逆向调试工具

6天前
1185

在安全研究与协议逆向领域,微信小程序的封闭性一直是一个核心议题。与传统的 Web 端不同,小程序默认不提供开发者调试面板。但在长期的分析实践中,社区已经探索出了开启调试权限的方法。无论是通过微信开发者工具的特定启动参数,还是利用类似 WMPFDebugger 的工具对 PC 端微信底层标志位进行 Patch,都可以成功在本地暴露出关键的 WebSocket 调试端口(通常为 127.0.0.1:62000)。

然而,获取 CDP(Chrome DevTools Protocol)调试端口仅仅是分析流程的开始。后续的手工调试工作流依然存在显著的效率瓶颈。

在逆向分析新小程序的接口签名(如常见的 sigx-sign)时,传统的流程通常如下:

随着前端打包压缩(Minification)以及控制流平坦化等 JavaScript 混淆技术在小程序端的普及,这种纯手工的静态分析与动态调试不仅耗时较长,且容易在复杂的调用栈中遗漏关键信息。

此前,为了优化 Web 端的逆向流程,我开发并开源了 js-reverse-mcp —— 一个结合大模型(LLM)与自动化框架的辅助工具。考虑到小程序的底层调试机制依然基于标准的 CDP 协议,我提出了一个初步的假设:能否将小程序调试端口接入现有的 js-reverse-mcp,利用大模型辅助完成断点设置和栈回溯工作?

这成为我重新审视小程序自动化调试方案的起点。

我的初步测试较为直接。js-reverse-mcp 的核心采集器基于 Playwright 的分支(Patchright)构建。我修改了底层配置,利用 playwright.chromium.connectOverCDP() 方法,将 browserUrl 指向了小程序的 WebSocket 调试端点。

按照 Web 端的逻辑,Playwright 连接 CDP 后会自动生成对应的 BrowserContext,进而可以通过 page.route() 拦截请求或注入脚本。

但在实际测试中,我遇到了预期之外的问题。

连接无法保持稳定,系统日志中频繁出现 Timeout 异常。数据采集器无法正常捕获完整的 HTTP 请求序列,在 Web 端稳定的断点逻辑也失去了作用。程序通常在连接目标 Target 后不久,便因内部状态异常而中断运行。

为了定位 Playwright 在这一环节失败的具体原因,我暂时移除了高层框架,在本地建立了基础测试工程,尝试仅使用 Node.js 的原生 chrome-remote-interface 库连接小程序的 CDP 端口。

通过对比 WebSocket 传输的底层协议帧,我确认了高层自动化框架在此场景下存在兼容性冲突的根源。

第一,Playwright 的架构设计强依赖于 DOM 生命周期。Playwright 的核心逻辑建立在 BrowserContextPage 的抽象之上。在状态采集器(如 PageCollector)切分请求历史或判断页面加载状态时,其底层逻辑依赖浏览器内核派发的 framenavigatedDOMContentLoaded 等标准生命周期事件。Playwright 默认目标 Target 必须触发这些事件,才能被视为可交互的页面状态。

第二,小程序逻辑层(AppService)脱离了 DOM 环境。微信小程序采用了双线程架构。负责界面渲染的是 WebView 层(或 Skyline),而负责网络请求发起、业务逻辑执行及核心加密算法运行的,是相对独立的逻辑层(AppService)。

在安卓系统上,逻辑层运行于纯粹的 V8 Isolate 中;在 iOS 上,则运行于 JavaScriptCore 线程中。该环境类似于 Web Worker,内部不包含 windowdocument 对象,也不涉及 DOM 树的解析过程。

因此,AppService 线程在其运行周期内,不会向 CDP 派发类似 DOMContentLoaded 的页面导航事件。

当 Playwright 尝试将获取到的 AppService Target 封装为标准 Page 对象时,其内部状态机会持续阻塞等待这些缺失的 DOM 事件。这直接导致了断点失效、上下文收集器超时以及连接中断。

结论评估:将小程序的隔离上下文直接适配基于单一浏览器窗口状态机的 Playwright 框架存在明显的架构不匹配。为了实现小程序的自动化与 AI 辅助分析,有必要剥离 DOM 层面的抽象,直接基于原生 CDP 协议构建调试模块。

在此基础上,我开始了新一轮的架构重构。

在确定需要剥离 DOM 依赖后,下一步是寻找合适的底层 CDP 客户端。在 Node.js 生态中虽然存在 chrome-remote-interface,但在纯异步环境下从头实现多路复用、断线重连和事件分发机制需要较高的工程成本。

在调研过程中,我关注到了 AI 智能体开源项目 browser-use 团队开发的 Python 基础库 —— cdp-use

分析 cdp-use 源码后,我发现其设计符合当前的架构需求。它基于 Python 的异步机制(asyncio),提供强类型的 CDP 接口。最关键的是,该库未对“页面”或“DOM”进行预设假定,专注于处理基础的 WebSocket 通信:接收 Endpoint,建立 Session,监听 Event 并执行 Command。

采用 cdp-use 意味着新工具的技术栈需从 Node.js 迁移至 Python。这一决策综合考虑了后续的开发需求。

在当前的开发生态中,Python 在 AI 智能体应用和数据处理领域具备相对优势。考虑到后续需要处理复杂的 Prompt 组装,并对底层返回的 JSON 结果进行结构化清洗,Python 在字符串处理和模型框架对接上提供了更高的便利性。

因此,基于 Python 和 cdp-use 的新项目 miniapp-cdp-mcp 正式开源。该项目利用 Target.attachToTarget 和独立 sessionId,在事件层面对小程序的网络通信进行拦截。

在底层通信建立后,随之而来的是目标识别(Target Identification)的挑战。

在标准的 Web 环境中,建立连接通常意味着获取当前的活跃页面 Target。但在微信小程序环境下,发送 Target.getTargets 指令会返回大量的并发进程。

受小程序的运行机制影响,返回列表中包含大量用于预加载的 preload- 线程,以及底层基础组件相关的隐藏 Target。如果探针未进行筛选直接挂载,大概率会连接到无实际业务逻辑的空闲线程,导致无法捕获网络请求或触发断点。

为了实现自动化的目标定位,工具需要具备筛选合适调试目标的能力。

针对微信小程序的进程特征,我在运行环境(cdp_runtime.py)中实现了一套启发式过滤逻辑。

该逻辑的处理流程为:

通过这套过滤规则,工具可以在小程序启动后,自动从进程列表中定位并挂载真实的 AppService 逻辑层上下文。

解决了框架兼容性和目标识别问题后,底层的 CDP 调试基建已基本稳定。接下来的核心任务是如何优化数据流,使大模型能够高效处理底层协议报文。

在建立稳定的 CDP 通信后,工具的核心工作在于完成大模型与底层环境之间的数据转换。如果在这一环节处理不当,容易导致大模型在复杂上下文中出现逻辑偏差。

在逆向分析中,Debugger.paused(断点触发)是关键事件。当代码执行被拦截时,CDP 会返回当前执行状态的数据。

原生的 CDP 响应是一个层级较深的 JSON 对象,包含了多层执行栈(Call Frames),每一层涉及函数名、脚本 ID、执行位置(Location)及作用域链(Scope Chain)中的变量详情。

从工程通信角度看,JSON 格式具备严谨性;但对于大模型(LLM)的文本解析机制而言,处理此类未优化的 JSON 数据效率相对较低。

为了提升大模型的解析效率,我在 Python 后端(Harness 层)引入了数据格式的重构流程。

该机制在接收到 CDP 的 JSON 报文后,会提取逆向分析所需的核心字段(如函数名、文件位置、关键变量),并将其转化为具有固定层级缩进的 Markdown 列表与代码块结构

选择 Markdown 的依据在于,大模型的预训练语料包含大量结构化的技术文档。Markdown 的列表符号、标题层次和代码区块标记,契合了模型对技术文档的解析逻辑。

由于剔除了大量 JSON 格式所需的结构符号(如花括号、引号),这一转换逻辑在实际传输中直接减少了无效字符的占比,从而降低了 Token 开销。同时,它移除了干扰视线的语法噪音,提升了模型在处理复杂混淆代码栈时的解析稳定性,使其能够更加连贯地梳理加密逻辑的调用链。

在数据格式优化之外,工具对外暴露的 API(即 MCP Tools)也进行了抽象化设计。

为了使大模型能够专注于逻辑分析,工具避免暴露底层的通信细节。API 被设计为高层的“意图驱动(Intent-Driven)”接口:


[培训]《冰与火的战歌:Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

收藏
免费 32
支持
分享
最新回复 (16)
雪    币: 224
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
学习一下
5天前
0
雪    币: 155
活跃值: (4571)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
学习
5天前
0
雪    币: 0
活跃值: (110)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
学习
5天前
0
雪    币: 2790
活跃值: (6181)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
学习
4天前
0
雪    币: 220
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
mark
4天前
0
雪    币: 264
活跃值: (835)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习一下
2天前
0
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
学习一下
1天前
0
雪    币: 2754
活跃值: (2957)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
学习一下
1天前
0
雪    币: 205
活跃值: (1149)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
学习一下
16小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
学习一下
15小时前
0
雪    币: 228
活跃值: (125)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
mark
11小时前
0
雪    币: 31
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
666
9小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
666
8小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
666
8小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
666
8小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
楼主可以的
8小时前
0
游客
登录 | 注册 方可回帖
返回