Find out what’s really happening in your network with LogRhythm NetMon Freemium

I recently discovered that LogRhythm, as well as very a full-featured Security Intelligence Platform and SIEM, also provide a “freemium” Network Monitor. The “freemium” refers to that fact that the software is 100% free, full-featured and not time-limited, but is capacity-limited. Those limits are 1Gbps of network bandwith and three days of history.

Those limits are fine for if you don’t already have anything like this currently running in your network, and depending on what kind of stuff you pump over your network, for the average small office they’ll be fine and give you some great insights into what’s going on.

Setup

The hardware requirements state that the system should have a minimum of 8GB RAM (12GB recommended), 4 CPU cores (minimum of 2), and unless you just want to monitor traffic from the NetMon box itself you’ll need two NICs.

NetMon freemium is available to download either as a VirtualBox VM, or as an ISO image. I chose the ISO option as I had an old Dell PowerEdge 2950 lying around so decided to run the software on that. I tried using Rufus but could not get it to boot properly, so I gave up and burnt the ISO onto a DVD.

I’d recommend plugging one of your two NICs into a network with DHCP enabled, and leave the other one disconnected initially. NetMon is based upon CentOS 7, and installation is really straightforward.

Once installed, you’ll be given a logon prompt. Log in as logrhythm with a password of changeme. Use the command:
ip address
to see what IP address has been obtained from DHCP – look for the line beginning inet in a section with eth near the beginning, e.g. 2: eth0. If DHCP didn’t work, reboot to get it to try again. Then from a web browser, open https://<ip address> and you’ll get a LogRhythm sign in page. (If you get a pop-up authentication box, just click Cancel on it, I’m not sure why this sometimes appears). The web-based credentials default to a username of admin and a password of changeme. Change the password.

Now connect the second NIC to your switch. From the NetMon GUI, go to Configuration – Engine, and set the Input Interface. This should be set to one of the options starting netmap, I only had one: netmap:eno2 so I picked this. Click Apply Changes then go to Diagnostics – Interface and start to watch the Packet Rate graph, this updates every few seconds so you can see the data start to arrive once you’ve done the network configuration on your switch.

I’ve configured the switch port to be in Switched Port ANalyser mode (SPAN), which is a way of sending all the traffic from one port or more ports or VLANs to another port. My office PCs are all on a particular VLAN so I’ve chosen to send all this traffic to my SPAN port. On a Cisco switch you do this by creating a monitor session. You can have multiple ones of these, and you may already have some set up, so first check what you have:

en
sh run | inc monitor

and you may be shown some lines such as:

monitor session 1 source interface Gi1/0/2 , Gi1/0/4
monitor session 1 destination interface Gi1/0/46

This means that in order to create a new monitor session, I have to use session 2, as session 1 is already in use. NIC2 of my server is plugged into port Gi1/0/47, and aside from a description, there is no other configuration on this switch port. To send all VLAN10 traffic to this port I used the commands:

conf t
monitor session 2 source vlan 10 both
monitor session 2 destination interface g1/0/47

At this point I saw the Received line jump up from zero in the Packet Rate graph, so I knew the command had worked and NetMon was receiving data.

Analyse your data

So now you’re getting data, and by clicking on the LogRhythm logo you’ll be taken to the dashboard, by default showing you:

  • Top Applications by Bandwidth (histogram)
  • Top Applications by Bandwidth (pie)
  • Top Applications by Packet Count (pie)
  • Analyze table

This gives a good overview of what’s happening right now on your network. You can click into the pie chart sections to filter data immediately, or click onto a section of the histogram to build a filter that sets the protocol and time range to give you more detail. For example, what’s all that smb traffic at 11:43? Click the pale blue section of the bar, click Apply Now and I get the timeline broken down into five second slots, and the Analyze Table lets me go through the sessions and see what was talking to what. I can see more information by clicking the “up” arrow just underneath the histogram, this gives me a table which shows the amount of data sent by the selected protocol per second:

