RunHidden

Nel post Esecuzione degli script DOS senza visualizzare la Console Windows – DevAdmin Blog avevo descritto alcuni approcci per eseguire script DOS in modalità nascosta, a volte però nasce la necessità di eseguire anche applicazioni in modalità nascosta in modo che l’interfaccia utente dell’appliacazione non infastidisca l’operatività dell’utente. Si pensi ad esempio ad applicazioni che devono essere necessariamente installate nella sessione utente e nel contesto di sicurezza dell’utente corrente per funzionare correttamente, una di queste è ad esempio ArubaSign, a riguardo si veda il mio post Distribuzione di ArubaSign tramite GPO utilizzando uno script PowerShell – DevAdmin Blog.

Nel post Esecuzione degli script DOS senza visualizzare la Console Windows – DevAdmin Blog avevo descritto nell’Approccio 3 come avviare avviare uno script DOS oppure un’applicazione in modalità nascosta tramite uno script VBS, ma tale approccio non è più raccomandabile dal momento che nell’Ottobre 2023 VBScript è stato deprecato e nelle versioni future di Windows, VBScript sarà disponibile come funzionalità su richiesta prima della rimozione dal sistema operativo (per maggiori informazioni si veda Deprecated features in the Windows client – What’s new in Windows | Microsoft Learn).

Se la necessità è quella di eseguire un’applicazione o uno script in una sessione utente nel contesto di sicurezza dell’utente che ha avviato la sessione anche l’Approccio 1 che prevedeva l’utilizzo un’operazione pianificata non è utilizzabile quindi rimane solo la possibilità di utilizzare tool di terze parti per avviare script o applicazioni in modo nascosto.

Per tale ragione ho deciso si sviluppare una semplice applicazione in C++ che ho denominato RunHidden e reso disponibile nel mio repository su GitHub ermannog/RunHidden (github.com).

La scelta di sviluppare in C++ piuttosto che in .NET nasce dal fatto che volevo un’applicazione di fatto molto semplice per avviare in modalità nascosta un’applicazione o uno script passato come parametro con le massime prestazioni possibili, ottimizzazione a basso livello e che garantisse un controllo più diretto sulla gestione della memoria e delle risorse.

Inoltre l’utilizzo del C++ consente di realizzare un’applicazione è indipendente dalla versione di .NET installata sul sistema che può essere distribuita come file eseguibile autonomo (EXE) senza richiedere un runtime specifico, ma solo le librerie del sistema operativo necessarie per l’esecuzione.

Nel sviluppare RunHidden ho fatto la scelta di compilare per sistemi x64 e di utilizzare nel codice le chiamate di sistema che terminano con W, ovvero quelle che utilizzano la codifica wide character e supportano i caratteri Unicode. Le chiamate di sistema che terminano con W accettano parametri stringa rappresentati da wchar_t, che possono contenere caratteri Unicode a 16 bit, mentre le chiamate di sistema che terminano con A che utilizzano la codifica ANSI, supportano i caratteri ASCII e ANSI e accettano parametri stringa rappresentati da char, che possono contenere caratteri ASCII o ANSI a 8 bit. Scendendo nel dettaglio le versioni “A” delle funzioni sono state introdotte in Windows per mantenere la compatibilità con le applicazioni legacy scritte utilizzando la codifica ANSI, con l’aumento dell’uso di Unicode per supportare una vasta gamma di lingue e caratteri, le versioni “W” delle funzioni sono diventate più comuni e consigliate per le nuove applicazioni.

Nel caso specifico di RunHidden per avviare uno script o un’applicazione ho utilizzato la chiamata di sistema CreateProcessW che accetta parametri di tipo wchar_t per i percorsi del file e gli argomenti del processo, consentendo il supporto completo di Unicode, mentre la CreateProcessA accetta parametri di tipo char per gli stessi scopi e si basa sulla codifica ANSI.

Fatte queste premesse RunHidden dovrebbe essere supportata su Windows 7 / Windows 2008 R2 e successivi a 64 bit.

Per evitare di visualizzare anche per brevi istanti l’applicazione RunHidden prima che questa avvii l’applicazione o lo script ho creato una applicazione Windows Desktop, ma nella funzione wWinMain è presente solo il codice per avviare lo script o l’applicazione contenuto nel parametro passato a RunHidden in questo modo non esiste alcuna GUI.

Infatti sebbene sembrerebbe più appropriato realizzare un’applicazione Console questa implicherebbe la visualizzazione della finestra della console per una breve frazione di secondo anche se nella funzione main si invoca l’istruzione ‘ShowWindow(GetConsoleWindow(), SW_HIDE);’ perché la finestra della console è già stata creata e mostrata dal sistema operativo.