PowerShell: Active Directory User to SID and SID to User

I was recently asked to find the username associated with a particular Active Directory SID (technically I was given the RID).

This is actually pretty easy in PowerShell, and quite intuitive using basic AD cmdlets.

Get the user for a given RID:

Get-ADUser -Filter * | Select-Object -Property SID,Name | Where-Object -Property SID -like "*-6640"

Get the SID for a given user:

Get-ADUser -Identity ad.user | Select-Object -Property Name,SID
Posted in PowerShell, Windows | Tagged , , , , , , , | 1 Comment

PowerShell Script to download latest SysInternals tools

The SysInternals tools are pretty much a must-have for any IT Pro, but they get updated randomly and I always like to have the latest versions. You can run them from the live site, but I like to have them stored within my network as not everything has internet access.

This script will copy all the tools to the specified folder. Run it as a scheduled task.

$DestinationFolder = "C:\sysint"

Write-Host "Connecting"
New-PSDrive -Name SysInt -PSProvider FileSystem -Root \\live.sysinternals.com\Tools
$Files = Get-ChildItem -Path SysInt:\ -Recurse

Write-Host "Copying"
$Copied = 0
foreach($File in $Files){
    Write-Progress -Activity "Update SysInt" -Status $File.Name -PercentComplete ($Copied / $Files.Count * 100)
    Copy-Item -Path $File.FullName -Destination $DestinationFolder -Force
    $Copied++
}
Write-Progress -Activity "Update SysInt" -Completed

Write-Host "Tidying up"
Remove-PSDrive -Name SysInt -PSProvider FileSystem

Enjoy!

Note that if you want to run this on Windows Server you need to enable Desktop Experience and then start the WebClient service, this is to enable the Windows WebDAV client functionality. If you don’t want to set the service to autostart you could modify the script to start the service at the beginning and stop it at the end.

Posted in PowerShell, Windows | Tagged , , , , , , , , | Leave a comment

AppLocker Executable policy breaks Windows 10 Jump Lists

Jump lists, very handy. You’ve pinned a piece of software to the taskbar, and then you can right-click the icon and get a list of pinned and/or recently used files or connections.

I recently enabled AppLocker executable policy and applied it to my Windows 10 (2015 LTSB) PC. I just enabled the default rules, so everyone is allowed to run stuff from Program Files and Windows folders, and administrators can run anything.

Once that had kicked in, as an unwanted side effect, I noticed that the jump lists had stopped working. On looking in the AppLocker event log I saw the following entry:

Log Name: Microsoft-Windows-AppLocker/Packaged app-Execution
Source: Microsoft-Windows-AppLocker
Date: 22/03/2016 11:40:41
Event ID: 8027
Task Category: None
Level: Error
Keywords:
User: RCMTECH\Robin
Computer: PC01.rcmtech.co.uk
Description:
No packaged apps can be executed while Exe rules are being enforced and no Packaged app rules have been configured.

There was one of these logged every time I right-clicked on a pinned app on the taskbar.

So rather like the event description hints at, I created a default AppLocker rule under Packaged app Rules: Allow Everyone to run all signed packaged apps, and once that had applied to my PC, jump lists are working again.

What’s interesting is that I have not enabled Packaged app Rules: they’re not being enforced, the “Configured” box is not ticked (whereas it is for Executable rules).

Posted in Security, Windows | Tagged , , , , , , , , , , , , , , , | Leave a comment

Send SMTP email with authentication from PowerShell

Email is a good way to send notifications from your PowerShell scripts, and it’s super easy. You just need an SMTP server, and use Send-MailMessage:

Send-MailMessage -From "testscript@rcmtech.co.uk" -To "robin@rcmtech.co.uk" -Subject "Something interesting just happened" -Body "Here's the details about the interesting thing" -SmtpServer smtp.rcmtech.co.uk

You can even omit the -SmtpServer bit if you’ve previously set the $PSEmailServer preference variable.