Click on the date on one of these rows, e.g. the one where 72.326MB was transferred, and it’ll filter again to that time but at 100ms granularity. I now only have one entry in the Analyze Table at the bottom, and can not only see the source and destination IP addresses (sadly it doesn’t convert these into DNS names). By expanding the line in the Analyze Table, I can see lots of info, most interestingly (because this is the SMB protocol) a list of all the filenames accessed. In my case, I can now see that this traffic was caused by a machine doing a full Active Directory Group Policy refresh, which is perfectly normal.

Over to you

I’ve found this product to be pretty good, it’s giving me insight into something that I had no visibility of until now, and I suspect most people would find the same. There are a lot more features that I’ve not looked at yet, such as alarms, customising dashboards, charts and tables.

There are some videos showing how to use NetMon on LogRhythm’s YouTube channel, and there’s also a community site you can sign up to for free for more resources and to ask for help. All in all, NetMon Freemium is going to be a nice additional tool for keeping an eye on my systems and data.

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

PowerShell Transcription to a file share breaks everything, and how to fix it

There’s been a bit of noise about PowerShell-based malware recently, and given the “assume breach” security mindset, I thought it was about time I enabled some of the PowerShell logging features in Windows. The basis behind “assume breach” is that you assume that your network security has already been breached and there are unauthorised things going on in your environment. The trick is to put in place suitable logging and monitoring to be able to detect and trace that activity.

The definitive source for PowerShell security config seems to still be the PowerShell (heart) the Blue Team blog post from mid-2015. This gives a lot of good info about what security features are available in PowerShell 5.0 and how to enable them in a sensible way. Most of them can be configured by Group Policy, e.g. transcription is enabled and configured via “Turn on PowerShell Transcription” in Windows Components – Administrative Templates – Windows PowerShell.

Based on that, and other things I’d read, PowerShell transcription to a network share seemed like exactly what I should have turned on. It gives you a detailed text log of everything that occurs in a PowerShell session, logged to an off-the-box location. Very handy.

So I turned it on.

And lots of things broke.

