BIOS Password managing with Dell Command | Monitor and workspace One

Advertisements

Today I will write me first English private Blog to share with you my project experience.

My learning since a couple of years are everyone is talking about BIOS passwords as part of security but in real life the most BIOS password will be set one time and never change in the time of using the device. With modern work and more mobility, it would be more and more complicated to change BIOS settings because not all devices are in your own network. I will show you in this blog how you could set a BIOS password on a device by PowerShell and Configuration Service Provider (CSP). All scripts are free, and you could use this own your risk without support.

BIOS password by PowerShell

There are a lot of different options to set a BIOS password on a Dell device, like WMI, Dell Command | PowerShell Provider and Dell Command | Configure.

In this Blog I will use the Dell Command | Monitor (DCM) because DCM can do more than BIOS settings e.g. Hardware monitoring by SNMP or Microsoft Event Viewer.

Download Software: https://www.dell.com/support/kbdoc/en-us/000177080/dell-command-monitor

If you click on extract at the installation GUI you will get the MSI for this software which make the deployment much easier.

word image BIOS Password managing with Dell Command | Monitor and workspace One 3

Documentation: https://www.dell.com/support/home/en-us/product-support/product/command-monitor/docs

The easiest way to modify BIOS settings in a full OS installation is by using PowerShell. DCM is offering a new class called DCIM_BIOSService which allow us to change BIOS settings.

We have talked about setting a BIOS password, but as a first step I would recommend to check if an BIOS password is already set. DCM is offering an own class DCIM_BIOSPassword which checks the status of AdminPwd and SystemPwd.

Today we are working with AdminPwd setting only so I will check this value on my machine first.

Advertisements
Get-CimInstance -Namespace root\dcim\sysman -ClassName DCIM_BIOSPassword -Filter "AttributeName='AdminPwd'" | select isSet

The result will be true (password is set) or false (password is not set).

In our first scenario we assume that no password is set. With the following string set you can set AdminPwd on a machine (Note: You need to start PowerShell ISE in Admin Mode)

Get-CimInstance -Namespace root\dcim\sysman -ClassName DCIM_BIOSService | Invoke-CimMethod -MethodName SetBIOSAttributes -Arguments @{[email protected]("AdminPwd");[email protected](“Your Password”)}

If anything is all right you get a set result 0.

The method may return the following errors:

0 (Success)—If the method is completed successfully.

Advertisements

1 (Failure) — If

  • the possible value is out of range. For example, trying to set value other than 0 to 23 for the attribute Autonoe Hour.
  • it is an unsupported BIOS operation. For example, trying to enable TPM when TPM is disabled.

2 (Authentication failure)—If the BIOS password is incorrect.

4294967295 (Invalid Possible Value)—If the possible value is invalid; or read-only.

Ok 😊 now we have set a AdminPwd on the machine, but we would like to change this. DCM is offering an attribute with the name AuthorizationToken. The AuthorizationToken is your old AdminPwd and need for authorization of change.

Get-CimInstance -Namespace root\dcim\sysman -ClassName DCIM_BIOSService | Invoke-CimMethod -MethodName SetBIOSAttributes -Arguments @{[email protected]("AdminPwd");[email protected](“Your New Password”);AuthorizationToken=”Your Old Password”} 

We have set and change a BIOS Password now but if you have enterprise environment, we need more automation.

I have written the following script for one of my customers. The script will set a new password if the device has no password and change it if there is an existing password. The most of customer using a password on a machine generation which are equal on all machines. From the point of security there is a risk. The script generates a unique password for each device, based on two parts. The first one is the ServiceTag and second a static key. If you don´t want use ServiceTag you could use every unique identifier of the machine like UUID, etc.

For the password change I have a problem where I can store the password of the device? I am using the Win10 Registry and stored the information on the machine locally. Yes, I am knowing it is not high secure, but you need access to the device, and you need to know which Keys are set and needed to have the password of the BIOS.

If the community have any great ideas where it is possible to store the information without need external licenses and it could be used if the device is in internal network or in internet, please let me know your ideas. The Password is split in two parts, so I am not spending time to encrypt these values, but it is on my list to test that as well in the future.

