I am trying to return an event log entry from the Windows security log using xPath (in PowerShell, in Event Viewer UI) and not succeeding.
This query doesn't work, as it returns zero results event though there is are appropriate entries in the log:
Get-WinEvent -FilterXPath "*[EventData[Data[@Name='CommandLine']='-ExecutionPolicy ByPass -File Do-Something.ps1']]" -LogName Security
The syntax of the query seems fine as changing the query value will return the expected results:
Get-WinEvent -FilterXPath "*[EventData[Data[@Name='CommandLine']='\??\C:\Windows\system32\conhost.exe 0xffffffff -ForceV1']]" -LogName Security
Same results if formatted as -FilterXML.
Alternative query strategy works, though is not efficient at all with big logs:
Get-WinEvent -LogName Security | Where-Object -Property Message -match '-ExecutionPolicy ByPass -File Do-Something.ps1'
So it seems that there is something in the xPath query value that is not quite kosher. I don't know what it is. What am I missing?
Here is EventData for the desired hit:
- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-a5ba-3e3b0328c30d}" />
<EventID>4688</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>13312</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2020-02-19T15:17:13.982780900Z" />
<EventRecordID>SCRUBBED</EventRecordID>
<Correlation />
<Execution ProcessID="4" ThreadID="256" />
<Channel>Security</Channel>
<Computer>SCRUBBED</Computer>
<Security />
</System>
- <EventData>
<Data Name="SubjectUserSid">SCRUBBED</Data>
<Data Name="SubjectUserName">SCRUBBED</Data>
<Data Name="SubjectDomainName">SCRUBBED</Data>
<Data Name="SubjectLogonId">SCRUBBED</Data>
<Data Name="NewProcessId">SCRUBBED</Data>
<Data Name="NewProcessName">C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Data>
<Data Name="TokenElevationType">%%1937</Data>
<Data Name="ProcessId">0x41c</Data>
<Data Name="CommandLine">-ExecutionPolicy ByPass -File Do-Something.ps1</Data>
<Data Name="TargetUserSid">S-1-0-0</Data>
<Data Name="TargetUserName">-</Data>
<Data Name="TargetDomainName">-</Data>
<Data Name="TargetLogonId">0x0</Data>
<Data Name="ParentProcessName">C:\Windows\System32\gpscript.exe</Data>
<Data Name="MandatoryLabel">SCRUBBED</Data>
</EventData>
</Event>
Here is EventData for the other hit that works but isn't interesting to me:
- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-a5ba-3e3b0328c30d}" />
<EventID>4688</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>13312</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2020-02-19T15:21:21.753690000Z" />
<EventRecordID>SCRUBBED</EventRecordID>
<Correlation />
<Execution ProcessID="4" ThreadID="96" />
<Channel>Security</Channel>
<Computer>SCRUBBED</Computer>
<Security />
</System>
- <EventData>
<Data Name="SubjectUserSid">SCRUBBED</Data>
<Data Name="SubjectUserName">SCRUBBED</Data>
<Data Name="SubjectDomainName">SCRUBBED</Data>
<Data Name="SubjectLogonId">SCRUBBED</Data>
<Data Name="NewProcessId">SCRUBBED</Data>
<Data Name="NewProcessName">C:\Windows\System32\conhost.exe</Data>
<Data Name="TokenElevationType">%%1936</Data>
<Data Name="ProcessId">0x690</Data>
<Data Name="CommandLine">\??\C:\Windows\system32\conhost.exe 0xffffffff -ForceV1</Data>
<Data Name="TargetUserSid">S-1-0-0</Data>
<Data Name="TargetUserName">-</Data>
<Data Name="TargetDomainName">-</Data>
<Data Name="TargetLogonId">0x0</Data>
<Data Name="ParentProcessName">C:\Program Files\Windows Defender\MpCmdRun.exe</Data>
<Data Name="MandatoryLabel">SCRUBBED</Data>
</EventData>
</Event>
Enabling command line process auditing here to reproduce this: https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing
Searching for the NewProcessName first:
$a = Get-WinEvent -FilterXPath "*[EventData[Data[@Name='NewProcessName']='C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe']]" Security
And looking at the xml:
$a[1] | foreach { $xml = [xml]$_.toxml(); $xml.event.eventdata.data }
Name #text
---- -----
SubjectUserSid S-1-5-21-1528843147-373324174-1919417755-1001
SubjectUserName admin
SubjectDomainName DESKTOP-JQ7B7RP
SubjectLogonId 0x31db1a
NewProcessId 0x7c4
NewProcessName C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
TokenElevationType %%1937
ProcessId 0x19d4
CommandLine -ExecutionPolicy ByPass -File do-something.ps1
TargetUserSid S-1-0-0
TargetUserName -
TargetDomainName -
TargetLogonId 0x0
ParentProcessName C:\Windows\System32\gpscript.exe
MandatoryLabel S-1-16-12288
It looks like there's strangely a space at the beginning and the end of the CommandLine property. The xml text is trimmed in event viewer. The spaces are still there with $xml.save('file.xml').
$a[1] | foreach { $xml = [xml]$_.toxml(); $xml.event.eventdata.data } |
where '#text' -match bypass | % { 'x' + $_.'#text' + 'x' }
x -ExecutionPolicy ByPass -File do-something.ps1 x
I ran this script as a group policy powershell login script.
Thus after adding the extra spaces, the nested predicate xpath becomes:
Get-WinEvent -FilterXPath "*[EventData[Data[@Name='CommandLine']=' -executionpolicy bypass -file do-something.ps1 ']]" Security
ProviderName: Microsoft-Windows-Security-Auditing
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
2/21/2020 3:16:13 PM 4688 Information A new process has been created....
2/21/2020 3:16:06 PM 4688 Information A new process has been created....
2/21/2020 3:03:24 PM 4688 Information A new process has been created....
2/21/2020 2:54:16 PM 4688 Information A new process has been created....
Alternative less "nested" xpath expressions. Functions like text() or substring() can't be used with windows logs, or "//" or "/Event", for some reason.
get-winevent security -FilterXPath "*/EventData/Data[@Name='CommandLine']=' -ExecutionPolicy ByPass -File Do-Something.ps1 '"
get-winevent security -FilterXPath "*/*/*[@Name='CommandLine']=' -ExecutionPolicy ByPass -File Do-Something.ps1 '"
get-winevent security -FilterXPath "Event/EventData/Data[@Name='CommandLine']=' -ExecutionPolicy ByPass -File Do-Something.ps1 '"
In powershell 6 and above this can be reduced to:
get-winevent @{logname = 'security'; commandline = ' -executionpolicy bypass -file do-something.ps1 ' }
Try to see if this works:
Get-WinEvent -LogName Security -FilterXPath "//Event//Data[@Name='CommandLine'][text()='-ExecutionPolicy ByPass -File Do-Something.ps1']"
User contributions licensed under CC BY-SA 3.0