把 DSH 改成取证专用机: APK 智能解析工作台 是从零怎么造出来的

作者:小谢取证 发布:2026-09-02 23:59 收录:2026-09-03 09:02 7 次阅读 约 6151 字
摘要:上期工作台开箱即用,这期把它从零造到 v2.1 的全过程摊开讲:两个插件包、一条 RPC 链路、jadx 和 arc 两台 MCP 随包自装,新电脑部署 4 步走完,外加一串拿夜熬的换的坑。
推荐理由:本文涵盖「MCP」、「AI取证」、「DSH」等多个主题,重点关注 MCP。

AI 取证实战 · 第 05 期(v2.1 增补版)

把 DSH 改成取证专用机:
APK 智能解析工作台
是从零怎么造出来的

两个插件包、一条 RPC 链路、两台 MCP 随包自装,全过程 + 新电脑部署拆给你看

第 04 期发了 小谢取证APK 智能解析工作台AI取证实战第04期:小谢取证APK智能解析工作台上线的使用效果之后,问得最多的两句话是:

「这个工作台是在哪跑起来的?」
「能不能教教怎么自己做一套?」

第一个问题的答案:DSH(DeepSeek Harness)。

第二个问题的答案就是本期——我把这台工作台从空目录一路造到 v2.1 发布的全过程拆开讲。不灌水,重点放在架构怎么搭、外部工具怎么接、拿到一台新电脑怎么从零装起来、以及我真实踩过的一串坑

以下是直接手把手教如何拿到“小谢取证APK智能解析工作台”压缩包后如何一步一步进行安装的详细视频教程。

也有搭建成功的反馈:

所以这期针对Android Remote Control MCP和ai问答没配置的问题又更新了V2.1版本。

先说结论:在 DSH 上做一个垂直领域工作台,比大多数人想的容易,也比大多数人想的坑多。容易在于它把 AI 会话、Web 界面、插件机制全都备好了;坑在于文档覆盖不到的边角,全是实战学费。