Enter-PSSession : Processing data from remote server ServerA failed with the following error message:
Could not find a part of the path '\\ServerB.rcmtech.co.uk\PowerShellTranscript$'. For more information, see the
about_Remote_Troubleshooting Help topic.
At line:1 char:1
+ enter-pssession -ComputerName ServerA
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (Server01:String) [Enter-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : CreateRemoteRunspaceFailed

The problem seems to be with how I admin my servers (remotely, not on the console) and how the transcription feature works.

The root of my problems seem to be Kerberos double-hop authentication.

Consider how you might have done similar things in the past:

  • From your PC, remote desktop onto ServerA, access a share on ServerB. No problems.
  • From your PC, run PSExec to get a remote command prompt on ServerA, access a share on ServerB. No problems.
  • Set the logging folder of a service running as NT Authority\System on ServerA to write to a UNC path on ServerB, having granted the account ServerA$ permission to the share and granted NTFS permissions to the folder. No problems.
  • Forwarded Windows Event Logs from ServerA to ServerB, and noticed how details of people interacting with ServerA appeared in Forwarded Events on ServerB. No problems.

So why is PowerShell transcription different? The transcription is done by delegation of the credentials from my PC by ServerA and using those to try to access the share on ServerB. This won’t work: assume I’m running PowerShell as an admin on my PC (OK, not best practice, but fixing that is going to take a long time) and that I then run the following command:

Invoke-Command -ComputerName ServerA -ScriptBlock {Get-ChildItem -Path \\ServerB\c$}

This will fail with an Access is Denied (PermissionDenied) error.

There are various ways to make the double-hop work. As far as I can tell, the best balance of security and ease of use is to use Resource-Based Kerberos Constrained Delegation.

This works by configuring the Active Directory computer object of ServerB to allow it to accept delegated credentials via ServerA:

Set-ADComputer -Identity ServerB -PrincipalsAllowedToDelegateToAccount (Get-ADComputer -Identity ServerA)

Possibly followed by running the following on ServerA:

klist purge -li 0x3e7

but only if you’d tried and failed to use delegated credentials from ServerA in the past 15 minutes. If you’d not tried to do that, the klist command is unecessary.

Also, annoyingly, this method will not allow you to enter a remote session from your PC to ServerA and then create a remote session from ServerA to ServerB. Resource-based Kerberos constrained delegation does not support WinRM, you’ll get a 0x8009030e error (a specified logon session does not exist).

So if you want all your servers to send their PowerShell transcripts to ServerB, you need to add all your servers to the list of PrincipalsAllowedToDelegateToAccount for ServerB, and keep adding new servers to that list as they are created. Pain in the neck.

How I’d like transcription to work is that the transcripts are written by the computer account where the PowerShell is being executed. I would have thought that this was possible, because the computer account is the NT Authority\System account, and that is as powerful and privileged an account as you can get in Windows. That way I would just configure the transcripts file share to have write access for the Domain Computers group, and everything would be well with the world.

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

Collect user and group SIDs and names from Active Directory

Ever found yourself looking through the Access Control List of a file/folder/share and mixed in along with the group names (hopefully not user names!) you see some SIDs? These look something like S-1-5-21-0123456789-0123456789-0123456789-0123.
These are the Security IDs of deleted groups and users. Wouldn’t it be handy to have a list of these so you could work out what it was that used to have permission, but that’s now been deleted? Yes it would, so I wrote a basic PowerShell script to collect all the SIDs and user names and store them in an XML file. It also has a field for whather the item is a user or a group, and also the date and time the item was added.
You can run the script as a regular user, but will need to AD PowerShell cmdlets installed (possibly via RSAT if on a client OS).

$XMLFile = "C:\Users\Public\Documents\UsersAndGroups.xml"
# Get users and groups from AD
$ADUsers = Get-ADUser -Filter * | Select-Object -Property Name,SID
$ADGroups = Get-ADGroup -Filter * | Select-Object -Property Name,SID
# Create an array to store AD users and groups
$UsersAndGroups = New-Object -TypeName System.Collections.ArrayList
# Add users to array
foreach($User in $ADUsers){
    $ThisUser = New-Object -TypeName System.Object
    Add-Member -InputObject $ThisUser -MemberType NoteProperty -Name SID -Value $User.SID.Value
    Add-Member -InputObject $ThisUser -MemberType NoteProperty -Name Name -Value $User.Name
    Add-Member -InputObject $ThisUser -MemberType NoteProperty -Name Type -Value "User"
    Add-Member -InputObject $ThisUser -MemberType NoteProperty -Name DateAdded -Value (Get-Date -Format s)
    $UsersAndGroups.Add($ThisUser) | Out-Null
}
# Add groups to array
foreach($Group in $ADGroups){
    $ThisGroup = New-Object -TypeName System.Object
    Add-Member -InputObject $ThisGroup -MemberType NoteProperty -Name SID -Value $Group.SID.Value
    Add-Member -InputObject $ThisGroup -MemberType NoteProperty -Name Name -Value $Group.Name
    Add-Member -InputObject $ThisGroup -MemberType NoteProperty -Name Type -Value "Group"
    Add-Member -InputObject $ThisGroup -MemberType NoteProperty -Name DateAdded -Value (Get-Date -Format s)
    $UsersAndGroups.Add($ThisGroup) | Out-Null
}
$UsersAndGroups.Count
# Get existing data if it already exists
if(Test-Path -Path $XMLFile){
    $XMLData = Import-Clixml -Path $XMLFile
    $XMLDataArrayList = New-Object -TypeName System.Collections.ArrayList
    $XMLDataArrayList.AddRange($XMLData)
    $XMLDataArrayList.Count
    # Update existing data with new SIDs
    foreach($Item in $UsersAndGroups){
        if($XMLData.SID -contains $Item.SID){
            #Write-Host $Item.SID -ForegroundColor Green
        }else{
            Write-Host $Item.SID -ForegroundColor Red
            $XMLDataArrayList.Add($Item) | Out-Null
        }
    }
    # Write updated data back to XML file
    $XMLDataArrayList | Export-Clixml -Path $XMLFile
}else{
    # Write first time data to XML file
    $UsersAndGroups | Export-Clixml -Path $XMLFile
}

To view the file, and be able to easily search it, just use:

Import-Clixml -Path "C:\Users\Public\Documents\UsersAndGroups.xml" | Out-GridView
Posted in PowerShell, Security, Windows | Tagged , , , , , , | Leave a comment

PowerShell Exchange mailbox move progress monitor

This is a very basic script that’ll give you a progress bar to monitor a mailbox move process. You’ll need to run it from an Exchange Management Shell PowerShell prompt.

param([string]$Identity = "")
$Stats = Get-MoveRequestStatistics -Identity $Identity
do
{
    $Stats = Get-MoveRequestStatistics -Identity $Identity
    Write-Progress -Activity "Moving $Identity" -Status ([string]$Stats.BytesTransferred+" transferred of "+[string]$Stats.TotalMailboxSize) -PercentComplete $Stats.PercentComplete
    Start-Sleep -Milliseconds 500
}
while (($Stats.PercentComplete -le 99) -and ($Stats.Status -eq "InProgress"))
do
{
    $Stats = Get-MoveRequestStatistics -Identity $Identity
    Write-Progress -Activity "Moving $Identity" -Status $Stats.Status -PercentComplete 100
    Start-Sleep -Milliseconds 500
}
while ($Stats.StatusDetail -ne "Completed")
$Stats.StatusDetail
Posted in Exchange, PowerShell | Tagged , , , , , , , | Leave a comment

Change BitLocker Recovery Password with PowerShell

When BitLocker detects certain changes to the computer it’ll trigger Recovery Mode, and prompt for the Recovery Password. Likewise, you also need the recovery password if you need to access the encrypted disk from another machine or via Windows Recovery Environment (Windows RE).

If you need to provide your users with their BitLocker recovery password, you might want to change it afterwards. It allows them to get into the disk via alternative methods and thus bypass NTFS security. This is a bad thing.

If you have BitLocker set up right, it’ll write any new recovery passwords that it generates to Active Directory. Therefore the script (which you might want to run as a scheduled task, even if only on demand) does not display the new recovery password to screen. You can easily modify it to show the password by removing “-WarningAction SilentlyContinue”.

$MountPoint = "C:"
# Register the event log source
$LogSource = "RCMTech"
New-EventLog -LogName Application -Source $LogSource -ErrorAction SilentlyContinue
# Get the key protectors
$KeyProtectors = (Get-BitLockerVolume -MountPoint $MountPoint).KeyProtector
foreach($KeyProtector in $KeyProtectors){
    if($KeyProtector.KeyProtectorType -eq "RecoveryPassword"){
        try{
            # Remove then re-add the RecoveryPassword protector
            Remove-BitLockerKeyProtector -MountPoint $MountPoint -KeyProtectorId $KeyProtector.KeyProtectorId | Out-Null
            # Assuming BitLocker is configured properly, the recovery password will be stored in Active Directory, don't display it on screen
            Add-BitLockerKeyProtector -MountPoint $MountPoint -RecoveryPasswordProtector -WarningAction SilentlyContinue | Out-Null
            # If we get this far, eveything has worked, write a success to the event log
            Write-EventLog -LogName Application -Source $LogSource -EntryType Information -EventId 1000 -Message "BitLocker Recovery Password for $MountPoint has been changed"
            Write-Host "Successfully changed BitLocker Recover Password" -ForegroundColor Green
        }
        catch{
            # Something went wrong, display the error details and write an error to the event log
            $Error[0]
            Write-EventLog -LogName Application -Source $LogSource -EntryType Warning -EventId 1001 -Message "Failed to change Bitlocker Recovery Password for $MountPoint"
        }
    }
}
Posted in PowerShell, Security, Windows | Tagged , , , , , , , , , | 1 Comment

Get or update SysInternals tools with PowerShell

This is version 2 – the previous version relied on mapping a new PSDrive directly to \\live.sysinternals.com\tools which made things easy, but that no longer seems to work (or at least not for me, might be my web filtering blocking it).

So as an alternative, here is one that pulls the files directly via HTTPS by parsing the listing from http://live.sysinternals.com/tools

$SysIntFolder = "C:\sysint"
$Page = (Invoke-WebRequest -Uri "https://live.sysinternals.com/tools").Content
$MatchedItems = ([regex]"<A HREF.*?<\/A>").Matches($Page)
$ItemCount = $MatchedItems.Count
$Copied = 0
foreach($Match in $MatchedItems.Value){
    
    if($Match -match ">(.*?\..*?)<"){
        $Matches[1]
        Write-Progress -Activity "Update SysInt" -Status $Matches[1] -PercentComplete ($Copied / $ItemCount * 100)
        Invoke-WebRequest -Uri ("https://live.sysinternals.com/tools/" + $Matches[1]) -OutFile (Join-Path -Path $SysIntFolder -ChildPath $Matches[1])
    }
    $Copied++

}
Write-Progress -Activity "Update SysInt" -Completed
Posted in PowerShell, Windows | Tagged , , , , , , | Leave a comment

Network List Manager in PowerShell

I’m writing a network diagnostic script, and wanted to use the network status and connectivity information that’s already been captured by the Network List Manager (NLM).

The code for pulling various bits of info is below. NLM_Connectivity was a good opportunity to learn how to work with enumeration of flags, so I’ve included several examples of working with these, to both list all the active connectivity types, and also ways to check for a specific connectivity type.

$NetworkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID(‘DCB00C01-570F-4A9B-8D69-199FDBA5723B’))

