AES. Encrypt array of bytes in powershell [closed] - algorithm

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am need to encrypt array of bytes([byte[]]) in powershell script using AES cryptography method. I am find function that encode string:
[Reflection.Assembly]::LoadWithPartialName("System.Security")
function Encrypt-String($String, $Passphrase, $salt="My Voice is my P455W0RD!", $init="Yet another key", [switch]$arrayOutput)
{
$r = new-Object System.Security.Cryptography.RijndaelManaged
$pass = [Text.Encoding]::UTF8.GetBytes($Passphrase)
$salt = [Text.Encoding]::UTF8.GetBytes($salt)
$r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8
$r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]
$c = $r.CreateEncryptor()
$ms = new-Object IO.MemoryStream
$cs = new-Object Security.Cryptography.CryptoStream $ms,$c,"Write"
$sw = new-Object IO.StreamWriter $cs
$sw.Write($String)
$sw.Close()
$cs.Close()
$ms.Close()
$r.Clear()
[byte[]]$result = $ms.ToArray()
if($arrayOutput) {
return $result
} else {
return [Convert]::ToBase64String($result)
}
}
Read code with comments at http://gallery.technet.microsoft.com/scriptcenter/PowerShell-Script-410ef9df
Help change the function so that it encode array of bytes and not a string
Ssory for my english. Hello from Russia :)

I am do that i am need. New code:
[Reflection.Assembly]::LoadWithPartialName("System.Security")
$String=$buff #ARRAY OF BYTES TO ENCODE
$Passphrase="Pas"
$salt="My Voice is my P455W0RD!"
$init="Yet another key"
$r = new-Object System.Security.Cryptography.AesManaged
$pass = [Text.Encoding]::UTF8.GetBytes($Passphrase)
$salt = [Text.Encoding]::UTF8.GetBytes($salt)
$r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8
$r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]
$r.Padding="Zeros"
$c = $r.CreateEncryptor()
$ms = new-Object IO.MemoryStream
$cs = new-Object Security.Cryptography.CryptoStream $ms,$c,"Write"
$cs.Write($String, 0,$String.Length)
$cs.Close()
$ms.Close()
$r.Clear()
[byte[]]$Encrypted = $ms.ToArray()

Related

Powershell: Why are my RegKey value checks failing using Get-ItemProperty when the value I am checking for is 0?