🚀 本期你将看到:
① 为什么工作台选 DSH 承载,而不是自己起一个 Web 服务
② 整体架构:两个插件包 + 一条 fx/* RPC 链路
③ 后端插件怎么注册自定义 RPC 端点(含 gateway 严格校验的坑)
④ jadx 怎么被做成"隐形引擎":自动探测、自动拉起、双路兜底
⑤ 动态链路自动化:模拟器自启、tcpdump 的 Android 14 大坑、自动注册登录
⑥ 前端面板:实时日志、AI 问答、防"面板消失"的状态持久化
⑦ 发布化四级配置:环境变量 > 配置文件 > 自动探测 > 默认
⑧ 两台 MCP 随包自动部署:jadx + arc,新电脑连模拟器里的控制 App 都不用手动装
⑨ 手把手:一台全新电脑从零部署(含离线/内网机怎么办、会不会泄露我的密钥)
⑩ 学费清单 + 三步验收法

1|先想清楚:为什么工作台长在 DSH 里

最早版本的工作台(第 02 期一个提示词,十五步DIY你的AI取证工作台)确实是自己起的:一个纯 Python 后端 + 一个单页前端,端口 8787,跟取证软件抢任务栏位置。能用,但有两个天花板:

  • AI 是外挂的
    。问答要自己管会话、自己拼上下文、自己处理流式返回,代码里一半的复杂度是给"接 AI"这件事交的;
  • 环境是双份的
    。8787 和 DSH 的 3080 各跑各的,杀进程杀出过"双进程监听同一端口、请求打到僵尸进程"的灵异现象。

DSH 反过来想就很清楚:它本身就是一个带 WebUI 的 AI 运行时。会话创建、提示词轮询、历史记录是现成的;插件机制是现成的;MCP 接入是现成的。工作台真正缺的只有两样——领域分析引擎和一个趁手的操作面板。这两样恰好都是插件能干的活。

于是 v1.1 起改成单进程架构:所有东西收进 DSH 一个进程,浏览器开 3080 就是取证工作台,AI 问答跟分析结果天然同上下文。这一步之后,"给报告追问一句这个 IP 还有什么线索"这种体验才真正顺滑。

(工作台的全部入口,就是侧栏里这一个按钮)

2|整体架构:两个插件包,一条链路

DSH 的插件放在 ~/.dsh/profiles/node_modules/ 下。工作台由两个插件包组成,一个管"脑子",一个管"脸":

插件包
职责
dsh-tool-forensics
后端引擎:RPC 端点注册 + APK 静态/动态分析 + 报告生成 + Python 分析器 + 随包 jadx jar + 随包 arc APK
dsh-client-ui-forensics
前端界面:侧栏入口、APK 面板、日志窗口、AI 问答、四张取证卡片

一次完整解析的数据流是这样走的:

[前端面板] 点「开始智能解析」
  │ conn.rpc.call('/api', 'fx/analyzeApk', {apkPath})
  ▼
[gateway] descriptor 精确校验参数 → 转发
  ▼
[apk_engine.js] 静态:spawn python + jadx MCP(8650)
                动态:ldconsole / adb / arc MCP(8080) / tcpdump
  ▼
[报告 HTML] 落盘 ~/.dsh/fx-reports/ → 前端四卡片渲染 + 导出

外部工具一共四个:jadx-headless(8650 端口,反编译)、android-remote-control MCP(8080 端口,控制雷电模拟器做动态交互)、adb、WSL2 里的 Python 兜底工具链。工作台对它们的原则只有一条:能自动拉起就绝不让人手开,拉不起来就给出明确指引。

(引擎、Python 分析器、jadx jar、arc APK、配置文件全在一个包里)

3|后端插件:怎么往 DSH 里塞自己的 RPC 端点

这是整套架构里文档最薄、也最关键的一环。DSH 静态 API 表和工作台需求对不上,走通的路子是运行时注册自定义后端 RPC,三步:

// ① 服务实例绑定到远端协议
bindTypertRemote(this, 'fxEngine', { namespace: 'fx' })

// ② 注册进 DI 容器 + 声明可调用方法(src-json 编解码)
ctx.root.provide(...) ctx.typert.register({ face:'host', invocations:[...] })

// ③ 前端直接按端点名调用
conn.rpc.call('/api', 'fx/analyzeApk', { args })

跑通这条链路后,工作台就有了自己的端点家族:fx/ping、fx/analyzeApk、fx/apkLog、fx/downloadApkReport 等十几个。

两个必须提前知道的规矩:

  • gateway 对参数是精确校验的
    。descriptor 里声明了什么字段,前端就只能传什么字段,多传一个 source 直接报 unexpected field——我加"上传来源"标记时被这个规则拦过一次,加字段要 descriptor 和方法签名一起改;
  • 端点名不能复用踩过的坑名
    。注册失败过一次后端点名会永久进入"已见过"集合,换个全新端点名重来,这是我拿一整晚调试换来的经验。

4|分析引擎:Python 负责算,jadx 负责反编译

静态分析的核心逻辑我没用 JS 写,而是保留 Python 分析器(apk_basic、dex_strings、axml_parse、pcap、apk_cert 等),由 JS 引擎 spawn 调用。两个细节:

  • spawn Python 时 PYTHONPATH 必须显式指定——Windows 的 py 启动器不吃 execFile 的 cwd,模块导入直接失败;
  • 子进程输出编码要处理。中文 Windows 下 adb/ldconsole/java 默认吐 GBK,Node 按 UTF-8 解码就成乱码。解法是拿原始字节,UTF-8 解出替换符就用 GBK 重解,再给 Java 单独注入 -Dfile.encoding=UTF-8

jadx 这块,工作台用的是 jadx-headless MCP 引擎(一个 jar,起 8650 端口暴露 MCP 工具),我写了个四十来行的 MCP 客户端就把它接进来了。重点不在接入,在可靠性设计

  • 探测优先
    :分析前先看 8650 活着没有,活着直接复用;死了无窗口自动拉起,最多等 30 秒;
  • 永远不吊死在一棵树上
    :实测一个 32206 类的恶意样本,jadx 全文索引只建了 15600 类——敏感信息检索直接失效。所以 jadx 结果只做"追加",同时跑自研的 dex 字符串全量扫描(27 万条字符串里扫 URL/IP/Key/13 类敏感行为);Manifest 被伪造成 128MB 的加固样本,jadx 和 androguard 都啃不动,就靠自己写的 AXML 二进制解析器兜底。两个兜底脚本各一百来行 Python,比调任何工具的耐心都省。

(日志是引擎里埋的 onLog 钩子逐条推出来的,做自动化就必须让人看见它干到哪一步了)

5|动态链路:模拟器自己开机、App 自己注册、包自己抓

动态分析是整条链路里硬件交互最多的一段,自动化按六步串:

环节
实现方式
① 设备就绪
adb 探测不在线 → ldconsole 启动雷电 → 轮询开机完成标记,上限 180 秒
② 装控制端
arc MCP 全自动部署
:引擎把 arc APK 装进模拟器 + 无头授权 + 配 token + 端口转发(详见第 8 节)
③ 安装样本
adb install -r -t(testOnly 包要带 -t),失败降级 pm install 兜底
④ 抓包
nohup tcpdump 后台常驻,结束后 pull 回本地解析
⑤ 注册登录
uiautomator 语义树识别界面 → 自动填表 → 提交,弹窗文案双通道识别
⑥ 本地取证
root 拉取 shared_prefs/databases,扫 URL/IP/Session/UID 线索

这一段埋着本期最贵的几个坑,全是 Android 侧的:

  • 坑一,adb root 会清掉端口转发
    。用 root 重启 adbd 之后,之前建立的 forward 全部失效,arc 连接 fetch failed。解法:root 之后无条件重建转发;
  • 坑二,Android 14 写 /sdcard 的 pcap 头是全零
    。SELinux 在捣乱,抓完的包 Wireshark 打不开。解法:加 -U(不缓冲逐包写)+ 落盘到 /data/local/tmp,拉回本地先验 magic 再进分析;
  • 坑三,tcpdump -i any 的链路层是 SLL2
    。我的 pcap 解析器只认 Ethernet 和 SLL,一份 88MB、50000 包的流量解出来 HTTP=0、DNS=0——差点误判"这个 App 不联网"。补上 SLL2 的 20 字节头解析后,同一份包解出 4 条 HTTP + 28 条 DNS + 14 条 TLS 会话,主 C2 域名当场浮出。

自动注册登录值得多说一句。规则只有一条:App 免邀请码可注册,就自动注册一个测试账号进登录态抓包,全程零人工。表单识别走"语义树 + 页面文案"双通道,注册提交按钮("同意协议并注册"这种长文案)单独识别防误点;密码太短自动换强密码重试;注册后跳回登录页也算软成功。真实效果:工作台自己注册了账号、自己进了会话列表、自己把 IM 长连接的 C2 域名抓了个正着。


(模拟器里那个测试账号和 arc 控制端,都是工作台几分钟前自己弄好的)

6|前端插件:面板、日志、AI 问答,和一个"面板消失"悬案

客户端插件负责往 DSH 侧栏注入入口,点开是全屏面板:左边干活(选检材、四张取证卡片),右边两个窗(分析日志、AI 问答)。日志走 1.5 秒轮询引擎里的日志钩子;AI 问答直接复用 DSH 现成的会话三件套(create → prompt → 轮询到 turn/end),把检材路径和分析结果摘要拼进上下文——这就是长在 DSH 里的好处,这些能力一个都不用自己做

"面板消失"悬案是这样:用户报"解析完成后面板自己关了,结果没了"。查了一圈前端没有跳转逻辑、后端日志干净,最后定位到解析期间机器负载高,DSH 前端心跳超时自动刷新了页面——React 状态全丢。修复思路不是阻止刷新(阻止不了),而是假设刷新必然发生:面板开合状态和分析结果全部落 localStorage,刷新后面板自己弹回来、结果自己恢复;大结果存之前先裁剪,防 5MB 配额溢出。做完之后这功能再没人报过丢结果。

还有一个前后端共同的坑:前端插件里有个版本常量和后端 BUILD 号比对,改了后端忘了改前端,界面右上角就常驻"进程可能未加载新版插件"警告。规矩立下来:后端版本号一 bump,前端常量必须同批同步

(状态持久化的验收画面)

7|发布化:从"我机器上能跑"到"谁的机器都能跑"

自己用的时候,引擎里写死了 jadx jar 路径、雷电安装目录、adb 路径。要发布,这些全是要命的。改造后所有外部依赖走四级配置,取数从高到低:

环境变量(FX_*) > fx.config.json > 自动探测 > 内置默认
  • 自动探测
    覆盖常见安装位置:雷电扫 D:/leidian、C:/LDPlayer、%LOCALAPPDATA% 等目录下"ldconsole + adb 同目录配对"的实锤;jadx 先看包内再看用户目录;IDA 扫 Program Files;
  • 能随包带的直接带
    :68MB 的 jadx jar 塞进插件包 tools/ 目录,新电脑连 JADX 都不用下载;
  • 探测不到就给指引
    :报错文案直接写清三种补救方式(放包内 / 改配置文件 / 设环境变量),而不是甩一个路径 undefined。

发布前最后一道验证:把 zip 解开扫一遍,本机路径出现 0 次才算过关。

8|两台 MCP 随包自装:jadx 之外,arc 也做到零人工

v2.0 只把 jadx 做成了随包。但动态分析还依赖第二个 MCP——android-remote-control(简称 arc),一个装在安卓模拟器里的控制端 App,它自己也起一个 MCP 服务(8080 端口),工作台靠它点界面、发指令、读屏幕。v2.0 时代这一步还得手动装 APK、手动开无障碍权限、手动配 token,换台电脑又得重来。

v2.1 把 arc 也照 jadx 的同构路子做成了随包自动部署——引擎里一个 ensureArc() 函数,一条自动部署链,全程零人工:

步骤
做了什么
① 探活
arc MCP 握手成功 → 秒回复用(幂等,绝不打断已运行环境)
② 装 APK
adb install -r -t
 随包 arc APK;已装则用 pm path 检测跳过,不重复装
③ 无头授权
一条命令开无障碍 + 通知监听 + 通知权限,不点一次 GUI
④ 广播配 token
am broadcast ADB_CONFIGURE
 塞 bearer_token + 端口 + 绑定地址 + 开机自启
⑤ 重启服务 + 转发
am force-stop
 再 am start(否则不重读配置)+ adb forward tcp:8080
⑥ 轮询握手
等服务真起来,握手成功返回(token 落盘 ~/.dsh/fx-arc-token.txt 复用,下次不重配)

这条链也踩了三个坑,都是"新电脑首跑"才暴露的:

  • 重装浪费
    :token 不一致时每次都重装 176MB APK,白耗 30-60 秒 → 加"已装检测",装了只改配置不重装;
  • am start 不重载配置
    :arc 服务在跑时,光 am start 不会重读广播配的 token,导致它一直拿旧 token 握手、永远 401 超时 → 必须先 am force-stop 停干净,再 start;
  • null 崩溃
    :arc 万一部署失败,后续交互阶段直接调它的方法会报"读取 null 属性" → 加了空值防护,arc 不可用时自动降级回纯 adb 截图点按。

最终效果:一台全新的、arc 从没装过的电脑,从"点开始解析"到"arc 50 个控制工具全部就绪",实测 9.6 秒全自动,第二次调用直接复用 0 秒。

(新电脑模拟测试:先卸载 arc、清空转发和 token,再触发部署,9.6 秒全自动)

9|手把手:一台全新电脑从零部署

这一节是纯操作指南。我发发布包最常收到的一句话就是"到底装哪、要装几个东西"。所以把新电脑部署一步步摊开。正常情况你只需要装两样:DSH 本身 + 雷电模拟器,其余全是解压覆盖。

第 0 步:确认这台电脑要跑静态还是静态+动态

只做静态分析(反编译、证书、敏感信息、加固识别),只要装了 DSH 就够,不用装模拟器。要做动态抓包/自动注册登录,才需要额外装雷电模拟器。心里先有这个分界。

第 1 步:安装并启动 DSH

按 DSH 官方方式安装,装完在命令行执行 dsh web(默认端口 3080),浏览器打开 http://127.0.0.1:3080 能看到界面即成功。工作台是以 DSH 插件的形态跑起来的,所以 DSH 是地基。

第 2 步:解压发布包,覆盖两个插件目录

发布 zip 解开有两个文件夹:dsh-tool-forensics(后端引擎)和 dsh-client-ui-forensics(前端界面)。把这两个文件夹整体拷进 DSH 的插件目录:

~/.dsh/profiles/node_modules/
# Windows 即
C:\Users\<你的用户名>\.dsh\profiles\node_modules\

里面已有同名目录就整体覆盖。这一步就是"装工作台"的全部动作——没有安装向导、没有 pip install、没有 npm build。

第 3 步(仅动态):装雷电模拟器,但 arc 控制端不用装

要跑动态分析的电脑,去雷电官网装 LDPlayer(任意版本,实例选 Android 13 及以上,其实就是雷电模拟器14的版本)。装完不用配任何东西——引擎会自动扫常见安装位置找到它。重点是:模拟器里那个 arc 控制端 App 你根本不用手动装,第一次跑动态分析时,引擎会自己把它推进模拟器、开好权限、配好 token(就是第 8 节那条自动部署链)。

第 4 步:重启 DSH,开面板

关掉再重新 dsh web,浏览器 Ctrl+F5 强刷,侧栏出现「🤖 APK 解析」入口,点开传一个 APK 就能跑。第一次动态分析会看到日志里刷 arc 部署那几行,之后就直接复用了。

🧭 一句话记忆:装 DSH → 解压覆盖两个插件目录 → (动态再装雷电)→ 重启强刷。全程没碰过任何配置项。

离线 / 内网取证机怎么办(关键取舍)

v2.1 我出了两个版本,就是为了照顾不同网络环境的机器:

版本
体积
arc 从哪来 / 适合谁
全包版
175.7MB
arc APK 随包,纯离线零配置——办案内网机选这个
瘦身版
63.1MB
arc 首跑联网自动下载 + 校验 + 缓存——网盘分发 / 学员电脑选这个

瘦身版不随包 arc,首次动态分析时引擎从镜像多源下载那个 176MB APK,做完 sha256 校验再缓存到 ~/.dsh/fx-arc-cache/,之后不再下载。万一这台机器完全离线,就把全包版里那个 arc APK 手动放进 tools/arc/ 目录(包里有说明文件),引擎照样用,其余不变。

两个取舍要交代的:

  • 为什么体积差这么多
    :全包版比瘦身版大 112MB,全是那个 arc APK。APK 本身已是压缩包,zip 再压几乎不省——所以随不随包直接决定体积;
  • 首跑下载慢是正常的
    :实测国内镜像不稳时,引擎会自动 fallback 到 GitHub 直连下完 176MB(约 6 分钟),日志窗口会显示"⏳ 下载 arc APK",别以为是卡死。

发布包会泄露我的大模型密钥吗?(安全边界)

这是分发前我自己必过的一关,也直接讲给要用这套包的人。结论:不会,而且架构上就不可能。三层隔离:

  • 密钥不在插件里
    。发布 zip 只打两个插件目录,AI 的 API 密钥由 DSH 的凭证存储托管注入运行进程,盘上根本没有明文,插件碰不到;
  • 模型配置不在包里
    。用哪家大模型、什么 endpoint 写在 DSH 全局的 settings.yaml 里,不是插件文件,压根不在打包范围——发布包里连我的模型地址都没有;
  • 配置里的敏感字段全空
    fx.config.json 里 arcToken、账号、邀请码都是空串,新电脑首跑各自生成自己的本地 token,跟我这台机器无关。唯一非空的默认密码是自动注册测试账号用的通用占位值,不是任何真实凭据。

发布前我会对整个 zip 跑一遍密钥扫描(sk- 样式串、apiKey 赋值、Bearer、阿里云 AK、私钥头 7 类正则),命中 0 次才允许外发。取证电脑可能被扣押,"盘上翻不出密钥"是硬性要求,这套包做到了。


(每次发版前的"合规门",扫描不过不外发)

10|学费清单:坑一览

解法
双进程同时监听 8787,请求打到僵尸进程
先查端口占用再启动;重启必杀残留
SQLite 同线程嵌套加锁死锁,所有分析卡死
Lock 换可重入 RLock
RPC 多传一个 source 字段被 gateway 拒
descriptor 与方法签名同步加字段
注册失败的端点名永久污染,重试无效
换全新端点名
ESM 插件里 require 未定义(从未执行过的分支埋雷)
顶部统一 import,全文件禁用 require
spawn Python 找不到自家模块
PYTHONPATH 显式指定,不依赖 cwd
日志中文乱码(GBK vs UTF-8)
原始字节 + 智能重解码 + Java 编码参数
adb root 清掉端口转发,arc 连不上
root 后无条件重建 forward
Android 14 的 pcap 头全零
tcpdump -U + 写 /data/local/tmp + 验 magic
SLL2 链路层不认,5 万包解出 0 条流量
按 linktype 分支解析,补 20 字节头
arc 首跑每次重装 176MB APK,白耗半分钟
加 pm path 已装检测,装了只改配置
arc 服务在跑时 am start 不重读 token,握手恒 401
先 am force-stop 停干净再 start
瘦身版 sha256 手抄错一位,永远校验失败死循环下载
哈希用 sha256sum 取权威值,不手抄
改完主引擎忘了同步发布副本 → 瘦身包"无 APK 又无下载链"必挂
打包前 cp 回源目录 + md5sum 比对
解析完面板"自己消失"
状态落 localStorage + 结果裁剪恢复
前后端版本号不同步,常驻不一致警告
BUMP 后端必同批改前端常量

(表中 浅色底纹 四行是 v2.1 arc 集成这轮新增的学费)

💡 共性规律:这些坑里,没有一个出在"业务逻辑"上,全出在边界——进程边界、编码边界、权限边界、版本边界、生命周期边界、网络边界。做自动化工具箱,一半的功夫是把边界焊死。

11|怎么知道自己做对了:三步验收

这套工作台每次改动,合并前都过三关:

  • 语法关
    :所有 JS 文件 node --check、所有 PY 文件编译检查,十秒钟的事,能拦住一半低级事故;
  • 断言关
    :每个功能域配一个自测脚本(报告渲染、自动注册判定、取证卡片、arc 部署、arc 下载……),改引擎必全绿。自动化判定逻辑最怕"改 A 坏 B",断言就是保险丝;
  • 端到端关
    :真实样本 APK 从上传到报告落盘全跑一遍,逐项断言包名、类别、证书指纹、通联数。v2.1 发布那天,arc 自动部署 9.6 秒全绿、下载链 3/3 全绿、动态报告零连接错误,跑的就是这套。

还有一个取证特色的验收习惯:拿伪装样本当考卷。那个包名叫计算器、主 Activity 却是聊天框架的样本,每次回归都要确认它继续被识破为"即时聊天"——工具会不会退步,反分析样本比单元测试诚实。

(v2.1 发布当夜的验收记录)

12|写在最后

回头看这条路线:v1.0 独立 Web 应用 → v1.1 收进 DSH 单进程 → 加 APK 静态/动态引擎 → 加日志与 AI 问答 → v2.0 跨电脑免配置(jadx 随包)→ v2.1 两台 MCP 全随包自装 + 双版本发布 + 密钥安全边界。没有一步是设计出来的,每一步都是上一步不够用时被迫长出来的。

这大概就是一线取证人做工具的正常轨迹:先解决自己的麻烦,再解决同事的麻烦,最后才谈产品。DSH 这类 AI 运行时给普通办案人省掉的,恰恰是"从脚本到产品"之间最劝退的那段工程距离——界面有插件机制、AI 有现成会话、能力用你熟悉的 Python 堆。

工具会长成什么样,取决于你手里有多少案子要办。先把下一个案子的取证流程里"最烦的那一步"自动化掉,工作台就已经开始生长了。

📦 本期资料领取:
「DSH 工作台插件开发笔记 + 完整踩坑复盘」,点击下面的视频号一键三连(点赞、关注、在看),公众号后台回复关键词 5 领取。
v2.1 发布包双版本(全包版 175.7MB / 瘦身版 63.1MB,jadx + arc 双 MCP 随包自装)回复 5 一并领取。

— 小谢 · AI 取证实战 · 第 05 期 · 完 —

敬请各位大佬关注:小谢取证


转载声明:本文转载自原发布平台 (作者:小谢取证), 原文标题《把 DSH 改成取证专用机: APK 智能解析工作台 是从零怎么造出来的》, 查看原文。 版权归原作者及原发布平台所有,本站仅作收录与展示,未对正文内容作实质性修改; 若涉及侵权请联系本站处理。