However, what if you don’t have your own internal mailserver, and the only one available needs credentials? Many ISPs require authenticated SMTP now. Sure, Send-MailMessage has a -Credentials options, but these need to be in the form of a System.Management.Automation.PSCredential object. You can use Get-Credential to generate one of these:

Get-Credential -Message "Cough up" -Username "your_username"

But Get-Credential doesn’t have an option to accept the password as plain text, and storing a password as plain text is bad practice anyway. Thus Get-Credential, in the form used above, will create the right kind of object that you can feed into Send-MailMessage, but it does it in the wrong kind of way – via a pop up a box for you to type your password into, which isn’t that handy for use in unattended scripting.

So the clever way to do this is to create yourself an encrypted password file. You can do this as follows:

Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath username@domain.net.securestring

Run the above, enter the password (which will be obscured with asterisks as you type it), and hit <Enter>. Now you’ve got a text file with an encrypted password in it. How does this work? Read-Host prompts for text, because we’ve used the -AsSecureString switch it returns the text entered as a System.Security.SecureString object. We then pass this to ConvertFrom-SecureString which takes that object and spits it out as text, encrypted with Windows Data Protection API (DPAPI). You can also use 128, 192 or 256-bit AES encryption.

So now we have the password in a file, and can use this to create a PSCredential object:

New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "username@myisp.net",(Get-Content -Path username@myisp.net.securestring | ConvertTo-SecureString)

So now shove the whole lot together, on one line (because we can, and bigger is better, right?):

Send-MailMessage -From "username@myisp.net" -To "robin@rcmtech.co.uk" -Subject "Something interesting just happened" -Body "Here's the details about the interesting thing" -SmtpServer smtp.myisp.net -Port 587 -Credential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "username@myisp.net",(Get-Content -Path username@myisp.net.securestring | ConvertTo-SecureString))

But to make it easier to interpret, here’s the same thing broken down with variables:

$PSEmailServer = "smtp.myisp.net"
$SMTPPort = 587
$SMTPUsername = "username@myisp.net"
$EncryptedPasswordFile = "username@myisp.net.securestring"
$SecureStringPassword = Get-Content -Path $EncryptedPasswordFile | ConvertTo-SecureString
$EmailCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SMTPUsername,$SecureStringPassword
$MailTo = "robin@rcmtech.co.uk"
$MailFrom = "username@myisp.net"
$MailSubject = "Something interesting just happened"
$MailBody = "Here's the details about the interesting thing"
Send-MailMessage -From $MailFrom -To $MailTo -Subject $MailSubject -Body $MailBody -Port $SMTPPort -Credential $EmailCredential

If your SMTP server requires it, you can also add -UseSsl to Send-MailMessage.

Posted in PowerShell | Tagged , , , , , , , , , , , , , , , , , , | Leave a comment

PowerShell Profiles

If you use the PowerShell prompt a lot and/or the PowerShell ISE, you might find your life made a little bit easier by setting up a PowerShell Profile.

All they are is a script that’s run each time you open the powershell.exe prompt or the powershell_ise.exe ISE (or both). You can put anything you like in them, e.g. adding the VMware PowerCLI snapins, setting the current folder, whatever. Note that $profile points to different files for the prompt vs the ISE.

The file is referenced via the built in variable $profile, which actually has several different options depending on whether you want the profile script to run for the PowerShell prompt, the ISE, both, the current user, any user on the PC, etc. Personally, I find the most useful one is the CurrentUserAllHosts, which means it runs for both the prompt and the ISE.

The WindowsPowerShell folder doesn’t exist, but we can create that and an empty profile script with New-Item:

New-Item -Path $profile.CurrentUserAllHosts -ItemType File -Force

If you’re in the ISE, you can then edit your new profile script by using:

psedit $profile.CurrentUserAllHosts

You might like to create a “Scripts” folder in your user profile, and then use the profile to set that as a PSDrive and change to it:

New-PSDrive -Name Scripts -PSProvider FileSystem -Root $env:USERPROFILE\Scripts
Set-Location -Path Scripts:\

Obviously, depending on what you put in your $profile it might delay your PowerShell startup experience somewhat.

 

Posted in PowerShell | Tagged , , , , , , , , | Leave a comment

List All Domain Controllers and roles with PowerShell

New job, new infrastructure, and I needed a way to quickly find out what Active Directory Domain Controllers were present, where they were located, and what roles and functions they all performed.
So I wrote this simple script to do it.

$DCs = Get-ADDomainController -Filter *
$Results = New-Object -TypeName System.Collections.ArrayList
foreach($DC in $DCs){
    [string]$OMRoles = ""
    $ThisResult = New-Object -TypeName System.Object
    Add-Member -InputObject $ThisResult -MemberType NoteProperty -Name Name -Value $DC.Name
    Add-Member -InputObject $ThisResult -MemberType NoteProperty -Name Site -Value $DC.Site
    Add-Member -InputObject $ThisResult -MemberType NoteProperty -Name IPv4Address -Value $DC.IPv4Address
    Add-Member -InputObject $ThisResult -MemberType NoteProperty -Name OperatingSystemVersion -Value $DC.OperatingSystemVersion
    Add-Member -InputObject $ThisResult -MemberType NoteProperty -Name IsGlobalCatalog -Value $DC.IsGlobalCatalog
    Add-Member -InputObject $ThisResult -MemberType NoteProperty -Name IsReadOnly -Value $DC.IsReadOnly
    foreach($OMRole in $DC.OperationMasterRoles){
        $OMRoles += ([string]$OMRole+" ")
    }
    Add-Member -InputObject $ThisResult -MemberType NoteProperty -Name OperationMasterRoles -Value $OMRoles
    $Results.Add($ThisResult) | Out-Null
}
$Results = $Results | Sort-Object -Property Site
$Results | Format-Table -AutoSize

You could also export the $Results object to CSV via Export-CSV.

Posted in PowerShell | Tagged , , , , , , , , , , , , , , | Leave a comment

Using the Windows Volume Shadow Copy Service (VSS)

Having just written an article about how to get items back from a volume shadow copy, I thought I should make some notes about how VSS works, how to configure it, and actually get VSS to create you some shadow copies! This is also useful because, on a filer server, it enables users to recover their own accidentally deleted or overwritten files and folders via the Previous Versions feature.

If you’ve never come across VSS before, TechNet has this to say:

Shadow Copies of Shared Folders provides point-in-time copies of files that are located on shared resources, such as a file server. With Shadow Copies of Shared Folders, users can view shared files and folders as they existed at points of time in the past. Accessing previous versions of files, or shadow copies, is useful because users can:

  • Recover files that were accidentally deleted. If you accidentally delete a file, you can open a previous version and copy it to a safe location.
  • Recover from accidentally overwriting a file. If you accidentally overwrite a file, you can recover a previous version of the file.
  • Compare versions of a file while working. You can use previous versions when you want to check what has changed between two versions of a file.

It’s probably something you want, assuming you have a bit of space somewhere to hold them. Note that due to how they work, a shadow copy only uses the amount of space necessary to hold the changes made to the volume. When you view the shadow copy, you’ll see the complete volume as it was when the shadow copy was taken, but behind the scenes the space used by that shadow copy is not that of a complete copy of the volume at that point in time.

You can store your shadow copies on a different volume. This can be a good idea, as otherwise the volume free space can seem to mysteriously vanish. However, the shadow copy volume possibly needs to be the same size or larger than your data volume as it has to hold a copy of all the changed data blocks from the data volume, which depends on the rate of change and how often you create shadow copies. You might also want to read the article Designing a Shadow Copy Strategy, which is old but still relevant.

Configure VSS for a file server

I’m doing this on Windows Server 2008 R2, just because that’s what my test VM is running. This stuff works back as far as Server 2003 though (but of course you’re not still using that in 2016…).

