Share via


Leveraging the new WinDbgX and Time-Travel-Trace –Script to list all access to files

 

WinDbg Preview a.k.a. WinDbgX aesthetically looks like a marriage between Visual Studio (VS) and WinDbg, however VS and WinDbg have not many things in common. For me, this is the good news. The bad news is that the support for managed code is as limited as WinDbg’s. You can download the preview here: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools

 

The most impressive feature of the new debugger is by far the ability to create dump files to later be analyzed as live debugging. This is called Time-Travel-Debugging (TTD). The idea is that you can record an actual live process (at a performance penalty) to later debug going back and forth in time, thus the name. A good use for this is to capture a ‘live dump’ on a production server and analyze the dump later on another environment with access to source code and symbols. If you are a software provider, this is golden. Sometimes, only a particular environment causes the error and your logs do not show much that can help you identify the problem. Recording on a place and debugging on your development lab does not require that you ship your private symbols and source code to a customer’s environment. You may learn more here: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/time-travel-debugging-overview

 

The analysis is done via a LinQ like syntax that can be used directly from the debugger command window or automated via a classic debugger extension or a JavaScript extension. In this post, I am presenting a proof-of-concept script that shows all instances when a file is accessed. More on WinDbg scripting here: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/javascript-debugger-scripting

 

Proof of concept OpenFileList.js (this script only WORKS with TTD dumps – .run files)

 "use strict";
  
     var FileAccess =
     {
         FILE_READ_DATA: 0x0001,    /* file & pipe */
         FILE_LIST_DIRECTORY: 0x0001,    /* directory */
         FILE_WRITE_DATA: 0x0002,    // file & pipe
         FILE_ADD_FILE: 0x0002,    // directory
  
         FILE_APPEND_DATA: 0x0004,    // file
         FILE_ADD_SUBDIRECTORY: 0x0004,    // directory
         FILE_CREATE_PIPE_INSTANCE: 0x0004,    // named pipe
  
  
         FILE_READ_EA: 0x0008,    // file & directory
  
         FILE_WRITE_EA: 0x0010,    // file & directory
  
         FILE_EXECUTE: 0x0020,    // file
         FILE_TRAVERSE: 0x0020,    // directory
  
         FILE_DELETE_CHILD: 0x0040,    // directory
  
         FILE_READ_ATTRIBUTES: 0x0080,    // all
  
         FILE_WRITE_ATTRIBUTES: 0x0100,    // all
  
         DELETE: 0x10000,
         WRITE_DAC: 0x40000,   
         WRITE_OWNER: 0x80000, 
         SYNCHRONIZE: 0x100000, 
         ACCESS_SYSTEM_SECURITY: 0x11F01FF,
  
  
         GENERIC_READ: 0x80000000,
         GENERIC_WRITE: 0x40000000,
         GENERIC_EXECUTE: 0x20000000,
         GENERIC_ALL: 0x10000000
     };
  
     var FileShare = 
     {
         FILE_SHARE_NONE: 0,
         FILE_SHARE_READ: 0x00000001,
         FILE_SHARE_WRITE: 0x00000002,
         FILE_SHARE_DELETE: 0x00000004
  
     };
  
 function PrintFileAccess(Access)
 {
     var flag = "";
     if(Access == 0)
       return "None";
     if(Access & FileAccess.FILE_ADD_FILE)
        flag = "FILE_ADD_FILE";
     if(Access & FileAccess.FILE_ADD_SUBDIRECTORY)
        flag = flag.concat(" FILE_ADD_SUBDIRECTORY");
     if(Access & FileAccess.FILE_APPEND_DATA)
        flag = flag.concat(" FILE_APPEND_DATA");
     if(Access & FileAccess.FILE_CREATE_PIPE_INSTANCE)
        flag = flag.concat(" FILE_CREATE_PIPE_INSTANCE");
     if(Access & FileAccess.FILE_DELETE_CHILD)
        flag = flag.concat(" FILE_DELETE_CHILD");
     if(Access & FileAccess.FILE_EXECUTE)
        flag = flag.concat(" FILE_EXECUTE");
     if(Access & FileAccess.FILE_LIST_DIRECTORY)
        flag = flag.concat(" FILE_LIST_DIRECTORY");
     if(Access & FileAccess.FILE_READ_ATTRIBUTES)
        flag = flag.concat(" FILE_READ_ATTRIBUTES");
     if(Access & FileAccess.FILE_READ_DATA)
        flag = flag.concat(" FILE_READ_DATA");
     if(Access & FileAccess.FILE_READ_EA)
        flag = flag.concat(" FILE_READ_EA");
     if(Access & FileAccess.GENERIC_ALL)
        flag = flag.concat(" GENERIC_ALL");
     if(Access & FileAccess.GENERIC_EXECUTE)
        flag = flag.concat(" GENERIC_EXECUTE");
     if(Access & FileAccess.GENERIC_READ)
        flag = flag.concat(" GENERIC_READ");
     if(Access & FileAccess.GENERIC_WRITE)
        flag = flag.concat(" GENERIC_WRITE");
     if(Access & FileAccess.FILE_TRAVERSE)
        flag = flag.concat(" FILE_TRAVERSE");
     if(Access & FileAccess.FILE_WRITE_DATA)
        flag = flag.concat(" FILE_WRITE_DATA");
     if(Access & FileAccess.FILE_WRITE_EA)
        flag = flag.concat(" FILE_WRITE_EA");
     if(Access & FileAccess.DELETE)
        flag = flag.concat(" DELETE");
     if(Access & FileAccess.WRITE_DAC)
        flag = flag.concat(" WRITE_DAC");
     if(Access & FileAccess.WRITE_OWNER)
        flag = flag.concat(" WRITE_OWNER");
     if(Access & FileAccess.SYNCHRONIZE)
        flag = flag.concat(" SYNCHRONIZE");
     if(Access & FileAccess.ACCESS_SYSTEM_SECURITY)
        flag = flag.concat(" ACCESS_SYSTEM_SECURITY");
  
  
  
     return flag;
 }
  
 function PrintFileShare(Share)
 {
     var flag = "";
     if(Share == 0)
       return "None";
     if(Share & FileShare.FILE_SHARE_DELETE)
        flag = "FILE_SHARE_DELETE";
     if(Share & FileShare.FILE_SHARE_READ)
        flag = flag.concat(" FILE_SHARE_READ");
     if(Share & FileShare.FILE_SHARE_WRITE)
        flag = flag.concat(" FILE_SHARE_WRITE");
     return flag;
        
 }
  
 function findFileHandle()
 {
     var fileOper = host.currentSession
         .TTD.Calls("KERNELBASE!CreateFileW", "KERNELBASE!CreateFileA");
     var locations = [];
     for(var loc of fileOper)
     {
         var posObj = {Start: loc.TimeStart, FileNameAddr: loc.Parameters[0],
               Access: loc.Parameters[1], ShareMode: loc.Parameters[2],
               Result: loc.ReturnAddress, Ansi: loc.Function.includes("CreateFileA") };
         
         locations.push(posObj);
         
     }
     return locations;
 }  
  
  
 function printFileName(location)
 {
     host.diagnostics.debugLog("------------------------------------------------\n");
  
     location.Start.SeekTo();
  
     host.diagnostics.debugLog((location.Result > 0 ? "(SUCCESS) " : "(Failure) ") +
                        (location.Ansi ? host.memory.readString(location.FileNameAddr) : host.memory.readWideString(location.FileNameAddr)) + "\n");
     var access = host.evaluateExpression(location.Access.toString(16)+" & 0xffffffff")
     var share = host.evaluateExpression(location.ShareMode.toString(16)+" & 0xffffffff")
  
     // host.diagnostics.debugLog(access.toString(16) + " " + share.toString(16)+" ");
                         
     host.diagnostics.debugLog("Access: ["+access.toString(16)+"] "+PrintFileAccess(access)+" Share: ["+
                     share.toString(16) + "] "+PrintFileShare(share) + "\n");  
     return;                   
 }
  
 function invokeScript()
 {
     host.diagnostics.debugLog("Collecting File Access information...\n");
  
  
  
     var currentPosition = host.currentThread.TTD.Position;
  
     var locations = findFileHandle();
     for (var location of locations)
     {
         printFileName(location);
     }
  
     currentPosition.SeekTo();
 }
  
  
  

 

