# Check if password is set
Get-WmiObject -Namespace root/hp/InstrumentedBIOS -Class HP_BIOSSetting | Where-Object Name -eq "Setup Password").IsSet
# Set password
(Get-WmiObject -Namespace root/hp/InstrumentedBIOS -Class HP_BIOSSettingInterface).SetBIOSSetting("Setup Password","<utf-16/>" + "NewPassword","<utf-16/>")
# Change password
(Get-WmiObject -Namespace root/hp/InstrumentedBIOS -Class HP_BIOSSettingInterface).SetBIOSSetting("Setup Password","<utf-16/>" + "NewPassword","<utf-16/>" + "OldPassword")
# Clear password
(Get-WmiObject -Namespace root/hp/InstrumentedBIOS -Class HP_BIOSSettingInterface).SetBIOSSetting("Setup Password","<utf-16/>","<utf-16/>" + "OldPassword")
Thursday, December 5, 2019
CI to Check HP BIOS settings
# Check-BIOSSetting.ps1
# by Mark Randol - randoltech.blogspot.com
# Checks the setting for the BIOS item in $BIOSItem
# Against the desired state in $DesiredValue
# If good returns the exact text in $DesiredValue
# If bad returns the string from BIOS
# If item is not found retruns $BIOSItem not found in BIOS settings.
# If script properly runs but is indeterminent then returns Error (should never happen)
$BIOSItem = "Boot Mode"
$DesiredValue = "*UEFI Native (Without CSM)"
$OutputString = "Error"
$ItemValue = (Get-WmiObject -Namespace root\HP\InstrumentedBIOS -Class HP_BIOSEnumeration | Where-Object Name -eq $BIOSItem).Value
if ($ItemValue) {
$CheckString = (($DesiredValue.Replace("*","\*")).Replace("(","\(")).Replace(")","\)")
if ($ItemValue -match $CheckString) {
$OutputString = $DesiredValue
}
else {
$OutputString = $ItemValue
}
}
else {
$OutputString = "$BIOSItem not found in BIOS settings."
}
Write-Output $OutputString
----------------------------------
Remediation Script:
(Get-WmiObject -Namespace root\HP\InstrumentedBIOS -Class HP_BIOSSettingInterface).SetBIOSSetting("TPM Device","Available","<utf-16/>" + "YourBIOSPasswordHere")
# by Mark Randol - randoltech.blogspot.com
# Checks the setting for the BIOS item in $BIOSItem
# Against the desired state in $DesiredValue
# If good returns the exact text in $DesiredValue
# If bad returns the string from BIOS
# If item is not found retruns $BIOSItem not found in BIOS settings.
# If script properly runs but is indeterminent then returns Error (should never happen)
$BIOSItem = "Boot Mode"
$DesiredValue = "*UEFI Native (Without CSM)"
$OutputString = "Error"
$ItemValue = (Get-WmiObject -Namespace root\HP\InstrumentedBIOS -Class HP_BIOSEnumeration | Where-Object Name -eq $BIOSItem).Value
if ($ItemValue) {
$CheckString = (($DesiredValue.Replace("*","\*")).Replace("(","\(")).Replace(")","\)")
if ($ItemValue -match $CheckString) {
$OutputString = $DesiredValue
}
else {
$OutputString = $ItemValue
}
}
else {
$OutputString = "$BIOSItem not found in BIOS settings."
}
Write-Output $OutputString
----------------------------------
Remediation Script:
(Get-WmiObject -Namespace root\HP\InstrumentedBIOS -Class HP_BIOSSettingInterface).SetBIOSSetting("TPM Device","Available","<utf-16/>" + "YourBIOSPasswordHere")
Thursday, November 21, 2019
Extracting Microsoft Surface Drivers
For the Surface Pro 6 I ended up downloading four .msi files and needed to extract them to get the drivers for import into SCCM. I wrote this little PowerShell script to iterate through all four and extract them for me complete with logs in case anything went wrong. Figured I would post it here in case anyone else finds it useful.
#Extract-MSIFiles.PS1
#Creates folders for each .msi and extracts contents into the folders
#By Mark Randol - randoltech.blogspot.com
$BasePath = "C:\Users\me\Downloads\Drivers\Surface Pro 6 1796 Commercial"
Start-Transcript -Path "$BasePath\Extract-MSIFiles.log" -Force
$SearchPath = $BasePath + "\*"
$MSIFiles = Get-ChildItem $SearchPath -Include *.msi
foreach ($File in $MSIFiles) {
$FileName = $File.Name
New-Item -Path "$BasePath" -Name $File.BaseName -ItemType "Directory"
$ExtractFolder = $BasePath + "\" + $File.BaseName
$ArguementString = "/a ""$BasePath" + "\" + "$Filename"" targetdir=""$ExtractFolder"" /l*v ""$BasePath\$FileName.log"" /qn"
Start-Process -FilePath "msiexec.exe" -ArgumentList $ArguementString
Wait-Process -Name msiexec -Timeout 90
}
Stop-Transcript
-Enjoy
#Extract-MSIFiles.PS1
#Creates folders for each .msi and extracts contents into the folders
#By Mark Randol - randoltech.blogspot.com
$BasePath = "C:\Users\me\Downloads\Drivers\Surface Pro 6 1796 Commercial"
Start-Transcript -Path "$BasePath\Extract-MSIFiles.log" -Force
$SearchPath = $BasePath + "\*"
$MSIFiles = Get-ChildItem $SearchPath -Include *.msi
foreach ($File in $MSIFiles) {
$FileName = $File.Name
New-Item -Path "$BasePath" -Name $File.BaseName -ItemType "Directory"
$ExtractFolder = $BasePath + "\" + $File.BaseName
$ArguementString = "/a ""$BasePath" + "\" + "$Filename"" targetdir=""$ExtractFolder"" /l*v ""$BasePath\$FileName.log"" /qn"
Start-Process -FilePath "msiexec.exe" -ArgumentList $ArguementString
Wait-Process -Name msiexec -Timeout 90
}
Stop-Transcript
-Enjoy
Wednesday, November 6, 2019
Detection Method for an APPX package
None of the standard SCCM application detection methods work for APPX packages. For an APPX package use "Use a custom script to detect the presence of this deployment type" and this command line as the script (modify for the package name and version number that you need obviously):
if ([version]((Get-AppxPackage *AppUp.ThunderboltControlCenter*).Version) -ge ([version]("1.41.648.5"))) { write-output $true }
Enjoy!
if ([version]((Get-AppxPackage *AppUp.ThunderboltControlCenter*).Version) -ge ([version]("1.41.648.5"))) { write-output $true }
Enjoy!
Tuesday, October 1, 2019
A little script to back up your BitLocker keys to Active Directory
If you are using Azure AD then change Backup-BitLockerKeyProtector to BackupToAAD-BitLockerKeyProtector
# Backup-BitlockerKeys.ps1
# by Mark Randol
# randoltech.blogspot.com
# This script iterates through all of your possibly encryptable drives
# and if they are encrypted, backs up the keys to Active Directory.
$PossibleDrives = Get-BitLockerVolume
foreach ($Drive in $PossibleDrives)
{
$DriveLetter = $Drive.MountPoint
$Protectors = ((Get-BitLockerVolume -MountPoint $DriveLetter).KeyProtector)
foreach ($Protectors in $Protectors) {
$ProtectorID = $Protector.KeyProtectorId
$ProtectorType = $Protector.KeyProtectorType
if ($ProtectorType -eq "RecoveryPassword") {
Backup-BitLockerKeyProtector -MountPoint $DriveLetter -KeyProtectorId $ProtectorID -Verbose
}
}
}
Wednesday, September 11, 2019
ThunderBolt Security Configuration Item for SCCM
This comes out of a need to secure ThunderBolt PCIe against DMA attacks while still allowing users (rather than just administrators) to approve attached devices. This attack is very serious as it can done on a machine that is in sleep or hibernate. As we know most laptop users never turn their computers off, they just close the lid. The computer goes to sleep and everything it was doing gets stored in memory. DMA = Direct Memory Access, so someone comes along, plugs in a malicious device and grabs everything stored in memory without even opening the lid of the computer.
Mitigation is two parts. One part is BIOS configuration. By default any modern ThunderBolt enabled computer will come with the BIOS set to require "User Approval" of any device that gets attached. The problem is (in the operating system) that approval require that the user actually be an administrator not just any user. That is not a usable solution in an enterprise environment. It also requires that the device(s) be approved every single time they are used. So, let's say you have a Thunderbolt dock... an administrator has to come and approve it every time you dock your laptop. That's just not workable.
So, we configure that BIOS to a newer standard, Secure Connect. That allows the device to only require approval the first time it is used. Unfortunately that approval still needs to be an administrator.
Finally we are to the point of my post. Here are two scripts to create a configuration item to detect existence of ThunderBolt and remediate the registry so that normal users can approve device connections.
A tech said to me "I don't see how this is any different than setting the BIOS to No Security". Well, as I explained to him, you must understand how the DMA attack works in this instance. The attack happens by simply attaching a malicious device (USB Key, SD Card, whatever) to the machine and the machine accepts its DMA request. This can happen even while the machine is in Sleep mode (no user interface). So, the difference between this and no security is that a user must actually be logged in and active to approve the connection. I can't just walk up to your machine while you are at lunch, plug in a USB key, and take everything that your OS has in memory away with me. I would have to have a valid login to approve the connection. The attack is a way around drive encryption. Having a valid logon is a way around drive encryption so this method makes your machine as secure as a machine that does not have ThunderBolt at all, meaning that nobody can run this particular DMA without a valid logon. Once someone has a valid logon, you have other mitigation that you need to have in place but that's a story for another time.
The first script, detection:
This script will detect the existence of the ThunderBolt registry branch. If it doesn't exist then your machine doesn't have ThunderBolt (or at least doesn't have drivers for it which amounts to the same thing, you are not vulnerable to the DMA attack) so it is compliant. If your machine does have the branch then it checks the AccessRule item to ensure that it is set to 1. By default this item will either not exist (IBM Lenovo) or be set to 0 (HP).
Create a new CI of type Script. I named mine "Win10 Core - ThunderBolt PCIe Security" to add it to my Win10 Core baseline.
The Setting Type is Script.
The Data Type is String.
Here is the Discovery Script:
Mitigation is two parts. One part is BIOS configuration. By default any modern ThunderBolt enabled computer will come with the BIOS set to require "User Approval" of any device that gets attached. The problem is (in the operating system) that approval require that the user actually be an administrator not just any user. That is not a usable solution in an enterprise environment. It also requires that the device(s) be approved every single time they are used. So, let's say you have a Thunderbolt dock... an administrator has to come and approve it every time you dock your laptop. That's just not workable.
So, we configure that BIOS to a newer standard, Secure Connect. That allows the device to only require approval the first time it is used. Unfortunately that approval still needs to be an administrator.
Finally we are to the point of my post. Here are two scripts to create a configuration item to detect existence of ThunderBolt and remediate the registry so that normal users can approve device connections.
A tech said to me "I don't see how this is any different than setting the BIOS to No Security". Well, as I explained to him, you must understand how the DMA attack works in this instance. The attack happens by simply attaching a malicious device (USB Key, SD Card, whatever) to the machine and the machine accepts its DMA request. This can happen even while the machine is in Sleep mode (no user interface). So, the difference between this and no security is that a user must actually be logged in and active to approve the connection. I can't just walk up to your machine while you are at lunch, plug in a USB key, and take everything that your OS has in memory away with me. I would have to have a valid login to approve the connection. The attack is a way around drive encryption. Having a valid logon is a way around drive encryption so this method makes your machine as secure as a machine that does not have ThunderBolt at all, meaning that nobody can run this particular DMA without a valid logon. Once someone has a valid logon, you have other mitigation that you need to have in place but that's a story for another time.
The first script, detection:
This script will detect the existence of the ThunderBolt registry branch. If it doesn't exist then your machine doesn't have ThunderBolt (or at least doesn't have drivers for it which amounts to the same thing, you are not vulnerable to the DMA attack) so it is compliant. If your machine does have the branch then it checks the AccessRule item to ensure that it is set to 1. By default this item will either not exist (IBM Lenovo) or be set to 0 (HP).
Create a new CI of type Script. I named mine "Win10 Core - ThunderBolt PCIe Security" to add it to my Win10 Core baseline.
The Setting Type is Script.
The Data Type is String.
Here is the Discovery Script:
#Created by Mark Randol - randoltech.blogspot.com
#This script detects existence of teh Thunderbolt Service registry branch
#and the setting of the "Approval Level" item within it
#Non-existence of the branch = compliant
#Non-existence ApprovalLevel within the branch = noncompliant
#ApprovalLevel 1 = compliant
#Any other value for ApprovalLevel = noncompliant
if (Test-Path -Path "HKLM:SYSTEM\CurrentControlSet\Services\ThunderboltService\TbtServiceSettings") {
$OutString = (Get-ItemProperty "HKLM:SYSTEM\CurrentControlSet\Services\ThunderboltService\TbtServiceSettings").ApprovalLevel
}
else {
$OutString = "1"
}
Write-Output $OutString
Return $OutString
Here is the Remediation Script:
# Change Thundebolt security approval level to allow users
# to accept Thundebolt equpiment without being local admin
# Originally created by Jens-Kristian Myklebust <jensmyklebust@outlook.com>
# Modified to work as an SCCM CI by Mark Randol - randoltech.blogspot.com
$logfile = "$env:windir\ccm\logs\Install_Fix-ThunderboltRegistry.log"
Start-Transcript -Path $logfile -force #start logging
$RegistryKey = "SYSTEM\CurrentControlSet\Services\ThunderboltService\TbtServiceSettings" #Registry key to modify
$RegistryPath = "HKLM:\$RegistryKey" #Full path to the registry key
$ServiceName = "AdobeARMservice" #"ThunderboltService"
#Set the registry Value
if ((Test-Path -Path $RegistryPath)){ #make sure we're on a machine that actually has the key
$TheService = Get-Service -Name $ServiceName
#Stop the Thunderbolt Service
if (($TheService)) {
$TheService | Stop-Service -Confirm:$false -Verbose
$TheService.WaitForStatus('Stopped')
}
$ACLinfo = Get-Acl "HKLM:\$RegistryKey" #Store original ACL info
#Give "SYSTEM" user full access to registry key
$RegKeyDotNETItem = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($RegistryKey,[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::ChangePermissions)
$DotNET_ACL = $RegKeyDotNETItem.GetAccessControl()
$DotNET_AccessRule = New-Object System.Security.AccessControl.RegistryAccessRule ("System","FullControl","Allow") -Verbose
$DotNET_ACL.SetAccessRule($DotNET_AccessRule)
$DotNET_AccessRule = New-Object System.Security.AccessControl.RegistryAccessRule ($env:USERNAME,"FullControl","Allow") -Verbose
$DotNET_ACL.SetAccessRule($DotNET_AccessRule)
$RegKeyDotNETItem.SetAccessControl($DotNET_ACL)
#check for existence of the property in the key
#if the property doesn't exist, create it
if (!((Get-ItemProperty $RegistryPath).ApprovalLevel)){
New-ItemProperty -Path $RegistryPath -Name 'ApprovalLevel' -Value 1 -PropertyType DWORD -Force -Verbose
}
#if the property does exist, change it to the correct value
else {
Set-ItemProperty -Path $RegistryPath -Name 'ApprovalLevel' -Value 1 -Verbose
}
#Put the security back on the registry
$RegKeyDotNETItem.SetAccessControl($ACLinfo)
#Restart service
if (($TheService)) {
$TheService | Start-Service -Confirm:$false -Verbose
$TheService.WaitForStatus('Running')
}
#>
}
Stop-Transcript #stop logging
Create a compliance rule, I named mine "ApprovalLevel" as that is the registry item that we are dealing with. Here are the settings for it:
Value = 1
Check the checkbox "Run the specified remediation script when this setting is noncompliant"
Check the checkbox "Report noncompliance if the setting instance is not found"
From there, add your new CI to a baseline, deploy the baseline at your (suspected) Thunderbolt enabled machines and it should set the setting for you.
With BIOS set to SecureConnect and this registry entry your users should be able to approve devices to connect to their computer and will only need to do it the first time similar to pairing a Bluetooth device.
- Enjoy
Wednesday, April 17, 2019
File Rename Script
Just a quick script to rename all files in a folder:
$theFolder = "\\server.domain.com\share\folder"
$theFiles = (Get-ChildItem -Path $myFolder -Filter Prefix*.type ).Name
foreach ($File in $myFiles)
{
$FullPathFileName = $theFolder + "\" + $File
$newName = ($File).Replace(" ","_")
Rename-Item -Path $FullPathFileName -NewName $newName -Force
}
$theFolder = "\\server.domain.com\share\folder"
$theFiles = (Get-ChildItem -Path $myFolder -Filter Prefix*.type ).Name
foreach ($File in $myFiles)
{
$FullPathFileName = $theFolder + "\" + $File
$newName = ($File).Replace(" ","_")
Rename-Item -Path $FullPathFileName -NewName $newName -Force
}
Wednesday, February 20, 2019
MBR to GPT conversion
This will run the MBR2GPT tool's validation before attempting conversion:
@ECHO OFF
MBR2GPT.EXE /validate
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
MBR2GPT.EXE /convert
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
:ERROR
EXIT /B %ERRORLEVEL%
@ECHO OFF
MBR2GPT.EXE /validate
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
MBR2GPT.EXE /convert
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
:ERROR
EXIT /B %ERRORLEVEL%
Tuesday, February 19, 2019
Decrypt all of the BitLocker encrypted drives
I needed Bitlocker actually OFF, not just suspended, so here's the script that I used to ensure that it got there:
For Win10:
-----------------------------------
For Win10:
-----------------------------------
#Decrypt-BitlockerDrives.PS1
#Script by Mark Randol
#randoltech.blogspot.com
#This script finds all local encrypted volumes and decrypt them.
#Does not exit until decryption is completed.
CLS
Clear-BitLockerAutoUnlock #Since we're decrypting all of the drives, and any Auto-Unlock protectors are tied to the encryption on the system drive, these need to go away.
$PossibleDrives = (Get-BitLockerVolume).MountPoint #get all of the drives that could possibly be encrypted
#Disable-BitLocker -MountPoint $PossibleDrives #start all of the discovered drives decrypting in parallel
foreach ($DriveLetter in $PossibleDrives) { #step through the drives in series to ensure they get decrypted
[int]$LastEncryptPercent = 100 #This variable stores the most recent change to the encryption percentage
[int]$CurrentEncryptPercent = 2 #This variable stores the current check that we are making on the encryption level
#If these two variables are equal we know that no progress has been made in decryption since the last check
do { #check the encryption level of the drive every five minutes until it is fully decrypted
$CurrentEncryptPercent = (Get-BitLockerVolume -MountPoint $DriveLetter).EncryptionPercentage
if ($CurrentEncryptPercent -ne $LastEncryptPercent) { #if the percentage of encryption has changed since the last check then write that to the output
$OutputString = "Drive " + $DriveLetter + $CurrentEncryptPercent.ToString() + "% encrypted"
Write-Output $OutputString
$LastEncryptPercent = (Get-BitLockerVolume -MountPoint $DriveLetter).EncryptionPercentage #Since the encryption percentage has changed, lets store the this percentage as our "last" (most recent)
}
Start-Sleep -Seconds 300 #wait five minutes before checking again
}
while ($CurrentEncryptPercent -ne 0)
}
Write-Output (Get-BitLockerVolume)
---------------------------------
For Win7
#Decrypt-BitlockerDrives.PS1
#Script by Mark Randol
#randoltech.blogspot.com
#
#This script will list out all of the encryptable volumes on the local machine and decrypt them
#Do not exit until decryption is completed.
#there are simpler ways to do this with modern Powershell commands (Get-BitLockerVolume for example)
#but those methods do not work with a native Windows 7 PowerShell environment so this was
#developed to help facilitate Windows 7 to Windows 10 migration.
$WMINameSpace = "root\CIMv2\Security\MicrosoftVolumeEncryption"
$WMIClass = "Win32_EncryptableVolume"
$BitLockerDrives = (Get-Wmiobject -Namespace $WMINameSpace -Class $WMIClass -ComputerName $env:COMPUTERNAME).DriveLetter
foreach ($LockedDrive in $BitLockerDrives) {
$Status = (Get-Wmiobject -Namespace $WMINameSpace -Class $WMIClass -ComputerName $env:COMPUTERNAME -Filter “DriveLetter=""$LockedDrive""”).ConversionStatus
if ($Status -ne 0) {
if ($Status -eq 1) {
Invoke-Command {manage-bde.exe -off C:}
}
}
foreach ($LockedDrive in $BitLockerDrives) {
$Status = (Get-Wmiobject -Namespace $WMINameSpace -Class $WMIClass -ComputerName $env:COMPUTERNAME -Filter “DriveLetter=""$LockedDrive""”).ConversionStatus
if ($Status -ne 0) {
do {
Start-Sleep 15
$Status = (Get-Wmiobject -Namespace $WMINameSpace -Class $WMIClass -ComputerName $env:COMPUTERNAME -Filter “DriveLetter=""$LockedDrive""”).ConversionStatus
}
until ($Status -eq 0)
}
}
{Exit $LASTEXITCODE}
Wednesday, January 16, 2019
Script to stamp the registry with your OSD variables
# Script by Mark Randol
# randoltech.blogspot.com
$registryPath = "HKLM:\Software\MyCompany\SCCM Operating System Deployment"
[String[]]$OSDVariables = "OSArchitecture","OSDAnswerFilePath","OSDComputerName","OSDImagePackageId","OSDImageVersion","OSDTargetSystemDrive","OSDTargetSystemParition","OSDTargetSystemRoot","OSVersionNumber","_OSDOSImagePackageId","_OSDTargetSystemRoot","_SMSTSAdvertID","_SMSTSAssignedSiteCode","_SMSTSBootImageID","_SMSTSBootMediaPackageID","_SMSTSLaunchMode","_SMSTSLogPath","_SMSTSMachineName","_SMSTSMediaType","_SMSTSOrgName","_SMSTSPackageID","_SMSTSPackageName","_SMSTSSiteCode","_SMSTSStandAloneMedia","_SMSTSSupportUnknownMachines","_SMSTSUserStatePath"
if (!(Test-Path $registryPath)) { New-Item -Path $registryPath -Force | Out-Null }
$InstallDate = Get-Date
New-ItemProperty -Path $registryPath -Name "OSInstallDateTime" -Value $InstallDate -PropertyType STRING -Force | Out-Null
$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
foreach ($OSDVariableName in $OSDVariables)
{
$OSDVariableValue = $tsenv.Value($OSDVariableName)
New-ItemProperty -Path $registryPath -Name $OSDVariableName -Value $OSDVariableValue -PropertyType STRING -Force | Out-Null
}
Thursday, January 10, 2019
Command lines for creating a bootable USB thumb drive
Command lines for creating a bootable USB thumb drive:
diskpart
list disk
sel dis #
clean
create par pri
sel par 1
format fs=ntfs quick <--- for Legacy
format fs=fat32 quick <--- for UEFI
act
exit
diskpart
list disk
sel dis #
clean
create par pri
sel par 1
format fs=ntfs quick <--- for Legacy
format fs=fat32 quick <--- for UEFI
act
exit
Subscribe to:
Posts (Atom)