Tra tutti i protocolli e le piattaforme supportati da Remote Desktop Manager, RDP su Windows è di gran lunga il più popolare. Sebbene Microsoft offra il proprio client desktop remoto ufficiale su tutte le piattaforme tranne Linux, l’unica interfaccia client RDP esposta per l’integrazione con terze parti è disponibile solo su Windows. FreeRDP è l’unico client RDP multipiattaforma adeguato, ma non sarà mai alla pari con il client RDP ufficiale di Windows (MSTSC). La realtà è che, per offrire le funzionalità richieste dai clienti, abbiamo bisogno della flessibilità di FreeRDP (open-source), ma all’interno del client RDP di Microsoft (closed-source).
Costruire le nostre porte
Sebbene il client RDP di Microsoft sia eccellente, non espone tutto ciò che è necessario per implementare tutte le richieste di funzionalità che riceviamo. Quando si arriva a un muro, si può scegliere di fermarsi, oppure provare a costruire nuove porte in punti dove prima non ce n’erano. È esattamente ciò a cui stiamo lavorando con il progetto Devolutions MsRdpEx: un insieme di nuove “porte” che abbiamo aperto utilizzando la Microsoft Detours Library per l’API hooking. Si basa sull’interfaccia RDP ActiveX pubblica per esporre componenti e proprietà interne altrimenti non accessibili. Una prima funzionalità di API Hooking RDP è già disponibile in RDM 2022.2.
Cos’è l’API hooking?
L’API hooking è più spaventoso di quanto sembri: modifica un programma in memoria per intercettare una chiamata di funzione e reindirizzarla verso una funzione “hook” che si controlla direttamente. Ad esempio, agganciando la funzione LoadLibrary, è possibile modificarne il comportamento in modo che il caricamento di “mstscax.dll” carichi invece “MsRdpEx.dll”. In altre parole, si può “ingannare” l’applicazione alterando ciò che la funzione fa realmente. Non tutte le funzioni possono essere agganciate facilmente: alcune sono più soggette a cambiamenti di altre, o semplicemente irraggiungibili.
Reverse engineering
È closed-source, giusto? Quindi non solo manca la documentazione, ma non c’è nemmeno codice sorgente da esaminare. Può saperne di più sul reverse engineering dei binari Microsoft nel nostro articolo del blog “Finding Secret RDP Registry Keys Using IDA Free”. È di gran lunga il processo più tedioso e dispendioso in termini di tempo, anche se il risultato finale consiste semplicemente nell’invertire un bit da qualche parte. Ad esempio, la nostra integrazione non ufficiale con MSRDC si è recentemente interrotta con un misterioso codice di errore 3334, e ci sono voluti due giorni interi di intenso debugging per scoprire che una nuova proprietà interna doveva essere impostata su “true”.
Opzioni RDP estese
Che tipo di opzione nel client RDP richiede l’API hooking? Ecco un breve elenco:
- UserSpecifiedServerName: un’opzione interna necessaria per specificare il nome del server per la convalida TLS e Kerberos, utilizzata insieme al protocollo RD Gateway, ma non esposta per le normali connessioni RDP come quelle che effettuiamo per Devolutions Gateway.
- KDCProxyName: un’opzione documentata pubblicamente per iniettare dinamicamente un server proxy KDC e consentire Kerberos, ma applicata solo per le connessioni RD Gateway.
- UsingSavedCreds: un’opzione interna impostata in modo errato se al momento della connessione viene specificata una password, anche se non è stata salvata, il che interrompe l’iniezione delle credenziali quando è abilitato il criterio di gruppo “Richiedi sempre la password alla connessione”.
- DisableUDPTransport: che ci creda o no, questa opzione interna può essere impostata solo tramite chiavi di registro, impedendo un controllo granulare da un gestore di connessioni.
Le prime due opzioni, UserSpecifiedServerName e KDCProxyName, sono essenziali per facilitare Kerberos quando ci si trova al di fuori della rete aziendale, eppure sono limitate specificamente al protocollo RD Gateway. Abbiamo in arrivo una funzionalità di proxy KDC in Devolutions Gateway per sfruttarle, ma avremmo preferito non dover fare un giro così lungo con l’API hooking per renderlo possibile fin dall’inizio.
Azure Virtual Desktop
Molti utenti hanno richiesto il supporto per Azure Virtual Desktop, e siamo attualmente a metà strada. Se le cose procedono bene, dovremmo avere una prima integrazione AVD in RDM 2022.3, con miglioramenti aggiunti in seguito. Ecco un elenco delle sfide che stiamo affrontando:
- MSRDC è necessario per AVD, ma non espone ufficialmente un’API per l’integrazione
- MSRDC richiede che RDP sia firmato lato server, impedendo la gestione delle impostazioni lato client
- Le estensioni del protocollo AVD non sono documentate, a differenza del normale protocollo RDP
- Anche le chiamate di controllo AVD per il webfeed RDP effettuate con Azure non sono documentate
Il primo passo è già stato completato: siamo riusciti a integrare MSRDC per le normali connessioni RDP, sia in modalità incorporata che esterna. MSRDC include una DLL pronta all’uso (rdclientax.dll) che espone la stessa interfaccia RDP ActiveX della DLL integrata di MSTSC (mstscax.dll).
AVD aggiunge circa 10 nuove opzioni per i file RDP, con le corrispondenti proprietà interne per l’ActiveX. Capire semplicemente quali fossero e cosa significassero è stata una sfida, ma per il momento siamo almeno riusciti a importarle ed esportarle correttamente in RDM.
Una firma problematica
Tutto andava bene finché non abbiamo incontrato un primo grande ostacolo: i file RDP di AVD sono firmati lato server e pubblicati tramite un webfeed speciale che solo MSRDC sa come recuperare. Tuttavia, MSRDC non stabilisce connessioni AVD con file RDP non firmati, e non è possibile modificare le opzioni RDP lato client senza interrompere la firma. Houston, abbiamo un problema.
Quando Remote Desktop Manager avvia MSTSC o MSRDC in modalità esterna, genera un file .RDP temporaneo con tutte le opzioni della voce di connessione. Se si modifica la voce di connessione RDP in RDM, si otterrà un file RDP diverso. L’unico modo per aggirare il problema è creare una voce di connessione collegata a un file RDP locale, non modificato, ma anche in questo caso non è comunque possibile modificarlo.
Perché non firmare i file localmente? Ci abbiamo pensato, ma ciò richiede un certificato rilasciato da un’autorità nota e affidabile. Anche le strategie di API hooking per utilizzare una firma valida da un certificato autofirmato erano limitate. Ci sono volute circa due settimane di lavoro per trovare finalmente un modo per aggirare il controllo della firma dei file RDP per le connessioni AVD e avviare una prima connessione AVD con MSRDC da RDM.
Siamo arrivati?
Stiamo facendo progressi lenti, ma costanti. Le connessioni AVD dispongono di un ulteriore contesto di autenticazione con Azure, e gestirlo correttamente sarà un progetto a sé stante. Anche l’iniezione delle credenziali RDP standard è interrotta, quindi dovremo probabilmente trovare un modo diverso per farlo. L’interfaccia utente per le opzioni specifiche di AVD non è ancora completa, e denominarle e strutturarle correttamente è difficile quando non sono documentate. L’obiettivo attuale è farlo funzionare prima con MSRDC come programma esterno, poiché le connessioni AVD con MSRDC in modalità incorporata comportano una serie diversa di sfide.
Conclusione
L’API hooking è un’ottima soluzione, ma dovrebbe essere considerata come ultima risorsa. Idealmente, la maggior parte di queste opzioni estese sarebbe stata esposta pubblicamente in modo ufficiale, così da non doverci dedicare così tanto tempo al reverse engineering e all’hooking delle API. È un cliente di Azure Virtual Desktop? In caso contrario, sarebbe interessato a utilizzare MSRDC al posto di MSTSC? Poiché entrambi questi casi non sono ufficialmente supportati, apprezzeremmo se poteste inviare un feedback a Microsoft a riguardo!