All scripts and Workspace One Sensors you can download here: https://github.com/SvenRiebe/BIOSPassword

#########################################
# Name: PowerShell Script for BIOS AdminPW setting on Dell Devices
#
# Description: PowerShell using Dell Command | Monitor for setting AdminPW on the machine. The script checking if any PW is existing and can setup new and change PW.
#
# Author: Sven Riebe Twitter: @SvenRiebe
# Version: 1.2.2
# Status: Test
<#
1.2.2   add check folder c:\temp if not there new-item for $Path
        log path is now a variable $Path
#>
#Variable for change
$PWKey = "Your Static Key"
#Variable not for change
# Check if BIOS Admin PW is set
$PWset = Get-CimInstance -Namespace root\dcim\sysman -ClassName dcim_BIOSPassword -Filter "AttributeName='AdminPwd'" | select -ExpandProperty isSet
# Return code form Dell Command | Monitor for setting Admin PW - Value 0 = OK rest issue is happen
$PWstatus = ""
# Computername of system
$DeviceName = Get-CimInstance -ClassName win32_computersystem | select -ExpandProperty Name

# OEM Serial number of device
$serviceTag = Get-CimInstance -ClassName win32_bios | select -ExpandProperty SerialNumber

# will be used as BIOS Admin PW build from $ServiceTag and $PWKey
$AdminPw = "$serviceTag$PWKey"

# actual system date
$Date = Get-Date

# Check if registry path is availible
$RegKeyexist = Test-Path 'HKLM:\SOFTWARE\Dell\BIOS'

# Value HKLM:\SOFTWARE\Dell\BIOS BIOS use value from registry
$PWKeyOld = ""

# Value HKLM:\SOFTWARE\Dell\BIOS ServiceTag use value from registry
$serviceTagOld = ""

# Old Admin PW generate by registry later
$AdminPwOld = ""

# Path for logging
$PATH = "C:\Temp\"

#check if c:\temp exist
if (!(Test-Path $PATH)) {New-Item -Path $PATH -ItemType Directory}

#Logging device data
Write-Output $env:COMPUTERNAME | out-file "$PATH\BIOS_Profile.txt" -Append
Write-Output "ServiceTag:         $serviceTag" | out-file "$PATH\BIOS_Profile.txt" -Append
Write-Output "Profile install at: $Date" | out-file "$PATH\BIOS_Profile.txt" -Append


#Checking RegistryKey availbility

if ($RegKeyexist -eq "True")
    {
    $PWKeyOld = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name BIOS | select -ExpandProperty BIOS
    $serviceTagOld = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name ServiceTag | select -ExpandProperty ServiceTag
    $AdminPwOld = "$serviceTagOld$PWKeyOld"
    Write-Output "RegKey exist"  | out-file "$PATH\BIOS_Profile.txt" -Append
    }
Else
    {
    New-Item -path "hklm:\software\Dell\BIOS" -Force
    New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "BIOS" -value "" -type string -Force
    New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "ServiceTag" -value "" -type string -Force
    New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Date" -value "" -type string -Force
    New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "" -type string -Force
    Write-Output "RegKey is set"  | out-file "$PATH\BIOS_Profile.txt" -Append
    }

#Checking AdminPW is not set on the machine

If ($PWset -eq $false)
    {
    $PWstatus = Get-CimInstance -Namespace root\dcim\sysman -ClassName DCIM_BIOSService | Invoke-CimMethod -MethodName SetBIOSAttributes -Arguments @{[email protected]("AdminPwd");[email protected]($AdminPw)} | select -ExpandProperty Setresult
    
#Setting of AdminPW was successful

    If ($PWstatus -eq 0)
        {
        New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "BIOS" -value $PWKey -type string -Force
        New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "ServiceTag" -value $serviceTag -type string -Force
        New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Date" -value $Date -type string -Force
        New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Ready" -type string -Force

        Write-Output "Password is set successful for first time"  | out-file "$PATH\BIOS_Profile.txt" -Append
        }

#Setting of AdminPW was unsuccessful

    else
        {
        New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Error" -type string -Force
        Write-Output "Error Passwort could not set" | out-file "$PATH\BIOS_Profile.txt" -Append
        }
    }


