1

I am trying to get the source network address for an RDP connection to send an email when a user connects to the server. I have everything but the source address. My script is triggered by event 1149 in the RemoteConnectionManager Operational log. I only need to access either the event data or source address from the system.

$SmtpClient = new-object system.net.mail.smtpClient
$MailMessage = New-Object system.net.mail.mailmessage
$SmtpClient.Host = "mail.scomage.com"
$mailmessage.from = ("[email protected]")
$mailmessage.To.add("[email protected]")
$mailmessage.Subject = “BWAQB RDP”
$mailmessage.Body = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name + “ logged into BWA QB Server”
$smtpclient.Send($mailmessage)

Final script after excellent help by Steven:

$LastEvent = Get-WinEvent -FilterHashtable `
    @{ LogName = "Microsoft-Windows-TerminalServices- 
RemoteConnectionManager/Operational"; Id = 1149} |
Select-Object *,
    @{ Name = 'UserName'; Expression = `
        { if ($_.Properties[0].Value) { $_.Properties[0].Value } else { "Administrator" } } },
    @{ Name = 'SourceIP'; Expression = { $_.Properties[2].Value } } |
Sort-Object TimeCreated |
Select-Object -Last 1

$MailParams = 
@{
    SmtpServer = "mail.scomage.com"
    From       = "[email protected]"
    To         = "[email protected]"
    Subject    = "BWAQB RDP " + $LastEvent.UserName + " " + $LastEvent.SourceIP
    Body       = $LastEvent.UserName + " logged into BWA QB Server at " + `
    $LastEvent.TimeCreated.ToString('g') + " From: " + $LastEvent.SourceIP
}

Send-MailMessage @MailParams

Script to send logon email:

$Event = Get-WinEvent -FilterHashTable @{
    LogName='Security'; ID=4624; StartTime=$DateLess10; } |
    Where-Object{$_.Properties[8].Value -eq 10 } | 
    Sort-Object TimeCreated |
    Select-Object -Last 1 

if( $Event.Properties[8].Value -eq 10 )
{
    $MailParams = 
    @{
        SmtpServer = "mail.scomage.com"
        From       = "[email protected]"
        To         = "[email protected]"
        Subject    = "BWAQB Remote Login " + $Event.Properties[5].Value + " " + $Event.Properties[18].Value
        Body       = $Event.Properties[5].Value + " logged into BWA QB Server at " + `
        $Event.TimeCreated.ToString('g') + " From: " + $Event.Properties[18].Value
    }
    Send-MailMessage @MailParams
}

1 Answer 1

2

Updated Based on Comments

Looks like the source address for the connection is recorded as the 3rd property in event 1149. Properties are an object array of type [System.Diagnostics.Eventing.Reader.EventProperty[]] which just means you have to access the sub-property .Value .

An example to get the last event:

$LastEvent =
Get-WinEvent -FilterHashtable @{ LogName = "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational"; Id = 1149} |
Select-Object *,
    @{ Name = 'UserName'; Expression = { $_.Properties[0].Value } },
    @{ Name = 'SourceIP'; Expression = { $_.Properties[2].Value } } |
Sort-Object TimeCreated |
Select-object -Last 1

Since I'm not sure Get-WinEvent will guarantee chronological order the the Sort-Object cmdlet is used. So it should result in the the last 1149 event. However, it doesn't guarantee it will be for the user that was returned by System.Security.Principal.WindowsIdentity]::GetCurrent().Name. I don't know what kind of machine this is or under what circumstances the script will be run. For example if it's a multi-user system (implied by Terminal Server) I suspect there's an edge case where last event may not be for the current user.

So, I'm guessing that we should isolate the last event for that user. We can do that with one of these samples:

Option 1:

$NTUserName = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$UserName = $NTUserName.Split('\')[-1]

$Events =
Get-WinEvent -FilterHashtable @{ LogName = "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational"; Id = 1149} |
Select-Object *,
    @{ Name = 'UserName'; Expression = { $_.Properties[0].Value } },
    @{ Name = 'SourceIP'; Expression = { $_.Properties[2].Value } } |
Group-Object -Property UserName -AsHashTable -AsString

$LastEvent = ($Events[$UserName] | Sort-Object TimeGenerated)[-1]

Option 2:

$NTUserName = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$UserName = $NTUserName.Split('\')[-1]

$LastEvent =
Get-WinEvent -FilterHashtable @{ LogName = "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational"; Id = 1149} |
Select-Object *,
    @{ Name = 'UserName'; Expression = { $_.Properties[0].Value } },
    @{ Name = 'SourceIP'; Expression = { $_.Properties[2].Value } } |
Where-Object{ $_.UserName -eq $UserName } |
Sort-Object TimeCreated |
Select-Object -Last 1

In both cases $LastEvent should have the last 1149 event for the current user. The first option has less sorting, because it is only sorting events for the specific user. you can use $LastEvent.SourceIP for the email.

A secondary note: You don't need to use System.Net.Mail.SMTPClient. you can use Send-MailMessage combined with command splatting that might look like:

$MailParams = 
@{
    SmtpServer = "mail.scomage.com"
    From       = "[email protected]"
    To         = "[email protected]"
    Subject    = "BWAQB RDP"
    Body       = $UserName + " logged into BWA QB Server at " + $LastEvent.TimeCreated.ToString('g') + " From: " + $LastEvent.SourceIP
}

Send-MailMessage @MailParams

Note: Above was also updated after your comments to take advantage of the newer revisions. Note: .ToString('g') results in date format like '6/30/2020 9:17 PM'

I'm not sure if the body or subject is exactly right, but you can work that out.

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for the response! I am an "old" guy who is way more comfortable in DOS than PowerShell. :) Do I have to do anything specific to make sure the select pulls the information from the most recent event 1149? Also, if I understand correctly, the select places all of the 1149 events in the log. Will they be in date order descending like they are presented in event viewer interface? If so, how do I access the first array element. Sorry to sound so naive. I am a longtime developer in many different languages, just not powershell.
Thanks again for all the details. I have posted my final script at the end of the question. With your help and a little Googling, my script does exactly what I need. It turns out the System.Security.Principal.WindowsIdentity]::GetCurrent().Name was always administrator since the scheduled task ran as that id. The users won't be connecting so fast (only 4 users) that I need to worry about getting the wrong log entry.
I thought this was working perfectly except that when the user id is null, it is not always the administrator. The null log entries are caused when the credentials are saved in the connector and the user does not have to enter the password. I was looking at the security log for logon events and I found what I think I need, but I don't know how to filter the get event by logon type 10. Those are the remote logins but it is the [8] of the property array. Can I filter by that?
I'm surprised I would think it logs the username regardless. I don't know of a way to do it directly, but you can add a | Where-Object{$_.Properties[8].Value -eq "UserName" after the Get-WinEvent command. Also you can limit the depth of the search by adding the StartTime = [DateTime] to the FilterHashtable. Example #15 in the help document shows a good example of that.
Apparently since the script is kicked off by the task manager and it runs under the administrator id then the session the script runs in is the administrator. I don't know why the saved user doesn't come through in the log. Good old Microsoft. Obviously saved creds follow a different logic path that doesn't populate those fields. Lazy programming!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.