@echo off @rem parse persistent state to carry across invocations @rem note this must be done before we go inside setlocal @rem @rem t clion core @rem t clioff <- recovers persisted "core" arg @rem replay persistent state from the cross-invocation stash. this will overwrite @rem existing saved state in place, if present, and is needed in case we are not @rem invoked from within the same instance of cmd. this will happen in PS1, for @rem instance. if exist %temp%\t-persist.cmd ( call %temp%\t-persist.cmd ) @rem figure out "i am" for %%i in (%*) do ( if %%i equ clion set __t_persist_iam=cli if %%i equ clioff set __t_persist_iam=cli if %%i equ srvon set __t_persist_iam=srv if %%i equ srvoff set __t_persist_iam=srv ) @rem persist iam-specific state for %%i in (%*) do ( if %%i equ core call :seteval __t_persist_core_%__t_persist_iam% 1 ) @rem commence detection of multiple stream requests. for %%i in (%*) do ( @rem pattern to follow for dup detection @rem whichever trace claims an element (on) unsets dup flag (at off) @rem ... remember on if "%__t_persist_dup_sec%" equ "" ( @rem note that this has to know that "core" disables @rem the security trace (gack) if "%__t_persist_core%" equ "" ( if %%i equ clion set __t_persist_dup_sec=cli if %%i equ srvon set __t_persist_dup_sec=srv ) ) if "%__t_persist_dup_rpcxdr%" equ "" ( if %%i equ clion set __t_persist_dup_rpcxdr=cli if %%i equ srvon set __t_persist_dup_rpcxdr=srv ) @rem ... detect who gets to unset the persisted state at off time. if %%i equ clioff ( if "%__t_persist_dup_sec%" equ "cli" set __t_persist_remove_dup_sec=1 if "%__t_persist_dup_rpcxdr%" equ "cli" set __t_persist_remove_dup_rpcxdr=1 ) if %%i equ srvoff ( if "%__t_persist_dup_sec%" equ "srv" set __t_persist_remove_dup_sec=1 if "%__t_persist_dup_rpcxdr%" equ "srv" set __t_persist_remove_dup_rpcxdr=1 ) ) setlocal enabledelayedexpansion @rem vars set fail=0 set exe= set tracelog= set disp= set sec= @rem parsed args set ca= set brief= set cli= set core= set nobin= set nocab= set srv= set circ= @rem recover persisted state call :geteval __t_persist_core_!__t_persist_iam! set core=!ret! @rem bin groups for the defined streams set dfsn_bins=dfssvc.exe dfs.sys set fr_bins=fde.dll fdeploy.dll shell32.dll set fskm_bins=cscobj.dll cscsvc.dll csc.sys dfsc.sys mup.sys mrxsmb10.sys mrxsmb20.sys mrxsmb.sys mrxdav.sys nfsrdr.sys rdbss.sys rpcxdr.sys ccffilter.sys resumekeyfilter.sys peerdist.dll peerdistsvc.dll peerdistsh.dll wkssvc.dll set fsum_bins=cscapi.dll cscui.dll webclnt.dll davclnt.dll davhlpr.dll set nbt_bins=netbt.sys smb.sys set nfs_bins=msnfsflt.sys nfssvr.sys portmap.sys rpcxdr.sys set sec_bins=kerberos.dll msv1_0.dll negoexts.dll pku2u.dll set smbhash_bins=hashgen.exe smbgproxy.dll smbhash.exe peerdisthash.dll peerdistsh.dll set srv_bins=srv.sys srv2.sys srvnet.sys witness.exe set tcp_bins=tcpip.sys for %%i in (%*) do ( if %%i equ clion set cli=1 if %%i equ clioff set cli=0 if %%i equ srvon set srv=1 if %%i equ srvoff set srv=0 if %%i equ nocab set nocab=1 if %%i equ nobin set nobin=1 if %%i equ brief set brief=1 if %%i equ ca set ca=1 call :checkcirc %%i ) @rem recover persisted state for stream ownership at stop time if "!cli!" equ "0" ( if "!__t_persist_dup_sec!" equ "cli" ( set sec=1 ) ) if "!srv!" equ "0" ( if "!__t_persist_dup_sec!" equ "srv" ( set sec=1 ) ) @rem choose one if defined cli ( if defined srv ( goto :usage ) ) @rem grab the current process list before turning on tracing @rem and be resilient to the absence of tasklist.exe set taskfile=%temp%\tasklist-!random!.txt for %%i in (tasklist.exe) do ( set exe=%%~$PATH:i ) if "!exe!" equ " " ( echo tasklist.exe is not present > !taskfile! ) else ( !exe! /FO csv /svc > !taskfile! ) set exe= @rem detect absence of logman (winpe), and map the circular log args @rem to the appropriate tool. for %%i in (logman.exe) do ( set exe=%%~$PATH:i ) if "!exe!" equ " " ( for %%i in (tracelog.exe) do ( set exe=%%~$PATH:i ) if "!exe!" equ " " ( echo tracelog is required && goto :eof ) set tracelog=1 if defined circ set circargs=-cir !circbuf! ) else ( if defined circ set circargs=-f bincirc -max !circbuf! ) if "!cli!" equ "1" ( @rem hack to work around inability to exit within calls. @rem primary failure is access denied, which will occur @rem on the first try. call :fskmon if !fail! neq 0 ( goto :eof ) call :fsumon if not defined core ( call :fron call :nbton call :tcpon call :secon ) goto :on_final ) if "!srv!" equ "1" ( call :dfsnon if !fail! neq 0 goto :eof call :srvon call :smbhashon call :nfson if not defined core ( call :secon ) goto :on_final ) if "!cli!" equ "0" ( call :etloff fskm call :etloff fsum if not defined core ( call :etloff fr call :etloff nbt call :etloff tcp if defined sec call :etloff sec ) @rem on off, use finalization goto :off ) if "!srv!" equ "0" ( call :etloff dfsn call :etloff srv call :etloff smbhash call :etloff nfs if not defined core ( if defined sec call :etloff sec ) @rem on off, use finalization goto :off ) :usage echo usage: t ^^on [brief^|ca] [core] [circ:N] echo usage: t ^^off [nocab] [nobin] echo used @on: echo brief - brief mode tracing flags (defined for fskm/mup) echo ca - brief mode for CA tracing (more restricted) echo core - only generate fsf team owned component traces echo circ - generate circular logs of size N megabytes. Default circular buffer size is 50 MB. echo used @off: echo nocab - do not compress traces echo nobin - do not gather system binaries matching the captured traces echo (please do not use if external to FSF/without direction) goto :eof @@@@@@@@@ @ @ tracing steps: @ @ 1. traceon: start a specific session with given stream @ 2. traceadd: add additional streams to the session @ 3. disp: dump rendering of what trace* did @ @rem always goes first - adds access denied check :fskmon @rem do brief if defined brief ( set flags=0x3333333 set level=0 ) else ( if defined ca ( set flags=0x101 set level=0 ) else ( set flags=0xfffffff set level=7 ) ) call :traceon fskm 20c46239-d059-4214-a11e-7d6769cbe020 csckm/dav/dfsc/mup/rdbss/smb !level! !flags! if !fail! neq 0 ( goto :eof ) @rem if CA tracing is on, do nothing else if !ca! neq 0 ( goto :eof ) @rem witness - per prashanth, useful interleaved with kernelmode call :traceadd fskm 47eba62c-87e6-4564-9946-0dd4e361ed9b witnesscli @rem csc - per molly, useful interleaved with kernelmode call :traceadd fskm 89D89015-C0DF-414c-BC48-F50E114832BC cscservice 7 0x7fffffff call :traceadd fskm 791cd79c-65b5-48a3-804c-786048994f47 fastsync call :traceadd fskm 17efb9ce-8cab-4f19-8b96-0d021d9c76f1 ccffilter call :traceadd fskm d5418619-c167-44d9-bc36-765beb5d55f3 dcluser @rem peerdist - per paul, useful interleaved with kernelmode call :traceadd fskm 1f8b121d-45b3-4022-a9fb-3857177a65c1 peerdist @rem nfs client call :traceadd fskm 355C2284-61CB-47bb-8407-4BE72B5577B0 nfsrdr @rem note: rpcxdr shared with server (below) @rem detect duplicated capture call :dup rpcxdr if !fail! equ 0 ( call :traceadd fskm 94B45058-6F59-4696-B6BC-B23B7768343D rpcxdr ) else ( set fail=0 ) call :disp goto :eof @@@@@@@@@ :secon @rem detect duplicated capture call :dup sec if !fail! neq 0 ( goto :eof ) @rem flags via larry's wiki @ http://mswikis/winsecurity/protocols/kerberos/Wiki%20Pages/how%20to%20turn%20on%20tracing.aspx call :traceon sec 6B510852-3583-4e2d-AFFE-A67F9F223438 kerberos 7 0x43 call :traceadd sec 5BBB6C18-AA45-49b1-A15F-085F7ED0AA90 ntlm 7 0x15003 call :traceadd sec 5AF52B0D-E633-4ead-828A-4B85B8DAAC2B negoexts 7 0x73 call :traceadd sec 2A6FAF47-5449-4805-89A3-A504F3E221A6 pku2u 7 0x1f3 call :disp goto :eof @@@@@@@@@ :fsumon @rem csc call :traceon fsum 361f227c-aa14-4d19-9007-0c8d1a8a541b cscnet call :traceadd fsum 0999b701-3e5d-4998-bc58-a775590a55d9 cscdll call :traceadd fsum 19EE4CF9-5322-4843-B0D8-BAB81BE4E81E cscapi call :traceadd fsum 66418A2A-72AF-4c1a-9C84-42F6865563BD cscui @rem dav call :traceadd fsum 91efb5a1-642d-42a4-9821-f15c73064fb5 WebClnt call :disp goto :eof @@@@@@@@@ :srvon call :traceon srv 3121cf5d-c5e6-4f37-be86-57083590c333 srvdl call :traceadd srv 2744F0B7-8455-44f8-9B64-5F589F9D163A srv2 call :traceadd srv c0183094-fdc6-493f-a3e8-697224f83f6f srvnet call :traceadd srv D8E0C67B-7D87-48b6-9290-42126E66FAEE srvsvc call :traceadd srv c5a38574-9827-4c24-b8fb-d6635475566f resumekeyfilter call :traceadd srv c73e561f-c5b4-4a82-9b63-34bde5718e61 witnesssvc call :disp goto :eof @@@@@@@@@ :smbhashon call :traceon smbhash 48be2803-12c0-4932-aa80-93372d5a9114 smbhash call :disp goto:eof @@@@@@@@@ :nfson call :traceon nfs CC9A5284-CC3E-4567-B3F6-3EB24E7CFEC5 MsNfsFltGuid call :traceadd nfs 3c33d8b3-66fa-4427-a31b-f7dfa429d78f NfsSvrGuid call :traceadd nfs fc33d8b3-66fa-4427-a31b-f7dfa429d78f NfsSvrGuid2 call :traceadd nfs 57294EFD-C387-4e08-9144-2028E8A5CB1A NfsSvrNlmGuid call :traceadd nfs f3bb9731-1d9f-4b8e-a42e-203bf1a32300 Nfs4SvrGuid call :traceadd nfs E18A05DC-CCE3-4093-B5AD-211E4C798A0D PortmapGuid @rem note: rpcxdr shared with client (above) @rem detect duplicated capture call :dup rpcxdr if !fail! equ 0 ( call :traceadd fskm 94B45058-6F59-4696-B6BC-B23B7768343D rpcxdr ) else ( set fail=0 ) call :disp goto :eof @@@@@@@@@ :fron call :traceon fr 2955e23c-4e0b-45ca-a181-6ee442ca1fc0 fr 4 0x1f call :traceadd fr 6b6c257f-5643-43e8-8e5a-c66343dbc650 UstCommon 7 0x0fffffff call :disp goto :eof @@@@@@@@@ :dfsnon call :traceon dfsn 27246e9d-b4df-4f20-b969-736fa49ff6ff dfsn call :disp goto :eof @@@@@@@@@ :nbton call :traceon nbt bca7bd7f-b0bf-4051-99f4-03cfe79664c1 nbtsmb call :disp goto :eof @@@@@@@@@ :tcpon rem - tcp-only == flags 0x80 from the original script call :traceon tcp eb004a05-9b1a-11d4-9123-0050047759bc tcp 7 0x80 call :disp goto :eof @@@@@@@@@ :etloff call :traceoff %1 @rem roll up the binaries associated with this trace, if specified if defined nobin goto :eof set bins=!bins! !%1_bins! goto :eof @@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ duplicate stream detectomatic :dup @rem 1 name of stream @rem if it isn't you ... if "!__t_persist_dup_%1!" equ "srv" ( if "!srv!" equ "1" ( goto :eof ) goto :dupfail ) if "!__t_persist_dup_%1!" equ "cli" ( if "!cli!" equ "1" ( goto :eof ) goto :dupfail ) goto :eof :dupfail echo info: %1 is already being captured (!__t_persist_dup_%1!) set fail=1 goto :eof @@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ high level trace fns @@@@@ :traceon @rem 1 etl name @rem 2 guid @rem 3 display name @rem 4 optional level @rem 5 optional flags call :stop %1 call :create %1 if !fail! equ 0 ( set disp=started %1 ^<- ) if !fail! neq 0 goto :eof call :traceadd %1 %2 %3 %4 %5 goto :eof :traceadd @rem 1 etl name @rem 2 guid @rem 3 display name @rem 4 optional level @rem 5 optional flags call :update %1 %2 %4 %5 if not errorlevel 1 ( set disp=!disp!%3 ) goto :eof :traceoff @rem 1 etl name call :stop %1 if not errorlevel 1 ( echo %1 -^> %1.etl ) goto :eof @@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ impl level trace fns @@@@@ :stop @rem 1 etl name if defined tracelog ( call :doit tracelog -stop %1 ) else ( call :doit logman stop -n %1 -ets ) set etl=!etl! %1.etl goto :eof :create @rem 1 etl name if defined tracelog ( call :doit tracelog -start %1 -f %1.etl -gs !circargs! @rem tracelog access denied case if !errorlevel! equ 5 ( @rem copy/paste of logman's output when running in normal context @rem could be better echo Access is denied. echo You're running with a restricted token, try running elevated. ) ) else ( call :doit logman create trace -n %1 -o %1.etl -mode globalsequence -ets !circargs! @rem logman access denied case if !errorlevel! equ -2147024891 ( @rem copy/paste of logman's output when running in normal context @rem could be better echo Access is denied. echo You're running with a restricted token, try running elevated. ) ) if !errorlevel! neq 0 ( echo %1 failed !errorlevel! @rem set resets errorlevel - must come last set fail=1 ) goto :eof :update @rem 1 etl name @rem 2 guid @rem 3 optional level @rem 4 optional flags if "%3" equ "" ( set level=7 ) else ( set level=%3 ) if "%4" equ "" ( set flags=0xfffffff ) else ( set flags=%4 ) if defined tracelog ( call :doit tracelog -enable %1 -guid #%2 -flags !flags! -level !level! ) else ( call :doit logman update %1 -p {%2} !flags! !level! -ets ) goto :eof @@@@@@@@@@@@@@@@@@@@@@@@@@@@ @rem finalization / cab generator @rem @rem two phase, second (*_final) is termination :off if defined nocab goto :off_final @rem construct cab directive file set dirfile=%temp%\tracecab-!random!.ddf set verfile=%temp%\version-!random!.txt set cabroot=t set cabname=!cabroot! @rem nosmash :retry if exist !cabname!.cab ( set cabname=!cabroot!-!random! goto :retry ) @rem os version data reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /t REG_SZ > !verfile! echo .set CabinetName1=!cabname!.cab > !dirfile! echo .set CompressionType=LZX >> !dirfile! echo .set DiskDirectory=. >> !dirfile! echo .set DiskDirectory1=. >> !dirfile! echo .set InfFileName=nul >> !dirfile! echo .set RptFileName=nul >> !dirfile! echo .set maxdisksize=0 >> !dirfile! echo !verfile! version.txt >> !dirfile! echo !taskfile! tasklist.txt >> !dirfile! for %%i in (!etl!) do echo %%i >> !dirfile! for %%i in (!bins!) do ( if exist %systemroot%\system32\%%i ( echo %systemroot%\system32\%%i bin\%%i >> !dirfile! ) else ( if exist %systemroot%\system32\drivers\%%i ( echo %systemroot%\system32\drivers\%%i bin\%%i >> !dirfile! ) ) ) echo --- echo compressing ... makecab /f !dirfile! > nul if !errorlevel! neq 0 ( echo failed to compress trace files - not deleting goto :off_final ) echo --- if defined bins echo compressed: matching system binaries echo compressed: version info +!etl! -^> !cabname!.cab echo done @rem cleanup call :doit del !dirfile! call :doit del !verfile! for %%i in (!etl!) do call :doit del %%i @rem finalization for off state :off_final call :doit del !taskfile! endlocal call :seteval __t_persist_core_%__t_persist_iam% goto :final @rem finalization for on state :on_final endlocal @rem finalization for on (and off) state :final @rem wipe persisted state if defined __t_persist_remove_dup_rpcxdr set __t_persist_dup_rpcxdr= set __t_persist_remove_dup_rpcxdr= if defined __t_persist_remove_dup_sec set __t_persist_dup_sec= set __t_persist_remove_dup_sec= set __t_persist_iam= @rem save persistent state to allow invocation from non-cmd instances, like PS1 (!) if exist %temp%\t-persist.cmd ( del /q %temp%\t-persist.cmd ) set | findstr __t_persist > %temp%\t-persist-tmp.cmd for /f %%i in (%temp%\t-persist-tmp.cmd) do (echo set %%i) >> %temp%\t-persist.cmd del /q %temp%\t-persist-tmp.cmd goto :eof @@@@@@@@@@@@@@@@@@@@@@@@@@@@ :doit %* > nul if errorlevel 1 ( echo failed: %* ) goto :eof :disp if !fail! equ 0 ( echo !disp! ) goto :eof :seteval set %1=%2 goto :eof :geteval set ret=!%1! goto :eof @rem Check for circular buffer option and buffer size. :checkcirc for /f "tokens=1,2 delims=:" %%i in ("%1") do ( if %%i equ circ ( set circ=1 set circbuf=%%j if "%%j" equ "" set circbuf=50 echo Enabling circular buffer of size !circbuf! MB ) ) goto :eof