#Checking AdminPW is exsting on the machine

else
    {
    
#Compare old and new AdminPW are equal

    If ($AdminPw -eq $AdminPwOld)
        {
        Write-Output "Password no change" | out-file "$PATH\BIOS_Profile.txt" -Append

        }

#Old and new AdminPW are different make AdminPW change

    else
        {
        $PWstatus = Get-CimInstance -Namespace root\dcim\sysman -ClassName DCIM_BIOSService | Invoke-CimMethod -MethodName SetBIOSAttributes -Arguments @{[email protected]("AdminPwd");[email protected]($AdminPw);AuthorizationToken=$AdminPwOld} | select -ExpandProperty Setresult
        
#Checking if change was successful

        If($PWstatus -eq 0)
            {
            Write-Output "Password is change successful" | out-file "$PATH\BIOS_Profile.txt" -Append
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Ready" -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "BIOS" -value $PWKey -type string -Force
            }

#Checking if change was unsuccessful. Most reason is there is a AdminPW is set by user or admin before the profile is enrolled

        else
            {
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Unknown" -type string -Force
            Write-Output "Unknown password on machine. This need to delete first" | out-file "$PATH\BIOS_Profile.txt" -Append
            }
        }
    } 

The script is storing all relevant information in the Registry.

BIOS = Static part of Password

Date = Date of setting/deleting Password

ServiceTag = Unique Part of Password (in my case I use the Serial No. Of the device)

Status = result of setting

Unknown = There is an existing password but not set by this script

Error = general issue e.g. Password does not match password policy

Ready = Success

Delete = Password is deleted by script

word image 1 BIOS Password managing with Dell Command | Monitor and workspace One 5

For a better troubleshooting the script is writing a log in Folder Temp which shows me when does the script execute on the machine and what is the result. No confidential information’s are stored in this file.

word image 2 BIOS Password managing with Dell Command | Monitor and workspace One 7

If you need to delete the Password, e.g. retiring device, etc. I have made a second script. The success will be stored in Registry and Log file as well.

#########################################
# Name: Powershell Script for BIOS AdminPW delete on Dell Devices
#
# Description: Powershell using Dell Command | Monitor for deleting AdminPW on the machine. The script checking if any PW is exist and can delete known PW on the machine.
#
# Author: Sven Riebe Twitter: @SvenRiebe
# Version: 1.0.2
# Status: Test

#Variable not for change
$PWset = Get-CimInstance -Namespace root\dcim\sysman -ClassName dcim_BIOSPassword -Filter "AttributeName='AdminPwd'" | select -ExpandProperty isSet
$PWstatus = ""
$DeviceName = Get-CimInstance -ClassName win32_computersystem | select -ExpandProperty Name
$serviceTag = Get-CimInstance -ClassName win32_bios | select -ExpandProperty SerialNumber
$AdminPw = "$serviceTag$PWKey"
$Date = Get-Date
$RegKeyexist = Test-Path 'HKLM:\SOFTWARE\Dell\BIOS'
$PWKeyOld = ""
$serviceTagOld = ""
$AdminPwOld = ""

#Logging device data
Write-Output $env:COMPUTERNAME | out-file "c:\temp\BIOS_Profile.txt" -Append
Write-Output "ServiceTag:         $serviceTag" | out-file "c:\temp\BIOS_Profile.txt" -Append
Write-Output "Profile install at: $Date" | out-file "c:\temp\BIOS_Profile.txt" -Append

#Generate exiting PW from Registry
$PWKeyOld = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name BIOS | select -ExpandProperty BIOS
$serviceTagOld = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name ServiceTag | select -ExpandProperty ServiceTag
$AdminPwOld = "$serviceTagOld$PWKeyOld"


#Checking AdminPW is not set on the machine

If ($PWset -eq $false)
    {
    Write-Output "No password is set on machine"  | out-file "c:\temp\BIOS_Profile.txt" -Append
    }
