HomeBlogMagic

Powershell Script zum manuellen entfernen von Treibern aus dem Driver Store

Immer wieder muss ich einen fehlerhaften Treiber aus dem System entfernen ohne dass dieser installiert ist, oder im Device Manager auftaucht.
Meist sind es Treiber die einen Bluescreen verursachen könnten wenn sie geladen werden.

Die Treiber sind allerdings mit Administrator Rechten geschützt, die man vorher entfernen muss.

Das ganze händisch über den Explorer zu machen ist sehr mühselig, deshalb habe ich dafür ein kleine Script zusammengestellt, dass das für mich automatisiert:

# Target Driver to remove
$Drivers = Get-ChildItem C:\Windows\System32\DriverStore\FileRepository\ExampleDriver*

Function Remove-File
{
    Param(
        [String]$File 
    )

    [Int]$Global:AccessAllowed              = 0x00000000
    [Int]$Global:AccessDenied               = 0x00000001
    [Int]$Global:AccessAudit                = 0x00000002

    [Int]$Global:SeOwnerDefaulted           = 0x00000001
    [Int]$Global:SeGroupDefaulted           = 0x00000002
    [Int]$Global:SeDaclPresent              = 0x00000004
    [Int]$Global:SeDaclDefaulted            = 0x00000008
    [Int]$Global:SeSaclPresent              = 0x00000010
    [Int]$Global:SeSaclDefaulted            = 0x00000020
    [Int]$Global:SeDaclAutoInheritReq       = 0x00000100
    [Int]$Global:SeSaclAutoInheritReq       = 0x00000200
    [Int]$Global:SeDaclAutoInherited        = 0x00000400
    [Int]$Global:SeSaclAutoInherited        = 0x00000800
    [Int]$Global:SeDaclProtected            = 0x00001000
    [Int]$Global:SeSaclProtected            = 0x00004000
    [Int]$Global:SeSelfRelative             = 0x00008000                              

    [Int]$Global:ObjectInheritAce           = 0x00000001
    [Int]$Global:ContainerInheritAce        = 0x00000002
    [Int]$Global:NoPropagateInheritAce      = 0x00000004
    [Int]$Global:InheritOnlyAce             = 0x00000008
    [Int]$Global:InheritedAce               = 0x00000010                              
    [Int]$Global:SuccessfulAccessAceFlag    = 0x00000040
    [Int]$Global:FailedAccessAceFlag        = 0x00000080

    [Int]$Global:FileReadData               = 0x00000001
    [Int]$Global:FileListDirectory          = 0x00000001
    [Int]$Global:FileWriteData              = 0x00000002
    [Int]$Global:FileAddFile                = 0x00000002
    [Int]$Global:FileAppendData             = 0x00000004
    [Int]$Global:FileAddSubdirectory        = 0x00000004
    [Int]$Global:FileReadEa                 = 0x00000008
    [Int]$Global:FileWriteEa                = 0x00000010
    [Int]$Global:FileExecute                = 0x00000020
    [Int]$Global:FileTraverse               = 0x00000020
    [Int]$Global:FileDeleteChild            = 0x00000040
    [Int]$Global:FileReadAttributes         = 0x00000080
    [Int]$Global:FileWriteAttributes        = 0x00000100
    [Int]$Global:Delete                     = 0x00010000
    [Int]$Global:ReadControl                = 0x00020000
    [Int]$Global:WriteDAC                   = 0x00040000
    [Int]$Global:WriteOwner                 = 0x00080000
    [Int]$Global:Synchronize                = 0x00100000

    Function New-RecoveryFileOwner(){
        Param(
            [Parameter(Mandatory=$True)]
            [System.Management.ManagementBaseObject]$SecurityDescriptor = $NULL,
            [Parameter(Mandatory=$True)]
            [System.String]$Domain = '',
            [Parameter(Mandatory=$True)]
            [System.String]$Name = ''
        )

        [System.Management.ManagementBaseObject]$TrusteeOld = $NULL
        [System.Management.ManagementBaseObject]$TrusteeNew = $NULL
        [System.Management.ManagementBaseObject]$AccountNew = $NULL
        [System.Management.ManagementBaseObject]$SidNew     = $NULL

        $TrusteeNew                 = (New-Object -TypeName System.Management.ManagementClass -ArgumentList 'Win32_Trustee' -ErrorAction Stop).CreateInstance()

        $AccountNew                 = Get-WmiObject -Class 'Win32_Account' -Filter "Name = '$Name' And Domain = '$Domain'" -ErrorAction Stop                    

        $SidNew                     = New-Object -TypeName System.Management.ManagementObject -ArgumentList "Win32_SID.SID='$($AccountNew.SID)'"

        $TrusteeNew.Domain          = $SidNew.ReferencedDomainName
        $TrusteeNew.Name            = $SidNew.AccountName
        $TrusteeNew.SID             = $SidNew.BinaryRepresentation
        $TrusteeNew.SIDLength       = $SidNew.SIDLength
        $TrusteeNew.SIDString       = $SidNew.SID

        return $TrusteeNew
    }

    Function New-RecoveryFileAce(){
        Param(
            [Parameter(Mandatory=$True)]
            [System.Management.ManagementBaseObject]$Trustee = $NULL        
        )

        [System.Management.ManagementBaseObject]$AceNew     = $NULL

        $AceNew                         = (New-Object -TypeName System.Management.ManagementClass -ArgumentList 'Win32_ACE' -ErrorAction Stop).CreateInstance()

        $AceNew.AccessMask              = ($Global:FileReadData        -bOr
                                           $Global:FileListDirectory   -bOr
                                           $Global:FileWriteData       -bOr
                                           $Global:FileAddFile         -bOr
                                           $Global:FileAppendData      -bOr
                                           $Global:FileAddSubdirectory -bOr
                                           $Global:FileReadEa          -bOr
                                           $Global:FileWriteEa         -bOr
                                           $Global:FileExecute         -bOr
                                           $Global:FileTraverse        -bOr
                                           $Global:FileDeleteChild     -bOr
                                           $Global:FileReadAttributes  -bOr
                                           $Global:FileWriteAttributes -bOr
                                           $Global:Delete              -bOr
                                           $Global:ReadControl         -bOr
                                           $Global:WriteDAC            -bOr
                                           $Global:WriteOwner          -bOr
                                           $Global:Synchronize)
        $AceNew.AceFlags                = 0
        $AceNew.AceType                 = $Global:AccessAllowed
        $AceNew.GuidInheritedObjectType = ''
        $AceNew.GuidObjectType          = ''
        $AceNew.Trustee                 = $TrusteeNew

        return $AceNew
    }

    [String]$Location = ''
    [String]$Domain = ''
    [String]$Name = ''
    [System.Management.ManagementObject]$LogicalFileSecuritySetting = $NULL
    [System.Management.ManagementBaseObject]$SecurityDescriptorOld  = $NULL
    [System.Management.ManagementBaseObject]$SecurityDescriptorNew  = $NULL
    [System.Management.ManagementBaseObject]$TrusteeOld             = $NULL
    [System.Management.ManagementBaseObject]$TrusteeNew             = $NULL
    [System.Management.ManagementBaseObject]$AceNew                 = $NULL

    $File = $File.Replace('\','\\')

    $Domain = (([System.Security.Principal.WindowsIdentity]::GetCurrent()).Name).Split('\')[0]
    $Name   = (([System.Security.Principal.WindowsIdentity]::GetCurrent()).Name).Split('\')[1]

    $SecurityDescriptorOld              = (New-Object -TypeName System.Management.ManagementClass -ArgumentList 'Win32_SecurityDescriptor' -ErrorAction Stop).CreateInstance()
    $SecurityDescriptorNew              = (New-Object -TypeName System.Management.ManagementClass -ArgumentList 'Win32_SecurityDescriptor' -ErrorAction Stop).CreateInstance()

    $LogicalFileSecuritySetting         = Get-WmiObject -Class 'Win32_LogicalFileSecuritySetting' -Filter "Path='$File'" -EnableAllPrivileges

    $SecurityDescriptorOld              = ($LogicalFileSecuritySetting.GetSecurityDescriptor()).Descriptor

    $TrusteeOld                         = $SecurityDescriptorOld.Owner
    $TrusteeNew                         = New-RecoveryFileOwner -SecurityDescriptor $SecurityDescriptorOld -Domain $Domain -Name $Name

    $SecurityDescriptorNew.ControlFlags = 0
    $SecurityDescriptorNew.Owner        = $TrusteeNew
    $SecurityDescriptorNew.Group        = $NULL
    $SecurityDescriptorNew.DACL         = $NULL
    $SecurityDescriptorNew.SACL         = $NULL

    $LogicalFileSecuritySetting.SetSecurityDescriptor($SecurityDescriptorNew)

    $AceNew                             = New-RecoveryFileAce -Trustee $TrusteeNew

    $SecurityDescriptorNew.ControlFlags = $Global:SeDaclPresent
    $SecurityDescriptorNew.Owner        = $NULL
    $SecurityDescriptorNew.Group        = $NULL
    $SecurityDescriptorNew.DACL         = @($AceNew)
    $SecurityDescriptorNew.SACL         = $NULL

    $LogicalFileSecuritySetting.SetSecurityDescriptor($SecurityDescriptorNew)

    Remove-Item -Path $File -Force -Recurse -ErrorAction Stop
}

foreach($Driver in $Drivers)
{
    Remove-File $Driver.FullName
}