首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
AI 工具与工作流
发新帖
19
8
[原创] 我们给 DeepSeek Harness 加了一个逆向模式:逆向 Agent 的未来,也许就是 Harness 插件
发表于: 2026-8-14 12:59
5079
[原创] 我们给 DeepSeek Harness 加了一个逆向模式:逆向 Agent 的未来,也许就是 Harness 插件
执着的猫
1
2026-8-14 12:59
5079
# 我们给 DeepSeek Harness 加了一个逆向模式:逆向 Agent 的未来,也许就是 Harness + 插件  ```sh 方案 A(推荐,一劳永逸):全局安装 CLI,之后 dsh 永久可用 npm install -g @deepseek-ai/dsh dsh plugin --profile web add dsh-js-reverse-plugin 安装后启动新的 dsh 会话: 三个技能出现在对话输入框 / 命令面板:js-ast-deobfuscation、iv8-env-runtime、iv8-jsvmp-recovery MCP 工具注册为 mcp__js-reverse__*(如 mcp__js-reverse__navigate_page) DeepSeek Harness 没有插件市场;插件发布在 npm:dsh-js-reverse-plugin。 ``` 命令执行完,Agent 选择器里多出“逆向模式”。三个逆向 skill、`js-reverse-mcp` 和 reverse preset 一起安装完成。用户不需要先向通用 Agent 解释什么是 iv8、怎样保护原始文件、JSVMP 应该如何验收;选择这个模式,会话就按这套方法开始。 我们的插件原本已经支持 Codex 和 Claude Code。如果这里只是“又兼容了一个宿主”,补一段 README 就够了。 我们随后看了 DSH 的源码,又检查了安装后的真实 profile。结果很清楚:DSH 没有把第三方插件拦在 Agent 外面。npm 包可以进入产品的 bundle 层,preset 可以挂载一棵 Agent 级插件子树,模型、工具、会话、策略乃至 Agent Loop 也由插件提供。 本文讨论的是这套 Agent 架构。兼容只是表面结果,我们的逆向模式是一个现成的例子。 > **对于逆向 Agent,DeepSeek Harness 这种“Agent 由插件组成”的模式,不是更好的选择,而是唯一正确的模式。**  ## 一、先看结果:一个 npm 包进入了 Agent 运行时 安装完成后,我们查看了本机的 `$DSH_HOME/profiles/web/package.json`。DSH 下次启动时读取的就是这份 profile: ```json { "dsh": { "profile": { "bundles": [ "@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-js-reverse-plugin" ] } }, "dependencies": { "dsh-js-reverse-plugin": "^0.2.0" } } ``` 我们的包和 `dsh-base`、`dsh-web-app` 并列出现在 bundle 列表中,已经成为整个 Web profile 的第三层配置。复制几份 Markdown 到此为止做不到这一点。 这个 <a href="elink@b79K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6*7K9r3W2*7K9s2g2G2k6r3g2E0j5h3!0Q4x3V1k6S2K9g2)9J5k6s2u0W2N6X3g2J5M7$3g2Q4x3X3c8J5k6i4y4G2N6i4u0U0k6i4y4Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8X3c8K6K9q4)9J5c8X3A6K6i4K6u0V1M7X3g2$3k6i4u0K6k6g2)9J5k6s2m8D9N6h3N6A6L8W2)9J5c8X3y4G2M7X3c8A6M7#2)9J5k6i4m8S2N6r3y4Z5i4K6u0W2P5h3#2D9">`cordis.patch.yml`</a> 插入两个运行项: ```yaml - insert: - id: js-reverse-plugin name: 'dsh-js-reverse-plugin' inject: [skills] - id: mcp-js-reverse name: '@deepseek-ai/dsh-mcp-client' config: transport: stdio serverName: js-reverse command: npx args: ['-y', 'js-reverse-mcp@4.0.1'] ``` 第一项加载插件自己的 <a href="elink@71eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6*7K9r3W2*7K9s2g2G2k6r3g2E0j5h3!0Q4x3V1k6S2K9g2)9J5k6s2u0W2N6X3g2J5M7$3g2Q4x3X3c8J5k6i4y4G2N6i4u0U0k6i4y4Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8X3c8K6K9q4)9J5c8X3A6K6i4K6u0V1M7X3g2$3k6i4u0K6k6g2)9J5k6s2m8D9N6h3N6A6L8W2)9J5c8X3W2F1k6r3g2^5i4K6u0W2K9Y4x3`.">`index.js`</a>,把三个 `SKILL.md` 注册到 DSH 的 skill registry;第二项复用 DSH 的 MCP client,启动 `js-reverse-mcp@4.0.1`。安装完成后,skill 和 `mcp__js-reverse__*` 工具会同时出现,来源就在这两行配置里。 Agent 选择器里的“逆向模式”来自第三部分。包内的 <a href="elink@882K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6*7K9r3W2*7K9s2g2G2k6r3g2E0j5h3!0Q4x3V1k6S2K9g2)9J5k6s2u0W2N6X3g2J5M7$3g2Q4x3X3c8J5k6i4y4G2N6i4u0U0k6i4y4Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8X3c8K6K9q4)9J5c8X3A6K6i4K6u0V1M7X3g2$3k6i4u0K6k6g2)9J5k6s2m8D9N6h3N6A6L8W2)9J5c8Y4m8J5k6i4y4W2N6q4)9J5c8Y4m8J5k6i4y4W2N6q4)9J5k6i4W2E0L8l9`.`.">`preset.yml`</a> 被安装到 `.agent-presets/reverse`: ```yaml name: 逆向模式 description: JS 逆向工程 Agent:证据驱动、逐步决策,配备 iv8 受控执行与 js-reverse 浏览器取证。 order: 2 ``` 安装动作也在 `index.js` 里。省去遍历和错误处理,只看两次注册: ```js for (const skill of collectSkills()) { ctx.skills.register(skill) } installPreset(join(presetUserRoot(), PRESET_ID)) ``` 到这里,我们只能证明这个包安装成功。它为什么能从“能力包”继续变成“Agent 模式”,要从 DSH 自己的插件树里找答案。  ## 二、沿着三段源码,看插件到底能走多深 <a href="elink@32fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6V1k6h3g2H3M7$3g2W2K9#2)9J5k6r3q4A6i4K6u0r3k6r3g2W2M7s2y4W2k6h3E0Q4x3X3c8Z5j5i4u0F1k6i4y4K6">DeepSeek Harness 官方 README</a> 用一句话概括设计:everything is a plugin。发布后的<a href="elink@7b1K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2J5k6h3c8V1K9i4c8Q4x3X3g2U0L8$3#2Q4x3V1k6J5i4K6u0r3c8r3g2W2M7q4y4W2k6h3E0Q4x3V1k6U0L8$3#2E0k6h3&6@1M7#2)9J5c8U0q4$3L8X3u0V1P5X3&6Q4x3V1k6S2N6i4c8Z5L8%4u0Q4y4h3k6Z5k6i4u0W2i4K6g2X3j5h3&6&6i4K6g2X3k6X3g2W2k6r3u0S2j5$3E0Q4y4h3k6X3L8%4u0Q4y4h3k6V1k6h3g2H3M7$3g2W2K9#2)9#2k6X3S2S2M7X3&6W2M7%4y4Q4x3V1j5`.">作者反馈帖</a>里,很快有人问:已经有这么多 Harness,为什么还需要一个新的? 如果 everything 只包括 skill、MCP 和 hook,这个问题没有得到回答。Codex 和 Claude Code 早就支持这些扩展。DSH 的差别出现在下面三段源码里。 ### 第一段:profile 从空列表开始组装产品 <a href="elink@a9eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6V1k6h3g2H3M7$3g2W2K9#2)9J5k6r3q4A6i4K6u0r3k6r3g2W2M7s2y4W2k6h3E0Q4x3X3c8Z5j5i4u0F1k6i4y4K6i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8Y4m8S2j5$3E0S2k6$3g2K6i4K6u0r3j5X3!0G2N6q4)9J5c8X3q4H3M7q4)9J5k6r3u0G2L8%4c8Q4x3V1k6K6M7X3y4Q4x3V1k6H3M7X3!0X3K9h3I4W2i4K6u0W2N6s2x3`.">`profile.ts`</a> 中,profile 记录有序的 bundle 列表;每个 bundle 在 manifest 里指向自己的 patch。最终组装发生在 `composeEntries()`: ```ts export function composeEntries( layers: readonly PatchOptions[][], warn: (message: string) => void = () => {}, ): EntryOptions[] { return applyEntryPatches([], structuredClone(layers.flat()), (message: string, ...args: unknown[]) => { let index = 0 warn(message.replace(/%C/g, () => JSON.stringify(args[index++]))) }) } ``` `applyEntryPatches()` 的第一个参数是 `[]`。DSH 没有先造好一个产品再开放几个插槽;bundle、profile patch、home patch 和命令行 overlay 直接在空列表上叠出本次启动的配置树。 `web` 和 `headless` 也由这套流程产生:两者共同使用 `dsh-base`,再分别加入 Web UI 或一次性 runner。用户安装的 bundle 继续叠在上面。 运行 `dsh --profile web --dump-config` 就能看到结果:命令打印当前机器将要启动的完整配置树。模型适配器、工具、持久化、sandbox、审批、前端都在里面,后续 patch 可以按 id 替换任意一行。 <a href="elink@19dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6V1k6h3g2H3M7$3g2W2K9#2)9J5k6r3q4A6i4K6u0r3k6r3g2W2M7s2y4W2k6h3E0Q4x3X3c8Z5j5i4u0F1k6i4y4K6i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8X3c8G2j5%4y4Q4x3V1k6S2M7X3y4Z5K9i4c8W2j5%4c8#2M7X3g2Q4x3X3g2E0k6l9`.`.">架构文档</a>对这件事的表述更加直接:`There is no privileged core to patch.` DSH 没有留下一块只能由官方修改的特权核心。 ### 第二段:Agent Loop 也注册在这棵树上 如果 Agent Loop 仍然固定,everything is a plugin 只完成了一半。我们接着看 <a href="elink@248K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6V1k6h3g2H3M7$3g2W2K9#2)9J5k6r3q4A6i4K6u0r3k6r3g2W2M7s2y4W2k6h3E0Q4x3X3c8Z5j5i4u0F1k6i4y4K6i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8Y4m8S2j5$3E0S2k6$3g2K6i4K6u0r3j5$3!0J5k6g2)9J5c8X3q4Y4k6h3&6@1i4K6u0V1L8r3!0G2M7q4)9J5c8Y4y4J5j5#2)9J5c8X3W2F1k6r3g2^5i4K6u0W2N6s2x3`.">`AgentLoop`</a>: ```ts export class AgentLoop extends Service implements AgentFactory { static inject = ['agents', 'sessions', 'llm', 'tools', 'systemPrompt'] constructor(ctx: Context, config: Config) { super(ctx, 'agentLoop') ctx.effect(() => ctx.agents.setFactory(this), 'agentLoop.setFactory()') } } ``` 先看类声明:默认 Loop 是一个 Cordis Service。再看 `inject`:LLM、tools、session 和 system prompt 都由外部服务提供。最后一行 `ctx.effect()` 把它注册为 `AgentFactory`,插件卸载时这次注册也会撤销。  于是换模型不用改 Loop,换工具管线不用改 Loop,换会话实现也不用改 Loop。默认 Loop 不合适时,替换提供 `agentLoop` 的插件即可。DSH 的扩展面穿过了请求组装、工具执行和下一步调度,不只停在函数调用列表。 ### 第三段:preset 挂载的是插件子树 截图里的“逆向模式”是不是一段预设提示词?<a href="elink@b4dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6V1k6h3g2H3M7$3g2W2K9#2)9J5k6r3q4A6i4K6u0r3k6r3g2W2M7s2y4W2k6h3E0Q4x3X3c8Z5j5i4u0F1k6i4y4K6i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8Y4m8S2j5$3E0S2k6$3g2K6i4K6u0r3M7s2u0W2M7$3g2@1i4K6u0r3j5h3N6W2L8Y4c8Q4x3X3c8H3M7X3g2K6k6i4c8K6i4K6u0r3M7%4u0U0i4K6u0r3L8h3!0#2L8Y4c8Q4x3X3g2@1M7H3`.`.">`mountPreset()`</a> 可以回答。 省去错误文案,关键代码只有三步: ```ts const scope = scopeOf(agentCtx) if (scope === undefined) { throw new Error(/* registrations would apply to every agent in the process */) } const handle = agentCtx.plugin(PresetTree, config) // 挂载完成并检查所有配置行之后 const leaked = leakedServices(agentCtx, fiber) if (leaked.length > 0) { throw new Error(/* row(s) published process-global service(s) */) } ``` 先确认 `agentCtx` 有 scope,再挂载整棵 `PresetTree`,最后检查服务有没有泄漏到进程全局。三步中任何一步失败,preset 都不会发布。 身份也没有被写死在 prompt builder 里。<a href="elink@cf7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6V1k6h3g2H3M7$3g2W2K9#2)9J5k6r3q4A6i4K6u0r3k6r3g2W2M7s2y4W2k6h3E0Q4x3X3c8Z5j5i4u0F1k6i4y4K6i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8Y4m8S2j5$3E0S2k6$3g2K6i4K6u0r3M7s2u0W2M7$3g2@1i4K6u0r3M7r3g2J5M7$3!0F1j5g2)9J5c8Y4y4J5j5#2)9J5c8X3W2F1k6r3g2^5i4K6u0W2N6s2x3`.">`dsh-persona`</a> 通过 `ctx.systemPrompt.section()` 注册 persona,只覆盖加入当前 preset 的 Agent。工具注册表同样支持 scoped registration;`tools.presentAs()` 还能让一个 preset 使用 Code Mode,同时让同一进程里的另一个 Agent 保持 native tools。 preset 在这里已经超出“角色模板”:它是一棵带作用域的 Agent 插件树。persona、tools、plan、compaction、subagent、workflow 可以一起挂载,也可以在整棵树卸载时一起撤销。  ### 还有一条约束:模型看见的内容必须能够重建 DSH 的 session log 不只是聊天记录。<a href="elink@9acK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6V1k6h3g2H3M7$3g2W2K9#2)9J5k6r3q4A6i4K6u0r3k6r3g2W2M7s2y4W2k6h3E0Q4x3X3c8Z5j5i4u0F1k6i4y4K6i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8Y4m8S2j5$3E0S2k6$3g2K6i4K6u0r3j5$3!0J5k6g2)9J5c8X3q4Y4k6h3&6@1i4K6u0V1L8r3!0G2M7q4)9J5c8Y4y4J5j5#2)9J5c8X3W2F1N6X3q4J5K9h3q4F1N6q4)9J5k6i4c8K6">`agent-loop invariant`</a> 会在 `llm/stream` 前重新派生 messages,并折叠 request header 中的 model、system prompt 和 tools,再逐项比较真实请求。任何模型可见内容如果无法从日志重建,运行时直接报错。 这条约束解释了为什么 session 也要进入插件体系。工具可以临时返回一个结果,但只要这个结果影响后续推理,它就必须进入可恢复的会话语义。Agent 恢复、fork、换 UI 时,事实不会因为提供它的插件已经离开调用栈而消失。  三段源码和一条 invariant 拼在一起,DSH 的设计才完整:profile 组装产品,preset 组装 Agent,scope 隔离不同 Agent,service 提供可替换实现,effect 管理生命周期,session event 保存模型依赖的事实。 再回头看“为什么还需要一个新的 Harness”,答案就在这里:DSH 开放到了 Agent 本身,不只增加几处插件入口。 > **对于逆向 Agent,DeepSeek Harness 这种“Agent 由插件组成”的模式,不是更好的选择,而是唯一正确的模式。** ## 三、为什么逆向会一路碰到 Agent 的核心 说“逆向任务变化很快”没有用。需要看这些变化最后落在什么地方。 假设目标是一个请求签名。最初看起来只需要浏览器工具:找到请求,设置 XHR 断点,查看调用栈,定位参数生成入口。`js-reverse-mcp` 可以完成这些动作。 定位之后,问题马上离开浏览器工具层。源码要不要修改?原始文件必须只读,格式化和 AST 变换只能进入派生副本。这是文件策略。 入口能不能直接在 Node.js 运行?不能。浏览器负责提供真实环境和对账样本,目标 JavaScript 进入 iv8 受控执行,Node.js 只做静态工程工作。这是执行环境。 入口后面如果是 JSVMP,Agent 还要保存 Bytecode、Handler、Opcode、CFG 和动态 Trace,并维护参考实现与独立实现的对应关系。这是会话状态和 workflow。 最后怎样算完成?服务器接受请求不能证明算法等价。独立实现必须和 iv8 中的参考实现精确相等。这又会改变任务停止条件和循环。 同一个“恢复签名”任务,已经连续穿过六层: | 逆向要求 | 只写进提示词会怎样 | DSH 中应该落在哪里 | |---|---|---| | 保护原始文件 | 模型记得时才遵守 | filesystem policy | | 从真实请求取证 | 只有原则,没有现场 | MCP tools | | 目标代码只在 iv8 执行 | 仍可能误用 Node.js | runtime / tool policy | | 保存断点、样本和 Trace | 压缩或恢复后容易丢失 | session event | | 按阶段推进任务 | 靠模型自行维持顺序 | workflow | | 精确等价后才结束 | 容易以“服务器接受”提前收工 | workflow / Agent Loop | 这张表给出了固定核心的问题。skill 和 MCP 可以增加知识与工具,却不能单独改变文件系统、会话语义和 Loop。于是所有约束只能继续堆进提示词:不要改原文件、不要用 Node.js、记得保存 Trace、服务器接受不算完成。 提示词能告诉 Agent 应该做什么,不能保证运行时只能这样做。逆向任务越复杂,这个差距越大。  DSH 允许这些要求各自进入正确的插件:浏览器能力留在 MCP,方法和验收标准留在 skill,文件限制进入 policy,证据进入 session event,阶段推进进入 workflow。普通 AST 任务可以少装几层,JSVMP 任务可以继续加入 Trace 与专用循环。不变的能力继续复用。 逆向 Agent 因此不能是一颗固定核心,外面挂一圈工具。目标变化会穿过工具、环境、策略、会话和循环,Agent 自己必须能够跟着重新组合。 ## 四、我们的插件提供了一次实际验证 在 DSH 出现以前,我们已经在 <a href="elink@294K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6*7K9r3W2*7K9s2g2G2k6r3g2E0j5h3!0Q4x3V1k6S2K9g2)9J5k6s2u0W2N6X3g2J5M7$3g2Q4x3X3c8J5k6i4y4G2N6i4u0U0k6i4x3`.">`ai-reverse-resources`</a> 中维护 `js-reverse-plugin`。三个 skill 使用同一份源码,`js-reverse-mcp` 独立发布到 npm,Codex 和 Claude Code 各自读取自己的插件清单。 这三个 skill 也不是同一套提示词换三个名字。`js-ast-deobfuscation` 管源码保护、混淆画像和 AST 路线;`iv8-env-runtime` 管入口定位、浏览器环境补齐和受控执行;`iv8-jsvmp-recovery` 管 Bytecode、Handler、Trace 和精确等价验收。前一个任务的结果会成为后一个任务的输入,但每个 skill 可以独立升级。 那套插件已经解决了分发问题:一个版本可以同时把方法和浏览器工具送到多个宿主。但安装以后,Agent 的模型、会话、策略和循环仍然由宿主定义。 接入 DSH 时,我们没有重写这些成熟能力。bundle 注册原有 skill 和 MCP,reverse preset 把它们与 DSH 已有的文件、shell、plan、goal、compaction、subagent 和 workflow 组合起来。  <a href="elink@2c4K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6*7K9r3W2*7K9s2g2G2k6r3g2E0j5h3!0Q4x3V1k6S2K9g2)9J5k6s2u0W2N6X3g2J5M7$3g2Q4x3X3c8J5k6i4y4G2N6i4u0U0k6i4y4Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8X3c8K6K9q4)9J5c8X3A6K6i4K6u0V1M7X3g2$3k6i4u0K6k6g2)9J5k6s2m8D9N6h3N6A6L8W2)9J5c8Y4m8J5k6i4y4W2N6q4)9J5c8X3q4Y4k6h3&6@1i4K6u0W2j5$3!0J5k6r3W2K6i4K6u0W2P5h3#2D9">`agent.cordis.yml`</a> 开头写着:`The capability set is unchanged.` 这一版沿用 standard preset 已经工作的通用能力集合,只加入逆向 persona,并接入我们的 skill 和 MCP。重复开发 shell、文件工具和任务系统不会让它更像一个逆向 Agent,正确的组合才会。 persona 中已经写明三条工作规则: ```text 保护原始输入:目标文件一律只读;分析前先做格式化派生副本。 受控执行:动态证据通过 iv8 或 js-reverse MCP 取得;Node.js 仅作静态工程工具。 等价验收:“服务器恰好接受”不是证明。 ``` 它们恰好对应上一章的文件、执行和停止条件。第一版先把成熟的方法、工具和 DSH 通用运行时组合起来;以后增加文件 policy、逆向证据事件或专用 workflow,仍然由同一个 reverse preset 选择。  从 DSH 发布到 `dsh-js-reverse-plugin@0.2.0` 上线,我们用很短的时间做出了一个可安装、可升级、可直接选择的逆向模式。安装后的真实 profile、真实 preset 和页面截图都能验证这件事。 这个速度来自清楚的分工:成熟的逆向能力保留自己的版本,DSH 的通用能力继续由 DSH 提供,reverse preset 只声明选择哪些组件以及怎样组合。三部分可以各自演进。 同样的办法也能继续加入 MCP 访问范围,甚至替换 Agent Loop。已有 skill 和 MCP 不需要推倒重来。 过去,我们的插件负责给 Agent 增加能力。现在,这个插件开始交付 Agent 的组成。逆向模式只是第一版,但路径已经通了。 ## 五、从一个 npm 包,到一种可以版本化的 Agent 最后再看一次 `dsh-js-reverse-plugin` 的 `package.json`。这次不看版本号,只看它交付了什么: ```json { "files": [ "index.js", "cordis.patch.yml", "skills", "preset" ], "dsh": { "bundle": { "patch": "./cordis.patch.yml" } } } ``` `skills` 装的是逆向方法,`cordis.patch.yml` 把 skill registrar 和 MCP client 插进运行时,`preset` 定义逆向 Agent 的组成,`index.js` 负责把前面几部分接到 DSH。MCP 也没有使用浮动的最新版,patch 明确写着 `js-reverse-mcp@4.0.1`。 因此,`0.2.0` 交付的已经不是一个孤立工具。这个版本同时确定了方法从哪里来、浏览器工具用哪个版本、运行时增加哪些配置、界面里出现哪一种 Agent。安装后的 profile 又把 `dsh-js-reverse-plugin: ^0.2.0` 和当前产品组合记录在一起。包、配置和实际运行结果能够互相对上。 这件事改变了 Agent 的交付单位。 过去发布一个 MCP,解决的是“Agent 能调用什么”;发布一个 skill,解决的是“Agent 应该怎样做”。它们到了宿主以后,模型怎么选、会话怎样保存、任务何时继续、循环何时结束,仍由宿主决定。现在 reverse preset 把这些组件放进一个明确的 Agent scope,bundle 再把这份组合送进 profile。用户安装的是一个 npm 包,最后得到的是一种可选择的运行方式。 下一版怎样扩展,也能从现有源码直接推出来。 假设我们要让断点、样本、Bytecode 和 Trace 在恢复会话后继续存在。DSH 已经规定:新的模型可见事实进入 `SessionEventMap`,再由 session log 重建。我们只需要在 reverse bundle 中加入逆向证据事件及其插件,并让 reverse preset 选择它,不需要另写一套会话系统。 再假设 JSVMP 恢复需要专门的停止条件:参考实现与独立实现没有精确相等,任务就不能结束。默认 `AgentLoop` 本来就是注册到 `AgentFactory` 的 Service;新的 Loop 可以由 reverse bundle 插入专用 profile,在产品组装层替换默认 factory。三个现有 skill、`js-reverse-mcp`、文件工具和 shell 都可以继续使用,DeepSeek Harness 的核心代码也不用为逆向任务增加分支。 两个改造进入的位置并不相同: | 新要求 | DSH 已有扩展点 | 进入哪一层 | |---|---|---| | 断点、样本和 Trace 跨会话保存 | `SessionEventMap` 与 session log | reverse bundle 提供事件插件,preset 选择对应能力 | | JSVMP 精确等价前不得结束 | `AgentLoop` / `AgentFactory` | reverse bundle 在专用 profile 中替换 Loop provider | 这不是对未来接口的猜测。前面已经从 DSH 源码确认了 session event、Agent Loop、preset scope 和 bundle patch 的位置;我们的 `0.2.0` 又确认了这些配置能够随 npm 包安装,并最终出现在 Agent 选择器里。从“增加一个逆向证据事件”到“替换一套任务循环”,使用的是同一套插件机制,只是前者扩展 session log 并由 preset 选择相应能力,后者进入产品 profile。 这也解释了为什么逆向尤其适合这种架构。普通 AST 解混淆只需要文件、skill 和基础工具;浏览器签名再加入 MCP 与 iv8;JSVMP 恢复继续加入长期证据、workflow,必要时更换 Loop。目标越复杂,选择的插件越多,但不必把所有能力永久塞进一个通用 Agent。 Harness 保存相对稳定的部分:插件生命周期、scope、session、工具管线和配置加载。逆向插件保存持续变化的部分:方法、工具、访问策略、证据类型、工作流和停止条件。两边各自升级,再由 preset 决定某个 Agent 此刻采用哪一种组合。  到这一步,Agent 也有了比“功能多少”更具体的衡量方式:某个任务到底需要哪组依赖,这组依赖能不能从配置中看见。`dsh --profile web --dump-config` 可以打印当前产品的完整插件树,preset 文件可以说明一个 Agent 选择了哪些能力,session log 可以说明模型实际看见了什么。方法、工具、状态和循环之间的关系,不再只藏在一段不断膨胀的系统提示词里。 换句话说,Agent 开始变成一个可以检查的依赖图。领域开发者负责维护变化快的节点,Harness 负责保证这些节点能够加载、隔离、记录和卸载;npm 包把节点及其组合关系一起送到用户手里。这比再造一个“内置所有逆向能力”的客户端更接近逆向工作的真实情况。 所以,未来的逆向 Agent 未必是一套独立开发、越写越大的宿主。它更可能是一份可以安装、检查和版本化的运行时组合:底下是 Harness,上面是按任务选择的插件。我们的逆向模式已经把这条路径从源码里的可能,变成了页面上可以直接选择的结果。 > **对于逆向 Agent,DeepSeek Harness 这种“Agent 由插件组成”的模式,不是更好的选择,而是唯一正确的模式。**
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
最后于
2026-8-17 20:12 被执着的猫编辑 ,原因: 修改安装方法
收藏
・
19
点赞
・
8
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
Lychow
非常支持你的观点!
2026-9-16 12:01
mb_uocwyezn
你的帖子非常有用,感谢分享!
2026-9-16 09:07
mb_reyfinlv
你的分享对大家帮助很大,非常感谢!
2026-8-25 17:19
孤独的街
为你点赞!
2026-8-15 17:28
abxy
这个讨论对我很有帮助,谢谢!
2026-8-15 16:03
gegon
+1
期待更多优质内容的分享,论坛有你更精彩!
2026-8-15 10:48
mb_zsmeyemp
感谢你分享这么好的资源!
2026-8-14 14:13
伟叔叔
你的分享对大家帮助很大,非常感谢!
2026-8-14 13:10
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
8
)
mb_ldbucrik
雪 币:
6
能力值:
( LV1,RANK:0 )
在线值:
发帖
0
回帖
693
粉丝
7
关注
私信
mb_ldbucrik
2
楼
太强了
2026-8-14 16:08
0
墨穹呢
雪 币:
4725
活跃值:
(8142)
能力值:
( LV3,RANK:20 )
在线值:
发帖
2
回帖
225
粉丝
18
关注
私信
墨穹呢
3
楼
感谢分享,依旧AI逆向最严厉的父亲
2026-8-15 16:34
0
ATrueMan
雪 币:
1050
活跃值:
(1645)
能力值:
( LV2,RANK:10 )
在线值:
发帖
11
回帖
87
粉丝
14
关注
私信
ATrueMan
4
楼
study
2026-8-17 16:01
0
学计算机睡觉
雪 币:
779
活跃值:
(1237)
能力值:
( LV3,RANK:30 )
在线值:
发帖
3
回帖
94
粉丝
4
关注
私信
学计算机睡觉
5
楼
666
2026-8-20 16:26
0
二兽
雪 币:
0
活跃值:
(25)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
1
粉丝
0
关注
私信
二兽
6
楼
自由度太高了
2026-8-22 22:45
0
呆萌的小白
雪 币:
1377
活跃值:
(1279)
能力值:
( LV2,RANK:10 )
在线值:
发帖
1
回帖
90
粉丝
1
关注
私信
呆萌的小白
7
楼
牛的
2026-8-31 23:14
0
呆萌的小白
雪 币:
1377
活跃值:
(1279)
能力值:
( LV2,RANK:10 )
在线值:
发帖
1
回帖
90
粉丝
1
关注
私信
呆萌的小白
8
楼
牛的
2026-8-31 23:14
0
童言
雪 币:
0
活跃值:
(41)
能力值:
( LV2,RANK:10 )
在线值:
发帖
0
回帖
5
粉丝
0
关注
私信
童言
9
楼
感谢分享啊.
2026-9-4 04:05
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
执着的猫
1
20
发帖
23
回帖
120
RANK
关注
私信
他的文章
[原创] 我们给 DeepSeek Harness 加了一个逆向模式:逆向 Agent 的未来,也许就是 Harness 插件
5079
[原创] Superpowers 这类“教 AI 怎么写代码”的插件,过时了吗?
454
[原创]Claude Code 客户端安全机制逆向分析(二):从上报机制看中转池账号风险
11196
[原创] 从一次拒绝服务说起——Claude Code 客户端安全机制逆向分析(一)
17415
从 Web 到小程序:用 AI-First 思维重构逆向调试工具
10451
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部