Monday, June 6, 2011

Find a logged on users computer name

One thing that is hard to track down without 3rd party tools or something like SCCM is finding the computer name of a domain user that he/she is using or last used. And those that do even just a little help desk support get a sour taste in their mouth when they begin to ask the question, "Do you know what your computer name is"?

Well, with a little work up front you should be able to get this info a bit easier without asking the user for any information. What you have to enable is pretty simple:

Enabling 'Audit Account Logon Events' for your domain controller policy so that all your domain controllers will audit Successful, or failure, user logon attempts. Your can read more about this here. Once you have auditing enabled you might want to increase the size of your security event log size because the log begins to fill up very quickly, especially if your auditing more then just the Account logon events.

Once you have enabled Account Logon events all successful user requests for Kerberos tickets will be logged in the Security Log at event id: 4768. Now all we have to do is query the DC for this event and parse the event for the username, computer name and time it was requested. Now I know there are problems with this method. Such as, what if you have hundreds of domain controllers, how would you know what DC authenticated that user? Or that user has been logged into several other computers? Well one of those problems can be resolved if you have event log forwarding for this event on your domain to a centralized server, this can only be used if you have Windows Server 2008 however. Anyhow, here is the script.

function Get-UserComputerName {
<# .SYNOPSIS Searches a specified Domain Controller for the computername of a logged on user. .DESCRIPTION Queries a DC for Event ID 4768 (Kerberos authentication ticket,TGT) request from the servers Security event log. .PARAMETER UserName SamAccount name of the user to search for .EXAMPLE PS> .\Get-UserComputerName -UserName "John_Doe" -Server "My_DC"
Searches for user John_Doe on Domain Controller My_DC
.EXAMPLE
PS> .\Get-UserComputerName -Username "John_Doe"
Searches for user John_Doe using the logged on server name for the current user
running the script.
.EXAMPLE
PS> .\Get-UserComputerName
Searches the current user on the logged on server name
#>

param([string]$username = $env:username,[string]$server = $env:logonserver)
$ErrorActionPreference = "silentlycontinue"
if ($server.StartsWith("\\")) {$server = $server.Remove(0,2)}

$events = Get-WinEvent -ComputerName $server -MaxEvents 5 -FilterHashTable @{logname="security";id=4768;data=$username}
# Check if error has been raised from EventLog Query.
if (!$?) {Write-Warning "No successful logon events were found on Server: $server for Username: $username"
break
}

foreach ($event in $events) {
$myObject = New-Object -TypeName system.Object
[string]$Computer = $event.message.split("`n") | Select-String "Client Address"
$addressLine = $computer.replace("Client Address:",'')
$addressLine = $addressLine.trim()
if ($addressLine.startswith("::ffff:")) { $address = $addressLine.replace("::ffff:",'') }
$DNSResult = [system.Net.Dns]::Resolve($address)
$ComputerName = $DNSResult.HostName
$timeStamp = $event.timecreated

$myObject | Add-Member -MemberType noteproperty -Name AuthDC -Value $server
$myObject | Add-Member -MemberType noteproperty -Name TimeStamp -Value $timeStamp
$myObject | Add-Member -MemberType noteproperty -Name UserName -Value $username
$myObject | Add-Member -MemberType noteproperty -Name IPAddress -Value $address
$myObject | Add-Member -MemberType noteproperty -Name ComputerName -Value $computerName
$myObject
}
}

No comments: