让你的窗口盖住任务管理器:通过 UIAccess 令牌提权实现"超级置顶"的多语言示例集。
Make your window sit above Task Manager: multi-language demos of "super topmost" via self-elevation with a UIAccess token (Windows 8+).
English Documentation: README.en.md
Windows 8+ 的窗口 Z 序按 Band(层段) 管理:普通的 SetWindowPos(HWND_TOPMOST)
只能在本 Band 内排序,永远盖不住任务管理器这类系统级置顶窗口。
进程令牌携带 TokenUIAccess 属性后,其置顶窗口会进入更高的
ZBID_UIACCESS 段——这就是"超级置顶"。
本仓库把 campfire 项目验证过的 零令牌复制提权链路 整理成文档,并用 6 种语言实现了完全同构的最小示例:每个示例只为自己提权,运行后是 一个带「不置顶 / 普通置顶 / 超级置顶」三个单选按钮的小窗口。
| 语言 | 目录 | 依赖 | 构建产物 |
|---|---|---|---|
| Rust | implementations/rust |
无(纯 std + FFI) | 单文件 exe |
| C | implementations/c |
Win32 SDK | 单文件 exe |
| C# | implementations/csharp |
.NET 8 (WinForms) | 单文件 exe |
| Go | implementations/go |
golang.org/x/sys | 单文件 exe |
| Python | implementations/python |
无(stdlib,tkinter) | 单脚本 |
| PowerShell | implementations/powershell |
系统自带 | 单脚本 |
六份实现共享同一套交接文件 schema、计划任务 XML、日志路径与切换语义, 可任意对照阅读;挑最熟的一门看即可。
# 任选其一
cd implementations/rust ; cargo build --release # target/release/super-topmost.exe
cd implementations/c ; cmd /c build-cl.cmd # 或 cmake;见该目录 README
cd implementations/csharp ; dotnet build -c Release # bin/Release/net8.0-windows/
cd implementations/go ; go build -ldflags="-H windowsgui" .
cd implementations/python ; pythonw super_topmost.py # pythonw 无控制台
cd implementations/powershell ; powershell -NoProfile -ExecutionPolicy Bypass -File super_topmost.ps1首次点击「超级置顶」会弹出一次 UAC 确认(链路需要管理员桥接一次), 之后窗口即位于系统级最高 Band;切回其他模式时程序会以普通令牌自动重启自己。
- 启动后默认 不置顶;
- 「不置顶 ⇄ 普通置顶」在当前窗口内即时生效;
- 「⇄ 超级置顶」因 UIAccess 只能在进程创建时携带,程序会关闭旧窗口、 经提权链路重启自身,由新窗口接管——任意时刻每种模式至多一个窗口;
- 获取失败(拒绝 UAC 等)时回退到切换前模式,绝不留下半开状态;
- 配置持久化于
%LOCALAPPDATA%\SuperTopmost\config.json, 日志写入%TEMP%\super-topmost.log。
完整行为规格见 docs/spec.md。
未提权实例 ──ShellExecuteEx("runas")──▶ 管理员桥接实例(不开窗)
│ 写交接 JSON 到 %TEMP%
│ 注册一次性计划任务(SYSTEM 身份)
▼
SYSTEM 辅助进程(自身 exe + worker 标志)
│ WTSQueryUserToken 直取会话主令牌 ★零复制★
│ SetTokenInformation(TokenUIAccess)
▼
最终进程:非特权 + UIAccess ✦
└─ 窗口 SetWindowPos(HWND_TOPMOST) → 落入 ZBID_UIACCESS 段
为什么不用经典的「复制 winlogon SYSTEM 令牌」方案?因为它已被现代系统内核封死
(反作弊驱动对 NtDuplicateToken 一刀切返回 ACCESS_DENIED,且关键进程令牌受 PPL 保护)。
零复制方案用 WTSQueryUserToken 直接取交互用户主令牌,完全绕开令牌复制。
深入阅读:
- docs/principle.md —— 原理:Band 分层、UIAccess、跨 Band 窗口树规则、为何运行时无法补授
- docs/scheme.md —— 链路详解:交接文件、任务 XML、安全模型、失败模式
- docs/spec.md —— 示例程序行为规格(状态机与切换矩阵)
- docs/case-studies.md —— 实战案例研究:三个真实 Bug 的完整诊断与修复(强烈推荐)
- docs/build.md —— 六语言构建指南
- docs/faq.md —— FAQ 与故障排查
| 项目 | 要求 |
|---|---|
| 操作系统 | Windows 10 1809+ / Windows 11(x64) |
| UAC | 开启(链路依赖一次管理员授权) |
| 各语言工具链 | 见上表 / docs/build.md |
点了超级置顶但窗口没盖上任务管理器?
先确认新窗口确实持有 UIAccess(状态栏显示"已持有"),再确认窗口处于置顶态。
UIAccess 只决定 Band,置顶本身仍需 HWND_TOPMOST——这是最常见的实现坑,
六个示例都已在代码注释中标出。
每次启动都弹 UAC?
正常情况下只有点击「超级置顶」才会弹一次。若启动就弹,说明上次链路中途退出 留下了残留配置——本仓库的示例会在启动时静默纠正(详见 docs/faq.md)。
UAC 通过了但什么都没发生 / 窗口框架和内容分离?
本项目开发中都真实踩过并已修复,诊断过程完整记录在 docs/case-studies.md:前者多为参数绑定即死或 商店版 PowerShell 宿主问题;后者是 UIAccess 进程映射前置顶导致跨 Band reparent 失败。自研实现遇到怪现象时先查这份文档。
更多见 docs/faq.md。
本项目仅用于演示 Windows 安全机制的教学目的:
- 示例只为 自身进程 提权,不提供为第三方程序提权的任何入口;
- 辅助进程有严格的信任边界校验(文件名格式、目标存在性、仅以交互用户身份启动),详见 docs/scheme.md 的安全模型一节;
- 请勿将本技术用于绕过企业安全策略或对抗安全软件。
方案源自 campfire(桌面篝火小部件)项目中对超级置顶的 工程实践与踩坑记录:借令牌方案失效的分析、SYSTEM 辅助任务链路、交接文件 回写轮询等设计均整理自该项目。