I'm writing a C# program that looks through the Windows event logs for remote desktop login attempts, then reports the logins with a csv of the time, IP addresses, username and domain. I can make it successfully read failed login attempts via the 'Security' log on event 4625, but I would like to make it be able to read successful login attempts, which are logged as event 1149 under 'Applications & Services logs -> Microsoft -> Windows -> terminalservices-remoteconnectionmanager -> Operational'. I've tried going to the event viewer to get the name of 'Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational', but it says it can't find the log. Here's the function I'm using to check:
using System.Diagnostics.Eventing.Reader;
(...)
private void CheckEventLog()
{
if (exportPath == null)
{
// Program exports result as a CSV file, this shows an error if an export path is not specified
DialogResult errorBox = MessageBox.Show("Please input an export path.", "Export error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (compInput.Text == "")
{
// For connecting to another computers logs; commented out because not working
// Normally this selects the executing computers name if nothing is inputted
// comp = Convert.ToString(System.Environment.MachineName);
}
else
{
comp = Convert.ToString(System.Environment.MachineName); // Same as above, but moved here so it always runs while the net function is disabled
// comp = compInput.ToString(); // This takes the computer name input from the box (if we were using that function)
username = usrImp.ToString();
password = pasImp.ToString();
SecureString securePassword = new SecureString();
// ^^ those 3 lines are also for if using net
foreach (char c in password)
{
securePassword.AppendChar(c);
}
// Normally there would be a } here, but since net is disabled AND there's warning text in compInput, we need the whole function to operate in the else statement
// Time to connect to the event log...
EventLogSession session = new EventLogSession(
comp, // On <- this computer (while net is disabled, on local computer)
username, // With this username
null, // On this domain (disabled)
securePassword, // With this password
SessionAuthentication.Default);
}
string FilePath = Convert.ToString(exportPath.Text);
// Creating the header for the CSV output
string csvHeader = "Date/Time,IP Address,Account Name,Account Domain";
var csv = new StringBuilder();
csv.AppendLine(csvHeader);
// Check the event log, logChoice is the input of the log input TextBox (My two examples are 'Security' [working] and 'Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational' [not working])
EventLog eventLog = new EventLog(logChoice, comp);
try
{
foreach (EventLogEntry entry in eventLog.Entries) // For each entry in the event log, check to see if the event number matches the one we're searching for
{
if (entry.InstanceId.ToString() == eventChoice)
{
// Console lines commented out, ready for use when debugging
// Console.WriteLine($"Event ID: {entry.InstanceId}");
// Console.WriteLine($"Time: {entry.TimeGenerated}");
DateTime Time = Convert.ToDateTime(entry.TimeGenerated);
// Console.WriteLine(Time);
// Console.WriteLine($"Message: {entry.Message}");
string message = entry.Message;
string ip = GetIP(message); // GetIP is a regex function to get extract an IP address from the event
// Console.WriteLine(ip);
string acc = GetAcc(message); // GetAcc is another regex function to get the account name attempting to log in
// Console.WriteLine(acc);
string domain = GetDomain(message); // Same as other two but for domain
// Console.WriteLine(domain);
string csvOutput = Time + "," + ip + "," + acc + "," + domain; // Formats the time, ip, account, and domain into a CSV string
Console.WriteLine(csvOutput);
csv.AppendLine(csvOutput.ToString());
}
}
eventLog.Close();
File.WriteAllText(FilePath, csv.ToString()); // Write out the csv file
csvOUT = csv.ToString();
}
// Error handling
catch (IOException ex)
{
DialogResult result = MessageBox.Show($"Error: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (InvalidOperationException IO)
{
DialogResult result = MessageBox.Show($"Error: {IO.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return;
}
I've tried removing the "/operational", replacing the dashes with slashes and vise versa, adding the "Applications & services", etc.
Thanks in advance. :)
