如何在 Powershell 中进行 LM 哈希

How to LM Hash in Powershell

好的,所以我已经为此做了一些工作,但我看不出如何取得进一步的进展。我一直 运行 遇到 DESCryptoServiceProvider 的障碍,不知何故它似乎没有给出正确的答案。

LM_Hash 的 sudo 代码版本是:

LMHASH = concat(DES(Upper(PWD)[0..7],KGS!@#$%),DES(Upper(PWD)[8..13],KGS!@#$%))

第一个问题是 LM Key 我一直看到至少两个变体,它的 "KGS!@#$%" 或 "KGS!+#$%" 都没有给我正确的答案,但两者似乎都不符合起源故事(它的 KGS和 SHIFT 12345 假设美国键盘 在英国那就是 "KGS!"£$%")

我很确定我现在已经正确设置了参数,但我的理解似乎让我失望了。这是我到目前为止所拥有的,感谢任何帮助我是 运行 Powershell V5.1 on Win 10,要加密的字符串作为 $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()

理论上,这应该使用字符串的前 7 个字符 ($str1) 作为密钥(末尾有一个空字节)使用 DES 加密密钥(无论是哪个密钥),然后我们执行此操作到下半部分 ($str2) 并将它们连接在一起以获得 LMHASH。

ASCII 编码的字符串 KGS!@#$% 是正确的魔法常量

using the first 7 characters of the string ($str1) as the key (with a null byte on the end)

然而,这是不正确的。密钥不是通过在末尾用单个 0 字节填充部分输入的 7 个字节来组成的,而是通过将输入分成 8 个 7 位块并将它们左移一次(产生 8 个字节)来组成的。

在 PowerShell 中实现它的最简单方法可能是使用字符串,所以我可能会这样做:

# 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()
}

然后重复 $str2 并连接生成的块以获得完整的 LM 哈希

任何有问题的人,基于 @mathias R. Jessen 上面的答案,这里有一个函数计算 LM-Hash 的一半,输入 7 个字符串并将哈希输出为十六进制。

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()
}

这给出了一半哈希值的正确结果,因此将每一半单独输入并连接字符串即可得到完整的 LM 哈希值