Wtrace 2.2

On the occasion of releasing wtrace 2.2, I decided to write a short post about new functionalities I added to this tool in the recent months. I hope you will find them interesting. Wtrace is a command line application which collects ETW traces from the system and the selected processes and outputs them to the console. It is very simple to use and runs on Windows 7+. Currently, it supports the collection of File I/O, TCP, ALPC, RPC, ISR, DPC, and PowerShell events.

Driver tracing (ISR/DPC)

If you use the -s switch during your trace, wtrace will also collect events measuring the time drivers spent in Interrupt Service Routines (ISRs) and Deferred Procedure Calls (DPCs). At the end of the trace, they will appear in the summary section, grouped by the driver name. Those should be minimal values compared to the overall time of the trace session. If you experience any lags in your system (nonresponsive desktop, sound stuttering) checking the ISR/DPC times might help diagnose the problem. If a driver spends too much time in either ISR or DPC, the regular user mode threads will not get access to the CPU on which the driver code runs. You may use -s switch alone or while tracing a process in the system. An example session:

PS> wtrace -s
System tracing has started. Press Ctrl + C to stop...
### Stopping NT Kernel Logger session...
### NT Kernel Logger session stopped. Number of lost events: 0

...
--------------------------------
              ISR
--------------------------------
'C:\Windows\system32\hal.dll', total: 30,655ms (6032 event(s))
'C:\Windows\system32\DRIVERS\HDAudBus.sys', total: 7,724ms (652 event(s))
'C:\Windows\system32\drivers\ACPI.sys', total: 0,218ms (12 event(s))

--------------------------------
              DPC
--------------------------------
'C:\Windows\system32\ntoskrnl.exe', total: 8,694ms (1179 event(s))
'C:\Windows\System32\drivers\dxgkrnl.sys', total: 7,295ms (806 event(s))
'C:\Windows\system32\DRIVERS\HDAudBus.sys', total: 3,201ms (652 event(s))
'C:\Windows\System32\drivers\tcpip.sys', total: 1,381ms (51 event(s))
'C:\Windows\system32\drivers\ndis.sys', total: 1,321ms (123 event(s))
'C:\Windows\system32\drivers\iaStorA.sys', total: 1,302ms (85 event(s))
'C:\Windows\system32\drivers\storport.sys', total: 1,178ms (165 event(s))
'C:\Windows\system32\DRIVERS\iusb3xhc.sys', total: 0,718ms (15 event(s))
'C:\Windows\system32\drivers\ACPI.sys', total: 0,557ms (20 event(s))
'C:\Windows\system32\drivers\NETIO.SYS', total: 0,250ms (30 event(s))
'C:\Windows\system32\DRIVERS\rassstp.sys', total: 0,197ms (98 event(s))
'C:\Windows\system32\drivers\Wdf01000.sys', total: 0,195ms (12 event(s))
'C:\Windows\System32\DRIVERS\netbt.sys', total: 0,158ms (3 event(s))
'C:\Windows\system32\DRIVERS\igdkmd64.sys', total: 0,105ms (29 event(s))
'C:\Windows\system32\DRIVERS\SCSIPORT.SYS', total: 0,059ms (6 event(s))
'C:\Windows\system32\drivers\usbccgp.sys', total: 0,050ms (6 event(s))
'C:\Windows\system32\drivers\afd.sys', total: 0,044ms (4 event(s))
'C:\Windows\System32\DRIVERS\srv.sys', total: 0,023ms (9 event(s))
'C:\Windows\system32\DRIVERS\nvlddmkm.sys', total: 0,011ms (6 event(s))
'C:\Windows\System32\Drivers\cng.sys', total: 0,005ms (1 event(s))
'C:\Windows\system32\drivers\HTTP.sys', total: 0,003ms (1 event(s))
'C:\Windows\System32\Drivers\Ntfs.sys', total: 0,003ms (1 event(s))
'C:\Windows\system32\drivers\luafv.sys', total: 0,002ms (1 event(s))
'C:\Windows\system32\DRIVERS\rdbss.sys', total: 0,002ms (1 event(s))

You may perform further DPC/ISR analysis in Windows Performance Analyzer, if necessary.