My server has a 40GB D drive for data and I’ve added a 40GB V drive for VSS use. As this ia a VM, I’ve done both of these as thin provisioned disks from VMware.

I’m running all the commands from an administrator command prompt, which vssadmin requires. I’m using Windows ISO files for the data. There is currently no shadow storage configured, and the drives have been freshly formatted:

C:\>vssadmin list shadowstorage
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.

No items found that satisfy the query.

C:\>dir d: /a
 Volume in drive D is Data
 Volume Serial Number is 1863-3C01

 Directory of D:\

28/01/2016  12:29              $RECYCLE.BIN
28/01/2016  11:25              System Volume Information
               0 File(s)              0 bytes
               2 Dir(s)  42,851,102,720 bytes free

C:\>dir v: /a
 Volume in drive V is VSS
 Volume Serial Number is 7468-48AD

 Directory of V:\

28/01/2016  12:29              $RECYCLE.BIN
28/01/2016  11:24              System Volume Information
               0 File(s)              0 bytes
               2 Dir(s)  42,851,102,720 bytes free

So now we’ll configure V: to be the shadow storage for D:, and to use the entire V: drive for that purpose:

C:\>vssadmin add shadowstorage /for=d: /on=v: /maxsize=unbounded
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.

Successfully added the shadow copy storage association

Now we’ll copy some data onto D:, and then check the space usage on D: and V: again:

C:\>dir D: /a
 Volume in drive D is Data
 Volume Serial Number is 1863-3C01

 Directory of D:\

28/01/2016  12:29              $RECYCLE.BIN
28/01/2016  11:25              System Volume Information
28/02/2011  12:41     3,181,234,176 Windows 7 Enterprise x64 English SP1 (X17-27625).iso
28/02/2011  12:38     2,433,157,120 Windows 7 Enterprise x86 English SP1 (X17-27617).iso
               2 File(s)  5,614,391,296 bytes
               2 Dir(s)  37,236,707,328 bytes free

C:\>dir v: /a
 Volume in drive V is VSS
 Volume Serial Number is 7468-48AD

 Directory of V:\

28/01/2016  12:29              $RECYCLE.BIN
28/01/2016  11:24              System Volume Information
               0 File(s)              0 bytes
               2 Dir(s)  42,851,102,720 bytes free

As expected, there has not been any data used on V: yet.
Now let’s create a shadow copy of D:

C:\>vssadmin create shadow /for=d:
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.

Successfully created shadow copy for 'd:\'
    Shadow Copy ID: {bbec09d9-3ed2-40b0-943d-5b459976fb80}
    Shadow Copy Volume Name: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1

And we can see more detail about the shadow copy:

C:\>vssadmin list shadows
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.

Contents of shadow copy set ID: {2d629a37-10e0-4fb4-bf45-e0702de26f50}
   Contained 1 shadow copies at creation time: 28/01/2016 12:40:16
      Shadow Copy ID: {bbec09d9-3ed2-40b0-943d-5b459976fb80}
         Original Volume: (D:)\\?\Volume{cadd2f53-ba6b-11e5-93f2-005056a200aa}\
         Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1
         Originating Machine: VSSTEST.rcmtech.co.uk
         Service Machine: VSSTEST.rcmtech.co.uk
         Provider: 'Microsoft Software Shadow Copy provider 1.0'
         Type: ClientAccessible
         Attributes: Persistent, Client-accessible, No auto release, No writers, Differential

Now the space usage on V: is:

C:\>dir V: /a
 Volume in drive V is VSS
 Volume Serial Number is 7468-48AD

 Directory of V:\

28/01/2016  12:29              $RECYCLE.BIN
28/01/2016  12:40              System Volume Information
               0 File(s)              0 bytes
               2 Dir(s)  40,737,103,872 bytes free

So the space has dropped by about 2GB. VSS stores its data inside the System Volume Information folder, which by default only the local SYSTEM account has access to. So that we can see what’s going on, I’ve given myself access to this folder – but you shouldn’t normally mess with it.

