Hi !
Here's a little PowerShell script to retrieve from the registry the username, Logon Date, Password Last Set and Creation date of the local users on a windows computer.
You can find here :
https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Get-username-fdcb6990
# Thanks to Boe Prox for his Get-RegistryKeyTimestamp function
(https://gallery.technet.microsoft.com/scriptcenter/Get-RegistryKeyLastWriteTim-63f4dd96)
function Get-RegistryKeyTimestamp
{
[OutputType('Microsoft.Registry.Timestamp')]
[cmdletbinding(
DefaultParameterSetName = 'ByValue'
)]
Param (
[parameter(ValueFromPipeline=$True, ParameterSetName='ByValue')]
[Microsoft.Win32.RegistryKey]$RegistryKey,
[parameter(ParameterSetName='ByPath')]
[string]$SubKey,
[parameter(ParameterSetName='ByPath')]
[Microsoft.Win32.RegistryHive]$RegistryHive,
[parameter(ParameterSetName='ByPath')]
[string]$Computername
)
Begin {
#region
Create Win32 API Object
Try
{
[void][advapi32]
} Catch
{
#region
Module Builder
$Domain
= [AppDomain]::CurrentDomain
$DynAssembly
= New-Object
System.Reflection.AssemblyName('RegAssembly')
$AssemblyBuilder
= $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) # Only run
in memory
$ModuleBuilder
= $AssemblyBuilder.DefineDynamicModule('RegistryTimeStampModule', $False)
#endregion
Module Builder
#region
DllImport
$TypeBuilder
= $ModuleBuilder.DefineType('advapi32', 'Public, Class')
#region
RegQueryInfoKey Method
$PInvokeMethod
= $TypeBuilder.DefineMethod(
'RegQueryInfoKey', #Method Name
[Reflection.MethodAttributes]
'PrivateScope, Public, Static, HideBySig,
PinvokeImpl', #Method Attributes
[IntPtr], #Method Return Type
[Type[]] @(
[Microsoft.Win32.SafeHandles.SafeRegistryHandle], #Registry Handle
[System.Text.StringBuilder],
#Class Name
[UInt32 ].MakeByRefType(), #Class Length
[UInt32], #Reserved
[UInt32 ].MakeByRefType(), #Subkey Count
[UInt32 ].MakeByRefType(), #Max Subkey Name
Length
[UInt32 ].MakeByRefType(), #Max Class Length
[UInt32 ].MakeByRefType(), #Value Count
[UInt32 ].MakeByRefType(), #Max Value Name
Length
[UInt32 ].MakeByRefType(), #Max Value Name
Length
[UInt32 ].MakeByRefType(), #Security
Descriptor Size
[long].MakeByRefType()
#LastWriteTime
) #Method
Parameters
)
$DllImportConstructor
= [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String]))
$FieldArray
= [Reflection.FieldInfo[]]
@(
[Runtime.InteropServices.DllImportAttribute].GetField('EntryPoint'),
[Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')
)
$FieldValueArray
= [Object[]] @(
'RegQueryInfoKey', #CASE SENSITIVE!!
$True
)
$SetLastErrorCustomAttribute
= New-Object
Reflection.Emit.CustomAttributeBuilder(
$DllImportConstructor,
@('advapi32.dll'),
$FieldArray,
$FieldValueArray
)
$PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute)
#endregion
RegQueryInfoKey Method
[void]$TypeBuilder.CreateType()
#endregion
DllImport
}
#endregion
Create Win32 API object
}
Process
{
#region
Constant Variables
$ClassLength
= 255
[long]$TimeStamp =
$null
#endregion
Constant Variables
#region
Registry Key Data
If
($PSCmdlet.ParameterSetName
-eq 'ByPath')
{
#Get
registry key data
$RegistryKey
= [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($RegistryHive,
$Computername).OpenSubKey($SubKey)
If
($RegistryKey -isnot
[Microsoft.Win32.RegistryKey]) {
Throw
"Cannot open or locate $SubKey on $Computername"
}
}
$ClassName
= New-Object
System.Text.StringBuilder $RegistryKey.Name
$RegistryHandle
= $RegistryKey.Handle
#endregion
Registry Key Data
#region
Retrieve timestamp
$Return
= [advapi32]::RegQueryInfoKey(
$RegistryHandle,
$ClassName,
[ref]$ClassLength,
$Null,
[ref]$Null,
[ref]$Null,
[ref]$Null,
[ref]$Null,
[ref]$Null,
[ref]$Null,
[ref]$Null,
[ref]$TimeStamp
)
Switch
($Return) {
0
{
#Convert
High/Low date to DateTime Object
$LastWriteTime
= [datetime]::FromFileTime($TimeStamp)
#Return
object
$Object
= [pscustomobject]@{
FullName = $RegistryKey.Name
Name = $RegistryKey.Name -replace
'.*\\(.*)','$1'
LastWriteTime = $LastWriteTime
}
$Object.pstypenames.insert(0,'Microsoft.Registry.Timestamp')
$Object
}
122
{
Throw
"ERROR_INSUFFICIENT_BUFFER (0x7a)"
}
Default
{
Throw
"Error ($return) occurred"
}
}
#endregion
Retrieve timestamp
}
}
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-LastLogonDate([byte[]]$F) {
$i=0
$lastLogon
= ""
$hexLastLogon
= @()
while($i -lt $F.Length) {
if($i -eq 8 -or ($i -gt 7 -and $i -lt 16)) {
$lastLogon
= $lastLogon
+ $F[$i]
$hexLastLogon
+= '{0:X2}'
-f $F[$i]
}
$i++
}
$i=$hexLastLogon.Length - 1
$lastLogon
= ""
while($i -ge 0) {
$lastLogon
= $lastLogon
+ $hexLastLogon[$i]
$i--
}
$lastLogon
= "0x$lastLogon"
return $lastLogon
}
function Get-PasswordLastSet([byte[]]$F) {
$i=0
$passwordLastSet
= ""
$hexPasswordLastSet
= @()
while($i -lt $F.Length) {
if($i -eq 24 -or ($i -gt 23 -and $i -lt 32)) {
$passwordLastSet
= $passwordLastSet
+ $F[$i]
$hexPasswordLastSet
+= '{0:X2}'
-f $F[$i]
}
$i++
}
$i=$hexPasswordLastSet.Length - 1
$passwordLastSet
= ""
while($i -ge 0) {
$passwordLastSet
= $passwordLastSet
+ $hexPasswordLastSet[$i]
$i--
}
$passwordLastSet
= "0x$passwordLastSet"
return $passwordLastSet
}
function Get-LastWriteTime($key) {
$RegistryKey
= Get-Item $key
$extendExport
= $RegistryKey
| Get-RegistryKeyTimestamp
return $extendExport
}
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 UserName
{Get-UserName($this.GetValue("V"))}
-PassThru |
Add-Member
ScriptProperty LastLogonDate
{Get-LastLogonDate($this.GetValue("F"))}
-PassThru |
Add-Member
ScriptProperty PasswordLastSet
{Get-PasswordLastSet($this.GetValue("F"))}
-PassThru
}
$localUsers = Get-UserKeys| %{
$logonDate
= $([datetime]::FromFileTime($_.LastLogonDate).ToLocalTime())
$passwordLastSet
= $([datetime]::FromFileTime($_.PasswordLastSet).ToLocalTime())
$subkey
= $_.UserName
$RegistryKey
= Get-Item "HKLM:\SAM\SAM\Domains\Account\Users\Names\$subkey"
$extendExport
= $RegistryKey
| Get-RegistryKeyTimestamp
$lastWriteTime
= $($extendExport.LastWriteTime.ToLocalTime())
"{0}::{1}::{2}::{3}"
-f ($_.UserName,$logonDate,$passwordLastSet,$lastWriteTime)}
"{0}::{1}::{2}::{3}" -f ("UserName","LogonDate","PasswordLastSet","LastWriteTime")
$localUsers
Result :
UserName::LogonDate::PasswordLastSet::LastWriteTime
Administrator::7/26/2012 3:22:17 AM::7/26/2012 3:27:03 AM::8/1/2015 10:10:34 AM
Guest::12/31/1600 7:00:00 PM::12/31/1600 7:00:00 PM::8/1/2015 10:10:34 AM
Test1::12/31/1600 7:00:00 PM::10/20/2013 3:53:30 AM::8/2/2015 4:36:30 PM
Test2::8/19/2013 1:30:05 AM::7/24/2013 3:47:52 PM::8/1/2015 10:10:34 AM
Test3::6/11/2015 7:16:26 PM::3/18/2015 5:12:51 PM::8/1/2015 10:10:34 AM
TestRegistry::8/1/2015 3:42:15 PM::8/1/2015 4:53:47 PM::8/1/2015 12:39:58 PM
Enjoy !