This is something I created to return a True or False whether or not specified computer certificates are installed. It writes this information to the registry for desktop management software scanning. My original objective was just to determine whether or not an old (about to expire) cert still existed, but I went ahead and added detection for the new one as well.
# AUTHOR: Eddie Jackson
# DATE: 03/28/2017
# USAGE: To verify if specified certs are in local
# store
# NOTES: Desktop Management will report on reg keys
# set to TRUE or FALSE
Clear-Host
# OLD Cert Thumbprint
$Cert1 = "12345678912C7409FBF28C86D208637123456789"
# New Cert Thumbprint
$Cert2 = "FD5C3FC1F3C405D1D468EF0A0A12345678912345"
# Reg Path
$RegPath = 'HKLM:\SOFTWARE\COMPANY\AppName\Cert'
# Clear Session
$OLD = ""
$NEW = ""
Remove-ItemProperty -Path $RegPath -Name "$Cert1" | Out-Null
Remove-ItemProperty -Path $RegPath -Name "$Cert2" | Out-Null
New-Item -Path $RegPath -Force | Out-Null
New-ItemProperty -Path $RegPath -Name "$Cert1" -Value "FALSE"
New-ItemProperty -Path $RegPath -Name "$Cert2" -Value "FALSE"
Start-Sleep 5 # time to verify reg keys are reset
# Assign Current Certs to variables
$OLD = Get-ChildItem Cert:\LocalMachine\My | Select -Property Thumbprint |
Where-Object {$_.Thumbprint -eq "$Cert1"} |
foreach { $_.Thumbprint }
$NEW = Get-ChildItem Cert:\LocalMachine\My | Select -Property Thumbprint |
Where-Object {$_.Thumbprint -eq "$Cert2"} |
foreach { $_.Thumbprint }
# Determine if Certs exist
if ($OLD -eq "$Cert1") {
#Write-Host "Old Exists"
New-ItemProperty -Path $RegPath -Name "$Cert1" -Value "TRUE" -Force | Out-Null
}
if ($NEW -eq "$Cert2") {
#Write-Host "New Exists"
New-ItemProperty -Path $RegPath -Name "$Cert2" -Value "TRUE" -Force | Out-Null
}
Microsoft has released a security update to address a vulnerability in implementations of Server Message Block 1.0 (SMBv1). Exploitation of this vulnerability could allow a remote attacker to take control of an affected system.
Note, ever since Windows 10 Build 1709, the reg keys don’t work so great (that’s because MS has removed the SMBv1 feature, altogether). Use dism or PowerShell cmdlets instead.
Disables the SMBv1 on the SMB client by running the below commands sc.exe config lanmanworkstation depend= bowser/mrxsmb20/nsi sc.exe config mrxsmb10 start= disabled
Enables the SMBv1 on the SMB client by running the below commands sc.exe config lanmanworkstation depend= bowser/mrxsmb10/mrxsmb20/nsi sc.exe config mrxsmb10 start= auto
Disables the SMBv2 and SMBv3 on the SMB client by running the below commands sc.exe config lanmanworkstation depend= bowser/mrxsmb10/nsi sc.exe config mrxsmb20 start= disabled
Enables the SMBv2 and SMBv3 on the SMB client by running the below commands sc.exe config lanmanworkstation depend= bowser/mrxsmb10/mrxsmb20/nsi sc.exe config mrxsmb20 start= auto
Here is a wmic command to return the value of the smBIOS UUID. Pretty useful for certain OS activation sequences and manually setting up a computer in SCCM.
Command wmic path win32_computersystemproduct get uuid
This is a quick way to update a client’s site code. Make sure you run as admin.
I ended up needing this, because while our SCCM was being configured at the forest level (which took a while), I was already testing the SCCM server. Without this, the clients could not communicate with the server.
Set objShell = CreateObject("WScript.Shell")
set objSMSClient = CreateObject ("Microsoft.SMS.Client")
'update site code
objSMSClient.SetAssignedSite "ABC",0
'restart process
objShell.Run "C:\Windows\CCM\CcmRestart.exe",0,true
msgbox " Site code has been changed!"
This will return missing patches (missing security and critical updates) based upon a KB text file. I used a fully patched computer + the published KBs from a patch server to create a master KBs.txt file. The KB file contains KBs by the numbers: KB11111, KB22222, etc (one per line). I also have a computers.txt file which permits you to query missing updates on multiple computers, remotely. Just to verify it was at least hitting the right ballpark number, I installed Belarc to crosscheck missing updates. So far, it has been 100% accurate.
The data comes out in CSV format (click image to zoom)
What you need
KBs.txt
Computers.txt
Admin access
The script I created below
Clear-Host
# Path to files
$filePath = "C:\scripts"
# the computers to check
$computerList = Get-Content -Path "$filePath\computers.txt"
# the KBs to check
$patchList = Get-Content -Path "$filePath\KBs.txt"
$E_Total = "" # exists total
$NE_Total = "" # not exists total
$Count = 0 # missing updates counter
$BoolCheck = 0
foreach ($computer in $computerList)
{
# is machine online?
$Ping = test-connection -ComputerName $computer -Count 2 -quiet
# yes, online
if($Ping)
{
# get current list of hotfixes on machine
$HotfixList = Get-HotFix -ComputerName $computer | select -Property "HotFixID"
# cycle through each patch in list
foreach($patch in $patchList)
{
$BoolCheck=0
# cycle through hotfixes on local machine
foreach ($Hotfix in $HotfixList)
{
# compare local machine hotfixes with our list
# if it matches, exists
if ($patch -eq $Hotfix.HotFixID)
{
$BoolCheck=1
break
}
}
if ($found -eq 1) {
$E_Total = "$E_Total,$patch"
}
if ($BoolCheck -eq 0) {
# $patch
$NE_Total = "$NE_Total,$patch"
$Count=$Count+1
}
}
# Write-Host "Found: $Computer$E_Total"
Write-Host "$Computer,Missing $count$NE_Total"
Write-Host " "
# Clear session
$E_Total = ""
$NE_Total = ""
$Count = 0
$BoolCheck = 0
}
# no, not online
else
{
Write-Host "$Computer,Not Online"
Write-Host " "
}
}
The KBs in the KBs.txt file I used…though, yours will most likely be different due to imaging practices and new KB releases.
I wrote this in C# to encrypt and decrypt a password, which could be stored in a file, or perhaps the registry. It converts the password into a byte string, that byte string is converted using base64, and then is encrypted using AES. Take note, I have added permutations for the byte streams. These should be changed for every password you encrypt. One final thought, the overall security of this process depends on the protection of your C# code. So…compile this, and keep any source code in a secure location. This is not meant to be used as a secure app for distribution, just as a method to generate the encrypted password. If you’re trying to create a standalone app, look into AppendChar.
Screenshot
Code
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace SecurePassword
{
class Encode_Decode
{
public static class Global
{
// set password
public const string strPassword = "LetMeIn99$";
// set permutations
public const String strPermutation = "ouiveyxaqtd";
public const Int32 bytePermutation1 = 0x19;
public const Int32 bytePermutation2 = 0x59;
public const Int32 bytePermutation3 = 0x17;
public const Int32 bytePermutation4 = 0x41;
}
// The console window
public static void Main(String[] args)
{
Console.Title = "Secure Password v2";
Console.WriteLine("Output---");
Console.WriteLine("");
Console.WriteLine("Password: " + Global.strPassword);
string strEncrypted = (Encrypt(Global.strPassword));
Console.WriteLine("Encrypted: " + strEncrypted);
string strDecrypted = (Decrypt(strEncrypted));
Console.WriteLine("Decrypted: " + strDecrypted);
Console.ReadKey();
}
// encoding
public static string Encrypt(string strData)
{
return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(strData)));
// reference https://msdn.microsoft.com/en-us/library/ds4kkd55(v=vs.110).aspx
}
// decoding
public static string Decrypt(string strData)
{
return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(strData)));
// reference https://msdn.microsoft.com/en-us/library/system.convert.frombase64string(v=vs.110).aspx
}
// encrypt
public static byte[] Encrypt(byte[] strData)
{
PasswordDeriveBytes passbytes =
new PasswordDeriveBytes(Global.strPermutation,
new byte[] { Global.bytePermutation1,
Global.bytePermutation2,
Global.bytePermutation3,
Global.bytePermutation4
});
MemoryStream memstream = new MemoryStream();
Aes aes = new AesManaged();
aes.Key = passbytes.GetBytes(aes.KeySize/8);
aes.IV = passbytes.GetBytes(aes.BlockSize/8);
CryptoStream cryptostream = new CryptoStream(memstream,
aes.CreateEncryptor(), CryptoStreamMode.Write);
cryptostream.Write(strData, 0, strData.Length);
cryptostream.Close();
return memstream.ToArray();
}
// decrypt
public static byte[] Decrypt(byte[] strData)
{
PasswordDeriveBytes passbytes =
new PasswordDeriveBytes(Global.strPermutation,
new byte[] { Global.bytePermutation1,
Global.bytePermutation2,
Global.bytePermutation3,
Global.bytePermutation4
});
MemoryStream memstream = new MemoryStream();
Aes aes = new AesManaged();
aes.Key = passbytes.GetBytes(aes.KeySize/8);
aes.IV = passbytes.GetBytes(aes.BlockSize/8);
CryptoStream cryptostream = new CryptoStream(memstream,
aes.CreateDecryptor(), CryptoStreamMode.Write);
cryptostream.Write(strData, 0, strData.Length);
cryptostream.Close();
return memstream.ToArray();
}
// reference
// https://msdn.microsoft.com/en-us/library/system.security.cryptography(v=vs.110).aspx
// https://msdn.microsoft.com/en-us/library/system.security.cryptography.cryptostream%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
// https://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes(v=vs.110).aspx
// https://msdn.microsoft.com/en-us/library/system.security.cryptography.aesmanaged%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
}
}
This is hashing I’ve done in C#. I have included MD5, SHA1, SHA256, SHA384, and SHA512, the hashes, and then validation of a working versus non-working password.
Screenshot
The code…just copy/paste into Visual Studio Console Project and compile.
using System;
using System.Text;
using System.Security.Cryptography;
public class ReturnHash
{
public static string ComputeHash(string plainText, string hashAlgorithm, byte[] saltBytes)
{
// Salt size
saltBytes = new byte[8];
// Convert Text to Array
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
// Create Array
byte[] plainTextSaltBytes =
new byte[plainTextBytes.Length + saltBytes.Length];
// Copy Text into Array
for (int i = 0; i < plainTextBytes.Length; i++)
plainTextSaltBytes[i] = plainTextBytes[i];
// Append Salt
for (int i = 0; i < saltBytes.Length; i++)
plainTextSaltBytes[plainTextBytes.Length + i] = saltBytes[i];
// Algorithm
HashAlgorithm hash;
// Initialize Class
switch (hashAlgorithm.ToUpper())
{
case "SHA1":
hash = new SHA1Managed();
break;
case "SHA256":
hash = new SHA256Managed();
break;
case "SHA384":
hash = new SHA384Managed();
break;
case "SHA512":
hash = new SHA512Managed();
break;
default:
hash = new MD5CryptoServiceProvider();
break;
}
byte[] hashBytes = hash.ComputeHash(plainTextSaltBytes);
byte[] hashSaltBytes = new byte[hashBytes.Length +
saltBytes.Length];
// Hash to Array
for (int i = 0; i < hashBytes.Length; i++)
hashSaltBytes[i] = hashBytes[i];
// Append Salt
for (int i = 0; i < saltBytes.Length; i++)
hashSaltBytes[hashBytes.Length + i] = saltBytes[i];
// Convert result into a base64-encoded string.
string hashValue = Convert.ToBase64String(hashSaltBytes);
// Return Result
return hashValue;
}
public static bool VerifyHash(string plainText,
string hashAlgorithm,
string hashValue)
{
// Base64-encoded hash
byte[] hashWithSaltBytes = Convert.FromBase64String(hashValue);
// Hash without Salt
int hashSizeInBits, hashSizeInBytes;
// Size of hash is based on the specified algorithm.
switch (hashAlgorithm.ToUpper())
{
case "SHA1":
hashSizeInBits = 160;
break;
case "SHA256":
hashSizeInBits = 256;
break;
case "SHA384":
hashSizeInBits = 384;
break;
case "SHA512":
hashSizeInBits = 512;
break;
default: // MD5
hashSizeInBits = 128;
break;
}
// Convert to bytes.
hashSizeInBytes = hashSizeInBits / 8;
// Verify Hash Length
if (hashWithSaltBytes.Length < hashSizeInBytes)
return false;
// Array to hold Salt
byte[] saltBytes = new byte[hashWithSaltBytes.Length -
hashSizeInBytes];
// Salt to New Array
for (int i = 0; i < saltBytes.Length; i++)
saltBytes[i] = hashWithSaltBytes[hashSizeInBytes + i];
string expectedHashString =
ComputeHash(plainText, hashAlgorithm, saltBytes);
return (hashValue == expectedHashString);
}
}
public class PasswordEncodingTest1
{
[STAThread]
static void Main(string[] args)
{
// Test Passwords
string rightPassword = "TRUEPassword$";
string wrongPassword = "FALSEPassword$";
string passwordHashMD5 =
ReturnHash.ComputeHash(rightPassword, "MD5", null);
string passwordHashSha1 =
ReturnHash.ComputeHash(rightPassword, "SHA1", null);
string passwordHashSha256 =
ReturnHash.ComputeHash(rightPassword, "SHA256", null);
string passwordHashSha384 =
ReturnHash.ComputeHash(rightPassword, "SHA384", null);
string passwordHashSha512 =
ReturnHash.ComputeHash(rightPassword, "SHA512", null);
Console.WriteLine("Hash and Comparison--- \r\n");
// md5
Console.WriteLine("MD5 {0}", passwordHashMD5);
Console.WriteLine("Right PW MD5 {0}",
ReturnHash.VerifyHash(
rightPassword, "MD5",
passwordHashMD5).ToString());
Console.WriteLine("Wrong PW MD5 {0}",
ReturnHash.VerifyHash(
wrongPassword, "MD5",
passwordHashMD5).ToString());
Console.WriteLine("");
// reference https://en.wikipedia.org/wiki/MD5
// https://msdn.microsoft.com/en-us/library/system.security.cryptography.md5(v=vs.110).aspx
// sha1
Console.WriteLine("SHA1 {0}", passwordHashSha1);
Console.WriteLine("Right PW SHA1 {0}",
ReturnHash.VerifyHash(
rightPassword, "SHA1",
passwordHashSha1).ToString());
Console.WriteLine("Wrong PW SHA1 {0}",
ReturnHash.VerifyHash(
wrongPassword, "SHA1",
passwordHashSha1).ToString());
Console.WriteLine("");
// reference https://en.wikipedia.org/wiki/SHA-1
// https://msdn.microsoft.com/en-us/library/system.security.cryptography.sha1(v=vs.110).aspx
// sha256
Console.WriteLine("SHA256 {0}", passwordHashSha256);
Console.WriteLine("Right PW SHA256 {0}",
ReturnHash.VerifyHash(
rightPassword, "SHA256",
passwordHashSha256).ToString());
Console.WriteLine("Wrong PW SHA256 {0}",
ReturnHash.VerifyHash(
wrongPassword, "SHA256",
passwordHashSha256).ToString());
Console.WriteLine("");
// reference https://en.wikipedia.org/wiki/SHA-2
// https://msdn.microsoft.com/en-us/library/system.security.cryptography.sha256(v=vs.110).aspx
// sha384
Console.WriteLine("SHA384 {0}", passwordHashSha384);
Console.WriteLine("Right PW SHA384 {0}",
ReturnHash.VerifyHash(
rightPassword, "SHA384",
passwordHashSha384).ToString());
Console.WriteLine("Wrong PW SHA384 {0}",
ReturnHash.VerifyHash(
wrongPassword, "SHA384",
passwordHashSha384).ToString());
Console.WriteLine("");
// reference https://msdn.microsoft.com/en-us/library/system.security.cryptography.sha384(v=vs.110).aspx
// sha512
Console.WriteLine("SHA512 {0}", passwordHashSha512);
Console.WriteLine("Right PW SHA512 {0}",
ReturnHash.VerifyHash(
rightPassword, "SHA512",
passwordHashSha512).ToString());
Console.WriteLine("Wrong PW SHA512 {0}",
ReturnHash.VerifyHash(
wrongPassword, "SHA512",
passwordHashSha512).ToString());
// reference https://msdn.microsoft.com/en-us/library/system.security.cryptography.sha512(v=vs.110).aspx
Console.WriteLine("");
Console.WriteLine("");
Console.ReadKey();
}
}
I created this to store passwords in a more secure manner. It could be used to encode a password, and also to retrieve and decode a password. I do permutations based upon a specified number to perform the shift in ASCII (polyalphabetic substitution cipher), but…I’d also like to add a more advanced method, which would increase the complexity of encoding using multiple formulas based upon positioning. As this will be considered v1, I’ll post v2 when complete.
In v2 (to provide better security for passwords, specifically), what I’m going to do is create unique formulas for each position. It may be written in VB or C#.
So, a potential password, let’s say LetMeIn99$, could look like this once encoded: AAAAAAAAAA.
The idea is that there is zero correlation between one position, to the next, as seen from the onlooker.
From Bruce Schneier’s Applied Cryptography, 2nd edition…
Substitution Ciphers
A substitution cipher is one in which each character in the plaintext is substituted for another character in the ciphertext. The receiver inverts the substitution on the ciphertext to recover the plaintext. In classical cryptography, there are four types of substitution ciphers:
— A simple substitution cipher, or monoalphabetic cipher, is one in which each character of the plaintext is replaced with a corresponding character of ciphertext. The cryptograms in newspapers are simple substitution ciphers.
— A homophonic substitution cipher is like a simple substitution cryptosystem, except a single character of plaintext can map to one of several characters of ciphertext. For example, “A” could correspond to either 5, 13, 25, or 56, “B” could correspond to either 7, 19, 31, or 42, and so on.
— A polygram substitution cipher is one in which blocks of characters are encrypted in groups. For example, “ABA” could correspond to “RTQ,” “ABB” could correspond to “SLL,” and so on.
— A polyalphabetic substitution cipher is made up of multiple simple substitution ciphers. For example, there might be five different simple substitution ciphers used; the particular one used changes with the position of each character of the plaintext.
The famous Caesar Cipher, in which each plaintext character is replaced by the character three to the right modulo 26 (“A” is replaced by “D,” “B” is replaced by “E,”…, “W” is replaced by “Z,” “X” is replaced by “A,” “Y” is
replaced by “B,” and “Z” is replaced by “C”) is a simple substitution cipher. It’s actually even simpler, because the ciphertext alphabet is a rotation of the plaintext alphabet and not an arbitrary permutation.
ROT13 is a simple encryption program commonly found on UNIX systems; it is also a simple substitution cipher. In this cipher, “A” is replaced by “N,” “B” is replaced by “O,” and so on. Every letter is rotated 13 places. Encrypting a file twice with ROT13 restores the original file.
P = ROT13 (ROT13 (P))
ROT13 is not intended for security; it is often used in Usenet posts to hide potentially offensive text, to avoid giving away the solution to a puzzle, and so forth.
Simple substitution ciphers can be easily broken because the cipher does not hide the underlying frequencies of the different letters of the plaintext. All it takes is about 25 English characters before a good cryptanalyst can reconstruct the plaintext [1434]. An algorithm for solving these sorts of ciphers can be found in [578,587,1600,78,1475,1236,880]. A good computer algorithm is [703].
Homophonic substitution ciphers were used as early as 1401 by the Duchy of Mantua [794]. They are much more complicated to break than simple substitution ciphers, but still do not obscure all of the statistical properties of the plaintext language. With a known-plaintext attack, the ciphers are trivial to break. A ciphertext-only attack is harder, but only takes a few seconds on a computer. Details are in [1261].
Polygram substitution ciphers are ciphers in which groups of letters are encrypted together. The Playfair cipher, invented in 1854, was used by the British during World War I [794]. It encrypts pairs of letters together. Its cryptanalysis is discussed in [587,1475,880]. The Hill cipher is another example of a polygram substitution cipher [732]. Sometimes you see Huffman coding used as a cipher; this is an insecure polygram substitution cipher.
Polyalphabetic substitution ciphers were invented by Leon Battista in 1568 [794]. They were used by the Union army during the American Civil War. Despite the fact that they can be broken easily [819,577,587,794] (especially with the help of computers), many commercial computer security products use ciphers of this form [1387,1390,1502]. (Details on how to break this encryption scheme, as used in WordPerfect, can be found in [135,139].) The Vigenère cipher, first published in 1586, and the Beaufort cipher are also examples of polyalphabetic substitution ciphers.
Polyalphabetic substitution ciphers have multiple one-letter keys, each of which is used to encrypt one letter of the plaintext. The first key encrypts the first letter of the plaintext, the second key encrypts the second letter of the plaintext, and so on. After all the keys are used, the keys are recycled. If there were 20 one-letter keys, then every twentieth letter would be encrypted with the same key. This is called the period of the cipher. In classical cryptography, ciphers with longer periods were significantly harder to break than ciphers with short periods. There are computer techniques that can easily break substitution ciphers with very long periods.
A running-key cipher—sometimes called a book cipher—in which one text is used to encrypt another text, is another example of this sort of cipher. Even though this cipher has a period the length of the text, it can also be broken easily [576,794].