C:\>dir "v:\System Volume Information" /a
 Volume in drive V is VSS
 Volume Serial Number is 7468-48AD

 Directory of v:\System Volume Information

28/01/2016  12:40              .
28/01/2016  12:40              ..
28/01/2016  11:24            20,480 tracking.log
28/01/2016  12:40            65,536 {3808876b-c176-4e48-b7ae-04046e6cc752}
28/01/2016  12:40     2,113,929,216 {db3a43f3-c5b1-11e5-88bc-005056a200aa}{3808876b-c176-4e48-b7ae-04046e6cc752}
               3 File(s)  2,114,015,232 bytes
               2 Dir(s)  40,737,103,872 bytes free

Note how the timestamp of the two files with GUIDs as their names matches when the shadow copy was taken. Note however that the GUIDs don’t match those reported via the vssadmin command…!
So let’s add some more files to the data drive. Clearly the free space drops on D:, but there are no changes to V: as we’ve not changed any blocks covered by our shadow copy:

C:\>dir d: /a
 Volume in drive D is Data
 Volume Serial Number is 1863-3C01

 Directory of D:\

28/01/2016  12:29              $RECYCLE.BIN
28/01/2016  12:40              System Volume Information
28/02/2011  12:41     3,181,234,176 Windows 7 Enterprise x64 English SP1 (X17-27625).iso
28/02/2011  12:38     2,433,157,120 Windows 7 Enterprise x86 English SP1 (X17-27617).iso
29/04/2014  10:34     3,234,070,528 Win_Ent_8.1_32BIT_English-Custom.ISO
24/04/2014  14:47     4,274,061,312 Win_Ent_8.1_64BIT_English-Custom.ISO
               4 File(s) 13,122,523,136 bytes
               2 Dir(s)  29,728,509,952 bytes free

C:\>dir v: /a
 Volume in drive V is VSS
 Volume Serial Number is 7468-48AD

 Directory of V:\

28/01/2016  12:29              $RECYCLE.BIN
28/01/2016  12:40              System Volume Information
               0 File(s)              0 bytes
               2 Dir(s)  40,737,103,872 bytes free

Let’s see how that changes if we take another shadow copy:

C:\>vssadmin create shadow /for=d:
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.

Successfully created shadow copy for 'd:\'
    Shadow Copy ID: {9f1f3eef-7e0d-4f55-ab72-3ed5ed2871cb}
    Shadow Copy Volume Name: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2

C:\>dir v: /a
 Volume in drive V is VSS
 Volume Serial Number is 7468-48AD

 Directory of V:\

28/01/2016  12:29              $RECYCLE.BIN
28/01/2016  12:40              System Volume Information
               0 File(s)              0 bytes
               2 Dir(s)  40,736,202,752 bytes free

No real change there, only a slight drop. What’s happened in the System Volume Information folder?

C:\>dir "v:\System Volume Information" /a
 Volume in drive V is VSS
 Volume Serial Number is 7468-48AD

 Directory of v:\System Volume Information

28/01/2016  12:52              .
28/01/2016  12:52              ..
28/01/2016  11:24            20,480 tracking.log
28/01/2016  12:40            65,536 {3808876b-c176-4e48-b7ae-04046e6cc752}
28/01/2016  12:52           901,120 {db3a43f3-c5b1-11e5-88bc-005056a200aa}{3808876b-c176-4e48-b7ae-04046e6cc752}
28/01/2016  12:52     2,113,929,216 {db3a4401-c5b1-11e5-88bc-005056a200aa}{3808876b-c176-4e48-b7ae-04046e6cc752}
               4 File(s)  2,114,916,352 bytes
               2 Dir(s)  40,736,202,752 bytes free

There’s a new small-ish file created when we took the last shadow copy, and the larger file has also been updated.
Now we’ll see how VSS handles some data drive changes. Let’s delete some of the files from D: and then copy some new ones onto it, and see how the free space on the two drives looks:

C:\>dir d: /a
 Volume in drive D is Data
 Volume Serial Number is 1863-3C01

 Directory of D:\

28/01/2016  12:29              $RECYCLE.BIN
13/08/2009  10:08     2,996,799,488 Server 2008 R2 x64 (X15-59754).iso
02/03/2011  14:41     3,166,720,000 Server 2008 R2 x64 SP1 (X17-22580).iso
28/01/2016  12:40              System Volume Information
29/04/2014  10:34     3,234,070,528 Win_Ent_8.1_32BIT_English-Custom.ISO
24/04/2014  14:47     4,274,061,312 Win_Ent_8.1_64BIT_English-Custom.ISO
               4 File(s) 13,671,651,328 bytes
               2 Dir(s)  29,179,383,808 bytes free

C:\>dir "v:\System Volume Information" /a
 Volume in drive V is VSS
 Volume Serial Number is 7468-48AD

 Directory of v:\System Volume Information

28/01/2016  12:52              .
28/01/2016  12:52              ..
28/01/2016  11:24            20,480 tracking.log
28/01/2016  12:40            65,536 {3808876b-c176-4e48-b7ae-04046e6cc752}
28/01/2016  12:52           901,120 {db3a43f3-c5b1-11e5-88bc-005056a200aa}{3808876b-c176-4e48-b7ae-04046e6cc752}
28/01/2016  12:59     3,523,215,360 {db3a4401-c5b1-11e5-88bc-005056a200aa}{3808876b-c176-4e48-b7ae-04046e6cc752}
               4 File(s)  3,524,202,496 bytes
               2 Dir(s)  39,326,916,608 bytes free

There were no changes when the two Windows 7 ISOs were deleted, but as you can see, the large file in V:\System Volume Information has grown quite a bit after the two new Windows Server 2008 R2 ISOs were added.
Whilst copying the new ISOs, I had Performance Monitor (perfmon) running to monitor disk reads and writes on D:, and disk writes on V:. The activity was interesting. As expected we have plenty of write activity to the data drive:data disk writes

There’s also quite a bit of read activity on the data disk:
data disk reads

Which corresponds to write activity on the VSS disk:
vss disk writes

So we can actually “see” VSS reading the blocks about to be overwritten on the data drive and writing them onto the VSS drive to preserve them for the shadow copies.

In order to access the data in the shadow copies, you can go via the GUI – just right-click the drive or a folder or file and select Properties – Previous Versions. This also works remotely if the drive or folder is shared.

previous versions

Alternatively, you can create a symbolic link to the shadow copy.

More about how VSS works

VSS operates at the block level, and uses a “copy on first write” principle to keep the data safe: when the blocks used on the data volume that are included in a shadow copy are about to be overwritten, it copies them to the shadow copy volume to enable the shadow copy of the data volume to remain intact.

Note that if you lose the data drive or the volume shadow copy drive, you will lose access to your shadow copies. Shadow copies are thus not a replacement for a proper backup regime, they instead complement it.

Also, if the data drive goes offline, but comes back online again, the GUI access to previous versions seems to break. The GUI just shows There are no previous versions available. The vssadmin command does still show the shadow copies though. To fix this, restart the Server service (aka lanmanserver).

VSS manages the space usage on the shadow copy volume by removing older shadow copies to make room for new ones as necessary. Note that many backup applications make use of VSS, and thus temporarily create shadow copies. These are then removed once the backup operation is finished, but can cause some/all of “your” shadow copies to be lost due to their temporary space usage. If the shadow copy volume is too small to hold a temporary shadow copy, the backup will fail.

Because VSS monitors changes at the block level (not the file level), disk defragmentation software can cause your shadow copies to be lost. The shadow copy volume watches all the block changes the the defrag has to do and thus might have to remove some/all of your shadow copies to keep track of those changes. Some defrag software, e.g. PerfectDisk, has a VSS compatibility setting to help with this. It is most problematic if your cluster size is less than 16KB, because this is the size that VSS uses internally and is thus unable to tell if the defrag IO is different to normal IO.

 

 

