Quantcast
Channel: Reading MFT
Viewing all articles
Browse latest Browse all 444

Reading MFT

$
0
0

Here is a very small example of using the PathFromFrn() to enumerate the MFT with path information. What I did was use ParentFileReference and append the filename.

BTW: It will be slow if you output to the debug window and it's currently synchrounous example.

You can easily use it like this:

 

Dim myMFT AsNew EnumMFT
myMFT.FindAllFiles(
"E:")

Imports System.Runtime.InteropServices

Public Class EnumMFT

    Private Const INVALID_HANDLE_VALUE = (-1)
    Private Const GENERIC_READ = &H80000000
    Private Const FILE_SHARE_READ = &H1
    Private Const FILE_SHARE_WRITE = &H2
    Private Const OPEN_EXISTING = 3
    Private Const FILE_READ_ATTRIBUTES = &H80
    Private Const FileNameInformationClass = 9
    Private Const FILE_FLAG_BACKUP_SEMANTICS = &H2000000
    Private Const FILE_OPEN_FOR_BACKUP_INTENT = &H4000
    Private Const FILE_OPEN_BY_FILE_ID = &H2000
    Private Const FILE_OPEN = &H1
    Private Const OBJ_CASE_INSENSITIVE = &H40


    Private Const FSCTL_ENUM_USN_DATA = &H900B3<StructLayout(LayoutKind.Sequential)> _
    Private Structure MFT_ENUM_DATA
        Dim StartFileReferenceNumber As Long
        Dim LowUsn As Long
        Dim HighUsn As Long
    End Structure<StructLayout(LayoutKind.Sequential)> _
    Private Structure USN_RECORD
        Dim RecordLength As Integer
        Dim MajorVersion As Short
        Dim MinorVersion As Short
        Dim FileReferenceNumber As Long
        Dim ParentFileReferenceNumber As Long
        Dim Usn As Long
        Dim TimeStamp As Long
        Dim Reason As Integer
        Dim SourceInfo As Integer
        Dim SecurityId As Integer
        Dim FileAttributes As Integer
        Dim FileNameLength As Short
        Dim FileNameOffset As Short
    End Structure<StructLayout(LayoutKind.Sequential)> _
    Private Structure IO_STATUS_BLOCK
        Dim Status As Integer
        Dim Information As Integer
    End Structure<StructLayout(LayoutKind.Sequential)> _
    Private Structure UNICODE_STRING
        Dim Length As Short
        Dim MaximumLength As Short
        Dim Buffer As IntPtr
    End Structure<StructLayout(LayoutKind.Sequential)> _
    Private Structure OBJECT_ATTRIBUTES
        Dim Length As Integer
        Dim RootDirectory As IntPtr
        Dim ObjectName As IntPtr
        Dim Attributes As Integer
        Dim SecurityDescriptor As Integer
        Dim SecurityQualityOfService As Integer
    End Structure

    '// MFT_ENUM_DATA
    <DllImport("kernel32.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function DeviceIoControl(ByVal hDevice As IntPtr, ByVal dwIoControlCode As Integer, ByRef lpInBuffer As MFT_ENUM_DATA, ByVal nInBufferSize As Integer, ByVal lpOutBuffer As IntPtr, ByVal nOutBufferSize As Integer, ByRef lpBytesReturned As Integer, ByVal lpOverlapped As IntPtr) As Boolean
    End Function<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function CreateFile(ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer, ByVal lpSecurityAttributes As IntPtr, ByVal dwCreationDisposition As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As IntPtr) As IntPtr
    End Function<DllImport("kernel32.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function CloseHandle(ByVal lpObject As IntPtr) As Int32
    End Function<DllImport("ntdll.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function NtCreateFile(ByRef FileHandle As IntPtr, ByVal DesiredAccess As Integer, ByRef ObjectAttributes As OBJECT_ATTRIBUTES, ByRef IoStatusBlock As IO_STATUS_BLOCK, ByVal AllocationSize As Integer, ByVal FileAttribs As Integer, ByVal SharedAccess As Integer, ByVal CreationDisposition As Integer, ByVal CreateOptions As Integer, ByVal EaBuffer As Integer, ByVal EaLength As Integer) As Integer
    End Function<DllImport("ntdll.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function NtQueryInformationFile(ByVal FileHandle As IntPtr, ByRef IoStatusBlock As IO_STATUS_BLOCK, ByVal FileInformation As IntPtr, ByVal Length As Integer, ByVal FileInformationClass As Integer) As Integer
    End Function

    Private m_hCJ As IntPtr
    Private m_Buffer As IntPtr
    Private m_BufferSize As Integer
    Private m_DriveLetter As String

    Private Function OpenVolume(ByVal szDriveLetter As String) As IntPtr

        Dim hCJ As IntPtr '// volume handle

        m_DriveLetter = szDriveLetter

        hCJ = CreateFile("\\.\" & szDriveLetter, GENERIC_READ, _
                         FILE_SHARE_READ Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, 0)

        Return hCJ

    End Function

    Private Sub Cleanup()

        If m_hCJ <> 0 Then
            ' Close the volume handle.
            CloseHandle(m_hCJ)
            m_hCJ = INVALID_HANDLE_VALUE
        End If

        If m_Buffer <> 0 Then
            ' Free the allocated memory
            Marshal.FreeHGlobal(m_Buffer)
            m_Buffer = IntPtr.Zero
        End If

    End Sub

    Public Sub FindAllFiles(ByVal szDriveLetter As String)

        Dim usnRecord As USN_RECORD
        Dim mft As MFT_ENUM_DATA
        Dim dwRetBytes As Integer
        Dim cb As Integer

        ' This shouldn't be called more than once.
        If m_Buffer.ToInt32 <> 0 Then
            Console.WriteLine("invalid buffer")
            Exit Sub
        End If

        ' Assign buffer size
        m_BufferSize = 65536 '64KB

        ' Allocate a buffer to use for reading records.
        m_Buffer = Marshal.AllocHGlobal(m_BufferSize)

        ' Open the volume handle
        m_hCJ = OpenVolume(szDriveLetter)

        ' Check if the volume handle is valid.
        If m_hCJ = INVALID_HANDLE_VALUE Then
            Console.WriteLine("Couldn't open handle to the volume.")
            Cleanup()
            Exit Sub
        End If

        mft.StartFileReferenceNumber = 0
        mft.LowUsn = 0
        mft.HighUsn = Long.MaxValue

        Do
            If DeviceIoControl(m_hCJ, FSCTL_ENUM_USN_DATA, mft, Marshal.SizeOf(mft), m_Buffer, m_BufferSize, dwRetBytes, IntPtr.Zero) Then
                cb = dwRetBytes
                ' Pointer to the first record
                Dim pUsnRecord As New IntPtr(m_Buffer.ToInt32() + 8)

                While (dwRetBytes > 8)
                    ' Copy pointer to USN_RECORD structure.
                    usnRecord = Marshal.PtrToStructure(pUsnRecord, usnRecord.GetType)
                    ' The filename within the USN_RECORD.
                    Dim FileName As String = Marshal.PtrToStringUni(New IntPtr(pUsnRecord.ToInt32() + usnRecord.FileNameOffset), _
                                                                    usnRecord.FileNameLength / 2)


                    If usnRecord.FileAttributes And vbDirectory Then
                        Dim dirPath As String = PathFromFrn(usnRecord.ParentFileReferenceNumber)
                        ' directory
                        Console.WriteLine("Directory {0} ", szDriveLetter & dirPath)
                    Else
                        ' files
                        Dim filePath As String = PathFromFrn(usnRecord.ParentFileReferenceNumber) & "\" & FileName
                        Console.WriteLine("File {0} ", szDriveLetter & filePath)
                    End If

                    ' Pointer to the next record in the buffer.
                    pUsnRecord = New IntPtr(pUsnRecord.ToInt32() + usnRecord.RecordLength)

                    dwRetBytes -= usnRecord.RecordLength

                End While

                ' The first 8 bytes is always the start of the next USN.
                mft.StartFileReferenceNumber = Marshal.ReadInt64(m_Buffer, 0)

            Else

                Exit Do

            End If ' DeviceIoControl)

        Loop Until cb <= 8

        '// cleanup
        Cleanup()
        Console.WriteLine("Done")

    End Sub



    Private Function PathFromFrn(ByVal Id As Long) As String

        Dim fOk As Integer
        Dim FileName As String = String.Empty
        Dim UnicodeString As UNICODE_STRING
        Dim ObjAttributes As OBJECT_ATTRIBUTES
        Dim IoStatusBlock As IO_STATUS_BLOCK
        Dim hFile As IntPtr ' out handle
        Dim Buffer As IntPtr = Marshal.AllocHGlobal(4096) ' Raw buffer
        Dim Refptr As IntPtr = Marshal.AllocHGlobal(8) ' 8 byte FileID
        Dim ObjAtt As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ObjAttributes)) 'pointer to the unicode string struct

        ' pointer>>fileid
        Marshal.WriteInt64(Refptr, 0, Id)

        ' 8 byte file id
        UnicodeString.Length = 8
        UnicodeString.MaximumLength = 8
        UnicodeString.Buffer = Refptr

        ' copy unicode structure to pointer
        Marshal.StructureToPtr(UnicodeString, ObjAtt, True)

        ' InitializeObjectAttributes Macro
        ObjAttributes.Length = Marshal.SizeOf(ObjAttributes)
        ObjAttributes.ObjectName = ObjAtt
        ObjAttributes.RootDirectory = m_hCJ
        ObjAttributes.Attributes = OBJ_CASE_INSENSITIVE

        fOk = NtCreateFile(hFile, 0, ObjAttributes, IoStatusBlock, 0, 0, _
                           FILE_SHARE_READ Or FILE_SHARE_WRITE, _
                           FILE_OPEN, FILE_OPEN_BY_FILE_ID Or FILE_OPEN_FOR_BACKUP_INTENT, 0, 0)

        If fOk <> INVALID_HANDLE_VALUE Then

            fOk = NtQueryInformationFile(hFile, IoStatusBlock, Buffer, 4096, FileNameInformationClass)

            If fOk = 0 Then

                ' The first 4 bytes is the length
                Dim FileLength As Integer = Marshal.ReadInt32(Buffer, 0)
                ' The filename is just after the first 4 bytes.
                FileName = Marshal.PtrToStringUni(New IntPtr(Buffer.ToInt32() + 4), FileLength / 2)

            End If

        End If
        ' free allocated memory and handles
        CloseHandle(hFile)
        Marshal.FreeHGlobal(Buffer)
        Marshal.FreeHGlobal(ObjAtt)
        Marshal.FreeHGlobal(Refptr)


        Return FileName
    End Function

End Class

Viewing all articles
Browse latest Browse all 444

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>