# Set enums for GetNetworks
$NLM_ENUM_NETWORK_CONNECTED=1
$NLM_ENUM_NETWORK_DISCONNECTED=2
$NLM_ENUM_NETWORK_ALL=3

$Networks = $NetworkListManager.GetNetworks($NLM_ENUM_NETWORK_CONNECTED)

foreach($Network in $Networks){
# Network name
$Network.GetName()

# Values from INetworkListManager interface https://msdn.microsoft.com/en-us/library/windows/desktop/aa370769(v=vs.85).aspx

# Network category
$NetCategories = New-Object -TypeName System.Collections.Hashtable
$NetCategories.Add(0x00,"NLM_NETWORK_CATEGORY_PUBLIC")
$NetCategories.Add(0x01,"NLM_NETWORK_CATEGORY_PRIVATE")
$NetCategories.Add(0x02,"NLM_NETWORK_CATEGORY_DOMAIN_AUTHENTICATED")
$NetCategories.Get_Item($Network.GetCategory())

# Domain type
$DomainTypes = New-Object -TypeName System.Collections.Hashtable
$DomainTypes.Add(0x00,"NLM_DOMAIN_TYPE_NON_DOMAIN_NETWORK")
$DomainTypes.Add(0x01,"NLM_DOMAIN_TYPE_DOMAIN_NETWORK")
$DomainTypes.Add(0x02,"NLM_DOMAIN_TYPE_DOMAIN_AUTHENTICATED")
$DomainTypes.Get_Item($Network.GetDomainType())

# NLM Connectivity
$NLMConnectivity = New-Object -TypeName System.Collections.Hashtable
$NLMConnectivity.Add(0x0000,"NLM_CONNECTIVITY_DISCONNECTED")
$NLMConnectivity.Add(0x0001,"NLM_CONNECTIVITY_IPV4_NOTRAFFIC")
$NLMConnectivity.Add(0x0002,"NLM_CONNECTIVITY_IPV6_NOTRAFFIC")
$NLMConnectivity.Add(0x0010,"NLM_CONNECTIVITY_IPV4_SUBNET")
$NLMConnectivity.Add(0x0020,"NLM_CONNECTIVITY_IPV4_LOCALNETWORK")
$NLMConnectivity.Add(0x0040,"NLM_CONNECTIVITY_IPV4_INTERNET")
$NLMConnectivity.Add(0x0100,"NLM_CONNECTIVITY_IPV6_SUBNET")
$NLMConnectivity.Add(0x0200,"NLM_CONNECTIVITY_IPV6_LOCALNETWORK")
$NLMConnectivity.Add(0x0400,"NLM_CONNECTIVITY_IPV6_INTERNET")

# Several methods for working with the connectivity flags

# Display all active connectivity types (method a)
foreach($Key in $NLMConnectivity.Keys){
$KeyBand = $Key -band $net.GetConnectivity()
if($KeyBand -gt 0){
$NLMConnectivity.Get_Item($KeyBand)
}
}

# Display all active connectivity types (method b)
$NLMConnectivity.Keys | Where-Object {$_ -band $Network.GetConnectivity()} | ForEach-Object {$NLMConnectivity.Get_Item($_)}

# Display all active connectivity types (method c)
switch ($Network.GetConnectivity()){
{$_ -band 0x0000}{"NLM_CONNECTIVITY_DISCONNECTED"}
{$_ -band 0x0001}{"NLM_CONNECTIVITY_IPV4_NOTRAFFIC"}
{$_ -band 0x0002}{"NLM_CONNECTIVITY_IPV6_NOTRAFFIC"}
{$_ -band 0x0010}{"NLM_CONNECTIVITY_IPV4_SUBNET"}
{$_ -band 0x0020}{"NLM_CONNECTIVITY_IPV4_LOCALNETWORK"}
{$_ -band 0x0040}{"NLM_CONNECTIVITY_IPV4_INTERNET"}
{$_ -band 0x0100}{"NLM_CONNECTIVITY_IPV6_SUBNET"}
{$_ -band 0x0200}{"NLM_CONNECTIVITY_IPV6_LOCALNETWORK"}
{$_ -band 0x0400}{"NLM_CONNECTIVITY_IPV6_INTERNET"}
}

# Display all active connectivity types (method d)
Enum NLM_CONNECTIVITY {
NLM_CONNECTIVITY_DISCONNECTED = 0x0000
NLM_CONNECTIVITY_IPV4_NOTRAFFIC = 0x0001
NLM_CONNECTIVITY_IPV6_NOTRAFFIC = 0x0002
NLM_CONNECTIVITY_IPV4_SUBNET = 0x0010
NLM_CONNECTIVITY_IPV4_LOCALNETWORK = 0x0020
NLM_CONNECTIVITY_IPV4_INTERNET = 0x0040
NLM_CONNECTIVITY_IPV6_SUBNET = 0x0100
NLM_CONNECTIVITY_IPV6_LOCALNETWORK = 0x0200
NLM_CONNECTIVITY_IPV6_INTERNET = 0x0400
}
[enum]::GetValues([NLM_CONNECTIVITY]) | Where-Object {$_.value__ -band $Network.GetConnectivity()}

# Check for a particular type of connectivity (method a)
if(0x0040 -band $Network.GetConnectivity()){Write-Host "NLM_CONNECTIVITY_IPV4_INTERNET is active"}

# Check for a particular type of connectivity (method b)
$NLMConnectivityActiveFlags = $NLMConnectivity.Keys | Where-Object {$_ -band $Network.GetConnectivity()} | ForEach-Object {$NLMConnectivity.Get_Item($_)}
if($NLMConnectivityActiveFlags.Contains("NLM_CONNECTIVITY_IPV4_SUBNET")){Write-Host "NLM_CONNECTIVITY_IPV4_SUBNET is active"}
}