Posted in Security, Storage, Windows | Tagged , , , , , , , , , , , , , , , , , | Leave a comment

Restore malware-encrypted files from VSS snapshots

There have sadly been a few cases recently where a user has unwittingly run CryptoWall (or CryptoLocker, TeslaCrypt) on their PC and then encrypted a big chunk of one of my shared network drives. A nice quick way to get the files back is by using the VSS shadow copies of the volume.

This won’t usually work locally on your own PC as one of the things these crypto malwares tend to do is remove all shadow copies, but if your data is on a separate file server they can’t usually remove the shadow copies from that.

The first part is manual, PowerShell doesn’t have any VSS integration still as far as I can tell, and it’s not worth the hassle parsing the output of vssadmin – it’s much easier to do this bit by hand.

I suggest you do all this remotely via PowerShell remoting. As such I’ll be prefixing some of the commands with cmd /c as they only exist in that environment (or PowerShell’s default aliases make them do different things to how they work in the regular command prompt).

Steps to recovery

  1. Enter-PSSession -ComputerName FS01 -Credential (Get-Credential -UserName campus\rc-admin -Message “Gimme”)
    You may not need the -Credential bit, just depends if you’re running PowerShell as a user that has admin rights on the file server or not.
    Your PowerShell prompt prefix should change to show that you’re operating on a remote machine:
    [fs01]:
  2. vssadmin list shadows
    This will give you a list of all the shadow copies. You probably want the most recently created one before your files got encrypted. You’re looking for the “creation time” in the second line of each batch of text, the drive letter the shadow copy is for is shown in brackets in the “Original Volume” line, and then you need to make a note of the “Shadow Copy Volume” line as you need it in the next step but one.
    e.g.:
    Contents of shadow copy set ID: {a8c93c0b-a6c8-4ad9-ab3c-699b36f69915}
    Contained 1 shadow copies at creation time: 26/01/2016 07:00:16
    Shadow Copy ID: {8bc3ce53-831f-41e6-ad75-68384cb74bfb}
    Original Volume: (D:)\\?\Volume{0dac1ea6-f36f-4240-b4c6-a3e8f579ef44}\
    Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy67
    Originating Machine: FS01.rcmtech.co.uk
    Service Machine: FS01.rcmtech.co.uk
    Provider: ‘Microsoft Software Shadow Copy provider 1.0’
    Type: ClientAccessible
    Attributes: Persistent, Client-accessible, No auto release, No writers, Differential
  3. We’re going to create a symbolic link to the shadow copy, but first we’re going to create a folder to hold the link, to be tidy.
    md VSS
  4. Now create the symbolic link, note that you need to add a backslash to the end of the Shadow Copy Volume path you copied earlier:
    cmd /c mklink /d C:\VSS\67 \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy67\
    Note that with PowerShell 5.0 (half-out at the time of writing) you can now create a symbolic link using New-Item -ItemType SymbolicLink.
  5. Now you can edit the variables and then run the script below.
  6. Once you’ve finished, remove the symbolic link to the VSS shadow copy:
    cmd /c rd C:\VSS\67

PowerShell Script

The script searches the path specified for any encrypted files, these are identified by their encrypted file extension. The last lot of these I had were “.micro”. If your malware variant uses a different random file extension for each file it encrypts, you’ll have a nice coding challenge on your hands!

Once it has identified the encrypted files, it goes through each of them in turn and generates what the original filename would have been, and calculates the path to  the same file inside the volume shadow copy. It then copies the original file back, deletes the encrypted file, and once all that is done, runs through and deletes all the “how to get your files unencrypted” instruction files that the malware leaves all over the place.

Note that PowerShell cannot handle “long” filenames, over 260 characters, (why, still???). If you have any of these you might want to investigate using RoboCopy as it can deal with them, and has been able to for years (which makes the lack of support in PowerShell even more annoying).

