saffi955/Shaduup
GitHub: saffi955/Shaduup
一款 Windows 桌面应用会话录制工具,通过 UI Automation 自动捕获无源码应用的控件树和界面状态,生成 AI 编程 agent 可直接读取的结构化 JSON 映射。
Stars: 0 | Forks: 0
# AppShadow
**像平时一样使用应用程序。AppShadow 会将该次会话转化为 AI agent 可读的结构化映射。**
大多数你可能需要研究、克隆或自动化的 Windows 软件都是以编译后的二进制文件形式发布的,没有可访问的源代码,也没有文档。将这种界面交给 AI 编程 agent 的通常做法是,对每个屏幕进行截图并手动描述每个控件,这会在一个应用程序上耗费数小时的工作和数以万计的 token。AppShadow 取代了这一手动步骤。它附加到正在运行的进程上,通过操作系统自身的 UI Automation 层监视你打开的每个菜单和触发的每个对话框,并生成一个可以直接交给 Claude 或任何其他编程 agent 的 `app_map.json`。
## 适用人群
任何需要重构无法查看源代码的 GUI 的人。
**UI/UX 和逆向工程师**,逐屏、逐控件地映射未文档化的应用程序的实际结构。
**重构遗留软件的团队**(Win32、MFC、Delphi、VB6 和其他 pre-web 工具包),在编写替代代码的哪怕一行之前,他们需要对每个菜单、对话框和快捷键进行精确盘点。
**QA 和 RPA 工程师**他们需要可靠的控制树(automation ID、边界矩形、enabled 状态),以便针对从未被设计为可自动化的应用程序编写脚本。
**无障碍审计员**检查屏幕阅读器能看见和不能看见的内容,因为 AppShadow 会准确呈现 UI Automation 暴露的内容以及它到底在何处变为空白。
**安全和产品研究员**在不触碰其二进制文件的情况下,构建 GUI 应用程序的攻击面或功能清单。
如果你的工作涉及盯着旧应用程序并敲打出它的功能,那么这个工具就是为你代劳这些打字工作的。
## 工作原理
由你来驱动应用程序。AppShadow 会自动跟随并捕获,并配有手动热键作为自动检测器遗漏任何内容时的兜底方案。
1. **事件监听器。** 一个 `SetWinEventHook` 订阅被过滤至你的目标的进程 ID,用于监视那些真正意味着发生了变化的事件:一个窗口进入前台、一个菜单打开、一个对话框出现。
2. **防抖。** 一个 300 毫秒的稳定计时器将一连串的事件折叠为一次捕获,因此一次点击只产生一个状态,而不是二十个。
3. **UIA 快照。** 可见的控制树通过 `pywinauto` 的 UI Automation 后端进行遍历:控件类型、名称、automation ID、边界矩形、enabled 状态,以及应用程序暴露的键盘快捷键。
4. **截图。** 目标窗口的区域,并且仅限该区域,将被抓取为 PNG。屏幕上的其他任何内容都不会被捕获。
5. **差异比较与去重。** 控制树的位置无关指纹会告知 AppShadow 以前是否见过此确切屏幕。你已经访问过的屏幕会获得一个新的导航边,而不是一个重复的节点。
6. **会话图。** 每次捕获都会被折叠进内存中不断增长的图中:状态是节点,导致进入每个状态的动作是边。在停止时,该图将作为 `app_map.json` 写入磁盘。
手动捕获热键(默认为 `Ctrl+Shift+C`)会直接跳到第 3 步,用于捕获由应用程序自身绘制、从而对自动监听器不可见的任何内容,并将该状态标记为 `needs_vision`,以便稍后通过截图填补空白。
## 产出内容
每个捕获的屏幕都会成为一个 JSON 节点,该节点专为 AI agent 直接读取而构建,而不是供人类翻阅的:
```
{
"state_id": "state_0023",
"kind": "menu_open",
"window_title": "Document1 - InPage 2012",
"breadcrumb": ["MainWindow", "File", "Export"],
"reached_by": { "action": "left_click", "on": "MenuItem:Export", "from": "state_0019" },
"screenshot": "screenshots/state_0023.png",
"controls": [
{ "type": "MenuItem", "name": "Export as PDF…", "shortcut": "Ctrl+Shift+E", "leads_to": "state_0024" },
{ "type": "MenuItem", "name": "Export as Image…", "leads_to": null },
{ "type": "MenuItem", "name": "Publish to Web…", "enabled": false }
],
"unexplored": ["MenuItem:Export as Image…"],
"ts": "2026-07-12T14:03:22+05:00"
}
```
## 针对真实的、无框架应用程序进行了验证
AppShadow 是针对 InPage 2012 进行构建和测试的,这是一款编译好的 Windows 桌面排版应用程序,没有可访问的框架,也没有文档。测试结果塑造了几项设计决策:
| 目标 | 捕获的控件 | 快照时间 | 展示内容 |
|---|---|---|---|
| 记事本(基准) | 24 | ~30 ms | 干净的控制树;Edit 正文已被正确隐去 |
| InPage 2012,完整主窗口 | 32 | ~530 ms | 工具栏、标尺和画布属于 owner drawn,对 UI Automation 不可见;被正确标记为 `needs_vision: true` |
| InPage 2012,文件菜单(限定于弹出窗口) | 5 | ~26 ms | 完整的标签、快捷键和 automation ID,完全在菜单关闭所允许的预算时间之内 |
整个窗口快照与菜单限定快照之间 20 倍的差距并不在于树的大小。InPage 自身的 UI Automation provider 在响应整个窗口时简直慢得要命,因此 AppShadow 将每次菜单捕获的范围限定在弹出窗口的 window handle 上,而不是应用程序的主窗口,这正是使其保持足够快、足以击败一个能在不到一秒内关闭的菜单的关键。完整的调查结果(包括像 `"New...\tCtrl+N"` 这样标签内嵌的快捷键是如何被拆分成一个合适的 `shortcut` 字段的)都在 [`docs/phase2_findings.md`](docs/phase2_findings.md) 和 [`docs/phase3_findings.md`](docs/phase3_findings.md) 中。
## 录制器窗口
一个小巧的、始终置顶的窗口,它从不遮挡你正在映射的应用程序。将十字准星拖放到目标窗口上,按下“开始”,然后像往常一样驱动应用程序。
标签:逆向工具