Posted in PowerShell | Tagged , , , , , , , , , | 1 Comment

Group Policy Preference Drive Maps closing

I’ve been dealing with an issue where users that leave Windows File Explorer windows open for extended periods find that they close now and then.

This seems to be a common problem with later versions of Windows (8.1, 10) and is caused by the Replace setting being used on the Group Policy Preference Drive Map.

The File Explorer windows close because Replace causes the drive map to be removed and re-added. You want to use Replace because you also want to use the option to Remove this item when it is no longer applied. And also because Update will not change a drive mapping that has been done manually by a user.

Part of the fix is to set the following group policy:

Computer Configuration/Administrative Templates/System/Group Policy/Configure Drive Maps preference extension policy processing
Enabled:
Allow processing across a slow network connection: Enabled
Process even if the Group Policy objects have not changed: Disabled
Background priority: Idle

The key setting being Process even if the Group Policy objects have not changed, set to Disabled.

This will stop File Explorer closing on every group policy refresh.

This is only part of the solution though. You might think that this would cause the drive maps preference to only be processed if a drive map preference within the GPO has changed. That would seem sensible, right? Well, no. If you have other stuff in the GPO, and any of that changes, the drive maps will still be processed (i.e. removed and re-added) even though they’ve not changed.

You can see this by looking in Event Viewer, in the Microsoft-Windows-GroupPolicy/Operational log, and information event 4016. The text will say:

