LUM.PasswordTool.psm1

Function Create-Pwd {
    param($string,
        $pwdLength = 8)

    $pwdLength = $pwdLength - 4

    $string = $string.tolower()
    $md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
    $utf8 = new-object -TypeName System.Text.UTF8Encoding
    $hash = [System.BitConverter]::ToString($md5.ComputeHash($utf8.GetBytes($string)))
    $hash = $hash.replace("-", "")
    $symbol = $($hash.substring(0, 2))
    $symbol = [Convert]::ToInt64($symbol, 16)
    $number = $symbol
    $lower = [math]::pow($symbol, 2)
    $upper = [math]::pow($symbol, 3)
    $charsSymbol = 35, 36, 40, 41, 42, 44, 45, 46, 47, 58, 59, 63, 64, 92, 95 | % { [Char] $_ }
    $charsNumber = 48..57 | % { [Char] $_ }
    $charsLower = 97..122 | % { [Char] $_ }
    $charsUpper = 65..90 | % { [Char] $_ }

    $symbol = $symbol % $charsSymbol.count
    $number = $number % $charsNumber.count
    $Lower = $Lower % $charsLower.count
    $Upper = $Upper % $charsUpper.count

    return $charsUpper[$Upper] + $hash.substring(0, $pwdLength).tolower() + $charsLower[$Lower] + $charsNumber[$Number] + $charsSymbol[$symbol]

}

Function Configure-Passwords {
    <#
    .SYNOPSIS
       Sets local admin passwords
    .DESCRIPTION
       Creates secure file containing encrypted password
       Creates 8 character passwords based on MachineName + Main Password
       Sets local admin passwords on all W10 machines found in domain.
       Updates CustomAttribute15 with hash value of password to maintain track of which computers have been updated.
    .PARAMETER PasswordFile
        The file containing the encrypted master password. if the fail does not exist, user will be asked to enter password and file will be created.
    .PARAMETER Username
        Default value is Administrator. Specify the name of the local administrator to change.
    .EXAMPLE
       Configure-Passwords -Passwordfile c:\temp\pwd.bin -Username localAdminumber +41441234567 -manipulatedNumber +41448888888 -credential $x
    .INPUTS
       Parameters
    .OUTPUTS
       Script results in output / verbose stream
    .NOTES
    +---------------------------------------------------------------------------------------------+
    | DATE : 2018.28.08
    | AUTHOR : Michael Lürsen
    | E-Mail : michael.luersen@mondaycoffee.com
    +---------------------------------------------------------------------------------------------+
    #>


    Param(
        [string]$passwordFile,
        [string]$username = 'Administrator'
    )

    if (!(test-path $passwordfile)) {
        [byte[]] $key = (1..16)
        $cred = get-credential -Message "Please enter the master password for generating local admin passwords" Username_Not_Required
        $cred.Password | ConvertFrom-SecureString -key $key | Set-Content $passwordfile
    }

    [byte[]] $key = (1..16)
    $securePassword = Get-Content $passwordfile | ConvertTo-SecureString -Key $key
    $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($securepassword)
    $password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

    $Computers = Get-ADComputer -filter {OperatingSystem -like "Windows 10*"}
    # $computers = get-adcomputer -filter{cn -eq "BGRMN065"}
    $customAttribute = (Create-Pwd -string $password)

    foreach ($Computer in $computers) {
        Write-Output "configuring $computer..."
        $lcaseComputer = ($($computer.name).tolower())

        $localPassword = Create-Pwd -string $lcaseComputer$password

        $hostname = $Computer.Name
        $currentCustomAtt = (Get-ADComputer -filter {cn -eq $hostname} -Properties extensionattribute15).extensionattribute15
        if ($customAttribute -ne $currentCustomAtt) {
            Write-Output "Attempting to set password on $computer"

            write-output "Working on $($computer.dnshostname) "
            $computername = $($computer.name)

            ([adsi]"WinNT://$($computer.dnshostname)/$username").SetPassword($localPassword)

            #$account = [ADSI]("WinNT://$($computer.dnshostname)/$username,user")
            #$account.psbase.invoke("setpassword",$password)

            if ($error.count -ne 0) {
                write-output "`tFailed to Change the administrator password on $($computer.dnshostname) - Error: $_"
                $error.clear()
            }
            else {
                write-output "`tPassword Change completed successfully, writing hash to custom attribute"
                write-output "Setting custom Attribute for $($computer.dnshostname) to $customAttribute"
                get-adcomputer -filter {cn -eq $computername} | set-adcomputer -replace @{extensionAttribute15 = $customAttribute}
            }
        }
        else {
            Write-Output "Computer $($computer.name) is already up to date"
        }
    }
}

Function Get-Password {
    <#
    .SYNOPSIS
       Gets local admin passwords
    .DESCRIPTION
       Generates password based on Hostname and Master Password
    .EXAMPLE
       Get-Password
    .INPUTS
       Credential box, enter hostname as username.
    .OUTPUTS
       Password
    .NOTES
    +---------------------------------------------------------------------------------------------+
    | DATE : 2018.28.08
    | AUTHOR : Michael Lürsen
    | E-Mail : michael.luersen@mondaycoffee.com
    +---------------------------------------------------------------------------------------------+
    #>


    $cred = get-credential -Message "Please enter the hostname as the username"
    $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($cred.password)
    $password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
    $hostname = $($cred.username).ToLower()


    $currentCustomAtt = (Get-ADComputer -filter {cn -eq $hostname} -Properties extensionattribute15).extensionattribute15
    $expectedCustomAtt = Create-Pwd -string $password
    if ($currentCustomAtt -ne $expectedCustomAtt) {
        write-host "Warning, we detected a mismatch. Possibly the expected password has not been set on the client computer" -ForegroundColor Red
    }

    $localAdminPwd = Create-Pwd -string $hostname$password
    #[System.Windows.Forms.MessageBox]::Show("$localAdminPwd" , "Local Admin Password" , 0)
    write-host "The local admin password for $hostname is: `n"
    write-host $localAdminPwd -ForegroundColor Green

}