else
    {
    $PWstatus = Get-CimInstance -Namespace root\dcim\sysman -ClassName DCIM_BIOSService | Invoke-CimMethod -MethodName SetBIOSAttributes -Arguments @{[email protected]("AdminPwd");[email protected]("");AuthorizationToken=$AdminPwOld} | select -ExpandProperty Setresult
        
#Checking if change was successful

        If($PWstatus -eq 0)
            {
            Write-Output "Password is delete from the machine" | out-file "c:\temp\BIOS_Profile.txt" -Append

            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "BIOS" -value "" -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "ServiceTag" -value "" -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Date" -value $Date -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Delete" -type string -Force
            }

#Checking if change was unsuccessful. Most reason is there is a AdminPW is set by user or admin before the profile is enrolled

        else
            {
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Unknown" -type string -Force
            Write-Output "Unknown password on machine. This need to delete first" | out-file "c:\temp\BIOS_Profile.txt" -Append
            }
        } 

You can run these scripts in different environments. For my environment I am using Workspace One. I want to be managing and control the status of deployment/undeployment of the password.

My first step is to encode the PowerShell script so that I can deploy this as CSP with include PowerShell.

There is an easy way for encoding. Camille Daybay (VMware) made a script which transfer the script in an xml. All you need to will find here.

https://github.com/CamilleDebay/Scripts/blob/master/UEM/Create-PowerShellProfile.ps1

After we have encoded the two script, we could make a custom profile in Workspace One UEM.

Start a new Profile and give them a specific name and assign a smart group with dell devices.

word image 3 BIOS Password managing with Dell Command | Monitor and workspace One 9

Switch to Custom settings and change Target to Workspace One Intelligent Hub and deselect Make Commands Atomic.

Now you can copy the Password setting xml information in Install Settings and Password delete xml in Remove settings.

word image 4 BIOS Password managing with Dell Command | Monitor and workspace One 11

Now click Save and Publish and the password will set on all devices of this smart group.

word image 5 BIOS Password managing with Dell Command | Monitor and workspace One 13

I have in my environment as well a data collection and orchestration tool Workspace One Intelligence. All my data´s are stored locally but how you could use these information’s for support cases?

I have created Workspace One Sensors which help me to get all data´s on a central place.

There are three relevant information´s I need to know.

  1. What is the password of this BIOS?
  2. When does is deployed to the device?
  3. Status of deployment (Unknown, Error, Ready, Delete)
word image 6 BIOS Password managing with Dell Command | Monitor and workspace One 15

Sensor BIOS_Profile_Date

##################################################################
#
# Name: Sensor Dell status change date AdminPW by BIOS Profile
#
# Author: Sven Riebe
#
# Status: test
#
# Version 1.0.0
#
# Date: 08-06-2021

$BiosProfilDate = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name Date | select -ExpandProperty Date
Write-Output $BiosProfilDate

Sensor BIOS_Profile_Password

# Description
# Return Type: String
# Execution Context: System
##################################################################
#
# Name: Sensor Dell actual AdminPW on the Device by BIOS Profile
#
# Author: Sven Riebe
#
# Status: test
#
# Version 1.0.1
#
# Date: 09-14-2021


<#
1.0.1   cover Static and Random PW
#>


#Variables
$HashKeyCheck = ""
$PWKey = ""
$serviceTag = ""
$AdminPw = ""

# this function is from https://stackoverflow.com/questions/5648931/test-if-registry-value-exists
function Test-RegistryValue {

param (

 [parameter(Mandatory=$true)]
 [ValidateNotNullOrEmpty()]$Path,

[parameter(Mandatory=$true)]
 [ValidateNotNullOrEmpty()]$Value
)

try {

Get-ItemProperty -Path $Path | Select-Object -ExpandProperty $Value -ErrorAction Stop | Out-Null
 return $true
 }

catch {

return $false

}

}

$HashKeyCheck = Test-RegistryValue -Path HKLM:\SOFTWARE\Dell\BIOS -Value Hash

If ($HashKeyCheck -match "false")
    {
    $PWKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name BIOS | select -ExpandProperty BIOS
    $serviceTag = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name ServiceTag | select -ExpandProperty ServiceTag
    $AdminPw = "$serviceTag$PWKey"
    }