Starting Group Policy Drive Maps Extension Processing. 

List of applicable Group Policy objects: (Changes were detected.)

Your GPO Name

So what I’ve now done is to move my GP Pref drive mappings into a dedicated GPO, which I’ll hardly ever have to change. Thus the group policy engine will hardly ever detect any changes, and thus users will hardly ever see their File Explorer windows closing.

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

Don’t display last username if C drive encrypted with BitLocker

I’m moving from encrypting laptops with a third party disk encryption product to BitLocker. The third party product uses a pre-boot username & password prompt, and only boots into Windows if the credentials are correct. Users then have to log on to Windows using the Active Directory credentials. The last username is remembered so they just type in their AD password and the desktop loads.

With BitLocker I’m using the Trusted Platform Module (TPM) in the laptops to tie the disk to the laptop, rather than giving users and extra set of credentials to remember. When they turn on, BitLocker checks the TPM and the laptop hardware for changes, and if all is normal Windows will boot and present the user with the logon screen. However, currently this means that a lost or stolen laptop will boot and display the name of the last user, which I don’t want. If the username isn’t displayed, there are now two pieces of information required to get past the Windows Logon screen.

I’ve achieved this using a Group Policy Preference, targeted with a WMI query. The GPPref sets the dontdisplaylastusername policy registry value if the C: drive is encrypted, or removes the value if the drive is not encrypted – i.e. during the transition phase, users with the old disk encryption won’t be forced to type in their AD username at the Windows logon screen, they’ll still be remembered from their previous logon.

