| gui | ||
| wiki | ||
| .gitignore | ||
| Program.cs | ||
| README.md | ||
| run_helper.cmd | ||
| setup-uac.cmd | ||
| winruntime.csproj | ||
WinRuntime
A SYSTEM-integrity helper that clicks Yes on a Windows UAC prompt exactly once, when explicitly armed. Built to automate UniGetUI's "Update as administrator" flow without you babysitting the elevation dialog.
Why it exists
When UniGetUI updates packages as administrator, Windows shows a UAC consent dialog ("Do you want to allow this app to make changes to your device?"). Normally you must click Yes manually, and on Win11 the secure-desktop UAC can't be automated with normal input simulation. This project runs a tiny helper at System integrity that listens for the UAC window and posts the keyboard messages that activate the Yes button — but only when you have armed it, and for exactly one prompt.
Architecture
Two components:
| Component | Runs as | Role |
|---|---|---|
winruntime.exe (C# / .NET 8) |
System (via gsudo -i System) |
Tray icon + listens for UAC window + performs the one-shot Yes click |
winruntimeui.exe (Go / Wails) |
normal user (elevated for password setup) | Password gate: arm / disarm / status, first-run password setup |
winruntimeui.exe ──named pipe──▶ winruntime.exe (System)
(arm with password) \__ clicks UAC Yes once, then disarms
The click
On this machine UAC is configured to show inline on the Default desktop (PromptOnSecureDesktop=0). Win11's UAC is DirectUI — EnumChildWindows returns zero button HWNDs, and SendInput from System integrity is denied (err=5). The working strategy is message-based:
PostMessage(hwnd, WM_SYSKEYDOWN, VK_Y, 0x20150001) // Alt held, 'Y' pressed
PostMessage(hwnd, WM_SYSKEYUP, VK_Y, 0xE0150001)
This activates the Yes accelerator. Note: posting plain Enter clicks No (the safe default) on Win11, so it is only a last-resort fallback.
Security model
The helper is disarmed by default and will never click unless armed:
- One-shot: each arm is consumed by exactly one UAC prompt, then the helper re-disarms (also on a 60 s timeout).
- Password: arming requires the password, verified against a salted SHA-256 hash. The plaintext password is never stored, logged, or sent in the clear over the pipe.
- Protected config: the hash lives in
C:\ProgramData\WinRuntime\winruntime.hashwith an ACL allowing only SYSTEM/Administrators — a non-elevated process can't delete it to force a reset. - Elevation-gated setup: the initial password can only be set by an elevated caller (verified via the pipe client's token). A non-elevated process gets
NEED_ADMIN. - Brute-force lockout: 3 wrong ARM attempts → 30 s lock, doubling each round.
- Password policy: minimum 8 characters.
Honest caveat: UAC in the default same-desktop configuration is a consent prompt, not a malware boundary. An already-elevated attacker on this machine can bypass all of this — that is by design.
Build
Helper (C#)
cd winruntime
dotnet publish -c Release -r win-x64 -o out
GUI (Wails / Go)
cd gui
wails build
copy build\bin\winruntimeui.exe ..\out\
Deploy & first run
0. One-time UAC prerequisites (per machine, elevated)
The whole approach depends on the UAC prompt appearing inline on your desktop rather than on the secure Winlogon desktop. A System helper in WinSta0 simply cannot see (or reach) the secure desktop.
Run as Administrator (or use the included script):
# setup-uac.cmd — must be elevated
.\setup-uac.cmd
That sets (under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System):
| Key | Value | Why |
|---|---|---|
EnableLUA |
1 |
UAC exists at all |
PromptOnSecureDesktop |
0 |
UAC shows inline on the Default desktop — required |
ConsentPromptBehaviorAdmin |
5 |
Keep "prompt for consent" (do NOT set 0, that silently auto-elevates everything and defeats the purpose) |
ValidateAdminCodeSignatures |
0 |
Don't require signed binaries for elevation |
Changes to EnableLUA/PromptOnSecureDesktop require a reboot to take effect. After the script, verify:
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v PromptOnSecureDesktop
You should see 0x0. The helper logs the detected input desktop at startup (input desktop = 'Default'); if you see Winlogon, the prompt is on the secure desktop and the inline prerequisite is missing.
1. Build
Helper (C#)
cd winruntime
dotnet publish -c Release -r win-x64 -o out
GUI (Wails / Go)
cd gui
wails build
copy build\bin\winruntimeui.exe ..\out\
2. Launch the helper as System
Requires gsudo:
gsudo -i System -- .\winruntime\run_helper.cmd
You'll see the WinRuntime shield icon in the tray.
3. One-time password setup (elevated)
Open the GUI as Administrator (elevation is required for the one-time password setup):
Start-Process .\winruntime\out\winruntimeui.exe -Verb RunAs
In the GUI: Set password (min 8 chars). From then on, normal launches can arm.
4. Arm & trigger
Click Arm (one click) with the password → trigger "Update as administrator" in UniGetUI → the helper clicks Yes once and disarms.
Daily use
- Arm: open the GUI (double-click the tray icon), enter password, click Arm. You have 60 s.
- Tray icon: double-click opens the GUI. Closing the GUI window hides it to the tray (process stays alive); re-open via the tray icon. Right-click → Exit / stop auto-click kills helper + GUI.
- Status sync: the GUI polls the helper every 2 s, so it flips to IDLE automatically after the one-shot click is consumed.
Files
winruntime/
├── Program.cs # helper: UAC detection + click strategies + pipe auth
├── winruntime.csproj
├── run_helper.cmd # gsudo System launcher for the helper
├── setup-uac.cmd # one-time registry prerequisites (elevated)
└── gui/ # Wails arm GUI (Go + vanilla JS)
├── main.go # app entry, hide-to-tray on close
├── app.go # pipe client: ARM/STATUS/SETUP/DISARM
└── frontend/ # UI (password field, arm/disarm, status)
Troubleshooting
ERR: helper not reachable— the helper isn't running (or not as System). Check the tray icon / restart viarun_helper.cmd.NEED_ADMINon Set password — run the GUI as Administrator.LOCKED:…— too many wrong ARM attempts; wait out the lockout.- No click happens — the helper must run at System integrity (
S-1-16-16384) and the UAC must be inline (not on the secure desktop). Checkwinruntime.logfor the detected integrity level and input desktop; if it showsWinlogon, runsetup-uac.cmd(elevated) and reboot.
Verification probe
uac_elev_probe.cmd (outside this repo) writes a marker to C:\Program Files\ from an elevated child — if the marker exists and the child reports ADMIN=YES, the Yes-click genuinely elevated the process. This is how the Alt+Y strategy was verified end-to-end.