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

------------------------------------------------

(...)