Basic event name filtering

It is possible to filter the events by their names using the -f switch. The filter value must appear anywhere in the event name (it does not support wildcards, and the search is case insensitive). Example:

PS> wtrace -f "fileio/create" notepad
1084,1959 (4044.7048) FileIO/Create 'C:\' (0xFFFFFA8024ED8820) rw-
1084,4550 (4044.7048) FileIO/Create 'C:\tools\notepad2_x86\Notepad2.exe' (0xFFFFFA802E30BF20) rw-
1084,9201 (4044.7048) FileIO/Create 'C:\' (0xFFFFFA802E30BF20) rw-
1085,0909 (4044.7048) FileIO/Create 'C:\tools\notepad2_x86\Notepad2.exe' (0xFFFFFA8024ED8820) rw-
1092,4074 (4044.7048) FileIO/Create 'C:\Windows\Prefetch\NOTEPAD2.EXE-5DB4E400.pf' (0xFFFFFA8024ED8820) ---
...

Automatic tracing of child processes

When your primary process spawns new processes that you would also like to trace you may start wtrace with the -c switch. In this mode, wtrace will automatically begin to trace every process which is a child of the primary process. An example when I monitored the cmd.exe starting notepad:

PS> .\wtrace.exe --newconsole -c cmd
1085,3112 (9112.4264) FileIO/Create 'C:\Windows\Prefetch\CMD.EXE-4A81B364.pf' (0xFFFFFA8022CF0AA0) ---
1086,0403 (9112.4264) FileIO/Create 'C:\temp' (0xFFFFFA8022CF0AA0) rw-
1087,5141 (9112.4264) ALPC cmd <--(0xA84)--- csrss (820.4712)
1095,6011 (9112.4264) ALPC cmd <--(0xA84)--- csrss (820.4720)
1149,6165 (9112.4264) ALPC cmd <--(0x674)--- conhost (8928.12720)
1167,2738 (9112.4264) ALPC cmd <--(0x674)--- conhost (8928.12720)
...
4779,1104 (14000.6408) FileIO/Create 'C:\' (0xFFFFFA802A66B800) rw-
4779,1312 (9112.4264) ALPC cmd <--(0x670)--- csrss (820.1004)
4779,1708 (9112.4264) ALPC cmd <--(0x670)--- csrss (820.1004)
4779,1881 (14000.6408) FileIO/Create 'C:\tools\notepad2_x86\Notepad2.exe' (0xFFFFFA8026E9D070) rw-
4779,2130 (14000.6408) FileIO/Close 'C:\' (0xFFFFFA802A66B800)
4779,2339 (9112.4264) ALPC cmd <--(0x670)--- csrss (820.1004)
4779,2478 (9112.4264) ALPC cmd <--(0x670)--- csrss (820.1004)
4779,2555 (9112.4264) ALPC cmd <--(0x670)--- csrss (820.1004)
...

Tracing PowerShell commands

The last feature I want to mention is the wtrace’s ability to output PowerShell commands executed in the PowerShell session. By default, ETW events reported by the Microsoft-Windows-PowerShell provider do not contain command parameters (7937 event). But you may enable detailed logging in the Local Group Policy Editor (Administrative Templates – Windows Components – Windows PowerShell). To learn more check this article. The interesting options are Turn on Module Logging and Turn on PowerShell Script Block Logging. After some experimentation, I discovered that the generated events differ between Windows versions. That is a bit surprising, and I do not yet understand why it happens. Also, the manifest produced by PerfView for the Microsoft-Windows-PowerShell provider (perfview /nogui usercommand dumpregisteredmanifest Microsoft-Windows-PowerShell) is quite complicated and convoluted. In the end, I recorded multiple ETW sessions and manually implemented the required events. Below you may find an example PowerShell command and the output that wtrace produces:

PS> get-content -Encoding byte C:\windows\notepad.exe | Select-Object -First 10 | Format-HexPrettyPrint
       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
0000: 4d 5a 90 00 03 00 00 00 04 00                    MZ........

