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) 中。 ## 录制器窗口 一个小巧的、始终置顶的窗口,它从不遮挡你正在映射的应用程序。将十字准星拖放到目标窗口上,按下“开始”,然后像往常一样驱动应用程序。

AppShadow recorder window, idle state    AppShadow recorder window, actively recording

状态栏会显示捕获的状态、菜单和对话框的实时计数。最后一行事件准确地告诉你刚刚捕获了什么以及它来自哪里。全局热键(`Ctrl+Shift+C` 强制捕获,`Ctrl+Shift+X` 停止)即使在目标应用程序获得焦点时也能起作用。 ## 入门指南 需要 Windows 和 Python 3.11 或更高版本。 ``` python -m venv .venv .venv\Scripts\pip install -r requirements.txt .venv\Scripts\python main.py ``` 将十字准星从 **Pick app** 拖动到要映射的窗口上,按下 **Start**,然后正常使用该应用程序。完成后按 **Stop**,`app_map.json` 以及 `screenshots/` 文件夹就会在一个新的 `sessions/` 目录中等候你。 另外两个入口点本身也很有用: ``` # One shot:立即对单个窗口进行快照并打印 JSON .venv\Scripts\python -m scrapers.windows_uia --title-re ".*Notepad.*" # Headless:从命令行记录会话,无需窗口 .venv\Scripts\python recorder.py --title-re ".*YourApp.*" --seconds 60 --app "YourApp.exe" ``` ## 架构 其核心特意设计为平台无关。所有了解 Windows 的内容都位于一个抽象接口之后,这正是能够让这个项目在不改动 schema 或会话图的哪怕一行代码的情况下,为 web、macOS 或 Android 开发抓取器的原因。 ``` appshadow/ ├─ main.py tkinter recorder window, global hotkeys, toasts ├─ recorder.py ShadowRecorder: wires the hook, debounce, scraper and screenshot grabber together ├─ config.py DPI awareness, timing, hotkeys, redaction rules ├─ core/ │ ├─ schema.py Control, Edge, State, Session (the JSON contract) │ └─ session.py tree hash diff engine, debounce, coverage tracking ├─ scrapers/ │ ├─ base.py abstract Scraper interface, the cross-platform seam │ └─ windows_uia.py pywinauto UIA walker + WinEventHook listener ├─ capture/ │ └─ screenshot.py mss window region grabs ├─ examples/ a hand built sample session and a React component rebuilt from nothing but its JSON └─ docs/ findings from testing against a real compiled application ``` ## 已完成功能与未来规划 捕获实时会话的端到端流程已经可以工作:事件监听器、防抖和差异比较引擎、UIA 快照功能、窗口范围限定的截图、录制器窗口、全局热键,以及停止时的覆盖率报告。路线图上剩余的工作是一个专用的导出器(它会在 JSON 之外额外输出一个 Mermaid 图)、长时间会话期间的定期自动保存、针对超大型应用程序的按菜单分片,以及 `scrapers/base.py` 已经为其预留了切入点的额外抓取器(web、macOS、Android)。 ## 许可证 在 [MIT 许可证](LICENSE) 下发布。
标签:逆向工具