I have been tasked with scripting regkey checks to make sure a sampling of machines are compliant with our security posture.
The script works great when checking for any non-zero value (such as the example input below).
however, there is a consistent theme where my code if erroneously reporting that the checks have failed if the desired value is 0. See example code below:
$failReview = "" #String to track compliance issues
$OutFile = "C:\local\file.text"
Function Test-STIG_SingleKey {
#check for single acceptable key value
#up to 3 additional acceptable key values may be checked for single key
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string[]] $CV, #Check Vulnerability number
[string[]] $Path, #RegKey Path
[string[]] $Key, #Key to check
[int] $value, #Expected Regkey value for compliance
$FailReview,
[Parameter(Mandatory=$false)]
[int] $value1, #optional acceptable value
[int] $value2, #optional acceptable value
[int] $value3 #optional acceptable value
)
Begin {}
Process {
$KeyObject = Get-ItemProperty $Path #Obtain RegKey object values using RegKey Path
$Exist = ([bool]($KeyObject.PSObject.Properties.name -imatch $Key)) #Check for match of key value property name and cast to boolean
If(!($Exist)){ #If does NOT exist
Write-Host " !!! $CV is a finding !!!" -ForegroundColor "Red"; $Global:failReview += "$CV, "} #This IS a finding, append CV to list for review
ElseIf (($KeyObject)."$Key" = $value){ #checks relevant object property value and compares to Primary expected value
Write-Host " $CV is not a finding" -ForegroundColor "Green"
}
ElseIf (((($KeyObject)."$Key" = $value1) -or (($KeyObject)."$Key" = $value2) -or (($KeyObject)."$Key" = $value3))) { #alternate acceptable value check
Write-Host " $CV is not a finding, alternate acceptable values used" -ForegroundColor "Green" #not a finding, but indicates alt value present
}
else {Write-Host " !!! $CV is a finding !!!" -ForegroundColor "Red"; $Global:FailReview += "$CV, "} #This IS a finding, append CV to list for review
}
End {Return $CV, $Path, $Key, $value, $KeyObject, $failReview | Out-File $OutFile -Append} #Pass all variable values to out-file for review if needed
}
#EXAMPLE INPUT:
Test-STIG_SingleKey -CV "V70955" `
-Path "HKLM:\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_HTTP_USERNAME_PASSWORD_DISABLE" `
-Key "excel.exe" `
-value 1
I can obtain the value manually by looking at $KeyObject.Key, but can't seem to get the output to evaluate to true if I'm looking for a 0.
I think this is likely because it's evaluating the 0 to $false at some point, but it's an int.
I've already tried casting to [int] and converting it to hex.
Any advice would be appreciated, because I've almost spent more time trying to figure this out then it would take to just manually look at the keys for the sampling that we require.
Thanks!
This is because in your if statements, you are setting ($KeyObject)."$Key" equal to something instead of checking if it is set to a particular value.
So
... ElseIf (($KeyObject)."$Key" = $value){ ...
should be
... ElseIf (($KeyObject)."$Key" -eq $value){ ...

How to LM Hash in Powershell

OK so i have been working on this for a bit, and i cant see how to get any further. I keep running into roadblocks with the DESCryptoServiceProvider and somehow it just doesnt seem to be comming out with the right answers.
the sudo code version of LM_Hash is:
LMHASH = concat(DES(Upper(PWD)[0..7],KGS!##$%),DES(Upper(PWD)[8..13],KGS!##$%))
First issue is the LM Key I keep seeing the atleast two variants its either "KGS!##$%" or "KGS!+#$%" neither gets me the right answers but both dont seem to fit with the origin story (its KGS and SHIFT 12345 assuming a US keyboard
on a UK thats "KGS!"£$%")
I am pretty sure i have the parameters set up correctly now, but my understanding seems to be failing me. here's what i have so far, any help is appreciated I am running Powershell V5.1 on Win 10, the string to encrypt is passed in as $string
$plaintext = "KGS!##$%"
$OEM = [System.Text.Encoding]::GetEncoding($Host.CurrentCulture.TextInfo.OEMCodePage)
$str1 = $OEM.GetBytes($string.substring(0,7)) +[Byte]$null
$str2 = $OEM.GetBytes($string.Substring(7)) +[Byte]$null
$IV = new-object "System.Byte[]" 8
$hasher = New-Object -TypeName System.Security.Cryptography.DESCryptoServiceProvider -Property #{key=$str1; IV = $IV; mode = [System.Security.Cryptography.CipherMode]::ECB; Padding=[System.Security.Cryptography.PaddingMode]::None}
$outbyte = new-object "System.Byte[]" 8
$encrypter1 = $hasher.CreateEncryptor()
$outbyte = $encrypter1.TransformFinalBlock($OEM.GetBytes($plaintext),0,8)
$data1 = [System.BitConverter]::ToString($outbyte).replace("-","")
$encrypter1.Dispose()
In theory this should encrypt the Key (which ever one it is) with DES using the first 7 characters of the string ($str1) as the key (with a null byte on the end) and then we do this to the second half ($str2) and concat them back together to get the LMHASH.
The ASCII-encoded string KGS!##$% is the correct magic constant to use
using the first 7 characters of the string ($str1) as the key (with a null byte on the end)
This, however, is incorrect. The key is not composed by padding the 7 bytes of partial input with a single 0-byte at the end, but by partitioning the input into 8 7-bit chunks and left-shifting them once (resulting in 8 bytes).
The easiest way to implement this in PowerShell is probably with strings, so I'd likely do something like this:
# Convert string to byte array
$inBytes = $OEM.GetBytes($str1)
# Create a binary string from our bytes
$bitString = ''
foreach($byte in $inBytes){
$bitstring += [convert]::ToString($byte, 2).PadLeft(8, '0')
}
# Partition the byte string into 7-bit chunks
[byte[]]$key = $bitString -split '(?<=\G.{7}(?<!$))' |ForEach-Object {
# Insert 0 as the least significant bit in each chunk
# Convert resulting string back to [byte]
[convert]::ToByte("${_}0", 2)
}
try{
# Create the first encryptor from our new key, and an empty IV
[byte[]]$iv = ,0 * 8
$enc = $hasher.GetEncryptor($key, $iv)
# Calculate half of the hash
$block1 = $enc.TransformFinalBlock($plaintext, 0, 8)
}
finally{
# Dispose of the encryptor
$enc.Dispose()
}
Then repeat for $str2 and concatenate the resulting blocks for the full LM hash
anyone having issues, based on #mathias R. Jessen
's answer above, here is a fuction that computes half the LM-Hash takes in 7 character string and outputs the hash as Hex.
Function LM-hash {
Param(
[Parameter(mandatory=$true,ValueFromPipeline=$true,position=0)]
[ValidateLength(7,7)]
[String]$Invalue
)
$plaintext = "KGS!##$%"
$OEM = [System.Text.Encoding]::GetEncoding($Host.CurrentCulture.TextInfo.OEMCodePage)
$inBytes = $OEM.GetBytes($invalue)
$bitString = ''
foreach($byte in $inBytes){
$bitstring += [convert]::ToString($byte, 2).PadLeft(8, '0')
}
[byte[]]$key = $bitString -split '(?<=\G.{7}(?<!$))' |ForEach-Object { [convert]::ToByte("${_}0", 2)}
$iv = new-object "System.Byte[]" 8
$DESCSP = New-Object -TypeName System.Security.Cryptography.DESCryptoServiceProvider -Property #{key=$key; IV = $IV; mode = [System.Security.Cryptography.CipherMode]::ECB; Padding=[System.Security.Cryptography.PaddingMode]::None}
$enc = $DESCSP.CreateEncryptor()
$block1 = $enc.TransformFinalBlock($OEM.GetBytes($plaintext), 0, 8)
return [System.BitConverter]::ToString($block1).replace("-","")
$enc.Dispose()
}
this gives the correct result for half the hash, so feeding each half in seperatley and concatenating the strings gives you a full LM hash

Faster iteration

I have this code, which is part of a function that returns a list of SQL rows based on a time range.
The query itself (1st line of code) is quite fast. But the foreach loop that extract the relevant data takes a while to complete.
I have around 350.000 lines to iterate, and despite it's has to take a while, I was wondering if there is any change I could make in order to make it faster.
$SqlDocmasterTableResuls = $this.SqlConnection.GetSqlData("SELECT DOCNUM, DOCLOC FROM MHGROUP.DOCMASTER WHERE ENTRYWHEN between '" + $this.FromDate + "' and '" + $this.ToDate + "'")
[System.Collections.ArrayList]$ListOfDocuments = [System.Collections.ArrayList]::New()
if ($SqlDocmasterTableResuls.Rows.Count)
{
foreach ($Row in $SqlDocmasterTableResuls.Rows)
{
$DocProperties = #{
"DOCNUM" = $Row.DOCNUM
"SOURCE" = $Row.DOCLOC
"DESTINATION" = $Row.DOCLOC -replace ([regex]::Escape($this.iManSourceFileServerName + ":" + $this.iManSourceFileServerPath.ROOTPATH)),
([regex]::Escape($this.iManDestinationFileServerName + ":" + $this.iManDestinationFileServerPath.ROOTPATH))
}
$DocObj = New-Object -TypeName PSObject -Property $DocProperties
$ListOfDocuments.Add($DocObj)
}
return $ListOfDocuments
Avoid appending to an array in a loop. The best way to capture loop data in a variable is to simply collect the loop output in a variable:
$ListOfDocuments = foreach ($Row in $SqlDocmasterTableResuls.Rows) {
New-Object -Type PSObject -Property #{
"DOCNUM" = $Row.DOCNUM
"SOURCE" = $Row.DOCLOC
"DESTINATION" = $Row.DOCLOC -replace ...
}
}
You don't need the surrounding if conditional, because if the table doesn't have any rows the loop should skip right over it, leaving you with an empty result.
Since you want to return the list anyway, you don't even need to collect the loop output in a variable. Just leave the output as it is and it will get returned anyway.
Also avoid repeating operations in a loop when their result doesn't change. Calculate the escaped source and destination paths once before the loop:
$srcPath = [regex]::Escape($this.iManSourceFileServerName + ':' + $this.iManSourceFileServerPath.ROOTPATH)
$dstPath = [regex]::Escape($this.iManDestinationFileServerName + ':' + $this.iManDestinationFileServerPath.ROOTPATH)
and use the variables $srcPath and $dstPath inside the loop.
Something like this should do:
$SqlDocmasterTableResuls = $this.SqlConnection.GetSqlData("SELECT ...")
$srcPath = [regex]::Escape($this.iManSourceFileServerName + ':' + $this.iManSourceFileServerPath.ROOTPATH)
$dstPath = [regex]::Escape($this.iManDestinationFileServerName + ':' + $this.iManDestinationFileServerPath.ROOTPATH)
foreach ($Row in $SqlDocmasterTableResuls.Rows) {
New-Object -Type PSObject -Property #{
'DOCNUM' = $Row.DOCNUM
'SOURCE' = $Row.DOCLOC
'DESTINATION' = $Row.DOCLOC -replace $srcPath, $dstPath
}
}
return
[edit - per Ansgar Wiechers, the PSCO accelerator is only available with ps3+.]
one other thing that may help is to replace New-Object with [PSCustomObject]. that is usually somewhat faster to use. something like this ...
$DocObj = [PSCustomObject]$DocProperties
another way to use that type accelerator is to do what Ansgar Wiechers did in his code sample, but use the accelerator instead of the cmdlet. like this ...
[PSCustomObject]#{
'DOCNUM' = $Row.DOCNUM
'SOURCE' = $Row.DOCLOC
'DESTINATION' = $Row.DOCLOC -replace $srcPath, $dstPath
}
hope that helps,
lee

Retrieve badpwdcount with LDAP on PDC [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I'm trying to get the values from "badpwdcount" attribute. Problem is in order to get accurate value I should query to PDC ( Primary Domain Controller ). At the moment, I'm using powershell to solve with LDAP search. The question : Is there any chance to get the value from PDC by using LDAP search?
For example:
$D = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$Domain = [ADSI]"LDAP://$D"
$ADSearch = New-Object System.DirectoryServices.DirectorySearcher
$ADSearch.SearchRoot ="LDAP://$Domain
This will search for the current domain. What should I do to get values from PDC?
Each Domain Controller keeps the server with PDC Emulator FSMO role updated with its count (so that the account can be locked out if the maximum number is exceeded), the total is not easily tracked, so we have to query each domain controller separately for that number.
# Import active directory modules
import-module activedirectory;
# Get all domain controllers
$dcs = get-adcomputer -filter * -searchbase "ou=domain controllers,dc=kamal,dc=local";
# Get all users - change "-filter {enabled -eq $true}" to a username to get just one user
$users = get-aduser -filter {enabled -eq $true} | sort name;
# Loop through all users found
foreach ($user in $users) {
$badpwdcount = 0;
# Loop through each domain controller
foreach ($dc in $dcs) {
$newuser = get-aduser $user.samaccountname -server $dc.name -properties badpwdcount;
# Increment bad password count
$badpwdcount = $badpwdcount + $newuser.badpwdcount;
}
# Highlight account if bad password count is greater than 0
if ($badpwdcount -gt 0) {
$outline = "******* " + $user.name + " - Badpwdcount: " + $badpwdcount + " *******";
}
else {
$outline = $user.name + " - Badpwdcount: " + $badpwdcount;
}
write-host $outline;
}
$Domain = $Domain.PdcRoleOwner

Powershell API Post Variable to Ducksboard

Trying to use the following Powershell script which I've taken from Github to push data into a Ducksboard dashboard. The function works excellently however I need to feed in a variable as part of the data. Of the two calls to the function included below the function which pushes in the actual value 44 works fine, however if I substitute it for my variable $qtybord the function falls over. I've tried a number of options to overcome the var being within the single quotes but cannot get it to work - can anyone help me?
# Squirt data to Duscksboard
function Execute-DucksboardApi
{
param(
[string] $url = $null,
[string] $data = $null,
[string] $apikey = $null,
[string] $contentType = "application/json",
[string] $codePageName = "UTF-8",
[string] $userAgent = $null
);
if ($url -and $data -and $apikey)
{
[System.Net.WebRequest]$webRequest = [System.Net.WebRequest]::Create($url);
$webRequest.ServicePoint.Expect100Continue = $false;
[System.Net.NetworkCredential]$credentials = New-Object System.Net.NetworkCredential($apikey, 'ignored');
$webRequest.Credentials = $credentials.GetCredential($url, 'Basic');
$webRequest.PreAuthenticate = $true;
$webRequest.ContentType = $contentType;
$webRequest.Method = "POST";
if ( $userAgent )
{
$webRequest.UserAgent = $userAgent;
}
$enc = [System.Text.Encoding]::GetEncoding($codePageName);
[byte[]]$bytes = $enc.GetBytes($data);
$webRequest.ContentLength = $bytes.Length;
[System.IO.Stream]$reqStream = $webRequest.GetRequestStream();
$reqStream.Write($bytes, 0, $bytes.Length);
$reqStream.Flush();
$resp = $webRequest.GetResponse();
$rs = $resp.GetResponseStream();
[System.IO.StreamReader]$sr = New-Object System.IO.StreamReader -argumentList $rs;
$sr.ReadToEnd();
}
}
$qtybord = 44
Execute-DucksboardApi -url 'https://push.ducksboard.com/v/123752/' -data '{"value": $qtybord}' -apikey 'tu2j3d3epqytWZD1haHnjJSJ1NqBrmvPe5SONc0VYge4BbIPi0'
Execute-DucksboardApi -url 'https://push.ducksboard.com/v/123752/' -data '{"value": 44}' -apikey 'tu2j3d3epqytWZD1haHnjJSJ1NqBrmvPe5SONc0VYge4BbIPi0'
*
try this:
-data "{`"value`": $qtybord}"
or
-data "{""value"": $qtybord}"
in single quote variable aren't expanded, in double quote you need to escape the double quote inside the string.
So make the -data parameter take $data instead and make $data = '{"value": ' + $qtyboard + '}' or just wrap that whole thing in parens after -data.
Also, if you're on PowerShell v3 you can play with something like this:
$data = New-Object -Type PSObject -Property #{
value = $qtyboard
} | ConvertTo-JSON

Resources