PS> .\wtrace -f powershell 9704
2658,9133 (9704.10280) PowerShell/Script
2658,9454 (9704.10280) PowerShell/Cmdlet Out-Default
2659,1716 (9704.10280) PowerShell/Cmdlet Get-Content
2659,7312 (9704.10280) PowerShell/Cmdlet Select-Object
2659,8044 (9704.10280) PowerShell/Function Format-HexPrettyPrint
2660,0039 (9704.10280) PowerShell/Cmdlet Write-Host
2663,2664 (9704.10280) PowerShell/Function PrintLine
2663,4364 (9704.10280) PowerShell/Cmdlet ForEach-Object
2663,9474 (9704.10280) PowerShell/Cmdlet
~~~~~~~~~~~~~~~~~ BEGIN ~~~~~~~~~~~~~~~~~
CommandInvocation(ForEach-Object): "ForEach-Object"
ParameterBinding(ForEach-Object): name="Process"; value=" '{0:x2}' -f $_ "
ParameterBinding(ForEach-Object): name="InputObject"; value="77"
ParameterBinding(ForEach-Object): name="InputObject"; value="90"
ParameterBinding(ForEach-Object): name="InputObject"; value="144"
ParameterBinding(ForEach-Object): name="InputObject"; value="0"
ParameterBinding(ForEach-Object): name="InputObject"; value="3"
ParameterBinding(ForEach-Object): name="InputObject"; value="0"
ParameterBinding(ForEach-Object): name="InputObject"; value="0"
ParameterBinding(ForEach-Object): name="InputObject"; value="0"
ParameterBinding(ForEach-Object): name="InputObject"; value="4"
ParameterBinding(ForEach-Object): name="InputObject"; value="0"
~~~~~~~~~~~~~~~~~  END  ~~~~~~~~~~~~~~~~~
2664,0567 (9704.10280) PowerShell/Cmdlet ForEach-Object
2664,4949 (9704.10280) PowerShell/Cmdlet
~~~~~~~~~~~~~~~~~ BEGIN ~~~~~~~~~~~~~~~~~
CommandInvocation(ForEach-Object): "ForEach-Object"
ParameterBinding(ForEach-Object): name="Process"; value="
                $Numeric = [Int32]$_
                if ($Numeric -ge 32 -and $Numeric -le 126) {
                    [Char]$_
                } else {
                    [Char]'.'
                }
            "
ParameterBinding(ForEach-Object): name="InputObject"; value="77"
ParameterBinding(ForEach-Object): name="InputObject"; value="90"
ParameterBinding(ForEach-Object): name="InputObject"; value="144"
ParameterBinding(ForEach-Object): name="InputObject"; value="0"
ParameterBinding(ForEach-Object): name="InputObject"; value="3"
ParameterBinding(ForEach-Object): name="InputObject"; value="0"
ParameterBinding(ForEach-Object): name="InputObject"; value="0"
ParameterBinding(ForEach-Object): name="InputObject"; value="0"
ParameterBinding(ForEach-Object): name="InputObject"; value="4"
ParameterBinding(ForEach-Object): name="InputObject"; value="0"
~~~~~~~~~~~~~~~~~  END  ~~~~~~~~~~~~~~~~~
2664,5918 (9704.10280) PowerShell/Cmdlet Write-Host
2667,1845 (9704.10280) PowerShell/Script CommandInvocation(Out-Default): "Out-Default"
2669,4010 (9704.10280) PowerShell/Script
2669,5340 (9704.10280) PowerShell/Function prompt
2669,7160 (9704.10280) PowerShell/Cmdlet Test-Path
2670,0204 (9704.10280) PowerShell/Cmdlet Get-Location
2670,1694 (9704.10280) PowerShell/Cmdlet Split-Path
2671,0039 (9704.10280) PowerShell/Function PSConsoleHostReadline
2671,1895 (9704.10280) PowerShell/Cmdlet Set-StrictMode
2671,5095 (9704.10280) PowerShell/Cmdlet
~~~~~~~~~~~~~~~~~ BEGIN ~~~~~~~~~~~~~~~~~
CommandInvocation(Set-StrictMode): "Set-StrictMode"
ParameterBinding(Set-StrictMode): name="Off"; value="True"
~~~~~~~~~~~~~~~~~  END  ~~~~~~~~~~~~~~~~~

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.