killchain-compendium/post exploitation/Seatbelt/Seatbelt/Commands/Windows/EventLogs/PoweredOnEventsCommand.cs

117 lines
4.1 KiB
C#

#nullable disable
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using Seatbelt.Output.Formatters;
using Seatbelt.Output.TextWriters;
namespace Seatbelt.Commands.Windows.EventLogs
{
internal class PoweredOnEventsCommand : CommandBase
{
public override string Command => "PoweredOnEvents";
public override string Description => "Reboot and sleep schedule based on the System event log EIDs 1, 12, 13, 42, and 6008. Default of 7 days, argument == last X days.";
public override CommandGroup[] Group => new[] {CommandGroup.System, CommandGroup.Remote};
public override bool SupportRemote => true;
public Runtime ThisRunTime;
public PoweredOnEventsCommand(Runtime runtime) : base(runtime)
{
ThisRunTime = runtime;
}
public override IEnumerable<CommandDTOBase?> Execute(string[] args)
{
// queries event IDs 12 (kernel boot) and 13 (kernel shutdown), sorts, and gives reboot schedule
// grab events from the last X days - 15 for default
var lastDays = 7;
if (!Runtime.FilterResults)
{
lastDays = 30;
}
if (args.Length == 1)
{
if (!int.TryParse(args[0], out lastDays))
{
WriteError("Could not parse number");
yield break;
}
}
WriteHost($"Collecting kernel boot (EID 12) and shutdown (EID 13) events from the last {lastDays} days\n");
WriteHost("Powered On Events (Time is local time)");
var startTime = DateTime.Now.AddDays(-lastDays);
var endTime = DateTime.Now;
// eventID 1 == sleep
var query = $@"
((*[System[(EventID=12 or EventID=13) and Provider[@Name='Microsoft-Windows-Kernel-General']]] or *[System/EventID=42]) or (*[System/EventID=6008]) or (*[System/EventID=1] and *[System[Provider[@Name='Microsoft-Windows-Power-Troubleshooter']]])) and *[System[TimeCreated[@SystemTime >= '{startTime.ToUniversalTime():o}']]] and *[System[TimeCreated[@SystemTime <= '{endTime.ToUniversalTime():o}']]]
";
var logReader = ThisRunTime.GetEventLogReader("System", query);
for (var eventDetail = logReader.ReadEvent(); eventDetail != null; eventDetail = logReader.ReadEvent())
{
string action = null;
switch (eventDetail.Id)
{
case 1:
action = "awake";
break;
case 12:
action = "startup";
break;
case 13:
action = "shutdown";
break;
case 42:
action = "sleep";
break;
case 6008:
action = "shutdown(UnexpectedShutdown)";
break;
}
yield return new PoweredOnEventsDTO()
{
DateUtc = (DateTime)eventDetail.TimeCreated?.ToUniversalTime(),
Description = action
};
}
}
}
internal class PoweredOnEventsDTO : CommandDTOBase
{
public DateTime DateUtc { get; set; }
public string Description { get; set; }
}
[CommandOutputType(typeof(PoweredOnEventsDTO))]
internal class PoweredOnEventsTextFormatter : TextFormatterBase
{
private string _currentDay = "";
public PoweredOnEventsTextFormatter(ITextWriter writer) : base(writer)
{
}
public override void FormatResult(CommandBase? command, CommandDTOBase result, bool filterResults)
{
var dto = (PoweredOnEventsDTO)result;
if (_currentDay != dto.DateUtc.ToShortDateString())
{
_currentDay = dto.DateUtc.ToShortDateString();
WriteLine();
}
WriteLine($" {dto.DateUtc.ToLocalTime(),-23} : {dto.Description}");
}
}
}
#nullable enable