Skip to main content

Find-EFSEncryptedFiles

This week, while delivering Microsoft course 20411D: Administering Windows Server 2012, I came up with an idea while delivering the chapter on encryption and advanced auditing.  One of the issues that we as Network Administrators needs to be aware of when removing a user account or formatting a client is the use of EFS.  When a user first encrypts a file or folder using EFS, a certificate is generated for EFS encryption.  If you lose this certificate, the data is no longer accessible.  One of my best practices has been to check for this certificate on the client prior to removing the account.  That way you know to start hunting for those encrypted files.
This cmdlet is going to help me modify this practice.  I’m going to do some more development with this code to also issue decrypt the files and folders.
This command was tested using the built in Domain Administrator account.  This account is the Disaster Recovery Key for files that were EFS encrypted with a domain user account.  Using this account allows you to still access these files.  It is not a good practice to leave this account enabled for use.  You may want to consider two alternative options.
1) Utilize a Data Recovery Agent
2) Disable EFS encryption in your environment.
For now, here is the Find-EFSEncryptedFiles cmdlet that I came up with last week
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
199
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
Function Find-EFSEncryptedFiles
{
<#
.SYNOPSIS
Returns files and folders on clients that have the "encrypted" attribute set
on NTFS formatted partitions.

.DESCRIPTION
Scans a remote clients hard drive for all EFS encrypted files.  This is only able
to search for files and folders on NTFS partitioned hard drives where the
Encrypted attribute is set.

.PARAMETER ComputerName

The name of the client to scan.

.PARAMETER SearchRoot

The default searchroot is the root of each fixed hard drive.  To accelerate the
search, provide the path to a specific users storage location on the
hard drive.

.PARAMETER ErrorLogPath

The location of where to store the names of all clients that could not be
contacted.

.EXAMPLE
"Client1", "Client2", "Client3" | Find-EFSEncryptedFiles

Scans three different clients for EFS encrypted Files.

.EXAMPLE
"Client1", "Client2", "Client3" | Find-EFSEncryptedFiles -SearchRoot "C:\Users\jyoder\Documents\Restricted2"

Scans three different clients for EFS encrypted files, but with the root of the search at
"C:\Users\jyoder\Documents\Restricted2".  This will accelerate the search.

.EXAMPLE
"Client1", "Client2", "Client3" | Find-EFSEncryptedFiles -Verbose  -ErrorLogPath H:\temp\EncryptErrors.txt

This example provides the same results as Example 1, but also contains Verbose output and
an error log of all clients that could not be reached.

.EXAMPLE
Get-Content -Path C:\Temp\EncryptErrors.txt | Find-EFSEncryptedFiles

This example reads an error log from a previous run of this command.  The error log
contains the names of the clients that could not be contacted the
first time the command was run.

.NOTES
===============================================================================
== Cmdlet: Find-EFSEncryptedFiles                                            ==
== Author: Jason A. Yoder                                                    ==
== Company: MCTExpert of Arizona                                             ==
== Date: June 14, 2014                                                       ==
== Copyright: All rights reserved.                                           ==
== Version: 1.0.0.0                                                          ==
== Legal: The user assumes all responsibility and liability for the usage of ==
== this PowerShell code.  MCTExpert of Arizona, Its officers, shareholders,  ==
== owners, and their relatives are not liable for any damages.  As with all  ==
== code, review it and understand it prior to usage.  It is recommended that ==
== this code be fully tested and validated in a test environment prior to    ==
== usage in a production environment.                                        ==
==                                                                           ==
== Does this code make changes: NO                                           ==
===============================================================================
#>
[cmdletbinding()]
Param(
    [Parameter(Mandatory=$True,
            ValueFromPipeline=$true)]
    [String[]]$ComputerName,
    [String]$SearchRoot = "",
    [String]$ErrorLogPath
)

    BEGIN
    {
        # If the user requests an Error Log to be generated, first verify
        # the path for the file by creating it (or erasing it) and set it
        # equal to $null.
        #
        # If the path is not valid, then display that the path is invalid.
        # Terminate the command if the path is invalid.
        If ($ErrorLogPath -ne "")
        {
           
            $ErrorLogAvailable = $False
            Try
            {
                $null | Out-File -FilePath $ErrorLogPath -ErrorAction Stop
                $ErrorLogAvailable = $True
            }
            Catch
            {
                $ColorHash = @{'ForegroundColor' = 'DarkRed'
                               'BackgroundColor' = 'Gray'}
                Write-Host "Error: Log Path is invalid              " @ColorHash
                Write-Host "Find-EFSEncryptedFiles has terminated.  " @ColorHash
                Write-Host "Correct the Errorlog path.  Refer to    " @ColorHash
                Write-Host "Get-Help Find-EFSEncryptedFile -Examples" @ColorHash
                Write-Host "for more information.                   " @ColorHash
                BREAK
            }
        }
    } # END: BEGIN BLOCK
    PROCESS{
       
        # Work on each client, one at a time.
        ForEach ($C in $Computername)
        {
            Write-Verbose "Connecting to $C"
            Try
            {
                # Initiate the remote session to the client.
                $S = New-PSSession -ComputerName $C -ErrorAction Stop
               
                Invoke-Command -ScriptBlock {
                Param($SearchRoot, $IncludeNetworkDrives)

                    # Collect the drive information
                        $Q = "Select DeviceID FROM win32_LogicalDisk WHERE DriveType = 3"
                        $Drives = Get-CimInstance -Query $Q

                    # This IF..ELSE block is used to determine the root of the search.
                    If ($SearchRoot -ne "")
                    {
                        If (Test-Path -Path $SearchRoot)
                        {
                            ForEach ($D in $Drives)
                            {
                                Get-ChildItem -Path $SearchRoot -Recurse -Attributes E |
                                Select-Object -Property FullName, Name
                            }
                        }
                        Else
                        {
                            $ColorHash = @{'ForegroundColor' =  'DarkRed'
                                           'BackgroundColor' =  'Yellow'}
                            Write-Host "The SearchRoot $SearchRoot does not exists on $(Hostname)" @ColorHash
                        }
                    }
                    Else
                    {
                      
                        ForEach ($D in $Drives)
                        {
                            Get-ChildItem -Path "$($D.DeviceID)\" -Recurse -Attributes E |
                            Select-Object -Property FullName, Name
                        }
                    }
                    } -Session $S -ArgumentList $SearchRoot, $IncludeNetworkDrives |
                Select-Object -Property Name, FullName, PSComputerName

                $S | Remove-PSSession
            } # END: TRY BLOCK
            Catch
            {
                Write-Host "Computer $C is offline" -ForegroundColor Red -BackgroundColor DarkRed
                If (($ErrorLogPath -ne "") -and ($ErrorLogAvailable -eq $true))
                {
                    $C | Out-File -FilePath $ErrorLogPath -Append
                }
            }
        } # END: ForEach ($C in $Computername)   
    } #End: PROCESS BLOCK
    END{}

} # END: Function Find-EFSEncryptedFiles

