mirror of
https://github.com/matthastings/PSalander
synced 2026-06-08 15:46:17 +00:00
Initial public release
* inital commit * wc * wc * wc * wc * wc * wc * moving to module * restructing dirs * switch to module * moving lib into EventTrace module * add stop session * WIP commit * rewording * Add support for multiple ETW providers in single session * working commit * Deleting old folders and adding new functions * Adding gitignore * Starting to add pester tests * Adding more pester testing * rearrange get-etwsession function * small change to etwsession function * Add more pester testing * Updating readme * Rearranged session enumeration functions * Adds provider directory and some notes * Add in keyword object * Fix failing pester test * Fix start-session to accept object * Pester tests now invoke full etw session * small change to tests * Get-ProviderKeywords to Get-ETWProviderKeywords * First parser commit * Small update to process parser * Ignoring etl files * Adding Providers and notes on DNS * Adds DNS Event Ids and Descriptions * Adding more DNS info * Adds some PoC work for parsing DNS events to objects * Adds event parsing, but there's a bug * Add parser for kernel process * Updating function docs * Remove failing test * Starting to add network events * Adding network connection support * Small change to docs * Add Start-ETWForensicCollection function * Minor spelling fix * adding more notes to kernel process events * Adding provider exists check * Adds .DS_Store * Moves synopsis inside function * starting kernel file * Adding in file event parser * Fixing bug in process id parsing * Add logic for process reuse * Fix bug in process reuse code * Adding DLLs for kernel session * Adds DNS to Start-ETWForensicCollection * Fixing image load bug with process end time * Adding DNS to etwforensic collection and log parsing * Updating DNS parsing * Fixing bug in filtering and dns * Removing debug strings * Add in EnableVerbosity option to etwforensic func * Adding in thread start/stop events * Add in thread keyword to forensic collection func * Major reword to support thread tracking * Fixing bug in DNS tracking * fixing minor bug in thread net connections * Updating readme * small change to readme * Add in kernel session support to capture command line * Updating kernel session parsing code * Updating readme * Fixing path and infinite loop bugs * Add new write-log function for console logging * Adding support for different logging levels * fixing a bunch of bugs * Adding more example in the readme * Renaming module * Adding files for rename * Final rename commit * Adding demo content * Updating readme * More Readme updates * Readme changes * Last readme updates for the night * Adds dcdemo files * Fixing small thread parsing bug * Updating demo.txt * Adding new demo.xml * Minor tweaks to demo.txt * More demo updates * Demo all the things * Adding powershell logging * Adds compressed etl files * Updating demo materials * Demo updates * Demo tweaks * other minor demo tweaks * Adding graph function
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
.vscode/*
|
||||
*.etl
|
||||
.DS_Store
|
||||
@@ -0,0 +1,27 @@
|
||||
@{
|
||||
|
||||
RootModule = "PSWasp.psm1"
|
||||
|
||||
ModuleVersion = "0.0.0.1"
|
||||
|
||||
Author = "Matt Hastings & Dave Hull"
|
||||
|
||||
# functions to export
|
||||
FunctionsToExport = @(
|
||||
'ConvertTo-ETWGuid',
|
||||
'Get-ETWForensicEventLog',
|
||||
'Get-ETWForensicGraph',
|
||||
'Get-ETWProviderKeywords',
|
||||
'Get-ETWProvider',
|
||||
'New-ETWProviderConfig',
|
||||
'Get-ETWSessionDetails',
|
||||
'Get-ETWSessionNames',
|
||||
'New-ETWProviderOption',
|
||||
'Start-ETWForensicCollection',
|
||||
'Start-ETWSession',
|
||||
'Start-ETWKernelSession',
|
||||
'Stop-ETWSession'
|
||||
|
||||
)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,914 @@
|
||||
# Setup initial assembly import
|
||||
$path = $PSScriptRoot + "\lib\Microsoft.Diagnostics.Tracing.TraceEvent.dll"
|
||||
try {
|
||||
Import-Module $path
|
||||
}
|
||||
catch {
|
||||
throw "Could not find TraceEvent DLL at path: $path"
|
||||
}
|
||||
# Verify assembly loaded
|
||||
if (-Not ([appdomain]::currentdomain.getassemblies()).location -contains $path) {
|
||||
throw "Failed to load TraceEvent DLL"
|
||||
}
|
||||
Get-ChildItem $PSScriptRoot -Directory |
|
||||
Where-Object { $_.Name -ne 'Tests' } |
|
||||
Get-ChildItem -Recurse |
|
||||
Where-Object { $_.Name -match ".*\.ps1$" } |
|
||||
ForEach-Object { . $_.FullName }
|
||||
|
||||
# Start Private Functions
|
||||
Function Test-IsSession
|
||||
{
|
||||
Param($SessionName)
|
||||
|
||||
( Get-ETWSessionNames ).Contains( $SessionName )
|
||||
|
||||
} # Test-IsSession
|
||||
|
||||
Function Test-IsProvider
|
||||
{
|
||||
Param($ProviderName)
|
||||
|
||||
( ( Get-ETWProvider ).Name ).Contains( $ProviderName )
|
||||
|
||||
} # Test-IsProvider
|
||||
|
||||
function Write-Log
|
||||
{
|
||||
param (
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Message,
|
||||
|
||||
[Parameter()]
|
||||
[ValidateSet('INFO','WARN', 'VERBOSE', 'DEBUG')]
|
||||
[string]$Severity = 'INFO'
|
||||
)
|
||||
|
||||
$DateTime = ( Get-Date -UFormat "%D %T" )
|
||||
|
||||
if ($Severity -eq 'INFO') { Write-Host ('{0} {1}: {2}' -f $DateTime, $Severity, $Message) }
|
||||
|
||||
if ($Severity -eq 'WARN') { Write-Warning ('{0} {1}: {2}' -f $DateTime, $Severity, $Message) }
|
||||
|
||||
if ($Severity -eq 'VERBOSE') { Write-Verbose ('{0} {1}: {2}' -f $DateTime, $Severity, $Message) }
|
||||
|
||||
if ($Severity -eq 'DEBUG') { Write-DEBUG ('{0} {1}: {2}' -f $DateTime, $Severity, $Message) }
|
||||
|
||||
} # Write-Log
|
||||
|
||||
|
||||
# End private functions
|
||||
|
||||
Function New-ETWProviderConfig
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Initialzates new ETW session object
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
New-ETWProviderConfig is a function that initializations and returns a new ETWProviderConfig object.
|
||||
The object is made of three properties: Name, Guid, and Keywords.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
$ProviderConfig = New-ETWProviderConfig
|
||||
|
||||
#>
|
||||
|
||||
$Config = New-Object psobject
|
||||
# Name of ETW provider to be started (Optional if Guid property is provided)
|
||||
$Config | Add-Member -NotePropertyName 'Name' -NotePropertyValue $null
|
||||
# Guid of ETW provider to be started (Optional if Name property is provided)
|
||||
$Config | Add-Member -NotePropertyName 'Guid' -NotePropertyValue $null
|
||||
# List of ProviderDataItem objects used as session filters (optional)
|
||||
# Initializes as an empty array
|
||||
$Config | Add-Member -NotePropertyName 'Keywords' -NotePropertyValue @()
|
||||
# Optional Provider options
|
||||
$Config | Add-Member -NotePropertyName 'Options' -NotePropertyValue $null
|
||||
|
||||
$Config
|
||||
|
||||
} # New-ETWProviderConfig
|
||||
|
||||
|
||||
Function ConvertTo-ETWGuid
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Converts an ETW provider name to a GUID
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
ConvertTo-ETWGuid is a function that takes a provider name [string] and return the its corresponding GUID
|
||||
|
||||
.PARAMETER ProviderName
|
||||
|
||||
Name of an ETW provider
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
ConvertTo-ETWGuid -ProviderName Microsoft-Windows-Kernel-Process
|
||||
|
||||
Returns GUID associated with the Microsoft-Windows-Kernel-Process provider
|
||||
|
||||
#>
|
||||
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
[Alias("Provider")]
|
||||
[string]
|
||||
$ProviderName)
|
||||
|
||||
$ProviderGuid = [Microsoft.Diagnostics.Tracing.Session.TraceEventProviders]::GetProviderGuidByName($ProviderName)
|
||||
If ($ProviderGuid -eq [System.Guid]::Empty) {
|
||||
|
||||
throw "$ProviderName either does not exist or has empty GUID"
|
||||
}
|
||||
else {
|
||||
$ProviderGuid
|
||||
}
|
||||
|
||||
} # ConvertTo-ETWGuid
|
||||
|
||||
Function Get-ETWProviderKeywords
|
||||
{
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Collects event keywords for a specified ETW provider
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-ETWProviderKeywords is a function that collections keywords for a given ETW provider.
|
||||
Keywords describe events collected by the provider and can be used to restrict what events are captured.
|
||||
|
||||
.PARAMETER Provider
|
||||
|
||||
Name of an ETW provider
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-ETWProviderKeywords -ProviderName Microsoft-Windows-Kernel-Process
|
||||
|
||||
Returns keywords associated with the Microsoft-Windows-Kernel-Process provider
|
||||
|
||||
#>
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
$ProviderName)
|
||||
|
||||
If ($ProviderName -is [string]) {
|
||||
$ProviderName = ConvertTo-ETWGuid($ProviderName)
|
||||
}
|
||||
|
||||
[Microsoft.Diagnostics.Tracing.Session.TraceEventProviders]::GetProviderKeywords($ProviderName)
|
||||
|
||||
} # Get-ETWProviderKeywords
|
||||
|
||||
Function Get-ETWProvider {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Returns a ProviderMetadata object for each enabled ETW provider.
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-ETWProvider is a function that returns objects representing ETW provider metadata
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-ETWProvider
|
||||
|
||||
Returns list of all ETW providers
|
||||
|
||||
#>
|
||||
|
||||
[System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession.GetProviderNames() | ForEach-Object {
|
||||
try {
|
||||
[System.Diagnostics.Eventing.Reader.ProviderMetadata]($_)
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
} # Get-ETWProvider
|
||||
|
||||
|
||||
|
||||
|
||||
Function New-ETWProviderOption
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Creates new TraceEventProviderOptions object
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
New-ETWProviderOption is a function that creates a new TraceEventProviderOptions object with the EventIDsToEnable/Disable properties set as lists.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
New-ETWProviderOption
|
||||
|
||||
Creates a new TraceEventProviderOptions object with the EventIDsToEnable/Disable properties set as lists. Adding to these properties will limit what events are captured during an ETW session.
|
||||
|
||||
#>
|
||||
|
||||
$Options = New-Object -TypeName Microsoft.Diagnostics.Tracing.Session.TraceEventProviderOptions
|
||||
$Options.EventIDsToEnable = New-Object System.Collections.Generic.List[Int]
|
||||
$Options.EventIDsToDisable = New-Object System.Collections.Generic.List[Int]
|
||||
|
||||
$Options
|
||||
}
|
||||
|
||||
Function Get-ETWSessionNames {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Generates list of ETW session names
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-ETWSessionNames is a function that enumerates active ETW sessions and return their names in an array.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-ETWSessionNames
|
||||
|
||||
Returns all active ETW sessions
|
||||
|
||||
#>
|
||||
|
||||
[Microsoft.Diagnostics.Tracing.Session.TraceEventSession]::GetActiveSessionNames()
|
||||
}
|
||||
|
||||
|
||||
Function Get-ETWSessionDetails {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Returns an array of active ETW session GetProviderNames
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-ETWSessionDetails is a function that returns a TraceEventSession object for a given session name
|
||||
|
||||
.PARAMETER SessionName
|
||||
|
||||
Name of ETW session
|
||||
|
||||
.Example
|
||||
|
||||
Get-ETWSessionDetails ProcessMonitor
|
||||
|
||||
Returns session details about the "ProcessMonitor" ETW session
|
||||
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
[string]
|
||||
$SessionName
|
||||
)
|
||||
# Verify session exists
|
||||
If ( -Not (Test-IsSession -SessionName $SessionName) ) {
|
||||
throw "Session does not exist"
|
||||
}
|
||||
try {
|
||||
[Microsoft.Diagnostics.Tracing.Session.TraceEventSession]::GetActiveSession($SessionName)
|
||||
}
|
||||
catch {
|
||||
throw "Failed to get session details"
|
||||
}
|
||||
|
||||
} # Get-ETWSession
|
||||
|
||||
|
||||
Function Start-ETWSession
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Starts an event tracing session
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Start-ETWSession is a function that starts an event tracing session with one or more ETW providers.
|
||||
Events from this session are written to a file at the location given by the $OutputFile argument.
|
||||
|
||||
.PARAMETER ProviderConfig
|
||||
|
||||
PSObject containing the name and GUID of the ETW provider to be started.
|
||||
Optionally the keyword property can restrict which events are enabled during the session.
|
||||
|
||||
.PARAMETER OutputFile
|
||||
|
||||
Location on disk where ETW events will be written. Full path should be provided.
|
||||
|
||||
.PARAMETER SessionName
|
||||
|
||||
Unique name describing the ETW session. This name will be visible from the Get-ETWSession function
|
||||
|
||||
.PARAMETER MaxFileSize
|
||||
|
||||
Max size of etl file before old events start being overwritten.
|
||||
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Start-ETWSession -ProviderConfig $Config -OutputFile C:\test.etl -SessionName TestSession -MaxBufferSize 100
|
||||
|
||||
Start an ETW session named "TestSession" and write events to the file "C:\test.etl".
|
||||
The ETW provider(s) name(s) and keywords are in the predefined variable "$Config.
|
||||
The $Config variable should be a single instance or array of objects created from the New-ETWProviderConfig function.
|
||||
The output file will grow up to 50 MB before the oldest events are overwritten
|
||||
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
[psobject]
|
||||
$ProviderConfig,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$SessionName,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$OutputFile,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[int]
|
||||
$MaxFileSize = 50
|
||||
)
|
||||
|
||||
BEGIN {
|
||||
|
||||
# Check if active session with same name already exists
|
||||
If ( (Test-IsSession -SessionName $SessionName) ) {
|
||||
|
||||
throw $SessionName+ " already exists. Cannot create again"
|
||||
}
|
||||
$ProviderConfig | ForEach-Object {
|
||||
# Verify either provider Name or Guid was provided
|
||||
If ( ( $_.Name -eq $null ) -and ($_.Guid -eq $null ) ) {
|
||||
|
||||
throw "Must provide either provider name or GUID"
|
||||
}
|
||||
|
||||
# Check that provider name exists
|
||||
If ( -Not ( $_.Name -eq $null ) -and -Not ( Test-IsProvider -ProviderName $_.Name ) ) {
|
||||
|
||||
Throw $_.Name + " is not a valid ETW Provider name"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Log "Session name set to $SessionName" -Severity "VERBOSE"
|
||||
Write-Log "Provider set to $ProviderName" -Severity "VERBOSE"
|
||||
$path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($OutputFile)
|
||||
}
|
||||
PROCESS {
|
||||
# Create our ETW Session options
|
||||
$options = New-Object -TypeName Microsoft.Diagnostics.Tracing.Session.TraceEventSessionOptions
|
||||
$options.Create
|
||||
# Create ETW session
|
||||
$session = New-Object -TypeName Microsoft.Diagnostics.Tracing.Session.TraceEventSession -ArgumentList @($SessionName, $path, $options)
|
||||
# Setting StopOnDispose to false will not end a session if powershell ends
|
||||
$session.StopOnDispose = $false
|
||||
# Setting max file size
|
||||
$session.CircularBufferMB = $MaxFileSize
|
||||
|
||||
# Set log level. Default, and only supported option at this time, is Verbose
|
||||
|
||||
$TraceEventLevel = 5 # Verbose
|
||||
# Start session
|
||||
$ProviderConfig | ForEach-Object {
|
||||
|
||||
# Keywords are used to filter what events are captured during an ETW session and are calculated via a bitmask
|
||||
# Adding the value for the enables to correct events. If keywords are not provided no event filters are used
|
||||
If ( $_.Keywords ) {
|
||||
$MatchAnyKeywords = $_.Keywords | ForEach-Object { $_.Value } | Measure-Object -Sum | Select-Object -ExpandProperty sum
|
||||
} else {
|
||||
$MatchAnyKeywords = [uint64]::MaxValue
|
||||
}
|
||||
|
||||
# Determine if provider should be enabled by GUID or name
|
||||
|
||||
If ( $_.Name ) {
|
||||
$ProviderID = $_.Name
|
||||
} else {
|
||||
$ProviderID = $_.Guid
|
||||
}
|
||||
|
||||
$result = $session.EnableProvider($ProviderID, $TraceEventLevel, $MatchAnyKeywords, $_.Options)
|
||||
|
||||
}
|
||||
|
||||
# EnableProvider returns false if session if not previously exist
|
||||
If ( $result -eq $False ) {
|
||||
Write-Log "Successfully started ETW session $SessionName" -Severity 'INFO'
|
||||
}
|
||||
else {
|
||||
throw "Failed to start session $SessionName"
|
||||
}
|
||||
}
|
||||
|
||||
} # Start-ETWSession
|
||||
|
||||
Function Start-ETWKernelSession
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Enables Windows Kernel ETW Provider
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
In ETW there is a special provider to get certain events from the Windows kernel. In some earlier Windows versions (Win7 and 2008R2) there is only one allowed kernel session with a static name.
|
||||
More recent versions allow for multiple sessions and multiple session names.
|
||||
|
||||
.PARAMETER OutputFile
|
||||
|
||||
Location on disk where Kernel ETW events will be written. Full path should be provided.
|
||||
|
||||
.PARAMETER MaxFileSize
|
||||
|
||||
Max size of etl file before old events start being overwritten.
|
||||
|
||||
.PARAMETER SessionName
|
||||
|
||||
Optional parameter to define a unique Kernel session name. On Win7 and 2008R2 this name has be to "NT Kernel Logger", which is the configured default value.
|
||||
The default value will work on modern Windows operating systems, but may cause issues if another session with the same name already exists.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Start-ETWKernelSession -OutputFile .\kernel_events.etl
|
||||
|
||||
This will start the kernel ETW provider, register a new sessin with the default name "NT Kernel Logger" and write output to the file "kernel_events.etl"
|
||||
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$OutputFile,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]
|
||||
$SessionName = [Microsoft.Diagnostics.Tracing.Parsers.KernelTraceEventParser]::KernelSessionName,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[int]
|
||||
$MaxFileSize = 50
|
||||
)
|
||||
|
||||
# For kernel events we are mostly concerned with Process events
|
||||
$Process = 0x00000001
|
||||
|
||||
$path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($OutputFile)
|
||||
|
||||
# Create ETW session options
|
||||
$options = New-Object -TypeName Microsoft.Diagnostics.Tracing.Session.TraceEventSessionOptions
|
||||
$options.Create
|
||||
|
||||
$session = New-Object -TypeName Microsoft.Diagnostics.Tracing.Session.TraceEventSession -ArgumentList @($SessionName, $path)
|
||||
|
||||
$session.StopOnDispose = $false
|
||||
|
||||
# Setting max file size
|
||||
$session.CircularBufferMB = $MaxFileSize
|
||||
|
||||
# Starts kernel session filtered to only collect process events
|
||||
$result = $session.EnableKernelProvider($Process)
|
||||
|
||||
} # Start-ETWKernelSession
|
||||
|
||||
|
||||
Function Stop-ETWSession {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Stop an ETW session
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Stop-ETWSession is a function that attaches to and stops an existing ETW session
|
||||
|
||||
.PARAMETER SessionName
|
||||
|
||||
Name of valid ETW Session
|
||||
|
||||
.PARAMETER StopKernelSession
|
||||
|
||||
Boolean parameter to also stop the default kernel provider session. Only works if kernel session name is "NT Kernel Logger"
|
||||
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Stop-ETWSession ProcessMonitor
|
||||
|
||||
Stops ETW session name "ProcessMonitor"
|
||||
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
[string]
|
||||
$SessionName,
|
||||
|
||||
[Parameter(Mandatory=$false)]
|
||||
[switch]
|
||||
$StopKernelSession = $false
|
||||
|
||||
|
||||
)
|
||||
|
||||
BEGIN {
|
||||
if ( -Not (Test-IsSession -SessionName $SessionName ) ) {
|
||||
throw "$SessionName is not a valid session"
|
||||
}
|
||||
}
|
||||
PROCESS {
|
||||
# Create our ETW Session options
|
||||
$options = New-Object -TypeName Microsoft.Diagnostics.Tracing.Session.TraceEventSessionOptions
|
||||
$options.Attach
|
||||
# Create ETW session
|
||||
$session = New-Object -TypeName Microsoft.Diagnostics.Tracing.Session.TraceEventSession -ArgumentList @($SessionName, "", $options)
|
||||
# Stop session
|
||||
$result = $session.stop()
|
||||
|
||||
if ($result) {
|
||||
Write-Log "Successfully stopped ETW session $SessionName" -Severity 'INFO'
|
||||
} else {
|
||||
Write-Log "Failed to stop ETW session $SessionName" -Severity 'INFO'
|
||||
}
|
||||
|
||||
If ($StopKernelSession) {
|
||||
$KernelName = "NT Kernel Logger"
|
||||
$session = New-Object -TypeName Microsoft.Diagnostics.Tracing.Session.TraceEventSession -ArgumentList @($KernelName, "", $options)
|
||||
# Stop session
|
||||
$KerResult = $session.stop()
|
||||
|
||||
if ($KerResult) {
|
||||
Write-Log "Successfully stopped kernel ETW session" -Severity 'INFO'
|
||||
} else {
|
||||
Write-Log "Failed to stop kernel ETW session" -Severity 'INFO'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} # Stop-ETWSession
|
||||
|
||||
Function Get-ETWForensicEventLog
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Parses ETL event log for forensically significant events
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-ETWForensicEventLog is a function tha parses an ETW event trace log for forensically significant information.
|
||||
The raw log can be read using the builtin Get-WinEvent cmdlet.
|
||||
|
||||
.PARAMETER Path
|
||||
|
||||
Path of the etl file to parse
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Get-ETWForensicEventLog -Path C:\logs\process.etl
|
||||
|
||||
Converts process.etl for forensically significant ETW events for supported providers and returns objects representing the forenically signifant information.
|
||||
|
||||
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$Path
|
||||
)
|
||||
|
||||
if (-not (Test-Path $path )) {
|
||||
$path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($OutputFile)
|
||||
}
|
||||
# Hash table mapping of supported ETW providers to parser functions
|
||||
$script:Providers = @{
|
||||
'Microsoft-Windows-Kernel-Process' = 'KernelProcessParser'
|
||||
'Microsoft-Windows-Kernel-Network' = 'KernelNetworkParser'
|
||||
'Microsoft-Windows-Kernel-File' = 'KernelFileParser'
|
||||
'Microsoft-Windows-DNS-Client' = 'DNSClientParser'
|
||||
'Microsoft-Windows-PowerShell' = 'PowerShellParser'
|
||||
}
|
||||
|
||||
$Events = @{}
|
||||
Write-Log "Found etw output file at: $path" -Severity 'INFO'
|
||||
Get-WinEvent -Path $Path -Oldest | Where-Object {
|
||||
$script:Providers.ContainsKey($_.ProviderName) } | ForEach-Object {
|
||||
&$script:Providers[$_.ProviderName] -Event $_ }
|
||||
|
||||
# Check if kernel output exists
|
||||
|
||||
$KernelSessPath = -join([IO.Path]::GetDirectoryName($path) + '\' + [IO.Path]::GetFileNameWithoutExtension($Path) + "_kernelsession" + [IO.Path]::GetExtension($Path))
|
||||
If ( Test-Path $KernelSessPath ) {
|
||||
Write-Log "Found kernel session etw file at: $KernelSessPath" -Severity 'INFO'
|
||||
Get-WinEvent -Path $KernelSessPath -Oldest |
|
||||
# Filter out any event that does not contain command line in eventpayload
|
||||
ForEach-Object {
|
||||
KernelSessionParser -EventPayload (([xml]$_.toxml()).Event.ChildNodes.EventPayload)[1]
|
||||
}
|
||||
}
|
||||
|
||||
$Events.Values
|
||||
} # Get-ETWForensicEventLog
|
||||
|
||||
Function Get-ETWForensicGraph
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Visualizes parent and child process relationships
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Get-ETWForensicGraph is a function that parses the output from Get-ETWForensicEventLog and visualizes parent and child relationships
|
||||
|
||||
.PARAMETER ETWObject
|
||||
|
||||
Output from Get-ETWForensicEventLog
|
||||
|
||||
.PARAMETER ParentProcessID
|
||||
|
||||
Starting process ID. Function will enumerate 5 layers of child processes from this starting point.
|
||||
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$True)]
|
||||
$ETWObject,
|
||||
|
||||
[Parameter(Mandatory=$True)]
|
||||
$ParentProcessID
|
||||
)
|
||||
$ImageName = $ETWObject | Where-Object { $_.ProcessId -eq $ParentProcessID } | ForEach-Object {
|
||||
|
||||
If ($_.ImageName) {
|
||||
$_.ImageName
|
||||
} else {"Unknown"}
|
||||
}
|
||||
|
||||
$ChildProcs = $ETWObject | Where-Object { $_.ProcessId -eq $ParentProcessID } | Select-Object -ExpandProperty ChildProcesses
|
||||
|
||||
$IMG = @"
|
||||
`t||
|
||||
`t||
|
||||
`t||
|
||||
|
||||
"@
|
||||
$2IMG = @"
|
||||
`t`t||
|
||||
`t`t||
|
||||
`t`t||
|
||||
|
||||
"@
|
||||
|
||||
$3IMG = @"
|
||||
`t`t`t||
|
||||
`t`t`t||
|
||||
`t`t`t||
|
||||
|
||||
"@
|
||||
|
||||
$4IMG = @"
|
||||
`t`t`t`t||
|
||||
`t`t`t`t||
|
||||
`t`t`t`t||
|
||||
|
||||
"@
|
||||
|
||||
$5IMG = @"
|
||||
`t`t`t`t`t||
|
||||
`t`t`t`t`t||
|
||||
`t`t`t`t`t||
|
||||
|
||||
"@
|
||||
|
||||
Write-Host `n`n$ImageName "($ParentProcessID)" -ForegroundColor Green
|
||||
$IMG
|
||||
$ChildProcs |
|
||||
ForEach-Object {
|
||||
$Proc = $_.ProcessID
|
||||
Write-Host `t $_.ImageName "($Proc)" -ForegroundColor Green
|
||||
If ($_.ChildProcesses) {
|
||||
$2IMG
|
||||
$_.ChildProcesses | ForEach-Object {
|
||||
$Proc = $_.ProcessId
|
||||
Write-Host `t`t $_.ImageName "($Proc)" -ForegroundColor Green
|
||||
|
||||
If ($_.ChildProcesses) {
|
||||
$3IMG
|
||||
$_.ChildProcesses | ForEach-Object {
|
||||
$Proc = $_.ProcessID
|
||||
Write-Host `t`t`t $_.ImageName "($Proc)" -ForegroundColor Green
|
||||
|
||||
If ($_.ChildProcesses) {
|
||||
$4IMG
|
||||
$_.ChildProcesses | ForEach-Object {
|
||||
$Proc = $_.ProcessID
|
||||
Write-Host `t`t`t`t $_.ImageName "($Proc)" -ForegroundColor Green
|
||||
|
||||
If ($_.ChildProcesses) {
|
||||
$5IMG
|
||||
$_.ChildProcesses | ForEach-Object {
|
||||
$Proc = $_.ProcessID
|
||||
Write-Host `t`t`t`t`t $_.ImageName "($Proc)" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Function Start-ETWForensicCollection
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Initiates an ETW session to collect forensically significant events
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Start-ETWForensicCollection is a function that initiates pre-defined event tracing providers and filters.
|
||||
This configuration was designed to enable forensically important providers and event types.
|
||||
|
||||
.PARAMETER OutputFile
|
||||
|
||||
Location on disk where ETW events will be written. Full path should be provided.
|
||||
|
||||
.PARAMETER SessionName
|
||||
|
||||
Unique name describing the ETW session. This name will be visible from the Get-ETWSession function
|
||||
|
||||
.PARAMETER EnableVerbose
|
||||
|
||||
Enables verbose event capture (ex. all file writes). Should only be enabled for short event captures.
|
||||
|
||||
.PARAMETER DisableKernelProvider
|
||||
|
||||
Disables kernel session during forensic capture. Disabling this provider results in command lines not being captured.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Start-ETWForensicCollection -OutputFile C:\test\out.etl -SessionName collection
|
||||
|
||||
Starts ETW session named collection and captured events are writen to the path 'C:\test\out.etl'.
|
||||
|
||||
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$SessionName,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]
|
||||
$OutputFile,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[switch]
|
||||
$EnableVerbose = $false,
|
||||
|
||||
[Parameter(Mandatory=$False)]
|
||||
[switch]
|
||||
$DisableKernelProvider = $false
|
||||
|
||||
)
|
||||
|
||||
# Resolve full path of output file
|
||||
$OutputFile = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($OutputFile)
|
||||
|
||||
$ProviderConfigs = @()
|
||||
|
||||
# Build config for kernel Process
|
||||
$KernelProcessName = 'Microsoft-Windows-Kernel-Process'
|
||||
|
||||
$KernelProcessConfig = New-ETWProviderConfig
|
||||
$KernelProcessConfig.Name = $KernelProcessName
|
||||
|
||||
# Only want to enable process start/stop and DLL load events
|
||||
$ProcessRegex = '_PROCESS$|_IMAGE$|_THREAD$'
|
||||
|
||||
Get-ETWProviderKeywords -ProviderName $KernelProcessConfig.Name |
|
||||
Where-Object { $_.Name -match $ProcessRegex } |
|
||||
ForEach-Object { $KernelProcessConfig.Keywords += $_ }
|
||||
|
||||
$ProviderConfigs += $KernelProcessConfig
|
||||
|
||||
# Build config for PowerShell events
|
||||
$PowerShellName = "Microsoft-Windows-PowerShell"
|
||||
$PowerShellConfig = New-ETWProviderConfig
|
||||
$PowerShellConfig.name = $PowerShellName
|
||||
|
||||
$ProviderConfigs += $PowerShellConfig
|
||||
|
||||
# Build config for network events
|
||||
$KernelNetworkName = 'Microsoft-Windows-Kernel-Network'
|
||||
|
||||
$KernelNetworkConfig = New-ETWProviderConfig
|
||||
$KernelNetworkConfig.Name = $KernelNetworkName
|
||||
|
||||
# List of event IDs to capture
|
||||
$IDs = @( 12 ) # IPv4 connection attempted
|
||||
|
||||
$NetOptions = New-ETWProviderOption
|
||||
|
||||
$IDs | ForEach-Object {
|
||||
$NetOptions.EventIDsToEnable.Add( $_ )
|
||||
}
|
||||
|
||||
$KernelNetworkConfig.Options = $NetOptions
|
||||
|
||||
$ProviderConfigs += $KernelNetworkConfig
|
||||
|
||||
# Build config for file events
|
||||
|
||||
$KernelFileName = 'Microsoft-Windows-Kernel-File'
|
||||
|
||||
$KernelFileConfig = New-ETWProviderConfig
|
||||
$KernelFileConfig.Name = $KernelFileName
|
||||
|
||||
# Only capturing file create, write, and delete events
|
||||
If ( $EnableVerbose ) {
|
||||
$FileRegex = "CREATE|WRITE|DELETE"
|
||||
}
|
||||
else { $FileRegex = "CREATE|DELETE" }
|
||||
|
||||
Get-ETWProviderKeywords -ProviderName $KernelFileConfig.Name |
|
||||
Where-Object { $_.Name -match $FileRegex } |
|
||||
ForEach-Object { $KernelFileConfig.Keywords += $_ }
|
||||
|
||||
$ProviderConfigs += $KernelFileConfig
|
||||
|
||||
# Build config for DNS capture
|
||||
$DNSClientName = 'Microsoft-Windows-DNS-Client'
|
||||
$DNSConfig = New-ETWProviderConfig
|
||||
$DNSConfig.Name = $DNSClientName
|
||||
|
||||
# List of event IDs to capture
|
||||
$IDs = @(3000, 3008)
|
||||
$DNSOptions = New-ETWProviderOption
|
||||
$IDs | ForEach-Object {
|
||||
$DNSOptions.EventIDsToEnable.Add( $_ )
|
||||
}
|
||||
$DNSConfig.Options = $DNSOptions
|
||||
# End DNS capture config
|
||||
|
||||
$ProviderConfigs += $DNSConfig
|
||||
|
||||
# Start ETW Session
|
||||
|
||||
try
|
||||
{
|
||||
Write-Log "Starting ETW forensic collection." -Severity 'INFO'
|
||||
Write-Log "Output will be written to: $OutputFile" -Severity 'INFO'
|
||||
|
||||
Start-ETWSession -SessionName $SessionName -OutputFile $OutputFile -ProviderConfig $ProviderConfigs
|
||||
} catch {
|
||||
|
||||
throw "Failed to start ETW forensic collection"
|
||||
}
|
||||
|
||||
If (-not $DisableKernelProvider) {
|
||||
try {
|
||||
$KerProviderFName = [IO.Path]::GetFileNameWithoutExtension($OutputFile) + "_kernelsession" `
|
||||
+ [IO.Path]::GetExtension($OutputFile)
|
||||
|
||||
$KernelFullPath = Join-Path (Split-Path $OutputFile) $KerProviderFName
|
||||
|
||||
Write-Log "Writing kernel output to: $KernelFullPath" -Severity 'INFO'
|
||||
|
||||
Start-ETWKernelSession -OutputFile $KernelFullPath
|
||||
} catch {
|
||||
throw "Failed to start ETW kernel session"
|
||||
}
|
||||
}
|
||||
|
||||
} # Start-ETWForensicCollection
|
||||
@@ -0,0 +1,62 @@
|
||||
ETW Kernel Session Event messages are not properly parsed by Get-WinEvent becuase the cmdlet does not have the correct xml format file
|
||||
|
||||
Therefore we have to parse relevant event properties using PowerShell structure parsing.
|
||||
|
||||
The first task is taking Get-WinEvent output and filtering it down to only return events with properties that contain the process command line
|
||||
|
||||
Here is an example event xml
|
||||
|
||||
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
|
||||
<System>
|
||||
<Provider Name="" Guid="{3d6fa8d0-fe05-11d0-9dda-00c04fd7ba7c}" />
|
||||
<EventID>0</EventID>
|
||||
<Version>4</Version>
|
||||
<Level>0</Level>
|
||||
<Task>0</Task>
|
||||
<Opcode>2</Opcode>
|
||||
<Keywords>0x0</Keywords>
|
||||
<TimeCreated SystemTime="2017-08-11T19:58:42.695093000Z" />
|
||||
<EventRecordID>2505</EventRecordID>
|
||||
<Correlation />
|
||||
<Execution ProcessID="11068" ThreadID="4056" ProcessorID="6" KernelTime="0" UserTime="0" />
|
||||
<Channel></Channel>
|
||||
<Computer>office-pc</Computer>
|
||||
<Security />
|
||||
</System>
|
||||
<ProcessingErrorData>
|
||||
<ErrorCode>15003</ErrorCode>
|
||||
<DataItemName></DataItemName>
|
||||
<EventPayload>80403A9D859FFFFF3C2B0000700300000100000001000000001049C10000000009000000A03CAC4007B0FFFF00000000000000000105000000000005150000007E92A50F78D99D9072051408E903000048785473722E65786500220043003A005C00500072006F006700720061006D002000460069006C00650073005C00570069006E0064006F007700730041007000700073005C006D006900630072006F0073006F00660074002E00770069006E0064006F007700730063006F006D006D0075006E00690063006100740069006F006E00730061007000700073005F00310037002E0038003400300030002E00340030003700340035002E0030005F007800360034005F005F003800770065006B007900620033006400380062006200770065005C00480078005400730072002E00650078006500220020002D005300650072007600650072004E0061006D0065003A00480078002E004900500043002E0053006500720076006500720000006D006900630072006F0073006F00660074002E00770069006E0064006F007700730063006F006D006D0075006E00690063006100740069006F006E00730061007000700073005F00310037002E0038003400300030002E00340030003700340035002E0030005F007800360034005F005F003800770065006B007900620033006400380062006200770065000000700070006C006500610065003300380061006600320065003000300037006600340033003500380061003800300039006100630039003900610036003400610036003700630031000000</EventPayload>
|
||||
</ProcessingErrorData>
|
||||
</Event>
|
||||
|
||||
|
||||
We are interested in the event payload. I've found the relevent messages always begin with "80".
|
||||
This filter seems to work: Get-WinEvent -Path <path to file> -Oldest | ? { ([xml]$_.toxml()).Event.ChildNodes.EventPayload -match "^80" }
|
||||
|
||||
Next we need to grab only the EventPayload xml node: $a | % { (([xml]$_.toxml()).Event.ChildNodes.EventPayload)[1] }
|
||||
|
||||
Convert string to hex string: -split '(..)' | ? {$_} | % {[char][convert]::ToUInt32($_,16)}
|
||||
|
||||
Once we have the relevant events we need to parse out two properties: Process ID and Process Command Line
|
||||
|
||||
Process ID is stored as a UInt32 at offset 0x08
|
||||
|
||||
[bitconverter]::toint16($u[8..12], 0)
|
||||
|
||||
ProcessCommandLine is a bit trickier. The ImageName is the first variable string the moves immediately to the commandline in the message and always starts at offset 0x40 and should be read until a double null byte (0x00 0x00) terminates the string
|
||||
|
||||
Start = 64
|
||||
#end = $array.length
|
||||
Length = 0
|
||||
$NullByte = $false
|
||||
|
||||
For Each
|
||||
|
||||
$u[$start..$u.length] |
|
||||
ForEach-Object {
|
||||
If ($NullByte -and ([uint16]$_ -eq 0)) {
|
||||
break
|
||||
}
|
||||
Elseif
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
function Get-KernelProcPath
|
||||
{
|
||||
|
||||
param($HexString)
|
||||
# Struct immediately preceeding image name and path is a variable length array
|
||||
# Count identifies the numer of items in array
|
||||
$Count = [convert]::ToUInt32($HexString[53], 16)
|
||||
# Fixed length per item
|
||||
$Length = 4
|
||||
# Start of image name and command line message
|
||||
$Start = ($Count * $Length) + 60
|
||||
$Length = 0
|
||||
$NullByte = $false
|
||||
$InString = $true
|
||||
|
||||
If (-not ($Start -gt $HexString.length) ){
|
||||
Do
|
||||
{
|
||||
$HexString[$start..$HexString.length] |
|
||||
ForEach-Object {
|
||||
$char = [char][convert]::ToUInt32($_, 16)
|
||||
If ($NullByte -eq $true -and ($char -eq 0)) {
|
||||
$InString = $false
|
||||
}
|
||||
elseif ($char -eq 0) {
|
||||
$length = $length + 1
|
||||
$NullByte = $true
|
||||
}
|
||||
else {
|
||||
$length = $length + 1
|
||||
$NullByte = $false
|
||||
}
|
||||
}
|
||||
} While ($InString -and (($Start + $Length) -lt $HexString.length))
|
||||
}
|
||||
$CommandBytes = -join($HexString[$Start..($Start + $Length)] |
|
||||
ForEach-Object { [char][convert]::ToUInt32($_, 16) } |
|
||||
Where-Object { $_ } )
|
||||
|
||||
# Remove image name
|
||||
$FullCommand = ($CommandBytes -split '\.exe')[1..7]
|
||||
# Bring everything back together
|
||||
$FullCommand -join '.exe'
|
||||
}
|
||||
|
||||
function Get-FullPathFromCommandLine
|
||||
{
|
||||
param($CommandLine)
|
||||
|
||||
If ($CommandLine[0] -eq '"' ) {
|
||||
|
||||
( $CommandLine -split '"' )[1]
|
||||
}
|
||||
else {
|
||||
( $CommandLine -split ' ' )[0]
|
||||
}
|
||||
}
|
||||
|
||||
function KernelSessionParser
|
||||
{
|
||||
param($EventPayload)
|
||||
|
||||
If ($EventPayload) { Write-Log $EventPayload -Severity "VERBOSE" }
|
||||
|
||||
# Convert string to byte array
|
||||
$EventPayload = $EventPayload |
|
||||
ForEach-Object { $_ -split '(..)' } |
|
||||
Where-Object { $_ }
|
||||
try {
|
||||
$ProcID = [convert]::ToUInt32(-join($EventPayload[11..8]), 16)
|
||||
} catch {$ProcID = $null}
|
||||
try {
|
||||
$CommandLine = Get-KernelProcPath -HexString $EventPayload
|
||||
} catch {$CommandLine = $null}
|
||||
|
||||
If ( $ProcID -and $CommandLine ) {
|
||||
# Grab image name for comparison to events dictionary
|
||||
try {
|
||||
$ImageName = [IO.Path]::GetFileNameWithoutExtension( (Get-FullPathFromCommandLine -CommandLine $CommandLine) )
|
||||
} catch { $ImageName = $null }
|
||||
|
||||
$Events.Values |
|
||||
# Check if process id and process full path match entry in events output
|
||||
Where-Object { $_.ImageName -and $_.ProcessId -eq $ProcID -and [IO.Path]::GetFileNameWithoutExtension($_.ImageName).ToLower() -eq $ImageName.ToLower() } |
|
||||
# Confirm property does not already exist
|
||||
ForEach-Object {
|
||||
If ( ($_.PSObject.Properties.Name -match 'CommandLine').Count -lt 1 ) {
|
||||
$_ | Add-Member -NotePropertyName "CommandLine" -NotePropertyValue $CommandLine
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,684 @@
|
||||
PS> Get-ETWProvider | Where-Object { $_.ProviderName -eq 'Microsoft-Windows-DNS-Client'} | % { $_.Events } | `
|
||||
select id,description | ft -Wrap -Property Id,Description | out-string | `
|
||||
Set-Content .\Providers\MS-Windows-DNS-Client\DNS-IDs-Descriptions.txt
|
||||
|
||||
Id Description
|
||||
-- -----------
|
||||
1000 There are currently no IPv4 DNS servers configured for any interface on this host. Please configure DNS server
|
||||
settings, or renew your dynamic IP settings.
|
||||
1001 Interface: %1 Total DNS Server Count: %2 Index: %3 Address: %6 (%4)
|
||||
1002 The DNS server being queried for interface %1 has changed to %3
|
||||
1003 The following DNS server(s) were successfully validated as active servers that can service this client. %2
|
||||
1005 The client was unable to validate the following as active DNS server(s) that can service this client. The
|
||||
server(s) may be temporarily unavailable, or may be incorrectly configured. %2
|
||||
1007 The primary DNS suffix for this machine is missing. In the absence of a primary DNS suffix, short unqualified
|
||||
names may not resolve through DNS
|
||||
1008 The primary DNS suffix for this machine is missing. In the absence of a primary DNS suffix, short unqualified
|
||||
names may not resolve through DNS
|
||||
1009 The primary DNS suffix for this machine (%1) does not match the Active Directory domain (%2) that it is
|
||||
currently joined to.
|
||||
1010 The primary DNS suffix for this machine (%1) does not match the Active Directory domain (%2) that it is
|
||||
currently joined to.
|
||||
1011 There was an error while attempting to read the local hosts file.
|
||||
1012 There was an error while attempting to read the local hosts file.
|
||||
1013 Name resolution for the name %1 timed out after none of the configured DNS servers responded.
|
||||
1014 Name resolution for the name %1 timed out after none of the configured DNS servers responded.
|
||||
1015 Name resolution for the name %1 timed out after the DNS server %3 did not respond.
|
||||
1016 A name not found error was returned for the name %1. Check to ensure that the name is correct. The response was
|
||||
sent by the server at %3.
|
||||
1017 The DNS server's response to a query for name %1 indicates that no records of the type queried are available,
|
||||
but could indicate that other records for the same name are present.
|
||||
1018 The response for the query %1 was a Link Local IP address %3. The response was sent by the server at %5.
|
||||
1019 There are currently no IPv6 DNS servers configured for any interface on this host. Please configure DNS server
|
||||
settings, or renew your dynamic IP settings.
|
||||
1020 Read DNS Name Resolution Policy Table: Key Name %1: DNSSEC Settings: DnsSecValidationRequired %2,
|
||||
DnsQueryOverIPSec %3, DnsEncryption %4 Direct Access Settings: DirectAccessServerList %5, EnableRemoteIPSEC %6
|
||||
RemoteEncryption %7 ProxyType %8 ProxyName %9
|
||||
1021 Matched Effective policy for query name %1: Key Name %2: DnsSecValidationRequired %3, DnsQueryOverIPSec %4,
|
||||
DnsEncryption %5 DirectAccessServerList %6, ProxyType %7 ProxyName %8
|
||||
1022 Name resolution for the name, %1, will not fall back to LLMNR or NetBIOS
|
||||
1023 Name resolution policy table has been corrupted. DNS resolution will fail until it is fixed. Contact your
|
||||
network administrator. For more information: read policy table for rule %1 failed with error %2
|
||||
1024 Transaction ID of the response for query %1 from server %3 did not match
|
||||
1025 The DNS server IP %3 of the response for query %1 is not configured on the client
|
||||
1026 The question (%2) in the response from server %4 does not match the original question %1
|
||||
1027 DNS Name resolution for the name, %1, failed because the client was unable to contact DNS servers. At least one
|
||||
of the interfaces is not in a private network and name resolution will not fall back to LLMNR or NetBIOS
|
||||
1028 Matched effective policy for query name %1: Key Name %2: DnsSecValidationRequired %3, DnsQueryOverIPSec %4,
|
||||
DnsEncryption %5 DirectAccessServerList %6, ProxyType %7 ProxyName %8 GenericServerList %9 IdnConfig %10
|
||||
3000 DNS Query is initiated for the name %1 and for the type %2 with query options %3
|
||||
3001 DNS Query operation is completed with result %1
|
||||
3002 DNS Cache lookup is initiated for the name %1 and for the type %2 with query options %3
|
||||
3003 DNS Cache lookup operation for the name %1 and for the type %2 is completed with result %3
|
||||
3004 DNS FQDN Query is initiated for the name %1 and for the type %2 with query options %3
|
||||
3005 DNS FQDN Query operation for the name %1 and for the type %2 is completed with result %3
|
||||
3006 DNS query is called for the name %1, type %2, query options %3, Server List %4, isNetwork query %5, network
|
||||
index %6, interface index %7, is asynchronous query %8
|
||||
3007 DnsQueryEx for the name %1 is pending
|
||||
3008 DNS query is completed for the name %1, type %2, query options %3 with status %4 Results %5
|
||||
3009 Network query initiated for the name %1 (is parallel query %2) on network index %3 with interface count %4 with
|
||||
first interface name %5, local addresses %6 and Dns Servers %7
|
||||
3010 DNS Query sent to DNS Server %3 for name %1 and type %2
|
||||
3011 Received response from DNS Server %3 for name %1 and type %2 with response status %4
|
||||
3012 NETBIOS query is initiated for name %1 on network index %2 with inteface count %3 with first interface name %4
|
||||
and local addresses %5
|
||||
3013 NETBIOS query is completed for name %1 with status %2 and results %3
|
||||
3014 NETBIOS query for the name %1 is pending
|
||||
3015 DnsQueryEx is canceled for the name %1
|
||||
3016 Cache lookup called for name %1, type %2, options %3 and interface index %4
|
||||
3018 Cache lookup for name %1, type %2 and option %3 returned %4 with results %5
|
||||
3019 Query wire called for name %1, type %2, interface index %3 and network index %4
|
||||
3020 Query response for name %1, type %2, interface index %3 and network index %4 returned %5 with results %6
|
||||
8001 Unable to start DNS Client service. Could not start the Remote Procedure Call (RPC) interface for this service.
|
||||
To correct the problem, you may restart the RPC and DNS Client services. To do so, use the following commands at
|
||||
a command prompt: (1) type 'net start rpc' to start the RPC service, and (2) type 'net start dnscache' to start
|
||||
the DNS Client service. See event details for specific error code information.
|
||||
8002 Unable to start DNS Client service because the system failed to allocate memory and may be out of available
|
||||
memory. Try closing any applications not in use or reboot the computer. See event details for specific error
|
||||
code information.
|
||||
8003 The system failed to register network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS Server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The cause of this DNS registration failure was because the DNS update request timed out after being sent to the
|
||||
specified DNS Server. This is probably because the authoritative DNS server for the name being updated is not
|
||||
running.
|
||||
|
||||
You can manually retry registration of the network adapter and its settings by typing 'ipconfig /registerdns' at
|
||||
the command prompt. If problems still persist, contact your network systems administrator to verify network
|
||||
conditions.
|
||||
8004 The system failed to register network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The cause of this DNS registration failure was because of DNS server failure. This may be due to a zone transfer
|
||||
that has locked the DNS server for the applicable zone that your computer needs to register itself with.
|
||||
|
||||
(The applicable zone should typically correspond to the Adapter-specific Domain Suffix that was indicated
|
||||
above.) You can manually retry registration of the network adapter and its settings by typing 'ipconfig
|
||||
/registerdns' at the command prompt. If problems still persist, contact your network systems administrator to
|
||||
verify network conditions.
|
||||
8005 The system failed to register network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason it could not register was because either: (a) the DNS server does not support the DNS dynamic update
|
||||
protocol, or (b) the primary zone authoritative for the registering names does not currently accept dynamic
|
||||
updates.
|
||||
|
||||
To add or register a DNS host (A or AAAA) resource record using the specific DNS name for this adapter, contact
|
||||
your DNS server or network systems administrator.
|
||||
8006 The system failed to register network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason it could not register was because the DNS server refused the dynamic update request. This could
|
||||
happen for the following reasons: (a) current DNS update policies do not allow this computer to update the DNS
|
||||
domain name configured for this adapter, or (b) the authoritative DNS server for this DNS domain name does not
|
||||
support the DNS dynamic update protocol.
|
||||
|
||||
To register a DNS host (A or AAAA) resource record using the specific DNS domain name for this adapter, contact
|
||||
your DNS server or network systems administrator.
|
||||
8007 The system failed to register network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The system could not register the DNS update request because of a security related problem. This could happen
|
||||
for the following reasons: (a) the DNS domain name that your computer is trying to register could not be updated
|
||||
because your computer does not have the right permissions, or (b) there might have been a problem negotiating
|
||||
valid credentials with the DNS server to update.
|
||||
|
||||
You can manually retry DNS registration of the network adapter and its settings by typing 'ipconfig
|
||||
/registerdns' at the command prompt. If problems still persist, contact your DNS server or network systems
|
||||
administrator. See event details for specific error code information.
|
||||
8008 The system failed to register network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason the DNS update request could not be completed was because of a system problem. You can manually retry
|
||||
DNS registration of the network adapter and its settings by typing 'ipconfig /registerdns' at the command
|
||||
prompt. If problems still persist, contact your DNS server or network systems administrator. See event details
|
||||
for specific error code information.
|
||||
8009 The system failed to register pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address :
|
||||
%6
|
||||
|
||||
The reason that the system could not register these RRs was because the update request that was sent to the
|
||||
specified DNS server timed out. This is probably because the authoritative DNS server for the name being
|
||||
registered is not running.
|
||||
|
||||
You can manually retry DNS registration of the network adapter and its settings by typing 'ipconfig
|
||||
/registerdns' at the command prompt. If problems still persist, contact your DNS server or network systems
|
||||
administrator. See event details for specific error code information.
|
||||
8010 The system failed to register pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address :
|
||||
%6
|
||||
|
||||
The cause was DNS server failure. This may be because the reverse lookup zone is busy or missing on the DNS
|
||||
server that your computer needs to update. In most cases, this is a minor problem because it does not affect
|
||||
normal (forward) name resolution.
|
||||
|
||||
If reverse (address-to-name) resolution is required for your computer, you can manually retry DNS registration
|
||||
of the network adapter and its settings by typing 'ipconfig /registerdns' at the command prompt. If problems
|
||||
still persist, contact your DNS server or network systems administrator. See event details for specific error
|
||||
code information.
|
||||
8011 The system failed to register pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address :
|
||||
%6
|
||||
|
||||
The reason that the system could not register these RRs was because (a) either the DNS server does not support
|
||||
the DNS dynamic update protocol, or (b) the authoritative zone where these records are to be registered does not
|
||||
allow dynamic updates.
|
||||
|
||||
To register DNS pointer (PTR) resource records using the specific DNS domain name and IP addresses for this
|
||||
adapter, contact your DNS server or network systems administrator.
|
||||
8012 The system failed to register pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address :
|
||||
%6
|
||||
|
||||
The reason that the system could not register these RRs was because the DNS server refused the update request.
|
||||
The cause of this could be (a) your computer is not allowed to update the adapter-specified DNS domain name, or
|
||||
(b) because the DNS server authoritative for the specified name does not support the DNS dynamic update protocol.
|
||||
|
||||
To register the DNS pointer (PTR) resource records using the specific DNS domain name and IP addresses for this
|
||||
adapter, contact your DNS server or network systems administrator.
|
||||
8013 The system failed to register pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address :
|
||||
%6
|
||||
|
||||
The reason that the system could not register these RRs was because of a security related problem. The cause of
|
||||
this could be (a) your computer does not have permissions to register and update the specific DNS domain name
|
||||
set for this adapter, or (b) there might have been a problem negotiating valid credentials with the DNS server
|
||||
during the processing of the update request.
|
||||
|
||||
You can manually retry DNS registration of the network adapter and its settings by typing 'ipconfig
|
||||
/registerdns' at the command prompt. If problems still persist, contact your DNS server or network systems
|
||||
administrator.
|
||||
8014 The system failed to register pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address :
|
||||
%6
|
||||
|
||||
The reason the system could not register these RRs during the update request was because of a system problem.
|
||||
You can manually retry DNS registration of the network adapter and its settings by typing 'ipconfig
|
||||
/registerdns' at the command prompt. If problems still persist, contact your DNS server or network systems
|
||||
administrator. See event details for specific error code information.
|
||||
8015 The system failed to register host (A or AAAA) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason the system could not register these RRs was because the update request it sent to the DNS server
|
||||
timed out. The most likely cause of this is that the DNS server authoritative for the name it was attempting to
|
||||
register or update is not running at this time.
|
||||
|
||||
You can manually retry DNS registration of the network adapter and its settings by typing 'ipconfig
|
||||
/registerdns' at the command prompt. If problems still persist, contact your DNS server or network systems
|
||||
administrator.
|
||||
8016 The system failed to register host (A or AAAA) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason the system could not register these RRs was because the DNS server failed the update request. The
|
||||
most likely cause of this is that the authoritative DNS server required to process this update request has a
|
||||
lock in place on the zone, probably because a zone transfer is in progress.
|
||||
|
||||
You can manually retry DNS registration of the network adapter and its settings by typing 'ipconfig
|
||||
/registerdns' at the command prompt. If problems still persist, contact your DNS server or network systems
|
||||
administrator.
|
||||
8017 The system failed to register host (A or AAAA) resource records for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
Either the DNS server does not support the DNS dynamic update protocol or the authoritative zone for the
|
||||
specified DNS domain name does not accept dynamic updates.
|
||||
|
||||
To register the DNS host (A or AAAA) resource records using the specific DNS domain name and IP addresses for
|
||||
this adapter, contact your DNS server or network systems administrator.
|
||||
8018 The system failed to register host (A or AAAA) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason the system could not register these RRs was because the DNS server contacted refused the update
|
||||
request. The reasons for this might be (a) you are not allowed to update the specified DNS domain name, or (b)
|
||||
because the DNS server authoritative for this name does not support the DNS dynamic update protocol.
|
||||
|
||||
To register the DNS host (A or AAAA) resource records using the specific DNS domain name and IP addresses for
|
||||
this adapter, contact your DNS server or network systems administrator.
|
||||
8019 The system failed to register host (A or AAAA) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason the system could not register these RRs was because of a security related problem. The cause of this
|
||||
could be (a) your computer does not have permissions to register and update the specific DNS domain name set for
|
||||
this adapter, or (b) there might have been a problem negotiating valid credentials with the DNS server during
|
||||
the processing of the update request.
|
||||
|
||||
You can manually retry DNS registration of the network adapter and its settings by typing 'ipconfig
|
||||
/registerdns' at the command prompt. If problems still persist, contact your DNS server or network systems
|
||||
administrator. See event details for specific error code information.
|
||||
8020 The system failed to register host (A or AAAA) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason the system could not register these RRs during the update request was because of a system problem.
|
||||
You can manually retry DNS registration of the network adapter and its settings by typing 'ipconfig
|
||||
/registerdns' at the command prompt. If problems still persist, contact your DNS server or network systems
|
||||
administrator. See event details for specific error code information.
|
||||
8021 The system failed to update and remove registration for the network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason for this failure is because the DNS server it sent the update request to timed out. The most likely
|
||||
cause of this failure is that the DNS server authoritative for the zone where the registration was originally
|
||||
made is either not running or unreachable through the network at this time.
|
||||
8022 The system failed to update and remove registration for the network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason for this failure is because the DNS server it sent the update to failed the update request. A
|
||||
possible cause of this failure is that the DNS server required to process this update request has a lock in
|
||||
place on the zone, probably because a zone transfer is in progress.
|
||||
|
||||
|
||||
8023 The system failed to update and remove registration for the network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason for this failure is because the DNS server sent the update either (a) does not support the DNS
|
||||
dynamic update protocol, or (b) the authoritative zone for the specified DNS domain name does not currently
|
||||
accept DNS dynamic updates.
|
||||
8024 The system failed to update and remove registration for the network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason the system could not perform the update request was the DNS server contacted refused update request.
|
||||
The cause of this is (a) this computer is not allowed to update the specified DNS domain name, or (b) because
|
||||
the DNS server authoritative for the zone that requires updating does not support the DNS dynamic update
|
||||
protocol.
|
||||
8025 The system failed to update and remove registration for the network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason the system could not perform the update request was because of a security related problem. The cause
|
||||
of this could be (a) your computer does not have permissions to register and update the specific DNS domain name
|
||||
set for this adapter, or (b) there might have been a problem negotiating valid credentials with the DNS server
|
||||
during the processing of the update request.
|
||||
|
||||
See event details for specific error code information.
|
||||
8026 The system failed to update and remove the DNS registration for the network adapter with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The system could not update to remove this DNS registration because of a system problem. See event details for
|
||||
specific error code information.
|
||||
8027 The system failed to update and remove pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address :
|
||||
%6
|
||||
|
||||
The system could not remove these PTR RRs because the update request timed out while awaiting a response from
|
||||
the DNS server. This is probably because the DNS server authoritative for the zone that requires update is not
|
||||
running.
|
||||
8028 The system failed to update and remove pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address : %6
|
||||
|
||||
The system could not remove these PTR RRs because the DNS server failed the update request. A possible cause is
|
||||
that a zone transfer is in progress, causing a lock for the zone at the DNS server authorized to perform the
|
||||
updates for these RRs.
|
||||
8029 The system failed to update and remove pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address :
|
||||
%6
|
||||
|
||||
The system could not remove these PTR RRs because either the DNS server does not support the DNS dynamic update
|
||||
protocol or the authoritative zone that contains these RRs does not accept dynamic updates.
|
||||
8030 The system failed to update and remove pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address :
|
||||
%6
|
||||
|
||||
The system could not remove these PTR RRs because the DNS server refused the update request. The cause of this
|
||||
might be (a) this computer is not allowed to update the specified DNS domain name specified by these settings,
|
||||
or (b) because the DNS server authorized to perform updates for the zone that contains these RRs does not
|
||||
support the DNS dynamic update protocol.
|
||||
8031 The system failed to update and remove pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address :
|
||||
%6
|
||||
|
||||
The system could not remove these PTR RRs because of a security related problem. The cause of this could be that
|
||||
(a) your computer does not have permissions to remove and update the specific DNS domain name or IP addresses
|
||||
configured for this adapter, or (b) there might have been a problem negotiating valid credentials with the DNS
|
||||
server during the processing of the update request. See event details for specific error code information.
|
||||
8032 The system failed to update and remove pointer (PTR) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Adapter-specific Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address :
|
||||
%6
|
||||
|
||||
The system could not remove these PTR RRs because because of a system problem. See event details for specific
|
||||
error code information.
|
||||
8033 The system failed to update and remove host (A or AAAA) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The system could not remove these host (A or AAAA) RRs because the update request timed out while
|
||||
awaiting a response from the DNS server. This is probably because the DNS server authoritative for the zone
|
||||
where these RRs need to be updated is either not currently running or reachable on the network.
|
||||
8034 The system failed to update and remove host (A or AAAA) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The system could not remove these host (A or AAAA) RRs because the DNS server failed the update request. A
|
||||
possible cause is that a zone transfer is in progress, causing a lock for the zone at the DNS server authorized
|
||||
to perform the updates for these RRs.
|
||||
8035 The system failed to update and remove host (A or AAAA) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason for this failure is because the DNS server sent the update either (a) does not support the DNS
|
||||
dynamic update protocol, or (b) the authoritative zone for the DNS domain name specified in these host (A or
|
||||
AAAA) RRs does not currently accept DNS dynamic updates.
|
||||
8036 The system failed to update and remove host (A or AAAA) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The request to remove these records failed because the DNS server refused the update request. The cause of this
|
||||
might be that either (a) this computer is not allowed to update the DNS domain name specified by these settings,
|
||||
or (b) because the DNS server authorized to perform updates for the zone that contains these RRs does not
|
||||
support the DNS dynamic update protocol.
|
||||
8037 The system failed to update and remove host (A or AAAA) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason for this failure was because of a security related problem. The cause of this could be that (a) your
|
||||
computer does not have permissions to remove and update the specific DNS domain name or IP addresses configured
|
||||
for this adapter, or (b) there might have been a problem negotiating valid credentials with the DNS server
|
||||
during the processing of the update request. See event details for specific error code information.
|
||||
8038 The system failed to update and remove host (A or AAAA) resource records (RRs) for network adapter
|
||||
with settings:
|
||||
|
||||
Adapter Name : %1
|
||||
Host Name : %2
|
||||
Primary Domain Suffix : %3
|
||||
DNS server list :
|
||||
%4
|
||||
Sent update to server : %5
|
||||
IP Address(es) :
|
||||
%6
|
||||
|
||||
The reason the update request failed was because of a system problem. See event details for specific error code
|
||||
information.
|
||||
60004 Error: %1 Location: %2 Context: %3
|
||||
60005 Warning: %1 Location: %2 Context: %3
|
||||
60006 Transitioned to State: %1 Context: %2
|
||||
60007 Updated Context: %1 Update Reason: %2
|
||||
60008 Name resolution policy table has been corrupted. DNS resolution will fail until it is fixed. Contact your
|
||||
network administrator. For more information: read policy table for rule %1 failed with error %2
|
||||
60101 SourceAddress: %1 SourcePort: %2 DestinationAddress: %3 DestinationPort: %4 Protocol: %5 ReferenceContext: %6
|
||||
60102 SourceAddress: %1 SourcePort: %2 DestinationAddress: %3 DestinationPort: %4 Protocol: %5 ReferenceContext: %6
|
||||
60103 Interface Guid: %1 IfIndex: %2 Interface Luid: %3 ReferenceContext: %4
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
DNS Notes:
|
||||
Get-ETWProvider | ? { $_.Name -match 'DNS' }
|
||||
|
||||
Only Microsoft-Windows-DNS-Client has keywords
|
||||
|
||||
Get Keywords:
|
||||
Get-ETWProvider | ? { $_.Name -match 'Microsoft-Windows-DNS-Client' } | % { $_.Keywords }
|
||||
|
||||
This returns:
|
||||
Name Value DisplayName
|
||||
---- ----- -----------
|
||||
ut:GenericEvent 256
|
||||
ut:DnsAutoLogKeyword 268435456
|
||||
ut:SendPath 4294967296
|
||||
ut:ReceivePath 8589934592
|
||||
ut:L3ConnectPath 17179869184
|
||||
ut:L2ConnectPath 34359738368
|
||||
ut:ClosePath 68719476736
|
||||
ut:Authentication 137438953472
|
||||
ut:Configuration 274877906944
|
||||
ut:Global 549755813888
|
||||
ut:Dropped 1099511627776
|
||||
ut:PiiPresent 2199023255552
|
||||
ut:Packet 4398046511104
|
||||
ut:Address 8796093022208
|
||||
ut:StdTemplateHint 17592186044416
|
||||
ut:PolicyTable 35184372088832
|
||||
ut:PerfCheckPoints 70368744177664
|
||||
ut:RegistrationEvent 140737488355328
|
||||
|
||||
Creating an ETL file using this provider:
|
||||
Start-ETWSession -ProviderName Microsoft-Windows-DNS-Client -OutputFile $env:temp\dnsout.etl -SessionName DNS-01
|
||||
|
||||
Above starts the session without any keywords. There is a Keywords argument, but I have not tried it yet.
|
||||
|
||||
Stopping the session:
|
||||
Stop-ETWSession -SessionName DNS-01
|
||||
|
||||
Get-WinEvent may be used to read the ETL file (note: -Oldest is required):
|
||||
Get-WinEvent -Path $env:temp\dnsout.etl -Oldest
|
||||
|
||||
There are likey other ways to read this file, I'm still investigating, but the above works.
|
||||
|
||||
ToDo: How can we create a session in memory, without writing to disk and have a "listener" that monitors for events we'e interested in?
|
||||
|
||||
This can be used to enumerate the methods on the given assembly, in this case Microsoft.Diagnostics.Tracing.TraceEvent:
|
||||
|
||||
try {
|
||||
import-module X:\PSalander\EventTrace\lib\Microsoft.Diagnostics.Tracing.TraceEvent.dll
|
||||
[Microsoft.Diagnostics.Tracing.TraceEvent].GetMethods() | Select-Object -ExpandProperty Name |
|
||||
Foreach-Object {
|
||||
[Microsoft.Diagnostics.Tracing.TraceEvent].GetMethod($_) | Select Name
|
||||
}
|
||||
} catch {
|
||||
$_
|
||||
} Finally {
|
||||
Remove-Module Microsoft.Diagnostics.Tracing.TraceEvent
|
||||
}
|
||||
|
||||
This does throw an exception on EventData because there are two EventData methods, resulting in an ambiguous call.
|
||||
|
||||
PIDs in the ETL file for dns lookups correspond to svchost processes.
|
||||
|
||||
Ids Purpose
|
||||
1001
|
||||
@@ -0,0 +1,25 @@
|
||||
1002 The DNS server being queried for interface %1 has changed to %3
|
||||
1026 The question (%2) in the response from server %4 does not match the original question %1
|
||||
3000 DNS Query is initiated for the name %1 and for the type %2 with query options %3
|
||||
3001 DNS Query operation is completed with result %1
|
||||
3002 DNS Cache lookup is initiated for the name %1 and for the type %2 with query options %3
|
||||
3003 DNS Cache lookup operation for the name %1 and for the type %2 is completed with result %3
|
||||
3004 DNS FQDN Query is initiated for the name %1 and for the type %2 with query options %3
|
||||
3005 DNS FQDN Query operation for the name %1 and for the type %2 is completed with result %3
|
||||
3006 DNS query is called for the name %1, type %2, query options %3, Server List %4, isNetwork query %5, network
|
||||
index %6, interface index %7, is asynchronous query %8
|
||||
3007 DnsQueryEx for the name %1 is pending
|
||||
3008 DNS query is completed for the name %1, type %2, query options %3 with status %4 Results %5
|
||||
3009 Network query initiated for the name %1 (is parallel query %2) on network index %3 with interface count %4 with
|
||||
first interface name %5, local addresses %6 and Dns Servers %7
|
||||
3010 DNS Query sent to DNS Server %3 for name %1 and type %2
|
||||
3011 Received response from DNS Server %3 for name %1 and type %2 with response status %4
|
||||
3012 NETBIOS query is initiated for name %1 on network index %2 with inteface count %3 with first interface name %4
|
||||
and local addresses %5
|
||||
3013 NETBIOS query is completed for name %1 with status %2 and results %3
|
||||
3014 NETBIOS query for the name %1 is pending
|
||||
3015 DnsQueryEx is canceled for the name %1
|
||||
3016 Cache lookup called for name %1, type %2, options %3 and interface index %4
|
||||
3018 Cache lookup for name %1, type %2 and option %3 returned %4 with results %5
|
||||
3019 Query wire called for name %1, type %2, interface index %3 and network index %4
|
||||
3020 Query response for name %1, type %2, interface index %3 and network index %4 returned %5 with results %6
|
||||
@@ -0,0 +1,245 @@
|
||||
function Convert-DNSEventProperties {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Converts MS-Windows-DNS-Client events properties first-order object noteproperties.
|
||||
|
||||
.DESCRIPTION
|
||||
Convert-DNSEventProperties takes an array of MS-Windows-DNS-Client events and converts the
|
||||
event properties to first-order noteproperties on the objects it returns
|
||||
|
||||
.PARAMETER Events
|
||||
An array of MS-Windows-DNS-Client events
|
||||
|
||||
.EXAMPLE
|
||||
$Events | Convert-DNSEventProperties | Format-List * -Force
|
||||
|
||||
TimeCreated : 5/26/2017 10:56:53 AM
|
||||
Id : 3008
|
||||
Message : DNS query is completed for the name v10.vortex-win.data.microsoft.com, type 1, query options 1073766400 with status 87 Results
|
||||
Name : v10.vortex-win.data.microsoft.com
|
||||
Type : 1
|
||||
Options : 1073766400
|
||||
Status : 87
|
||||
Result :
|
||||
|
||||
TimeCreated : 5/26/2017 10:56:53 AM
|
||||
Id : 3009
|
||||
Message : Network query initiated for the name v10.vortex-win.data.microsoft.com (is parallel query 1) on network index 0 with
|
||||
interface count 1 with first interface name Ethernet0, local addresses 192.168.123.53; and Dns Servers 192.168.123.10;
|
||||
Name : v10.vortex-win.data.microsoft.com
|
||||
isParallelQry : 1
|
||||
NetworkIndex : 0
|
||||
InterfaceCount : 1
|
||||
FirstInterfaceName : Ethernet0
|
||||
LocalAddresses : 192.168.123.53;
|
||||
DNSServers : 192.168.123.10;
|
||||
|
||||
.NOTES
|
||||
General notes
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
[System.Diagnostics.Eventing.Reader.EventLogRecord[]]
|
||||
$Events
|
||||
)
|
||||
|
||||
Process {
|
||||
# Create Object with common properties
|
||||
$Events | Foreach-Object {
|
||||
$_Event = $_
|
||||
$Obj = New-Object psobject
|
||||
$Obj | Add-Member -NotePropertyName 'TimeCreated' -NotePropertyValue $_Event.TimeCreated
|
||||
$Obj | Add-Member -NotePropertyName 'Id' -NotePropertyValue $_Event.Id
|
||||
$Obj | Add-Member -NotePropertyName 'Message' -NotePropertyValue $_Event.Message
|
||||
|
||||
# Add properties based on Event Id
|
||||
switch ( $_Event.Id ) {
|
||||
1002 {
|
||||
# DNS server for interface
|
||||
$Obj | Add-Member -NotePropertyName 'Interface' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'DNSServer' -NotePropertyValue $_Event.Properties[2].value
|
||||
break
|
||||
} # DNS server for interface
|
||||
|
||||
1026 {
|
||||
# Response question doesn't match request question
|
||||
$Obj | Add-Member -NotePropertyName 'ResponseQuestion' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'DNSServer' -NotePropertyValue $_Event.Properties[3].value
|
||||
$Obj | Add-Member -NotePropertyName 'RequestQuestion' -NotePropertyValue $_Event.Properties[0].value
|
||||
break
|
||||
} # Response question doesn't match request question
|
||||
|
||||
3001 {
|
||||
# Query result
|
||||
$Obj | Add-Member -NotePropertyName 'Result' -NotePropertyValue $_Event.Properties[0].value
|
||||
break
|
||||
} # Query result
|
||||
|
||||
3002 {
|
||||
# Cache lookup for name, type, query options
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'Options' -NotePropertyValue $_Event.Properties[2].value
|
||||
break
|
||||
} # Cache lookup for name, type, query options
|
||||
|
||||
3003 {
|
||||
# Cache lookup for name, type completed with result
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'Result' -NotePropertyValue $_Event.Properties[2].value
|
||||
break
|
||||
} # Cache lookup for name, type completed with result
|
||||
|
||||
3004 {
|
||||
# FQDN query initiated for name, type, with options
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'Options' -NotePropertyValue $_Event.Properties[2].value
|
||||
break
|
||||
} # FQDN query initiated for name, type, with options
|
||||
|
||||
3005 {
|
||||
# FQDN query for name, type completed with result
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'Result' -NotePropertyValue $_Event.Properties[2].value
|
||||
break
|
||||
} # FQDN query for name, type completed with result
|
||||
|
||||
3006 {
|
||||
# Query for name, type, options, server list, isNetwork, network index, interface index, asynchronous
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'Options' -NotePropertyValue $_Event.Properties[2].value
|
||||
$Obj | Add-Member -NotePropertyName 'ServerList' -NotePropertyValue $_Event.Properties[3].value
|
||||
$Obj | Add-Member -NotePropertyName 'isNetworkQuery' -NotePropertyValue $_Event.Properties[4].value
|
||||
$Obj | Add-Member -NotePropertyName 'NetworkIndex' -NotePropertyValue $_Event.Properties[5].value
|
||||
$Obj | Add-Member -NotePropertyName 'InterfaceIndex' -NotePropertyValue $_Event.Properties[6].value
|
||||
$Obj | Add-Member -NotePropertyName 'Asynchronous' -NotePropertyValue $_Event.Properties[7].value
|
||||
break
|
||||
} # Query for name, type, options, server list, isNetwork, network index, interface index, asynchronous
|
||||
|
||||
3007 {
|
||||
# DNSQueryEx for name is pending
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
break
|
||||
} # DNSQueryEx for name is pending
|
||||
|
||||
3008 {
|
||||
# DNS query completed for name, type, options with status, and results
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'Options' -NotePropertyValue $_Event.Properties[2].value
|
||||
$Obj | Add-Member -NotePropertyName 'Status' -NotePropertyValue $_Event.Properties[3].value
|
||||
$Obj | Add-Member -NotePropertyName 'Result' -NotePropertyValue $_Event.Properties[4].value
|
||||
break
|
||||
} # DNS query completed for name, type, options with status, and results
|
||||
|
||||
3009 {
|
||||
# Network query initiated for name, is parallel query, on network index with iface count
|
||||
# with first iface name, local addresses and DNS servers
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'isParallelQry' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'NetworkIndex' -NotePropertyValue $_Event.Properties[2].value
|
||||
$Obj | Add-Member -NotePropertyName 'InterfaceCount' -NotePropertyValue $_Event.Properties[3].value
|
||||
$Obj | Add-Member -NotePropertyName 'FirstInterfaceName' -NotePropertyValue $_Event.Properties[4].value
|
||||
$Obj | Add-Member -NotePropertyName 'LocalAddresses' -NotePropertyValue $_Event.Properties[5].value
|
||||
$Obj | Add-Member -NotePropertyName 'DNSServers' -NotePropertyValue $_Event.Properties[6].value
|
||||
break
|
||||
} # Network query initiated for name, is parallel query, on network index with iface count
|
||||
# with first iface name, local addresses and DNS servers
|
||||
|
||||
3010 {
|
||||
# Query sent to server for name and type
|
||||
$Obj | Add-Member -NotePropertyName 'Server' -NotePropertyValue $_Event.Properties[2].value
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
break
|
||||
} # Query sent to server for name and type
|
||||
|
||||
3011 {
|
||||
# Received response from server for name and type with response status
|
||||
$Obj | Add-Member -NotePropertyName 'Server' -NotePropertyValue $_Event.Properties[2].value
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'Status' -NotePropertyValue $_Event.Properties[3].value
|
||||
break
|
||||
} # Received response from server for name and type with response status
|
||||
|
||||
3012 {
|
||||
# NETBIOS query initiated for name, network index, interface count, first interface name and
|
||||
# local addresses
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'NetworkIndex' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'InterfaceCount' -NotePropertyValue $_Event.Properties[2].value
|
||||
$Obj | Add-Member -NotePropertyName 'FirstInterfaceName' -NotePropertyValue $_Event.Properties[3].value
|
||||
$Obj | Add-Member -NotePropertyName 'LocalAddresses' -NotePropertyValue $_Event.Properties[4].value
|
||||
break
|
||||
} # NETBIOS query initiated for name, network index, interface count, first interface name and
|
||||
# local addresses
|
||||
|
||||
3013 {
|
||||
# NETBIOS query completed for name with status and result
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Status' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'Results' -NotePropertyValue $_Event.Properties[2].value
|
||||
break
|
||||
} # NETBIOS query completed for name with status and result
|
||||
|
||||
3014 {
|
||||
# NETBIOS query for name is pending
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
break
|
||||
} # NETBIOS query for name is pending
|
||||
|
||||
3015 {
|
||||
# DNSQueryEx canceled for name
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
break
|
||||
} # DNSQueryEx canceled for name
|
||||
|
||||
3016 {
|
||||
# Cache lookup called for name, type, options and interface index
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'Options' -NotePropertyValue $_Event.Properties[2].value
|
||||
$Obj | Add-Member -NotePropertyName 'InterfaceIndex' -NotePropertyValue $_Event.Properties[3].value
|
||||
break
|
||||
} # Cache lookup called for name, type, options and interface index
|
||||
|
||||
3018 {
|
||||
# Cache lookup for name, type and option returned value with results
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'Option' -NotePropertyValue $_Event.Properties[2].value
|
||||
$Obj | Add-Member -NotePropertyName 'Value' -NotePropertyValue $_Event.Properties[3].value
|
||||
$Obj | Add-Member -NotePropertyName 'Results' -NotePropertyValue $_Event.Properties[4].value
|
||||
break
|
||||
} # Cache lookup for name, type and option returned value with results
|
||||
|
||||
3019 {
|
||||
# Query wire called for name, type, interface index and network index
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'InterfaceIndex' -NotePropertyValue $_Event.Properties[2].value
|
||||
$Obj | Add-Member -NotePropertyName 'NetworkIndex' -NotePropertyValue $_Event.Properties[3].value
|
||||
break
|
||||
} # Query wire called for name, type, interface index and network index
|
||||
|
||||
3020 {
|
||||
# Response for name, type, interface index and network index returned value with results
|
||||
$Obj | Add-Member -NotePropertyName 'Name' -NotePropertyValue $_Event.Properties[0].value
|
||||
$Obj | Add-Member -NotePropertyName 'Type' -NotePropertyValue $_Event.Properties[1].value
|
||||
$Obj | Add-Member -NotePropertyName 'InterfaceIndex' -NotePropertyValue $_Event.Properties[2].value
|
||||
$Obj | Add-Member -NotePropertyName 'NetworkIndex' -NotePropertyValue $_Event.Properties[3].value
|
||||
$Obj | Add-Member -NotePropertyName 'Value' -NotePropertyValue $_Event.Properties[4].value
|
||||
$Obj | Add-Member -NotePropertyName 'Results' -NotePropertyValue $_Event.Properties[5].value
|
||||
break
|
||||
} # Response for name, type, interface index and network index returned value with results
|
||||
} # End switch
|
||||
|
||||
$Obj
|
||||
}
|
||||
} # End Convert-DNSEventProperties
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
function Win10DNSResponse
|
||||
{
|
||||
param($Event)
|
||||
$IPRegex = '([0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||
|
||||
# Only type 28 responses contain domain to IP mappings
|
||||
If ( $Event.Properties[1].value -eq 28 -and $Event.Properties[4].value -match $IPRegex ) {
|
||||
|
||||
$ProcID = [int32]$Event.ProcessID
|
||||
|
||||
$IPAddress = $matches[0]
|
||||
|
||||
$NewDNSObject = New-Object -TypeName psobject
|
||||
$NewDNSObject | Add-Member -NotePropertyName 'DomainName' -NotePropertyValue $Event.Properties[0].value
|
||||
$NewDNSObject | Add-Member -NotePropertyName 'IPv4Address' -NotePropertyValue $IPAddress
|
||||
$NewDNSObject | Add-Member -NotePropertyName 'ThreadID' -NotePropertyValue $Event.ThreadID
|
||||
|
||||
If ( $Events.ContainsKey( $ProcID ) ) {
|
||||
|
||||
If ( ($Events[$ProcID].PSObject.Properties.Name -match 'DomainLookups').Count -lt 1 ) {
|
||||
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'DomainLookups' -NotePropertyValue @()
|
||||
|
||||
}
|
||||
|
||||
$Events[ $ProcID ].DomainLookups += $NewDNSObject
|
||||
|
||||
$Events[$ProcID].Threads |
|
||||
Where-Object { $_.threadID -eq $Event.ThreadID } |
|
||||
ForEach-Object {
|
||||
If ( ($_.PSObject.Properties.Name -match 'DomainLookups').Count -lt 1 ) {
|
||||
$_ | Add-Member -NotePropertyName 'DomainLookups' -NotePropertyValue @()
|
||||
}
|
||||
$_.DomainLookups += $NewDNSObject
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
$NewProcessObject = New-Object -TypeName psobject
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ProcessID' -NotePropertyValue $ProcID
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'DomainLookups' -NotePropertyValue @()
|
||||
|
||||
$NewProcessObject.DomainLookups += $NewDNSObject
|
||||
|
||||
$Events.Add( $ProcID, $NewProcessObject )
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function Win2012DNSResponse
|
||||
{
|
||||
param($Event)
|
||||
|
||||
|
||||
$ProcID = [int32]$Event.ProcessID
|
||||
|
||||
$NewDNSObject = New-Object -TypeName psobject
|
||||
$NewDNSObject | Add-Member -NotePropertyName 'DomainName' -NotePropertyValue $Event.Properties[0].value
|
||||
|
||||
If ( $Events.ContainsKey( [int32]$ProcID ) ) {
|
||||
|
||||
If ( ($Events[$ProcID].PSObject.Properties.Name -match 'DomainLookups').Count -lt 1 ) {
|
||||
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'DomainLookups' -NotePropertyValue @()
|
||||
|
||||
}
|
||||
|
||||
$Events[ $ProcID ].DomainLookups += $NewDNSObject
|
||||
|
||||
$Events[$ProcID].Threads |
|
||||
Where-Object { $_.threadID -eq $Event.ThreadID } |
|
||||
ForEach-Object {
|
||||
If ( ($_.PSObject.Properties.Name -match 'DomainLookups').Count -lt 1 ) {
|
||||
$_ | Add-Member -NotePropertyName 'DomainLookups' -NotePropertyValue @()
|
||||
}
|
||||
$_.DomainLookups += $NewDNSObject
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
$NewProcessObject = New-Object -TypeName psobject
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ProcessID' -NotePropertyValue $ProcID
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'DomainLookups' -NotePropertyValue @()
|
||||
|
||||
$NewProcessObject.DomainLookups += $NewDNSObject
|
||||
|
||||
$Events.Add( $ProcID, $NewProcessObject )
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function DNSClientParser
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
[System.Diagnostics.Eventing.Reader.EventRecord]
|
||||
$Event
|
||||
|
||||
)
|
||||
|
||||
$script:KernProcEvents = @{
|
||||
3008 = 'Win10DNSResponse'
|
||||
3000 = 'Win2012DNSResponse'
|
||||
}
|
||||
|
||||
If ( $script:KernProcEvents.ContainsKey($Event.Id) ) {
|
||||
&$script:KernProcEvents[$_.Id] $Event
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
+ Identify interesting DNS Events
|
||||
+ 25 events see Monitored-DNS-Events
|
||||
- Determine best way to represent them
|
||||
- As objects? Each event it's own object? Get-WinEvent already returns
|
||||
objects, we just need code that can pull the properties we want from those
|
||||
objects.
|
||||
@@ -0,0 +1,86 @@
|
||||
Get-ETWProvider | ? {$_.Name -match "kernel-file"} | % {$_.Events} | select id, keywords
|
||||
# No descriptions for this provider
|
||||
|
||||
Id Keywords
|
||||
-- --------
|
||||
10 {, KERNEL_FILE_KEYWORD_FILENAME}
|
||||
11 {, KERNEL_FILE_KEYWORD_FILENAME}
|
||||
12 {, KERNEL_FILE_KEYWORD_CREATE, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
12 {, KERNEL_FILE_KEYWORD_CREATE, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
13 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
13 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
14 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
14 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
15 {, KERNEL_FILE_KEYWORD_READ, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
15 {, KERNEL_FILE_KEYWORD_READ, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
16 {, KERNEL_FILE_KEYWORD_WRITE, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
16 {, KERNEL_FILE_KEYWORD_WRITE, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
17 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
17 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
18 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
18 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
19 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
19 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
20 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
20 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
21 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
21 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
22 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
22 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
23 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
23 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
24 {, KERNEL_FILE_KEYWORD_OP_END, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
25 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
25 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
26 {, KERNEL_FILE_KEYWORD_DELETE_PATH}
|
||||
26 {, KERNEL_FILE_KEYWORD_DELETE_PATH}
|
||||
27 {, KERNEL_FILE_KEYWORD_RENAME_SETLINK_PATH}
|
||||
27 {, KERNEL_FILE_KEYWORD_RENAME_SETLINK_PATH}
|
||||
28 {, KERNEL_FILE_KEYWORD_RENAME_SETLINK_PATH}
|
||||
28 {, KERNEL_FILE_KEYWORD_RENAME_SETLINK_PATH}
|
||||
29 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
29 {, KERNEL_FILE_KEYWORD_FILEIO}
|
||||
30 {, KERNEL_FILE_KEYWORD_CREATE_NEW_FILE}
|
||||
30 {, KERNEL_FILE_KEYWORD_CREATE_NEW_FILE}
|
||||
|
||||
|
||||
Get-ETWProviderKeywords -ProviderName "Microsoft-Windows-kernel-file"
|
||||
|
||||
Name Description Value
|
||||
---- ----------- -----
|
||||
KERNEL_FILE_KEYWORD_FILENAME ... 16
|
||||
KERNEL_FILE_KEYWORD_FILEIO ... 32
|
||||
KERNEL_FILE_KEYWORD_OP_END ... 64
|
||||
KERNEL_FILE_KEYWORD_CREATE ... 128
|
||||
KERNEL_FILE_KEYWORD_READ ... 256
|
||||
KERNEL_FILE_KEYWORD_WRITE ... 512
|
||||
KERNEL_FILE_KEYWORD_DELETE_PATH ... 1024
|
||||
KERNEL_FILE_KEYWORD_RENAME_SETLINK_PATH ... 2048
|
||||
KERNEL_FILE_KEYWORD_CREATE_NEW_FILE ... 4096
|
||||
Microsoft-Windows-Kernel-File/Analytic ... 9223372036854775808
|
||||
|
||||
|
||||
|
||||
|
||||
PS Z:\workspaces\PSalander> $a | % {$_.id} | Group-Object
|
||||
|
||||
Count Name Group
|
||||
----- ---- -----
|
||||
19338 15 {15, 15, 15, 15...}
|
||||
6831 12 {12, 12, 12, 12...}
|
||||
6466 16 {16, 16, 16, 16...}
|
||||
28 30 {30, 30, 30, 30...}
|
||||
1 26 {26}
|
||||
|
||||
General Notes
|
||||
|
||||
Event 30 tracks new files created and each event contains the process ID and file path
|
||||
|
||||
Event 26 tracks file deletion Events
|
||||
|
||||
|
||||
Event 12 seems to be general calls to CreateFile (getting handle to file )
|
||||
|
||||
Event 16 records file writes. References FileObject and not path
|
||||
In order to match this event back to file path need to first parse/track Event 12
|
||||
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Kernel-File' Guid='{edd08927-9cc4-4e65-b970-c2560fb5c289}'/><EventID>16</EventID><Version>1</Version><Level>4</Level><Task>16</Task><Opcode>0</Opcode><Keywords>0x8000000000000220</Keywords><TimeCreated SystemTime='2017-06-26T01:37:12.555489800Z'/><EventRecordID>26930</EventRecordID><Correlation/><Execution ProcessID='4560' ThreadID='4372' ProcessorID='0' KernelTime='0' UserTime='1'/><Channel></Channel><Computer>DESKTOP-US5J4M3</Computer><Security/></System><EventData><Data Name='ByteOffset'>0</Data><Data Name='Irp'>0xffffc7810221e378</Data><Data Name='FileObject'>0xffffc780ff6048f0</Data><Data Name='FileKey'>0xffff96090b10ac00</Data><Data Name='IssuingThreadId'>4372</Data><Data Name='IOSize'>9</Data><Data Name='IOFlags'>395776</Data><Data Name='ExtraFlags'>0</Data></EventData></Event>
|
||||
@@ -0,0 +1,144 @@
|
||||
$OpenFiles = @{}
|
||||
|
||||
function FileOpen
|
||||
{
|
||||
param($Event)
|
||||
|
||||
$FileID = $Event.Properties[0].value
|
||||
$FilePath = $Event.Properties[6].value
|
||||
|
||||
if ( -Not $OpenFiles.ContainsKey( $FileID ) ){
|
||||
$OpenFiles.Add( $FileID, $FilePath )
|
||||
}
|
||||
|
||||
} # FileOpen
|
||||
|
||||
function FileWrite
|
||||
{
|
||||
param($Event)
|
||||
|
||||
$FileID = $Event.Properties[1].value
|
||||
|
||||
# Confirm file object is known
|
||||
If ( $OpenFiles.ContainsKey( $FileID ) ) {
|
||||
|
||||
$ProcID = [int32]$Event.ProcessId
|
||||
$BytesWrite = $Event.Properties[5].value
|
||||
$Action = "WRITE"
|
||||
|
||||
$NewFileObj = New-Object -TypeName psobject
|
||||
|
||||
$NewFileObj | Add-Member -NotePropertyName 'FilePath' -NotePropertyValue $OpenFiles[ $FileID ]
|
||||
$NewFileObj | Add-Member -NotePropertyName 'Action' -NotePropertyValue $Action
|
||||
$NewFileObj | Add-Member -NotePropertyName 'BytesWritten' -NotePropertyValue $BytesWrite
|
||||
$NewFileObj | Add-Member -NotePropertyName 'ThreadID' -NotePropertyValue $Event.ThreadID
|
||||
|
||||
If ( $Events.ContainsKey( $ProcID ) ) {
|
||||
|
||||
If ( ($Events[$ProcID].PSObject.Properties.Name -match 'FileIO').Count -lt 1 ) {
|
||||
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'FileIO' -NotePropertyValue @()
|
||||
|
||||
}
|
||||
|
||||
$Events[$ProcID].FileIO += $NewFileObj
|
||||
|
||||
$Events[$ProcID].Threads |
|
||||
Where-Object { $_.threadID -eq $Event.ThreadID } |
|
||||
ForEach-Object {
|
||||
If ( ($_.PSObject.Properties.Name -match 'FileIO').Count -lt 1 ) {
|
||||
$_ | Add-Member -NotePropertyName 'FileIO' -NotePropertyValue @()
|
||||
}
|
||||
$_.FileIO += $NewFileObj
|
||||
}
|
||||
}
|
||||
else {
|
||||
$NewProcessObject = New-Object -TypeName psobject
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ProcessID' -NotePropertyValue $ProcID
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'FileIO' -NotePropertyValue @()
|
||||
|
||||
$NewProcessObject.FileIO += $NewFileObj
|
||||
|
||||
$Events.Add( $ProcID, $NewProcessObject )
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} # FileWrite
|
||||
|
||||
function FileCreateDelete
|
||||
{
|
||||
param($Event)
|
||||
|
||||
$ProcID = [int32]$Event.ProcessId
|
||||
$FilePath = $Event.Properties[6].value
|
||||
|
||||
If ( $Event.Id -eq 26 ) {
|
||||
$Action = "DELETE"
|
||||
}
|
||||
Elseif ($Event.Id -eq 30) {
|
||||
$Action = "CREATE"
|
||||
}
|
||||
|
||||
|
||||
$NewFileObj = New-Object -TypeName psobject
|
||||
|
||||
$NewFileObj | Add-Member -NotePropertyName 'FilePath' -NotePropertyValue $FilePath
|
||||
$NewFileObj | Add-Member -NotePropertyName 'Action' -NotePropertyValue $Action
|
||||
$NewFileObj | Add-Member -NotePropertyName 'ThreadID' -NotePropertyValue $Event.ThreadID
|
||||
|
||||
|
||||
If ( $Events.ContainsKey( $ProcID ) ) {
|
||||
|
||||
If ( ($Events[$ProcID].PSObject.Properties.Name -match 'FileIO').Count -lt 1 ) {
|
||||
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'FileIO' -NotePropertyValue @()
|
||||
|
||||
}
|
||||
$Events[$ProcID].FileIO += $NewFileObj
|
||||
|
||||
$Events[$ProcID].Threads |
|
||||
Where-Object { $_.threadID -eq $Event.ThreadID } |
|
||||
ForEach-Object {
|
||||
If ( ($_.PSObject.Properties.Name -match 'FileIO').Count -lt 1 ) {
|
||||
$_ | Add-Member -NotePropertyName 'FileIO' -NotePropertyValue @()
|
||||
}
|
||||
$_.FileIO += $NewFileObj
|
||||
}
|
||||
}
|
||||
else {
|
||||
$NewProcessObject = New-Object -TypeName psobject
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ProcessID' -NotePropertyValue $ProcID
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'FileIO' -NotePropertyValue @()
|
||||
|
||||
$NewProcessObject.FileIO += $NewFileObj
|
||||
|
||||
$Events.Add( $ProcID, $NewProcessObject )
|
||||
|
||||
}
|
||||
|
||||
|
||||
} # FileCreateDelete
|
||||
|
||||
function KernelFileParser
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
[System.Diagnostics.Eventing.Reader.EventRecord]
|
||||
$Event
|
||||
|
||||
)
|
||||
|
||||
$script:KernProcEvents = @{
|
||||
12 = 'FileOpen'
|
||||
16 = 'FileWrite'
|
||||
26 = 'FileCreateDelete'
|
||||
30 = 'FileCreateDelete'
|
||||
}
|
||||
|
||||
If ( $script:KernProcEvents.ContainsKey($Event.Id) ) {
|
||||
&$script:KernProcEvents[$_.Id] $Event
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
Get-ETWProvider | Where-Object { $_.Name -eq 'Microsoft-Windows-Kernel-Network'} | % { $_.Events } | select id,description | ft -Wrap -Property Id,Description
|
||||
|
||||
Id Description
|
||||
-- -----------
|
||||
10 TCPv4: %2 bytes transmitted from %4:%6 to %3:%5.
|
||||
11 TCPv4: %2 bytes received from %4:%6 to %3:%5.
|
||||
12 TCPv4: Connection attempted between %4:%6 and %3:%5.
|
||||
13 TCPv4: Connection closed between %4:%6 and %3:%5.
|
||||
14 TCPv4: %2 bytes retransmitted from %4:%6 to %3:%5.
|
||||
15 TCPv4: Connection established between %4:%6 and %3:%5.
|
||||
16 TCPv4: Reconnect attempt between %4:%6 and %3:%5.
|
||||
17 TCPv4: Connection attempt failed with error code %2.
|
||||
18 TCPv4: %2 bytes copied in protocol on behalf of user for connection between %4:%6 and %3:%5.
|
||||
26 TCPv6: %2 bytes transmitted from %4:%6 to %3:%5.
|
||||
27 TCPv6: %2 bytes received from %4:%6 to %3:%5.
|
||||
28 TCPv6: Connection attempted between %4:%6 and %3:%5.
|
||||
29 TCPv6: Connection closed between %4:%6 and %3:%5.
|
||||
30 TCPv6: %2 bytes retransmitted from %4:%6 to %3:%5.
|
||||
31 TCPv6: Connection established between %4:%6 and %3:%5.
|
||||
32 TCPv6: Reconnect attempt between %4:%6 and %3:%5.
|
||||
34 TCPv6: %2 bytes copied in protocol on behalf of user for connection between %4:%6 and %3:%5.
|
||||
42 UDPv4: %2 bytes transmitted from %4:%6 to %3:%5.
|
||||
43 UDPv4: %2 bytes received from %4:%6 to %3:%5.
|
||||
49 UDPv4: Connection attempt failed with error code %2.
|
||||
58 UDPv6: %2 bytes transmitted from %4:%6 to %3:%5.
|
||||
59 UDPv6: %2 bytes received from %4:%6 to %3:%5.
|
||||
|
||||
|
||||
Get-ETWProviderKeywords -ProviderName Microsoft-Windows-Kernel-Network
|
||||
|
||||
|
||||
Name Description Value
|
||||
---- ----------- -----
|
||||
KERNEL_NETWORK_KEYWORD_IPV4 16
|
||||
KERNEL_NETWORK_KEYWORD_IPV6 32
|
||||
Microsoft-Windows-Kernel-Network/Analytic 9223372036854775808
|
||||
|
||||
Event Log xml
|
||||
|
||||
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
|
||||
<System>
|
||||
<Provider Name="Microsoft-Windows-Kernel-Network" Guid="{7dd42a49-5329-4832-8dfd-43d979153a88}" />
|
||||
<EventID>12</EventID>
|
||||
<Version>0</Version>
|
||||
<Level>4</Level>
|
||||
<Task>10</Task>
|
||||
<Opcode>12</Opcode>
|
||||
<Keywords>0x8000000000000010</Keywords>
|
||||
<TimeCreated SystemTime="2017-06-09T23:42:28.277200000Z" />
|
||||
<EventRecordID>0</EventRecordID>
|
||||
<Correlation />
|
||||
<Execution ProcessID="4" ThreadID="300" ProcessorID="0" KernelTime="1661" UserTime="0" />
|
||||
<Channel></Channel>
|
||||
<Computer>office-pc</Computer>
|
||||
<Security />
|
||||
</System>
|
||||
<EventData>
|
||||
<Data Name="PID">2456</Data>
|
||||
<Data Name="size">0</Data>
|
||||
<Data Name="daddr">1142973847</Data>
|
||||
<Data Name="saddr">3388997642</Data>
|
||||
<Data Name="dport">20480</Data>
|
||||
<Data Name="sport">11985</Data>
|
||||
<Data Name="mss">1396</Data>
|
||||
<Data Name="sackopt">1</Data>
|
||||
<Data Name="tsopt">0</Data>
|
||||
<Data Name="wsopt">1</Data>
|
||||
<Data Name="rcvwin">65612</Data>
|
||||
<Data Name="rcvwinscale">8</Data>
|
||||
<Data Name="sndwinscale">9</Data>
|
||||
<Data Name="seqnum">0</Data>
|
||||
<Data Name="connid">0</Data>
|
||||
</EventData>4
|
||||
@@ -0,0 +1,112 @@
|
||||
function IPv4Connection
|
||||
{
|
||||
param($Event)
|
||||
|
||||
$ProcID = [int32]$Event.Properties[0].value
|
||||
|
||||
$DestIP = [System.Net.IPAddress]$Event.Properties[2].value
|
||||
|
||||
# Ports are returned in BIG-IP system encoding
|
||||
# Converts the decimal port value to the equivalent 2-byte hexadecimal value.
|
||||
# Reverses the order of the two hexadecimal bytes.
|
||||
# Converts the resulting 2-byte hexadecimal value to its decimal equivalent.
|
||||
# https://support.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/ltm-concepts-11-5-0/10.html
|
||||
|
||||
$DestPort = "{0:x}" -f [int]$Event.Properties[4].value |
|
||||
ForEach-Object { $_ -split '(..)' } |
|
||||
Where-Object { $_ }
|
||||
|
||||
[array]::Reverse($DestPort)
|
||||
|
||||
$DestPort = [Convert]::ToInt32( -join( $DestPort ), 16 )
|
||||
|
||||
$NewNetworkObj = New-Object -TypeName psobject
|
||||
$NewNetworkObj | Add-Member -NotePropertyName 'DestinationIP' -NotePropertyValue $DestIP.IPAddressToString
|
||||
$NewNetworkObj | Add-Member -NotePropertyName 'DestinationPort' -NotePropertyValue $DestPort
|
||||
$NewNetworkObj | Add-Member -NotePropertyName 'ThreadID' -NotePropertyValue $Event.ThreadID
|
||||
$NewNetworkObj | Add-Member -NotePropertyName 'Count' -NotePropertyValue 1
|
||||
|
||||
|
||||
If ( $Events.ContainsKey( $ProcID ) ) {
|
||||
|
||||
If ( ($Events[$ProcID].PSObject.Properties.Name -match 'NetConnections').Count -lt 1 ) {
|
||||
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'NetConnections' -NotePropertyValue @()
|
||||
|
||||
}
|
||||
|
||||
# This will only add connection if an identical one (port and IP) has not already been added
|
||||
|
||||
$found = $Events[ $ProcID ].NetConnections |
|
||||
Where-Object { $_.DestinationIP -eq $NewNetworkObj.DestinationIP -and $_.DestinationPort -eq $NewNetworkObj.DestinationPort -and $_.ThreadID -eq $NewNetworkObj.ThreadID } |
|
||||
ForEach-Object { $true }
|
||||
|
||||
# Add netork threading object if not there
|
||||
$Events[$ProcID].Threads |
|
||||
Where-Object { $_.threadID -eq $Event.ThreadID } |
|
||||
ForEach-Object {
|
||||
If ( ($_.PSObject.Properties.Name -match 'NetConnections').Count -lt 1 ) {
|
||||
$_ | Add-Member -NotePropertyName 'NetConnections' -NotePropertyValue @()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
If ( -Not $found ) {
|
||||
|
||||
$Events[ $ProcID ].NetConnections += $NewNetworkObj
|
||||
|
||||
$Events[$ProcID].Threads |
|
||||
Where-Object { $_.threadID -eq $Event.ThreadID } |
|
||||
ForEach-Object { $_.NetConnections += $NewNetworkObj }
|
||||
|
||||
} else {
|
||||
# If connection does exist increment count by 1
|
||||
$Events[ $ProcID ].NetConnections |
|
||||
Where-Object { $_.DestinationIP -eq $NewNetworkObj.DestinationIP -and $_.DestinationPort -eq $NewNetworkObj.DestinationPort -and $_.ThreadID -eq $NewNetworkObj.ThreadID } |
|
||||
ForEach-Object { $_.Count = $_.Count + 1 }
|
||||
|
||||
# Increment thread counter by 1
|
||||
$Events[$ProcID].Threads |
|
||||
Where-Object { $_.threadID -eq $Event.ThreadID } |
|
||||
Where-Object { ($_.NetConnections).DestinationIP -eq $NewNetworkObj.DestinationIP -and `
|
||||
($_.NetConnections).DestinationPort -eq $NewNetworkObj.DestinationPort } |
|
||||
ForEach-Object { $_.NetConnections } |
|
||||
ForEach-Object {$_.Count = $_.Count + 1}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
$NewProcessObject = New-Object -TypeName psobject
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ProcessID' -NotePropertyValue $ProcID
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'NetConnections' -NotePropertyValue @()
|
||||
|
||||
$NewProcessObject.NetConnections += $NewNetworkObj
|
||||
|
||||
$Events.Add( $ProcID, $NewProcessObject )
|
||||
}
|
||||
} # IPv4Connection
|
||||
|
||||
|
||||
function KernelNetworkParser
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
[System.Diagnostics.Eventing.Reader.EventRecord]
|
||||
$Event
|
||||
|
||||
)
|
||||
|
||||
$script:KernProcEvents = @{
|
||||
12 = 'IPv4Connection'
|
||||
}
|
||||
|
||||
If ( $script:KernProcEvents.ContainsKey($Event.Id) ) {
|
||||
&$script:KernProcEvents[$_.Id] $Event
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
Id Description
|
||||
-- -----------
|
||||
1 Process %1 started at time %2 by parent %3 running in session %4 with name %5.
|
||||
2 Process %1 (which started at time %2) stopped at time %3 with exit code %4.
|
||||
3 Thread %2 (in Process %1) started.
|
||||
4 Thread %2 (in Process %1) stopped.
|
||||
5 Process %3 had an image loaded with name %7.
|
||||
6 Process %3 had an image unloaded with name %7.
|
||||
7 Base CPU priority of thread %2 in process %1 was changed from %3 to %4.
|
||||
8 CPU priority of thread %2 in process %1 was changed from %3 to %4.
|
||||
9 Page priority of thread %2 in process %1 was changed from %3 to %4.
|
||||
10 I/O priority of thread %2 in process %1 was changed from %3 to %4.
|
||||
11 Execution of the process %1 has been suspended.
|
||||
12 Execution of the process %1 has been resumed.
|
||||
13 Job %1 started with status code %2.
|
||||
14 Job %1 terminated with status code %2.
|
||||
15 Enumerated process %1 had started at time %2 by parent %3 running in session %4 with name %6.
|
||||
16
|
||||
17
|
||||
18
|
||||
19
|
||||
20
|
||||
|
||||
XML of process stop event properties
|
||||
|
||||
<Data Name='ProcessID'>5636</Data>
|
||||
<Data Name='CreateTime'>2017-05-31T22:05:58.721944300Z</Data>
|
||||
<Data Name='ExitTime'>2017-05-31T22:07:28.692039900Z</Data>
|
||||
<Data Name='ExitCode'>1</Data>
|
||||
<Data Name='TokenElevationType'>3</Data>
|
||||
<Data Name='HandleCount'>208</Data>
|
||||
<Data Name='CommitCharge'>4456448</Data>
|
||||
<Data Name='CommitPeak'>4493312</Data>
|
||||
<Data Name='CPUCycleCount'>199385866</Data>
|
||||
<Data Name='ReadOperationCount'>0</Data>
|
||||
<Data Name='WriteOperationCount'>0</Data>
|
||||
<Data Name='ReadTransferKiloBytes'>0</Data>
|
||||
<Data Name='WriteTransferKiloBytes'>0</Data>
|
||||
<Data Name='HardFaultCount'>0</Data>
|
||||
<Data Name='ImageName'>backgroundTask</Data>
|
||||
|
||||
XML of process start event properties
|
||||
|
||||
<Data Name='ProcessID'>5068</Data>
|
||||
<Data Name='CreateTime'>2017-05-31T22:07:26.486024400Z</Data>
|
||||
<Data Name='ParentProcessID'>852</Data>
|
||||
<Data Name='SessionID'>1</Data>
|
||||
<Data Name='Flags'>0</Data>
|
||||
<Data Name='ImageName'>\Device\HarddiskVolume1\Windows\System32\dllhost.exe</Data>
|
||||
<Data Name='ImageChecksum'>60860</Data>
|
||||
<Data Name='TimeDateStamp'>1468636009</Data>
|
||||
<Data Name='PackageFullName'></Data>
|
||||
<Data Name='PackageRelativeAppId'></Data>
|
||||
|
||||
XML of image load event properties
|
||||
|
||||
<Data Name='ImageBase'>0x7ff7e4830000</Data>
|
||||
<Data Name='ImageSize'>0x9000</Data>
|
||||
<Data Name='ProcessID'>5068</Data>
|
||||
<Data Name='ImageCheckSum'>60860</Data>
|
||||
<Data Name='TimeDateStamp'>1468636009</Data>
|
||||
<Data Name='DefaultBase'>0x7ff7e4830000</Data>
|
||||
<Data Name='ImageName'>\Device\HarddiskVolume1\Windows\System32\dllhost.exe</Data>
|
||||
|
||||
Provider Keywords
|
||||
|
||||
|
||||
Name Description Value
|
||||
---- ----------- -----
|
||||
WINEVENT_KEYWORD_PROCESS 16
|
||||
WINEVENT_KEYWORD_THREAD 32
|
||||
WINEVENT_KEYWORD_IMAGE 64
|
||||
WINEVENT_KEYWORD_CPU_PRIORITY 128
|
||||
WINEVENT_KEYWORD_OTHER_PRIORITY 256
|
||||
WINEVENT_KEYWORD_PROCESS_FREEZE 512
|
||||
WINEVENT_KEYWORD_JOB 1024
|
||||
WINEVENT_KEYWORD_ENABLE_PROCESS_TRACING_CALLBACKS 2048
|
||||
WINEVENT_KEYWORD_JOB_IO 4096
|
||||
WINEVENT_KEYWORD_WORK_ON_BEHALF 8192
|
||||
WINEVENT_KEYWORD_JOB_SILO 16384
|
||||
Microsoft-Windows-Kernel-Process/Analytic 9223372036854775808
|
||||
@@ -0,0 +1,237 @@
|
||||
function ConvertTo-Hex
|
||||
{
|
||||
param($DecInt)
|
||||
|
||||
"0x{0:X}" -f $DecInt
|
||||
}
|
||||
|
||||
|
||||
function ThreadStart
|
||||
{
|
||||
param($Event)
|
||||
|
||||
$ProcID = [int32]$Event.Properties[0].value
|
||||
|
||||
# Thread property descriptions found at https://msdn.microsoft.com/fr-fr/dd765166
|
||||
$NewThread = New-Object -TypeName psobject
|
||||
$NewThread | Add-Member -NotePropertyName 'ThreadID' -NotePropertyValue $Event.Properties[1].value
|
||||
$NewThread | Add-Member -NotePropertyName 'StackBase' -NotePropertyValue (ConvertTo-Hex $Event.Properties[2].value)
|
||||
$NewThread | Add-Member -NotePropertyName 'StackLimit' -NotePropertyValue (ConvertTo-Hex $Event.Properties[3].value)
|
||||
$NewThread | Add-Member -NotePropertyName 'UserStackBase' -NotePropertyValue (ConvertTo-Hex $Event.Properties[4].value)
|
||||
$NewThread | Add-Member -NotePropertyName 'UserStackLimit' -NotePropertyValue (ConvertTo-Hex $Event.Properties[5].value)
|
||||
$NewThread | Add-Member -NotePropertyName 'StartAddr' -NotePropertyValue (ConvertTo-Hex $Event.Properties[6].value)
|
||||
$NewThread | Add-Member -NotePropertyName 'Win32StartAddr' -NotePropertyValue (ConvertTo-Hex $Event.Properties[7].value)
|
||||
$NewThread | Add-Member -NotePropertyName 'TebBase' -NotePropertyValue (ConvertTo-Hex $Event.Properties[8].value)
|
||||
$NewThread | Add-Member -NotePropertyName 'SubProcessTag' -NotePropertyValue $Event.Properties[9].value
|
||||
$NewThread | Add-Member -NotePropertyName 'ThreadStartTime' -NotePropertyValue $Event.TimeCreated
|
||||
|
||||
|
||||
If ( $Events.ContainsKey( $ProcID ) ) {
|
||||
|
||||
If ( ($Events[$ProcID].PSObject.Properties.Name -match 'Threads').Count -lt 1 ) {
|
||||
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'Threads' -NotePropertyValue @()
|
||||
|
||||
}
|
||||
|
||||
$Events[$ProcID].Threads += $NewThread
|
||||
}
|
||||
else {
|
||||
|
||||
$NewProcessObject = New-Object -TypeName psobject
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ProcessID' -NotePropertyValue $ProcID
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'Threads' -NotePropertyValue @()
|
||||
|
||||
$NewProcessObject.Threads += $NewThread
|
||||
|
||||
$Events.Add( $ProcID, $NewProcessObject )
|
||||
}
|
||||
|
||||
# Add image load to corresponding process thread
|
||||
# Need to calculate image end address
|
||||
$Events[$ProcId].LoadedImages |
|
||||
# Verify loadedimage property does not already exist
|
||||
# Verify the thread start address is between the image load and end addresses
|
||||
Where-Object { ( [uint64]$NewThread.Win32StartAddr -gt [uint64]$_.ImageBase) -and ([uint64]$NewThread.Win32StartAddr -lt [uint64](ConvertTo-Hex ([uint64]$_.ImageBase + [uint64]$_.ImageSize))) } |
|
||||
ForEach-Object {
|
||||
$NewThread | Add-Member -NotePropertyName 'LoadedImage' -NotePropertyValue $_.ImageName
|
||||
$NewThread | Add-Member -NotePropertyName 'ImageBase' -NotePropertyValue $_.ImageBase
|
||||
$NewThread | Add-Member -NotePropertyName 'ImageSize' -NotePropertyValue $_.ImageSize
|
||||
}
|
||||
|
||||
} # ThreadStart
|
||||
|
||||
|
||||
function ThreadStop
|
||||
{
|
||||
param($Event)
|
||||
|
||||
$ProcID = [int32]$Event.Properties[0].value
|
||||
$ThreadID = $Event.Properties[1].value
|
||||
|
||||
If ( $Events.ContainsKey( [int32]$ProcID ) -and ($Events[[int32]$ProcID].Threads).ThreadID -contains $ThreadID ) {
|
||||
|
||||
$Events[$ProcId].Threads |
|
||||
Where-Object {$_.ThreadID -eq $ThreadID} |
|
||||
ForEach-Object {
|
||||
If ( ($_.PSObject.Properties.Name -match 'ThreadEndTime').Count -lt 1 ) {
|
||||
$_ | Add-Member -NotePropertyName 'ThreadEndTime' -NotePropertyValue $Event.TimeCreated
|
||||
# The number of CPU clock cycles used by the thread. This value includes cycles spent in both user mode and kernel mode.
|
||||
# Found at https://msdn.microsoft.com/en-us/library/windows/desktop/ms684943(v=vs.85).aspx
|
||||
$_ | Add-Member -NotePropertyName 'CycleTime' -NotePropertyValue $Event.Properties[10].value
|
||||
}
|
||||
}
|
||||
}
|
||||
} # ThreadStop
|
||||
|
||||
function ImageLoad
|
||||
{
|
||||
param($Event)
|
||||
|
||||
$ProcID = [int32]$Event.Properties[2].value
|
||||
|
||||
$NewLoadImgObj = New-Object -TypeName psobject
|
||||
$NewLoadImgObj | Add-Member -NotePropertyName 'ImageBase' -NotePropertyValue (ConvertTo-Hex $Event.Properties[0].value)
|
||||
$NewLoadImgObj | Add-Member -NotePropertyName 'ImageSize' -NotePropertyValue (ConvertTo-Hex $Event.Properties[1].value)
|
||||
$NewLoadImgObj | Add-Member -NotePropertyName 'ImageName' -NotePropertyValue $Event.Properties[6].value
|
||||
|
||||
|
||||
If ( $Events.ContainsKey( $ProcID ) ) {
|
||||
|
||||
If ( ($Events[$ProcID].PSObject.Properties.Name -match 'LoadedImages').Count -lt 1 ) {
|
||||
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'LoadedImages' -NotePropertyValue @()
|
||||
|
||||
|
||||
}
|
||||
$Events[$ProcID].LoadedImages += $NewLoadImgObj
|
||||
}
|
||||
else {
|
||||
|
||||
$NewProcessObject = New-Object -TypeName psobject
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ProcessID' -NotePropertyValue $ProcID
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'LoadedImages' -NotePropertyValue @()
|
||||
|
||||
$NewProcessObject.LoadedImages += $NewLoadImgObj
|
||||
|
||||
$Events.Add( $ProcID, $NewProcessObject )
|
||||
}
|
||||
|
||||
# Add image load to corresponding process thread
|
||||
# Need to calculate image end address
|
||||
$ImageEndAddr = ConvertTo-Hex ([uint64]$NewLoadImgObj.ImageBase + [uint64]$NewLoadImgObj.ImageSize)
|
||||
$Events[$ProcId].Threads |
|
||||
# Verify loadedimage property does not already exist
|
||||
Where-Object { ($_.PSObject.Properties.Name -match 'LoadedImage').Count -lt 1 } |
|
||||
# Verify the thread start address is between the image load and end addresses
|
||||
Where-Object { ( [uint64]$_.Win32StartAddr -gt [uint64]$NewLoadImgObj.ImageBase) -and ([uint64]$_.Win32StartAddr -lt [uint64]$ImageEndAddr) } |
|
||||
ForEach-Object {
|
||||
$_ | Add-Member -NotePropertyName 'LoadedImage' -NotePropertyValue $NewLoadImgObj.ImageName
|
||||
$_ | Add-Member -NotePropertyName 'ImageBase' -NotePropertyValue $NewLoadImgObj.ImageBase
|
||||
$_ | Add-Member -NotePropertyName 'ImageSize' -NotePropertyValue $NewLoadImgObj.ImageSize
|
||||
}
|
||||
|
||||
} # ImageLoad
|
||||
|
||||
|
||||
function ProcessStart
|
||||
{
|
||||
param($Event)
|
||||
$ParentPID = [int32]$Event.Properties[2].value
|
||||
$ProcID = [int32]$Event.Properties[0].value
|
||||
|
||||
If ( $Events.ContainsKey( [int32]$ProcID ) ) {
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'CreateTime' -NotePropertyValue $Event.Properties[1].value
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'ParentPID' -NotePropertyValue $ParentPID
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'SessionID' -NotePropertyValue $Event.Properties[3].value
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'ImageName' -NotePropertyValue $Event.Properties[5].value
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
$NewProcessObject = New-Object -TypeName psobject
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ProcessID' -NotePropertyValue $ProcID
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'CreateTime' -NotePropertyValue $Event.Properties[1].value
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ParentPID' -NotePropertyValue $ParentPID
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'SessionID' -NotePropertyValue $Event.Properties[3].value
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ImageName' -NotePropertyValue $Event.Properties[5].value
|
||||
|
||||
$Events.Add( $ProcID, $NewProcessObject )
|
||||
}
|
||||
|
||||
# Check if parent process is known and add to list
|
||||
If ( $Events.ContainsKey( $ParentPID ) ) {
|
||||
|
||||
# Check if property has been added and if not then add
|
||||
If ( ($Events[ $ParentPID ].PSObject.Properties.Name -match 'ChildProcesses').Count -lt 1 ) {
|
||||
|
||||
$Events[ $ParentPID ] | Add-Member -NotePropertyName 'ChildProcesses' -NotePropertyValue @()
|
||||
|
||||
}
|
||||
|
||||
$Events[ $ParentPID ].ChildProcesses += $NewProcessObject
|
||||
}
|
||||
|
||||
} # ProcessStart
|
||||
|
||||
function ProcessStop
|
||||
{
|
||||
|
||||
param($Event)
|
||||
$ProcID = [int32]$Event.Properties[0].value
|
||||
|
||||
|
||||
If ( $Events.ContainsKey( $ProcId ) ) {
|
||||
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'EndTime' -NotePropertyValue $Event.Properties[2].value
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'ReadOperationCount' -NotePropertyValue $Event.Properties[9].value
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'WriteOperationCount' -NotePropertyValue $Event.Properties[10].value
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'ReadTransferKiloBytes' -NotePropertyValue $Event.Properties[11].value
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'WriteTransferKiloBytes' -NotePropertyValue $Event.Properties[12].value
|
||||
|
||||
# To account for PID reuse we have to rename process keys from PID when they are complete
|
||||
$UniqueKey = Get-Random
|
||||
# Add new entry with random number as key
|
||||
$Events.Add( [int32]$UniqueKey, $Events[$ProcID] )
|
||||
# Delete key/value with PID
|
||||
$Events.Remove( $ProcID )
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
$NewProcessObject = New-Object -TypeName psobject
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ProcessID' -NotePropertyValue $ProcID
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'EndTime' -NotePropertyValue $Event.Properties[2].value
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ReadOperationCount' -NotePropertyValue $Event.Properties[9].value
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'WriteOperationCount' -NotePropertyValue $Event.Properties[10].value
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'ReadTransferKiloBytes' -NotePropertyValue $Event.Properties[11].value
|
||||
$NewProcessObject | Add-Member -NotePropertyName 'WriteTransferKiloBytes' -NotePropertyValue $Event.Properties[12].value
|
||||
|
||||
$UniqueKey = Get-Random
|
||||
# Add new entry with random number as key
|
||||
$Events.Add( [int32]$UniqueKey, $NewProcessObject )
|
||||
}
|
||||
}
|
||||
function KernelProcessParser
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
[System.Diagnostics.Eventing.Reader.EventRecord]
|
||||
$Event
|
||||
|
||||
)
|
||||
|
||||
$script:KernProcEvents = @{
|
||||
1 = 'ProcessStart'
|
||||
2 = 'ProcessStop'
|
||||
3 = 'ThreadStart'
|
||||
4 = 'ThreadStop'
|
||||
5 = 'ImageLoad'
|
||||
}
|
||||
|
||||
If ( $script:KernProcEvents.ContainsKey($Event.Id) ) {
|
||||
&$script:KernProcEvents[$_.Id] $Event
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
function CmdletRun
|
||||
{
|
||||
param($Event)
|
||||
$ProcID = [int32]$Event.ProcessID
|
||||
$MessageArray = ($Event.Properties[2].Value) -split " "
|
||||
|
||||
# CmdletRun can have many different events for this we just want to capture what cmdlets were run
|
||||
If ( $MessageArray[0] -eq "Command" -and $MessageArray[3].Trim() -eq "Started." ) {
|
||||
If ( $Events.ContainsKey( $ProcID ) ) {
|
||||
|
||||
If ( ($Events[$ProcID].PSObject.Properties.Name -match 'Commands').Count -lt 1 ) {
|
||||
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'Commands' -NotePropertyValue @()
|
||||
|
||||
}
|
||||
|
||||
$Events[$ProcID].Commands += $MessageArray[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ScriptBlock
|
||||
{
|
||||
param($Event)
|
||||
$ProcID = [int32]$Event.ProcessID
|
||||
If ( $Events.ContainsKey( $ProcID ) ) {
|
||||
|
||||
If ( ($Events[$ProcID].PSObject.Properties.Name -match 'ScriptBlocks').Count -lt 1 ) {
|
||||
|
||||
$Events[$ProcID] | Add-Member -NotePropertyName 'ScriptBlocks' -NotePropertyValue @()
|
||||
|
||||
}
|
||||
|
||||
$Events[$ProcID].ScriptBlocks += $Event.Properties[2].Value
|
||||
}
|
||||
}
|
||||
|
||||
function PowerShellParser
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
|
||||
[System.Diagnostics.Eventing.Reader.EventRecord]
|
||||
$Event
|
||||
|
||||
)
|
||||
|
||||
$script:KernProcEvents = @{
|
||||
7937 = 'CmdletRun'
|
||||
4104 = 'ScriptBlock'
|
||||
}
|
||||
|
||||
If ( $script:KernProcEvents.ContainsKey($Event.Id) ) {
|
||||
&$script:KernProcEvents[$_.Id] $Event
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
Set-StrictMode -Version Latest
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$TestDir = Split-Path $MyInvocation.MyCommand.Path -Parent
|
||||
$RootModuleDir = Resolve-Path "$TestDir\.."
|
||||
$Module = "$RootModuleDir\EventTrace.psd1"
|
||||
|
||||
|
||||
|
||||
Import-Module $Module -Force -ErrorAction Stop
|
||||
|
||||
# Global session name
|
||||
$SessName = "PesterETWSession"
|
||||
# Global output file
|
||||
$OutputFile = Join-Path (Resolve-Path .) "etw_session.etl"
|
||||
# Global provider
|
||||
$ProviderName = "Microsoft-Windows-Kernel-Process"
|
||||
|
||||
Describe 'New-ETWProviderConfig' {
|
||||
Context 'output validation' {
|
||||
It 'Should return PS object' {
|
||||
(New-ETWProviderConfig).PSObject.TypeNames[1] | Should Be 'System.Object'
|
||||
}
|
||||
|
||||
It 'Should contain 3 properties' {
|
||||
New-ETWProviderConfig | Get-Member | Where-Object {$_.MemberType -eq 'NoteProperty' } | `
|
||||
Measure-Object | Select-Object -ExpandProperty count | Should be 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'ConvertTo-ETWGuid' {
|
||||
Context 'input validation' {
|
||||
It 'Should should accept string input' {
|
||||
{ ConvertTo-ETWGuid -ProviderName $ProviderName } | Should Not Throw
|
||||
}
|
||||
|
||||
It "Should error on non-existent provider" {
|
||||
{ ConvertTo-ETWGuid -ProviderName "DOES NOT EXIST" } | Should Throw
|
||||
}
|
||||
|
||||
It 'Should generate errors when required parameters are not provided' {
|
||||
{ ConvertTo-ETWGuid -ProviderName } | Should Throw
|
||||
}
|
||||
}
|
||||
|
||||
Context 'output validation' {
|
||||
It 'Should return type GUID' {
|
||||
{ ConvertTo-ETWGuid -ProviderName $ProviderName -is [System.Guid] } | Should Be $true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Get-ETWProviderKeywords' {
|
||||
Context 'input validation' {
|
||||
It 'Should require input' {
|
||||
{ Get-ETWProviderKeywords -Provider } | Should Throw
|
||||
}
|
||||
|
||||
It 'Should accept string input' {
|
||||
{ Get-ETWProviderKeywords -Provider $ProviderName }
|
||||
}
|
||||
|
||||
It "Should error on non-existent provider" {
|
||||
{ Get-ETWProviderKeywords -ProviderName "DOES NOT EXIST" } | Should Throw
|
||||
}
|
||||
}
|
||||
Context 'output validation'{
|
||||
It 'Should return properly formatted ProviderDataItem objects' {
|
||||
$Result = Get-ETWProviderKeywords -Provider $ProviderName
|
||||
|
||||
$Result[0].PSObject.TypeNames[0] | Should be 'Microsoft.Diagnostics.Tracing.Session.ProviderDataItem'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'New-ETWProviderOption' {
|
||||
Context 'output validation' {
|
||||
It 'Should return provider options object' {
|
||||
(New-ETWProviderOption).PSObject.TypeNames[0] | Should be 'Microsoft.Diagnostics.Tracing.Session.TraceEventProviderOptions'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Get-ETWProvider' {
|
||||
Context 'output validation' {
|
||||
It 'Should generate output'{
|
||||
{ Get-ETWProvider } | Should Not BeNullOrEmpty
|
||||
}
|
||||
It 'Should return properly formatted ProviderMetadata objects' {
|
||||
$Result = Get-ETWProvider
|
||||
|
||||
$Result[0].PSObject.TypeNames[0] | Should be 'System.Diagnostics.Eventing.Reader.ProviderMetadata'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Get-ETWSessionDetails' {
|
||||
Context 'input validation' {
|
||||
It 'Should require input' {
|
||||
{ Get-ETWSessionDetails -SessionName } | Should Throw
|
||||
}
|
||||
|
||||
It 'Should error when invalid name provided' {
|
||||
{ Get-ETWSessionDetails -SessionName "not valid" } | Should Throw "Session does not exist"
|
||||
}
|
||||
}
|
||||
|
||||
Context 'output validation' {
|
||||
It 'Should return TraceEventSessionObject' {
|
||||
$SessionName = (Get-ETWSessionNames)[0]
|
||||
|
||||
$Result = Get-ETWSessionDetails -SessionName $SessionName
|
||||
$Result[0].PSObject.TypeNames[0] | Should be 'Microsoft.Diagnostics.Tracing.Session.TraceEventSession'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Describe 'Start-ETWSession' {
|
||||
$ProviderConfig = New-ETWProviderConfig
|
||||
$ProviderConfig.Name = $ProviderName
|
||||
$ProviderConfig.Keywords = Get-ETWProviderKeywords -Provider $ProviderName | Where-Object {
|
||||
$_.Name -match "_process$|_image$|_thread$" }
|
||||
|
||||
Context 'input validation' {
|
||||
It 'Should generate errors when required params are not provided' {
|
||||
{ Start-ETWSession -SessionConfig -SessionName -OutputFile } | Should Throw
|
||||
}
|
||||
InModuleScope EventTrace{
|
||||
It 'Should fail to run if session already exists' {
|
||||
Mock Test-IsSession { return $true }
|
||||
|
||||
{ Start-ETWSession -ProviderConfig $null -OutputFile $OutputFile -SessionName $SessName } `
|
||||
| Should Throw
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
It 'Output file should not exist' {
|
||||
Test-Path $OutputFile | Should be $false
|
||||
}
|
||||
}
|
||||
|
||||
Context 'output validation' {
|
||||
It 'Should create ETW session' {
|
||||
(Start-ETWSession -SessionName $SessName -OutputFile $OutputFile -ProviderConfig $ProviderConfig)[1] | Should be $true
|
||||
}
|
||||
|
||||
# sleep for 2 seconds to verify file is created and events generated
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
It 'Should create etl output file' {
|
||||
Test-Path $OutputFile | Should Be $true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Describe 'Stop-ETWSession' {
|
||||
Context 'input validation' {
|
||||
It 'Should generate an error when a non-existent session is provided' {
|
||||
{ Stop-ETWSession -SessionName "does not exist" } | Should Throw
|
||||
}
|
||||
}
|
||||
|
||||
Context "output validation" {
|
||||
It 'Should stop session' {
|
||||
(Stop-ETWSession -SessionName $SessName)[1] | Should be $true
|
||||
}
|
||||
|
||||
# size of blank etl file is 64 KB
|
||||
It 'Output file should exist and be larger than 64 KB' {
|
||||
(Get-ChildItem $OutputFile).Length / 1Kb | Should BeGreaterThan 64
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Describe 'Get-ETWEventLog' {
|
||||
Context 'input validation' {
|
||||
It 'Should error when required parameter not provided' {
|
||||
{ Get-ETWEventLog -Path } | Should Throw
|
||||
}
|
||||
}
|
||||
|
||||
# Context 'output validation' {
|
||||
# It 'Should properly parse output' {
|
||||
# (Get-ETWEventLog -Path $OutputFile).Count | Should BeGreaterThan 1
|
||||
# }
|
||||
# }
|
||||
}
|
||||
|
||||
|
||||
Describe 'Cleanup tests' {
|
||||
Context 'Remove module' {
|
||||
It 'Should not throw error removing module' {
|
||||
{ Remove-Module 'EventTrace' } | Should Not Throw
|
||||
}
|
||||
}
|
||||
Context 'Delete test etl file' {
|
||||
It 'Should delete output file' {
|
||||
{ Remove-Item $OutputFile -Force } | Should Not Throw
|
||||
}
|
||||
|
||||
It 'Output file should not exist' {
|
||||
Test-Path $OutputFile | Should be $false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1,78 @@
|
||||
# PSEventDetect
|
||||
# PSWasp
|
||||
|
||||
PSWasp is a PowerShell project that enables users to easily interact with Event Tracing for Windows (ETW); specifically designed for forensic collection and analysis. Originally intended as a Windows debugging utility, ETW has evolved to support a myriad of diverse use cases. Modern Windows operating systems (8.1, 2012, Win10, and Server 2016) ship with hundreds of application and kernel layer ETW providers, any of which could capture and log critical information during an investigation. PSalandar enables users to easily start and capture events from one or many ETW providers.
|
||||
|
||||
## Requirements
|
||||
- .NET 4.0 or greater
|
||||
- PowerShell 3.0 or greater
|
||||
|
||||
## External Dependencies
|
||||
- PSWasp uses and ships a copy of the Microsoft's TraceEvent DLL [License](https://www.microsoft.com/net/dotnet_library_license.htm)
|
||||
|
||||
## Examples
|
||||
|
||||
### List all ETW providers on a System
|
||||
|
||||
```Get-ETWProvider```
|
||||
|
||||
### List all active ETW sessions
|
||||
|
||||
```Get-ETWSessionNames```
|
||||
|
||||
### Enumerate details from active ETW sessions
|
||||
Warning: Enumerating session details has been found to inadvertently stop ETW sessions in some cases.
|
||||
|
||||
```Get-ETWSessionDetails```
|
||||
|
||||
### Start Forensic Collection with PSWasp
|
||||
|
||||
#### Create provider object
|
||||
Defines the provider name or GUID, filtering keywords, or other filtering options
|
||||
This example configures the `Micorsoft-Windows-Kernel-Process` provider and only enables the `Process`, `Image`, and `Thread` keywords
|
||||
```
|
||||
$ProviderConfig = New-ETWProviderConfig
|
||||
$ProviderConfig.Name = 'Microsoft-Windows-Kernel-Process'
|
||||
$ProcessRegex = '_PROCESS$|_IMAGE$|_THREAD$'
|
||||
Get-ETWProviderKeywords -ProviderName $ProviderConfig.Name |
|
||||
Where-Object { $_.Name -match $ProcessRegex } |
|
||||
ForEach-Object { $ProviderConfig.Keywords += $_ }
|
||||
```
|
||||
|
||||
#### Start ETW Session
|
||||
|
||||
```Start-ETWSession -ProviderConfig $ProviderConfig -SessionName <unique session name> -OutputFile <path to etl file>```
|
||||
|
||||
### Stop ETW Session
|
||||
|
||||
```Stop-ETWSession -SessionName <previously provided unique session name>```
|
||||
|
||||
### Parse any .ETL Log
|
||||
|
||||
```Get-WinEvent -Path <path to ETL file> -Oldest```
|
||||
|
||||
### Start ETW forensic session with kernel session
|
||||
Kernel session is an optional argument that starts a unique kernel session. Enabling this session allows for the capture of process command line arguments.
|
||||
|
||||
Note: Kernel session is enabled by default use `-DisableKernelProvider` to disable
|
||||
|
||||
```Start-ETWForensicCollection -SessionName <unique session name> -OutputFile <path to etl file>```
|
||||
|
||||
### Parse .ETL file generated from Start-ETWForensicCollection
|
||||
Will automatically identify and parse any kernel session output files from the same session
|
||||
|
||||
```Get-ETWForensicEventLog -Path <path to ETL file>```
|
||||
|
||||
|
||||
|
||||
## Useful links
|
||||
https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Tracing/TraceEvent/docs/TraceEvent.md
|
||||
https://blogs.msdn.microsoft.com/vancem/2012/12/20/using-tracesource-to-log-etw-data-to-a-file/
|
||||
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363668(v=vs.85).aspx
|
||||
https://github.com/Microsoft/perfview/blob/master/src/TraceEvent/TraceEventSession.cs
|
||||
https://blogs.technet.microsoft.com/office365security/hidden-treasure-intrusion-detection-with-etw-part-1/
|
||||
https://blogs.technet.microsoft.com/office365security/hidden-treasure-intrusion-detection-with-etw-part-2/
|
||||
|
||||
## Referenced Work
|
||||
|
||||
- Module design for PSWasp was heavily influenced by [CimSweep](https://github.com/PowerShellMafia/CimSweep). It should be a model for all PS modules follow.
|
||||
- Zak Brown and the Microsoft OS365 folks do great ETW work and have their own open source ETW library [krabsetw](https://github.com/microsoft/krabsetw)
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
# Version: 1.1
|
||||
function Start-Demo
|
||||
{
|
||||
param($file="demo\demo.txt", [int]$command=0)
|
||||
$CommentColor = "Yellow"
|
||||
$MetaCommandColor = "Red"
|
||||
Clear-Host
|
||||
|
||||
$_Random = New-Object System.Random
|
||||
$_lines = @(Get-Content $file)
|
||||
$_starttime = [DateTime]::now
|
||||
$_PretendTyping = $true
|
||||
$_InterkeyPause = 200
|
||||
# Write-Host -for $CommentColor @"
|
||||
# NOTE: Start-Demo replaces the typing but runs the actual commands.
|
||||
# .
|
||||
# <Demo [$file] Started. Type `"?`" for help>
|
||||
# "@
|
||||
|
||||
|
||||
# We use a FOR and an INDEX ($_i) instead of a FOREACH because
|
||||
# it is possible to start at a different location and/or jump
|
||||
# around in the order.
|
||||
for ($_i = $Command; $_i -lt $_lines.count; $_i++)
|
||||
{
|
||||
if ($_lines[$_i].StartsWith("#"))
|
||||
{
|
||||
Write-Host -NoNewLine $("`n[$_i]PS> ")
|
||||
Write-Host -NoNewLine -Foreground $CommentColor $($($_Lines[$_i]) + " ")
|
||||
continue
|
||||
}else
|
||||
{
|
||||
# Put the current command in the Window Title along with the demo duration
|
||||
$_Duration = [DateTime]::Now - $_StartTime
|
||||
$Host.UI.RawUI.WindowTitle = "[{0}m, {1}s] {2}" -f [int]$_Duration.TotalMinutes, [int]$_Duration.Seconds, $($_Lines[$_i])
|
||||
Write-Host -NoNewLine $("`n[$_i]PS> ")
|
||||
$_SimulatedLine = $($_Lines[$_i]) + " "
|
||||
for ($_j = 0; $_j -lt $_SimulatedLine.Length; $_j++)
|
||||
{
|
||||
Write-Host -NoNewLine $_SimulatedLine[$_j]
|
||||
if ($_PretendTyping)
|
||||
{
|
||||
if ([System.Console]::KeyAvailable)
|
||||
{
|
||||
$_PretendTyping = $False
|
||||
}
|
||||
else
|
||||
{
|
||||
Start-Sleep -milliseconds $(10 + $_Random.Next($_InterkeyPause))
|
||||
}
|
||||
}
|
||||
} # For $_j
|
||||
$_PretendTyping = $true
|
||||
} # else
|
||||
|
||||
|
||||
$_OldColor = $host.UI.RawUI.ForeGroundColor
|
||||
$host.UI.RawUI.ForeGroundColor = $MetaCommandColor
|
||||
$_input=[System.Console]::ReadLine().TrimStart()
|
||||
$host.UI.RawUI.ForeGroundColor = $_OldColor
|
||||
|
||||
|
||||
switch ($_input)
|
||||
{
|
||||
################ HELP with DEMO
|
||||
"?"
|
||||
{
|
||||
Write-Host -ForeGroundColor $CommentColor @"
|
||||
Running demo: $file
|
||||
.
|
||||
(!) Suspend (#x) Goto Command #x (b) Backup (d) Dump demo
|
||||
(fx) Find cmds using X (px) Typing Pause Interval (q) Quit (s) Skip
|
||||
(t) Timecheck (?) Help
|
||||
.
|
||||
NOTE 1: Any key cancels "Pretend typing" for that line. Use <SPACE> unless you
|
||||
want to run a one of these meta-commands.
|
||||
.
|
||||
NOTE 2: After cmd output, enter <CR> to move to the next line in the demo.
|
||||
This avoids the audience getting distracted by the next command
|
||||
as you explain what happened with this command.
|
||||
.
|
||||
NOTE 3: The line to be run is displayed in the Window Title BEFORE it is typed.
|
||||
This lets you know what to explain as it is typing.
|
||||
"@
|
||||
$_i -= 1
|
||||
}
|
||||
|
||||
|
||||
#################### PAUSE
|
||||
{$_.StartsWith("p")}
|
||||
{
|
||||
$_InterkeyPause = [int]$_.substring(1)
|
||||
$_i -= 1
|
||||
}
|
||||
|
||||
|
||||
#################### Backup
|
||||
"b" {
|
||||
if($_i -gt 0)
|
||||
{
|
||||
$_i --
|
||||
|
||||
while (($_i -gt 0) -and ($_lines[$($_i)].StartsWith("#")))
|
||||
{ $_i -= 1
|
||||
}
|
||||
}
|
||||
|
||||
$_i --
|
||||
$_PretendTyping = $false
|
||||
}
|
||||
|
||||
|
||||
#################### QUIT
|
||||
"q"
|
||||
{
|
||||
Write-Host -ForeGroundColor $CommentColor "<Quit demo>"
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
#################### SKIP
|
||||
"s"
|
||||
{
|
||||
Write-Host -ForeGroundColor $CommentColor "<Skipping Cmd>"
|
||||
}
|
||||
|
||||
|
||||
#################### DUMP the DEMO
|
||||
"d"
|
||||
{
|
||||
for ($_ni = 0; $_ni -lt $_lines.Count; $_ni++)
|
||||
{
|
||||
if ($_i -eq $_ni)
|
||||
{ Write-Host -ForeGroundColor $MetaCommandColor ("*" * 80)
|
||||
}
|
||||
Write-Host -ForeGroundColor $CommentColor ("[{0,2}] {1}" -f $_ni, $_lines[$_ni])
|
||||
}
|
||||
$_i -= 1
|
||||
}
|
||||
|
||||
|
||||
#################### TIMECHECK
|
||||
"t"
|
||||
{
|
||||
$_Duration = [DateTime]::Now - $_StartTime
|
||||
Write-Host -ForeGroundColor $CommentColor $(
|
||||
"Demo has run {0} Minutes and {1} Seconds`nYou are at line {2} of {3} " -f
|
||||
[int]$_Duration.TotalMinutes,
|
||||
[int]$_Duration.Seconds,
|
||||
$_i,
|
||||
($_lines.Count - 1)
|
||||
)
|
||||
$_i -= 1
|
||||
}
|
||||
|
||||
|
||||
#################### FIND commands in Demo
|
||||
{$_.StartsWith("f")}
|
||||
{
|
||||
for ($_ni = 0; $_ni -lt $_lines.Count; $_ni++)
|
||||
{
|
||||
if ($_lines[$_ni] -match $_.SubString(1))
|
||||
{
|
||||
Write-Host -ForeGroundColor $CommentColor ("[{0,2}] {1}" -f $_ni, $_lines[$_ni])
|
||||
}
|
||||
}
|
||||
$_i -= 1
|
||||
}
|
||||
|
||||
|
||||
#################### SUSPEND
|
||||
{$_.StartsWith("!")}
|
||||
{
|
||||
if ($_.Length -eq 1)
|
||||
{
|
||||
Write-Host -ForeGroundColor $CommentColor "<Suspended demo - type 'Exit' to resume>"
|
||||
function Prompt {"[Demo Suspended]`nPS>"}
|
||||
$host.EnterNestedPrompt()
|
||||
}else
|
||||
{
|
||||
trap [System.Exception] {Write-Error $_;continue;}
|
||||
Invoke-Expression $(".{" + $_.SubString(1) + "}| out-host")
|
||||
}
|
||||
$_i -= 1
|
||||
}
|
||||
|
||||
|
||||
#################### GO TO
|
||||
{$_.StartsWith("#")}
|
||||
{
|
||||
$_i = [int]($_.SubString(1)) - 1
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
#################### EXECUTE
|
||||
default
|
||||
{
|
||||
trap [System.Exception] {Write-Error $_;continue;}
|
||||
Invoke-Expression $(".{" + $_lines[$_i] + "}| out-host")
|
||||
$_Duration = [DateTime]::Now - $_StartTime
|
||||
$Host.UI.RawUI.WindowTitle = "[{0}m, {1}s] {2}" -f [int]$_Duration.TotalMinutes, [int]$_Duration.Seconds, $($_Lines[$_i])
|
||||
[System.Console]::ReadLine()
|
||||
}
|
||||
} # Switch
|
||||
} # for
|
||||
$_Duration = [DateTime]::Now - $_StartTime
|
||||
Write-Host -ForeGroundColor $CommentColor $("<Demo Complete {0} Minutes and {1} Seconds>" -f [int]$_Duration.TotalMinutes, [int]$_Duration.Seconds)
|
||||
Write-Host -ForeGroundColor $CommentColor $([DateTime]::now)
|
||||
} # function
|
||||
Executable
BIN
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,56 @@
|
||||
Import-Module .\PSWasp
|
||||
Get-Module PSWasp | select -Expand ExportedCommands
|
||||
Get-ETWProvider | select -Expand id | Group-Object | Measure-Object
|
||||
Get-ETWProvider | where name -match 'kernel-process$' | select *
|
||||
Get-ETWProvider | where name -match 'kernel-process$' | select -Expand Keywords
|
||||
cls
|
||||
Get-ETWProvider | where name -match 'kernel-process$' | select -Expand tasks
|
||||
Get-ETWProvider | where name -match 'kernel-process$' | % Events | select id, description
|
||||
Get-ETWSessionNames
|
||||
$EmpireSession = Import-Clixml demo\demo.xml
|
||||
$EmpireSession | where imagename -match "powershell" | select processid, imagename
|
||||
$EmpireSession | Where ProcessID -eq 5392 | gm -MemberType NoteProperty | select Name
|
||||
cls
|
||||
$EmpireSession | where ProcessID -eq 5392 | select -Expand Commands -Unique
|
||||
$EmpireSession | where processid -eq 5392 | select -expand scriptblocks | select-string "Get-GPPPassword"
|
||||
cls
|
||||
$EmpireSession | where ProcessID -eq 5392 | select -Expand ChildProcesses | select Commandline
|
||||
$EmpireSession | Where Imagename -match "certutil"
|
||||
cls
|
||||
$EmpireSession | Where imagename -match "certutil" | select -Expand Domainlookups
|
||||
$EmpireSession | Where imagename -match "certutil" | select -Expand NetConnections
|
||||
$EmpireSession | Where Imagename -match "runas"
|
||||
$EmpireSession | Where Imagename -match "runas" | select -Expand ChildProcesses | select imagename
|
||||
$EmpireSession | Where Imagename -match "runas" | select -Expand ChildProcesses | select -Expand childprocesses | select commandline
|
||||
cls
|
||||
$EmpireSession | Where Imagename -match "notepad" | select -Expand FileIO
|
||||
$EmpireSession | Where Imagename -match "cscript"
|
||||
$EmpireSession | Where Imagename -match "cscript" | select -Expand ChildProcesses | select processid, imagename
|
||||
$EmpireSession | Where ProcessId -eq 6804 | select -Expand Commandline
|
||||
$EmpireSession | where processid -eq 6804 | select -Expand commands -Unique | sort
|
||||
$EmpireSession | where processid -eq 6804 | select -Expand scriptblocks | select-string "Invoke-Empire"
|
||||
cls
|
||||
$EmpireSession | Where ProcessId -eq 6804 | select -Expand FileIO
|
||||
$EmpireSession | Where ProcessId -eq 6804 | select -Expand DomainLookups
|
||||
$EmpireSession | Where ProcessId -eq 6804 | select -Expand NetConnections
|
||||
$EmpireSession | where processid -eq 6804 | select ReadTransferKiloBytes, WriteTransferKiloBytes
|
||||
$EmpireSession | Where ProcessId -eq 6804 | select -Expand LoadedImages
|
||||
cls
|
||||
$EmpireSession | Where DomainLookups -match "lets.popa.box" | select processid, imagename
|
||||
$EmpireSession | Where ProcessID -eq 1924 | select imagename, commandline
|
||||
$EmpireSession | Where ProcessID -eq 1924 | select -Expand FileIO
|
||||
$EmpireSession | Where ProcessID -eq 1924 | select -Expand ChildProcesses | select -Expand CommandLine
|
||||
$EmpireSession | Where ProcessID -eq 1924 | select -Expand DomainLookups
|
||||
$EmpireSession | Where ProcessID -eq 1924 | select -Expand LoadedImages
|
||||
cls
|
||||
$EmpireSession | Where ProcessID -eq 1924 | select -Expand LoadedImages | where ImageName -match "automation"
|
||||
$EmpireSession | Where ProcessID -eq 1924 | select -Expand threads
|
||||
cls
|
||||
$EmpireSession | Where ProcessID -eq 1924 | select -Expand threads | where ThreadID -eq 6204
|
||||
$EmpireSession | where processid -eq 1924 | select -Expand Commands -Unique
|
||||
$MimiKaz = $EmpireSession | where processid -eq 1924 | select -expand scriptblocks
|
||||
$MimiKaz[7].Substring(0,800)
|
||||
cls
|
||||
Get-ETWForensicGraph -ETWObject $EmpireSession -ParentProcessID 1924
|
||||
cls
|
||||
Get-ETWForensicGraph -ETWObject $EmpireSession -ParentProcessID 5392
|
||||
Binary file not shown.
Reference in New Issue
Block a user