The configuration is as follows:
Computer Configuration – Preferences – Windows Settings – Registry
General tab:

Action: Replace
Hive: HKEY_LOCAL_MACHINE
Key Path: SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system
Value: dontdisplaylastusername
Value type: REG_DWORD
Value Data: 00000001

Common tab:

Remove this item when it is no longer applied: ticked
Item-level targeting: ticked

Targeting…:
WMI query:

Query: select IsVolumeInitializedForProtection from Win32_EncryptableVolume where DriveLetter = 'C:' and IsVolumeInitializedForProtection = True
Namespace: root\CIMv2\Security\MicrosoftVolumeEncryption
Property: IsVolumeInitializedForProtection
Posted in Security, Storage, Windows | Tagged , , , , | Leave a comment

PowerShell: BitLocker Encryption Progress Bar

When enabling Bitlocker I want to know how far through the process of encrypting the drive it has got.

The script gets the encryption status from the manage-bde.exe command, parses it using a regular expression to get the percent complete, and goes into a loop updating a progress bar until the progress gets to 100%. Then the script quits.

Here’s the script:

function Get-BDEPercent{
    $BDEStatus = & manage-bde.exe -status c:
    $BDEStatus = $BDEStatus -join " "
    $Matches = $null
    $BDEStatus -match '\:\s([\d]{2,})\.\d\%' | Out-Null
    $Matches[1]
}

$Loop = $true

while($Loop){
    [int]$PercentComplete = Get-BDEPercent
    if($PercentComplete -ne 100){
        Write-Progress -Activity "Bitlocker Drive Encryption Status" -Status "Encrypting" -PercentComplete $PercentComplete
        Start-Sleep -Seconds 5
    }else{
        Write-Progress -Activity "Bitlocker Drive Encryption Status" -Completed
        $Loop = $false
    }
}
Posted in PowerShell, Storage, Windows | Tagged , , , , , , , , | Leave a comment