# Before running this script:
# Use: vssadmin list shadows to find the latest unencrypted shadow copy - see the date & time they were created
# Record the Shadow Copy Volume, and use this to create a symbolic link:
# Create a folder to hold the symbolic link: md C:\VSS
# Then use: cmd /c mklink /d C:\VSS\67 \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy67\
# You need to add a trailing backslash to the Shadow Copy Volume name produced by vssadmin.
# Once done, remove the symbolic link by using: cmd /c rd C:\VSS\67

# This is the path on the file server that got encrypted:
$EncryptedPath = "D:\SharedFolder\Documents\Guidance\"
# This is the path to your shadow copy symbolic link:
$VSSPath = "C:\VSS\67\"
# File extension that the encrypted files have:
$Extension = ".micro"
# File name (minus extension) used for the "How to get your stuff unencrypted" files:
$RecoverFileFilter = "help_recover_instructions+ntl"

$FileList = Get-ChildItem -LiteralPath $EncryptedPath -Filter *$Extension -Recurse -Force
$TotalFiles = $FileList.Count
Write-Host ("Found "+$TotalFiles)
$Counter = 0
foreach($EncryptedFile in $FileList){
    $DestFileName = $EncryptedFile.FullName.Replace($Extension,"")
    $VSSFileName = $DestFileName.Replace("D:\",$VSSPath)
    try{
        # Use LiteralPath to prevent problems with paths containing special characters, e.g. square brackets
        Copy-Item -LiteralPath $VSSFileName -Destination $DestFileName -ErrorAction Stop
        Remove-Item -LiteralPath $EncryptedFile.FullName -Force
    }
    catch{
        $Error[0]
    }
    Write-Progress -Activity "Fixing" -Status $DestFileName -PercentComplete ($Counter/$TotalFiles*100)
    $Counter++
}
Write-Progress -Activity "Fixing" -Completed
Write-Host "Done recoverying files. Now cleaning up."

$RecoveryFileList = Get-ChildItem -LiteralPath $EncryptedPath -Filter *$RecoverFileFilter* -Recurse
foreach($RecoveryFile in $RecoveryFileList){
    try{
        Remove-Item -LiteralPath $RecoveryFile.FullName -force -ErrorAction Stop
    }
    catch{
        $Error[0]
    }
}

Have fun with it! ;-)

Posted in PowerShell | Tagged , , , , , , , , , , , , , , | 4 Comments

PowerShell script to get VMs and their datastores from an offline VMware ESXi host via vCenter

I recently had the local storage controller fail in one of my ESXi hosts. The host carried on running, and the VMs on it carried on running, but it wasn’t very happy. It was unresponsive via the vSphere client, and there was a good chance that it wouldn’t boot up once it was shutdown. I wasn’t able to vMotion the VMs off it – they’d get part way through and then fail after a while.

My recovery plan was as follows: Shut down all the VMs running on the failing host, remove the host (and thus all its VMs) from vSphere, browse to the VMs on their various datastores and re-add them onto the remaining hosts by double-clicking their .vmx files.

Which was all fairly straightforward except that I still have a LOT of legacy SAN datastores, and the VMs could be on any of them. So I wrote this script to interrogate vCenter and tell me where the VMs live on a particular host. This script does not talk to the host, so will work even if it is powered off. You will need to have VMware PowerCLI installed.

Connect-VIServer -Server vcenter.rcmtech.co.uk
$VMs = Get-VM
# Note that the hostname here needs to be written exactly as the host appears in the vSphere client
$VMHost = Get-VMHost -Name deadhost.rcmtech.co.uk
foreach($VM in $VMs){
    if($VM.VMHost -like "deadhost*"){
        $VM.Name,$VM.Harddisks
    }
}

Simple but effective – albeit slow, but PowerCLI seems to be painfully slow anyway.

Posted in PowerShell, vSphere | Tagged , , , , , , , , | Leave a comment