Files
netdesk/native/host/src/bin/privacy_probe.rs
T

147 lines
5.4 KiB
Rust

//! Privacy-mode feasibility probe. Determines whether a window marked
//! `SetWindowDisplayAffinity(WDA_EXCLUDEFROMCAPTURE)` is hidden from THIS host's
//! own screen capture — both DXGI Desktop Duplication (`grab`) and the GDI
//! BitBlt fallback (`grab_seed`). If it is, a fullscreen black excluded window
//! is a real, driver-free privacy mode: the local monitor shows black while the
//! remote operator still captures the desktop behind it.
//!
//! Method: show a small solid-magenta popup at a known spot, capture with the
//! affinity OFF (control — magenta must appear) then ON (magenta must vanish),
//! and count magenta pixels in each frame. Safe: the window is small and shown
//! for ~2s, then destroyed. Developed by Akronlogic.
#![cfg(windows)]
use std::time::{Duration, Instant};
use windows::core::w;
use windows::Win32::Foundation::{COLORREF, HINSTANCE, HWND, LPARAM, LRESULT, WPARAM};
use windows::Win32::Graphics::Gdi::CreateSolidBrush;
use windows::Win32::UI::WindowsAndMessaging::{
CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW, PeekMessageW, RegisterClassW,
SetWindowDisplayAffinity, ShowWindow, TranslateMessage, MSG, PM_REMOVE, SW_SHOW,
WDA_EXCLUDEFROMCAPTURE, WDA_NONE, WNDCLASSW, WS_EX_TOPMOST, WS_POPUP, WS_VISIBLE,
};
use netdesk_host::capture::DxgiCapturer;
unsafe extern "system" fn wndproc(h: HWND, m: u32, w: WPARAM, l: LPARAM) -> LRESULT {
DefWindowProcW(h, m, w, l)
}
fn pump(ms: u64) {
let end = Instant::now() + Duration::from_millis(ms);
while Instant::now() < end {
unsafe {
let mut msg = MSG::default();
while PeekMessageW(&mut msg, None, 0, 0, PM_REMOVE).as_bool() {
let _ = TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
std::thread::sleep(Duration::from_millis(15));
}
}
/// Count magenta (B=255,G=0,R=255 with tolerance) pixels in a BGRA buffer.
fn count_magenta(buf: &[u8]) -> usize {
buf.chunks_exact(4)
.filter(|p| p[0] >= 250 && p[1] <= 6 && p[2] >= 250)
.count()
}
/// Freshest DXGI frame over `ms` (None if the duplication reported no change).
fn freshest_dxgi(cap: &mut DxgiCapturer, ms: u64) -> Option<Vec<u8>> {
let end = Instant::now() + Duration::from_millis(ms);
let mut last = None;
while Instant::now() < end {
if let Ok(Some(f)) = cap.grab(80) {
last = Some(f);
}
}
last
}
fn main() {
unsafe {
let hinst = HINSTANCE::default();
let brush = CreateSolidBrush(COLORREF(0x00FF_00FF)); // B=FF,G=00,R=FF = magenta
let class = w!("NdPrivacyProbe");
let wc = WNDCLASSW {
lpfnWndProc: Some(wndproc),
hInstance: hinst,
lpszClassName: class,
hbrBackground: brush,
..Default::default()
};
let atom = RegisterClassW(&wc);
if atom == 0 {
eprintln!("RegisterClassW failed");
std::process::exit(1);
}
let hwnd = match CreateWindowExW(
WS_EX_TOPMOST,
class,
w!("nd-privacy-probe"),
WS_POPUP | WS_VISIBLE,
120,
120,
520,
380,
None,
None,
hinst,
None,
) {
Ok(h) => h,
Err(e) => {
eprintln!("CreateWindowExW failed: {e}");
std::process::exit(1);
}
};
let _ = ShowWindow(hwnd, SW_SHOW);
pump(400);
let mut cap = match DxgiCapturer::new(0) {
Ok(c) => c,
Err(e) => {
eprintln!("DxgiCapturer::new failed: {e}");
let _ = DestroyWindow(hwnd);
std::process::exit(1);
}
};
// CONTROL: affinity OFF — the window must be visible to both captures.
let _ = SetWindowDisplayAffinity(hwnd, WDA_NONE);
pump(300);
let ctl_gdi = cap.grab_seed().map(|b| count_magenta(&b)).unwrap_or(usize::MAX);
let ctl_dxgi = freshest_dxgi(&mut cap, 700).map(|b| count_magenta(&b));
// EXCLUDE: affinity ON — the window must vanish from capture.
let _ = SetWindowDisplayAffinity(hwnd, WDA_EXCLUDEFROMCAPTURE);
pump(400);
let exc_gdi = cap.grab_seed().map(|b| count_magenta(&b)).unwrap_or(usize::MAX);
let exc_dxgi = freshest_dxgi(&mut cap, 900).map(|b| count_magenta(&b));
let _ = DestroyWindow(hwnd);
println!("PRIVACY_PROBE control_gdi_magenta={ctl_gdi} exclude_gdi_magenta={exc_gdi}");
println!(
"PRIVACY_PROBE control_dxgi_magenta={:?} exclude_dxgi_magenta={:?}",
ctl_dxgi, exc_dxgi
);
let gdi_ok = ctl_gdi > 1000 && exc_gdi == 0;
// DXGI: control should show magenta; exclude should show none. If the
// duplication reported no change in a phase (None), note it.
let dxgi_ok = matches!((ctl_dxgi, exc_dxgi), (Some(c), Some(e)) if c > 1000 && e == 0);
if gdi_ok && dxgi_ok {
println!("VERDICT: PRIVACY_WDA_WORKS — WDA_EXCLUDEFROMCAPTURE hides the window from BOTH DXGI and GDI capture");
} else if gdi_ok {
println!("VERDICT: PRIVACY_WDA_GDI_ONLY — GDI excludes it; DXGI result {:?}/{:?} (inconclusive or not excluded)", ctl_dxgi, exc_dxgi);
} else {
println!("VERDICT: PRIVACY_WDA_FAILS — the window was still captured; privacy needs an IDD virtual display");
}
}
}