Blogbeitrag

04 | 10 | 2016

PowerShell Hack: UPD-Platte für einen User aushängen

Geschrieben von um 20:57 Uhr

User Profile Disk in RDS ab Server 2012 ist ein cooles Feature, was in der Regel auch super funktioniert. Doch wenn’s mal nicht funktioniert, wird es ärgerlich: Meistens liegt die Ursache nämlich darin, dass eine VHDX mit dem umgeleiteten Benutzerprofil nicht aus dem Session Host oder der VDI-Maschine ausgehängt wurde. Danach manuell zu suchen ist ein ziemlicher Schmerz, aber wenn man Admin-Recht und das AD-Modul in Powershell hat, kann man das recht gut automatisieren.

Wir gehen vom Benutzernamen und den Fileserver aus, auf dem die UPDs liegen:

$user = 'u0003'

$file_server = 'FILESERVER'

Für den Fall, dass jemand den Usernamen als NETBIOS oder UPN eingibt, normalisieren wir ihn noch zu SAMAccountName:

$user_sam = (Get-ADUser $user).SAMAccountName

Als erstes brauchen wir die SID des Users, da nach ihr die Platte benannt ist:

$sid = (Get-ADUser $user).SID.Value

Der nachfolgende Code geht auf die Arbeit von Jeffrey Patton (@jeffpatton) zurück und fragt offene Dateien direkt beim Fileserver ab:

$fs = [adsi]"WinNT://$file_server/LanmanServer"
$fsres = $fs.PSBase.Invoke("Resources")
foreach ($file in $fsres) {
    try {
        $path = $file.GetType().InvokeMember("Path","GetProperty",$null,$file,$null)
        if ($path -like "*$($sid).VHDX") {
            try {
                $rdsh = $file.GetType().InvokeMember("User","GetProperty",$null,$file,$null)
                break
            } catch {}
        }
    } catch {}
}
if ($rdsh -like "*$") { $rdsh = $rdsh.Substring(0, $rdsh.Length - 1) } else { $rdsh = $null; $path = $null }

Wenn also jetzt in $rdsh ein Wert enthalten ist, ist es ein Computername. Jetzt sollte man natürlich prüfen, ob da eine Sitzung offen ist usw., aber für den Proof of Concept schauen wir einfach nur, ob eine Disk für diesen User an diesem Host eingebunden ist:

$disk_id = (Get-WMIObject -ComputerName $rdsh -Class Win32_Volume | where { ($_.Label –like "User Disk") –and ($_.Name –like "C:\Users\$user_sam\") }).DeviceID

Um die Disk nun auszuhängen, muss man auf dem Terminalserver den folgenden Befehl ausführen:

Get-DiskImage –DevicePath $disk_id.Substring(0,$disk_id.Length -1) | Dismount-DiskImage

Das Problem dabei ist, dieser Befehl muss mit erhöhten Rechten ausgeführt werden. Damit scheidet PowerShell-Remoting als Vehikel schon mal aus.
Ein Ansatz wäre es, auf allen Terminalservern einen geplanten Task mit erhöhten Rechten einzurichten, der aus einer Datei die Platten-ID liest und sie dann aushängt. Dann würde man remote die Datei beschreiben und anschließend den geplanten Task anschubsen.
Ich habe ein Skript auf PSGallery veröffentlicht, das alle möglichen Sicherheitsabfragen und Automatismen implementiert und am Ende den Befehl ausgibt, den man am Terminalserver per Copy&Paste eingeben muss: https://www.powershellgallery.com/packages/Disconnect-RDUserProfileDisk

Beitragsdetails

Tags » «

gravatar

Kategorie » Allgemein «

Trackback: Trackback-URL |  Kommentar-Feed: RSS 2.0 | 471 Worte

Beitrag kommentieren

Kommentar schreiben ...

Deine E-Mail-Adresse wird nicht veröffentlicht.

(X)HTML Tags zur Formatierung der Kommentare

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>