This is an example of the output:

 Collecting File Access information...
 ------------------------------------------------
 Setting position: 1DB4F:4D
 (2370.2184): Break instruction exception - code 80000003 (first/second chance not available)
 Time Travel Position: 1DB4F:4D
 KERNELBASE!CreateFileW:
 00007ffe`d0258460 4883ec58        sub     rsp,58h
 Collecting File Access information...
 ------------------------------------------------
 Setting position: 1DB4F:4D
 (2370.2184): Break instruction exception - code 80000003 (first/second chance not available)
 Time Travel Position: 1DB4F:4D
 KERNELBASE!CreateFileW:
 00007ffe`d0258460 4883ec58        sub     rsp,58h
 Collecting File Access information...
 ------------------------------------------------
 Setting position: 1DB4F:4D
 (SUCCESS) C:\windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.SharePoint\v4.0_15.0.0.0__71e9bce111e9429c\Microsoft.SharePoint.dll
 Access: [0x4c4b400]  WRITE_DAC ACCESS_SYSTEM_SECURITY Share: [0x1]  FILE_SHARE_READ
 ------------------------------------------------
 Setting position: 42094:4D
 (SUCCESS) C:\windows\Microsoft.Net\assembly\GAC_64\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll
 Access: [0x4c4b400]  WRITE_DAC ACCESS_SYSTEM_SECURITY Share: [0x1]  FILE_SHARE_READ
 ------------------------------------------------
 Setting position: 4211F:4D
 (SUCCESS) C:\windows\Microsoft.Net\assembly\GAC_64\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll
 Access: [0x4c4b400]  WRITE_DAC ACCESS_SYSTEM_SECURITY Share: [0x1]  FILE_SHARE_READ
 ------------------------------------------------
 Setting position: 1DBCD:4D
 (SUCCESS) C:\windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.SharePoint\v4.0_15.0.0.0__71e9bce111e9429c\Microsoft.SharePoint.dll
 Access: [0x4c4b400]  WRITE_DAC ACCESS_SYSTEM_SECURITY Share: [0x1]  FILE_SHARE_READ
 ------------------------------------------------
 Setting position: 414C5:4D
 (SUCCESS) C:\windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.SharePoint.Publishing\v4.0_15.0.0.0__71e9bce111e9429c\Microsoft.SharePoint.Publishing.dll
 Access: [0x4c4b400]  WRITE_DAC ACCESS_SYSTEM_SECURITY Share: [0x1]  FILE_SHARE_READ
 ------------------------------------------------
 Setting position: 4219E:4D
 (SUCCESS) C:\windows\Microsoft.Net\assembly\GAC_64\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll
 Access: [0x4c4b400]  WRITE_DAC ACCESS_SYSTEM_SECURITY Share: [0x1]  FILE_SHARE_READ
 ------------------------------------------------
 Setting position: 1DC4B:4D
 (SUCCESS) C:\windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.SharePoint\v4.0_15.0.0.0__71e9bce111e9429c\Microsoft.SharePoint.dll
 Access: [0x4c4b400]  WRITE_DAC ACCESS_SYSTEM_SECURITY Share: [0x1]  FILE_SHARE_READ
 ------------------------------------------------
 Setting position: 4221C:4D
 (SUCCESS) C:\windows\Microsoft.Net\assembly\GAC_64\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll
 Access: [0x4c4b400]  WRITE_DAC ACCESS_SYSTEM_SECURITY Share: [0x1]  FILE_SHARE_READ
 ------------------------------------------------
 (...)