Comments

Popular posts from this blog

How to list all the AD LDS instances on a server

AD LDS allows you to provide directory services to applications that are free of the confines of Active Directory.  To list all the AD LDS instances on a server, follow this procedure: Log into the server in question Open a command prompt. Type dsdbutil and press Enter Type List Instances and press Enter . You will receive a list of the instance name, both the LDAP and SSL port numbers, the location of the database, and its status.

How to run GPResult on a remote client with PowerShell

In the past, to run the GPResult command, you would need to either physically visit this client, have the user do it, or use and RDP connection.  In all cases, this will disrupt the user.  First, you need PowerShell remoting enabled on the target machine.  You can do this via Group Policy . Open PowerShell and type this command. Invoke-Command –ScriptBlock {GPResult /r} –ComputerName <ComputerName> Replace <ComputerName> with the name of the target.  Remember, the target needs to be online and accessible to you.

Error icon when creating a GPO Preference drive map

You may not have an error at all.  Take a look at the drive mapping below. The red triangle is what threw us off.  It is not an error.  It is simply a color representation of the Replace option of the Action field in the properties of the drive mappings. Create action This give you a green triangle. The Create action creates a new mapped drive for users. Replace Action The Replace action gives you a red triangle.  This action will delete and recreate mapped drives for users. The net result of the Replace action is to overwrite all existing settings associated with the mapped drive. If the drive mapping does not exist, then the Replace action creates a new drive mapping. Update Action The Update action will have a yellow triangle. Update will modify settings of an existing mapped drive for users. This action differs from Replace in that it only updates settings defined within the preference item. All other settings remain as configured on the mapped drive. If the