else
    {
    $AdminPw = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name Hash | select -ExpandProperty Hash
    } 

Sensor BIOS_Profile_Status

##################################################################
#
# Name: Sensor Dell status AdminPW by BIOS Profile
#
# Author: Sven Riebe
#
# Status: test
#
# Version 1.0.0
#
# Date: 08-06-2021

$BiosProfilStatus = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name Status | select -ExpandProperty Status
Write-Output $BiosProfilStatus

You will find these three sensors in the same repository as the other scripts.

It takes some time but now I can use Dashboards and Reports to work with the device BIOS password.

Status of BIOS Password status

word image 7 BIOS Password managing with Dell Command | Monitor and workspace One 17

Audit Report

If you want to have an audit report, you can do this as well. You get a view about status and date of change, e.g. if you have a policy which rules all passwords need to be change all three month you could make filters to show you all relevant devices.

word image 8 BIOS Password managing with Dell Command | Monitor and workspace One 19

If you like more security I am make a new script which working with a random generated password. My learning with Workspace One and custom profile, it will run at each start of the machine. This is a huge problem because every restart the machine gets a new BIOS password if anything is going wrong there are lot of device with unknown BIOS passwords. To be secure that the profile not generated each start a BIOS password I am making a time loop for 180 days. What does this mean? If the BIOS password not older then 179 days, the password change is skipped after 180 days it will be changed. The random password will be stored in Win10 Registry as well in the value Hash.

The PW generator is base on the following source code https://gist.github.com/indented-automation/2093bd088d59b362ec2a5b81a14ba84e and the function check if a Reg Key available by https://stackoverflow.com/questions/5648931/test-if-registry-value-exists.

Thx for sharing 😊

I have integrated both functions in my script base on the existing version with a time check of the last BIOS password check.

#########################################
# Name: Powershell Script for BIOS AdminPW setting on Dell Devices
#
# Description: Powershell using Dell Command | Monitor for setting AdminPW with random PW on the machine. The script checking if any PW is exist and can setup new and change PW.
#
# Author: Sven Riebe Twitter: @SvenRiebe
# Version: 1.0.3
# Status: Test

<#
1.0.1   add check folder c:\temp if not there new-item for $Path
        log path is now a variable $Path
1.0.2   move request for AdminPwold from line 104 to 168
        additional setting RegKey "Hash" at unsuccessfull to be secure that Hash is not empty if AdminPWOld asking for
1.0.3   checking if password older than 180 days before a new PW will deployed
        New Function Test-RegistryValue
        Adjust special char to use only Char are same keyboard position on DE / US Keyboard to make it easier for manuel typing later
#>


#Variable you can change

## Days a password need exist before it will be change
$PWTime = "180"

## Logging Path
$PATH = "C:\Temp\"

## length of your BIOS Password max 32 char. The BIOS supporting only a max 0f 32 Characters. Recommand to set 12.
$PWLength = 12


# This function is from https://gist.github.com/indented-automation/2093bd088d59b362ec2a5b81a14ba84e
function New-Password {
  
    [CmdletBinding()]
    [OutputType([String])]
    param (
        # The length of the password which should be created.
        [Parameter(ValueFromPipeline)]        
        [ValidateRange(8, 255)]
        [Int32]$Length = 10,

        # The character sets the password may contain. A password will contain at least one of each of the characters.
        [String[]]$CharacterSet = ('abcdefghijklmnopqrstuvwxyz',
                                   'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                                   '0123456789',
                                   '!$%'),
<#
For Dell 7th Generation and newer client products, you should use the following guidelines:
BIOS passwords can include:
The following special characters (ASCII 0x21 – 0x2f):
! " # $ % & ' ( ) * + , - . /
A number (ASCII 0x30 – 0x39):
0 1 2 3 4 5 6 7 8 9
One of the following special characters (ASCII 0x3a – 0x40):
: ; < = > ? @
A capital English letter (ASCII 0x41 – 0x5a):
A - Z
One of the following special characters (ASCII 0x5b – 0x60):
[ \ ] ^ _ `
A lower case English letter (ASCII 0x61 – 0x7a):
a - z
One of the following special characters (ASCII 0x7b – 0x7e):
{ | } ~
#>
        # The number of characters to select from each character set.
        [Int32[]]$CharacterSetCount = (@(1) * $CharacterSet.Count)
    )

    begin {
        $bytes = [Byte[]]::new(4)
        $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
        $rng.GetBytes($bytes)

        $seed = [System.BitConverter]::ToInt32($bytes, 0)
        $rnd = [Random]::new($seed)

        if ($CharacterSet.Count -ne $CharacterSetCount.Count) {
            throw "The number of items in -CharacterSet needs to match the number of items in -CharacterSetCount"
        }

        $allCharacterSets = [String]::Concat($CharacterSet)
    }

    process {
        try {
            $requiredCharLength = 0
            foreach ($i in $CharacterSetCount) {
                $requiredCharLength += $i
            }

            if ($requiredCharLength -gt $Length) {
                throw "The sum of characters specified by CharacterSetCount is higher than the desired password length"
            }

            $password = [Char[]]::new($Length)
            $index = 0
        
            for ($i = 0; $i -lt $CharacterSet.Count; $i++) {
                for ($j = 0; $j -lt $CharacterSetCount[$i]; $j++) {
                    $password[$index++] = $CharacterSet[$i][$rnd.Next($CharacterSet[$i].Length)]
                }
            }

            for ($i = $index; $i -lt $Length; $i++) {
                $password[$index++] = $allCharacterSets[$rnd.Next($allCharacterSets.Length)]
            }

            # Fisher-Yates shuffle
            for ($i = $Length; $i -gt 0; $i--) {
                $n = $i - 1
                $m = $rnd.Next($i)
                $j = $password[$m]
                $password[$m] = $password[$n]
                $password[$n] = $j
            }

            [String]::new($password)
        } catch {
            Write-Error -ErrorRecord $_
        }
    }
}

# this function is from https://stackoverflow.com/questions/5648931/test-if-registry-value-exists
function Test-RegistryValue {

param (

 [parameter(Mandatory=$true)]
 [ValidateNotNullOrEmpty()]$Path,

[parameter(Mandatory=$true)]
 [ValidateNotNullOrEmpty()]$Value
)

try {

Get-ItemProperty -Path $Path | Select-Object -ExpandProperty $Value -ErrorAction Stop | Out-Null
 return $true
 }

catch {

return $false

}

}



#Variable not for change
$PWset = Get-CimInstance -Namespace root\dcim\sysman -ClassName dcim_BIOSPassword -Filter "AttributeName='AdminPwd'" | select -ExpandProperty isSet
$PWstatus = ""
$DeviceName = Get-CimInstance -ClassName win32_computersystem | select -ExpandProperty Name
$serviceTag = Get-CimInstance -ClassName win32_bios | select -ExpandProperty SerialNumber
$AdminPw = ""
$Date = Get-Date -Format yyyy-MM-dd
$DateExpire = ""
$RegKeyexist = Test-Path 'HKLM:\SOFTWARE\Dell\BIOS'
$PWKeyOld = ""
$serviceTagOld = ""
$AdminPwOld = ""
$DateTransfer = (Get-Date).AddDays($PWTime)
$BIOSVersion = Get-CimInstance -ClassName win32_bios | select -ExpandProperty SMBIOSBIOSVersion


#check if c:\temp exist
if (!(Test-Path $PATH)) {New-Item -Path $PATH -ItemType Directory}

#Logging device data
Write-Output $env:COMPUTERNAME | out-file "$Path\BIOS_Profile.txt" -Append
Write-Output "ServiceTag:         $serviceTag" | out-file "$Path\BIOS_Profile.txt" -Append
Write-Output "Profile install at: $Date" | out-file "$Path\BIOS_Profile.txt" -Append


#Checking RegistryKey availbility

if ($RegKeyexist -eq "True")
    {
    Write-Output "RegKey exist"  | out-file "$Path\BIOS_Profile.txt" -Append

    $RegKeyCheckUpdate = Test-RegistryValue -Path HKLM:\SOFTWARE\Dell\BIOS -Value Update

    
    If ($RegKeyCheckUpdate -eq $false)
        {
        New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Update" -value $Date -type string -Force
        Write-Output "RegKey Update generated" | out-file "$Path\BIOS_Profile.txt" -Append
        }
    else
        {
        Write-Output "Field Update exist" | out-file "$Path\BIOS_Profile.txt" -Append
        }

        
    }
Else
    {
    New-Item -path "hklm:\software\Dell\BIOS" -Force
    New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "BIOS" -value $BIOSVersion -type string -Force
    New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "ServiceTag" -value "" -type string -Force
    New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Date" -value "" -type string -Force
    New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "" -type string -Force
    New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Hash" -value "" -type string -Force
    New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Update" -value $Date -type string -Force
    
    Write-Output "RegKey is set"  | out-file "$Path\BIOS_Profile.txt" -Append
    }

#check if BIOS password older that 180 days

$DateExpire = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name Update | select -ExpandProperty Update


if ((Get-Date -Format yyyyMMdd) -ge (Get-Date $DateExpire -Format yyyyMMdd))
    {

    $AdminPw = New-Password -Length $PWLength 
    
    # only for security need to delete if script is working stable
    Write-Output "Password: $AdminPW" | out-file "$Path\BIOS_Profile.txt" -Append

    #Checking AdminPW is not set on the machine    
    If ($PWset -eq $false)
        {
        $PWstatus = Get-CimInstance -Namespace root\dcim\sysman -ClassName DCIM_BIOSService | Invoke-CimMethod -MethodName SetBIOSAttributes -Arguments @{[email protected]("AdminPwd");[email protected]($AdminPw)} | select -ExpandProperty Setresult
    
    #Setting of AdminPW was successful

        If ($PWstatus -eq 0)
            {
            
            #$DateTransfer = (Get-Date).AddDays($PWTime)
                         
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "BIOS" -value $BIOSVersion -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "ServiceTag" -value $serviceTag -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Date" -value $Date -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Ready" -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Hash" -value $AdminPw -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Update" -value (Get-Date $DateTransfer -Format yyyy-MM-dd) -type string -Force

            Write-Output "Password is set successful for first time"  | out-file "$Path\BIOS_Profile.txt" -Append
            }

    #Setting of AdminPW was unsuccessful

        else
            {
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Error" -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Hash" -value $AdminPw -type string -Force
            Write-Output "Error Passwort could not set" | out-file "$Path\BIOS_Profile.txt" -Append
            }
        }


    #Checking AdminPW is exsting on the machine

    else
        {
    
    #Compare old and new AdminPW are equal
    $AdminPwOld = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name Hash | select -ExpandProperty Hash
    
        If ($AdminPw -eq $AdminPwOld)
            {
            Write-Output "Password no change" | out-file "$Path\BIOS_Profile.txt" -Append
    
            }

    #Old and new AdminPW are different make AdminPW change
        else
            {
            $PWstatus = Get-CimInstance -Namespace root\dcim\sysman -ClassName DCIM_BIOSService | Invoke-CimMethod -MethodName SetBIOSAttributes -Arguments @{[email protected]("AdminPwd");[email protected]($AdminPw);AuthorizationToken=$AdminPwOld} | select -ExpandProperty Setresult
        
    #Checking if change was successful

            If($PWstatus -eq 0)
                {
                New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Ready" -type string -Force
                New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "BIOS" -value $BIOSVersion -type string -Force
                New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Hash" -value $AdminPw -type string -Force
                New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Date" -value $Date -type string -Force
                New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Update" -value (Get-Date $DateTransfer -Format yyyy-MM-dd) -type string -Force

                Write-Output "Password is change successful" | out-file "$Path\BIOS_Profile.txt" -Append
                }

    #Checking if change was unsuccessful. Most reason is there is a AdminPW is set by user or admin before the profile is enrolled

            else
                {
                New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Unknown" -type string -Force
                New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Date" -value $Date -type string -Force
                
                Write-Output "Unknown password on machine. This need to delete first" | out-file "$Path\BIOS_Profile.txt" -Append
                }
            }
     }
    }
else
    {
    Write-Output "Password is not older than 180 Days. No Password Change" | out-file "$Path\BIOS_Profile.txt" -Append
    } 

The process to encode and making a custom profile is the same as before. You will need a uninstall script as well. We are using now a other Registry field as before to the script need a little bit tuning.

#########################################
# Name: Powershell Script for BIOS AdminPW random delete on Dell Devices
#
# Description: Powershell using Dell Command | Monitor for deleting AdminPW on the machine. The script checking if any PW is exist and can delete known PW on the machine.
#
# Author: Sven Riebe Twitter: @SvenRiebe
# Version: 1.0.1
# Status: Test

<#
1.0.1   reset RegKey Update to date to day
#>

#Variable not for change
$PWset = Get-CimInstance -Namespace root\dcim\sysman -ClassName dcim_BIOSPassword -Filter "AttributeName='AdminPwd'" | select -ExpandProperty isSet
$BIOSVersion = Get-CimInstance -ClassName win32_bios | select -ExpandProperty SMBIOSBIOSVersion
$PWstatus = ""
$DeviceName = Get-CimInstance -ClassName win32_computersystem | select -ExpandProperty Name
$serviceTag = Get-CimInstance -ClassName win32_bios | select -ExpandProperty SerialNumber
$AdminPw = "$serviceTag$PWKey"
$Date = Get-Date
$RegKeyexist = Test-Path 'HKLM:\SOFTWARE\Dell\BIOS'
$PWKeyOld = ""
$serviceTagOld = ""
$AdminPwOld = ""

#Logging device data
Write-Output $env:COMPUTERNAME | out-file "c:\temp\BIOS_Profile.txt" -Append
Write-Output "ServiceTag:         $serviceTag" | out-file "c:\temp\BIOS_Profile.txt" -Append
Write-Output "Profile install at: $Date" | out-file "c:\temp\BIOS_Profile.txt" -Append

#Generate exiting PW from Registry
$AdminPwOld = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Dell\BIOS\' -Name Hash | select -ExpandProperty Hash


#Checking AdminPW is not set on the machine

If ($PWset -eq $false)
    {
    Write-Output "No password is set on machine"  | out-file "c:\temp\BIOS_Profile.txt" -Append
    }
else
    {
    $PWstatus = Get-CimInstance -Namespace root\dcim\sysman -ClassName DCIM_BIOSService | Invoke-CimMethod -MethodName SetBIOSAttributes -Arguments @{[email protected]("AdminPwd");[email protected]("");AuthorizationToken=$AdminPwOld} | select -ExpandProperty Setresult
        
#Checking if change was successful

        If($PWstatus -eq 0)
            {
            Write-Output "Password is delete from the machine" | out-file "c:\temp\BIOS_Profile.txt" -Append

            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "BIOS" -value $BIOSVersion -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "ServiceTag" -value $serviceTag -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Date" -value $Date -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Hash" -value "" -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Delete" -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Update" -value (Get-Date -Format yyyy-MM-dd) -type string -Force
            }

#Checking if change was unsuccessful. Most reason is there is a AdminPW is set by user or admin before the profile is enrolled

        else
            {
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Date" -value $Date -type string -Force
            New-Itemproperty -path "hklm:\software\Dell\BIOS" -name "Status" -value "Unknown" -type string -Force
            Write-Output "Unknown password on machine. This need to delete first" | out-file "c:\temp\BIOS_Profile.txt" -Append
            }
        } 

But if you have other great ideas, please share this with me. Thx 😊

On my list are building the same function in Microsoft Intune and encrypt the password before it will be stored in the registry and using Microsoft Key Vault to store the information´s for more security, but any way a BIOS Password is not a Windows Password you need physical access.

A notice:

At the time of this writing, I was employed by Dell Technologies. However, Dell has no control over the creation or content of this article or has directly endorsed this article. The only indirect support is that I may have used one of my existing Dell test devices for this article.

Leave a comment