How to define filename and get filename from FILE_BOTH_DIR_INFORMATION?

Knife Nan 1 Reputation point
2022-05-01T01:40:35.037+00:00

I want to hook NtQueryDirectoryFile and I hooked it, everything is ok but I can't get the filename? please help me

below is the main code, sorry for my poor english:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct FILE_BOTH_DIR_INFORMATION
        {
            public uint NextEntryOffset;
            public uint FileIndex;
            public LARGE_INTEGER CreationTime;
            public LARGE_INTEGER LastAccessTime;
            public LARGE_INTEGER LastWriteTime;
            public LARGE_INTEGER ChangeTime;
            public LARGE_INTEGER EndOfFile;
            public LARGE_INTEGER AllocationSize;
            public uint FileAttributes;
            public uint FileNameLength;
            public uint EaSize;
            public char ShortNameLength;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
            public string ShortName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string FileName;
        }


static int NtQueryDirectoryFile_Hooked(IntPtr FileHandle, IntPtr pEvent, IntPtr ApcRoutine, IntPtr ApcContext, IntPtr IoStatusBlock, IntPtr FileInformation, IntPtr Length, IntPtr FileInformationClass, IntPtr ReturnSingleEntry, IntPtr FileName, IntPtr RestartScan)
        {
            var result = NtQueryDirectoryFile(FileHandle, pEvent, ApcRoutine, ApcContext, IoStatusBlock, FileInformation, Length, FileInformationClass, ReturnSingleEntry, FileName, RestartScan);

            if (result == STATUS_NO_MORE_FILES)
                return result;

            if (result != 0)
                return result;

            var fileInfo = (FILE_BOTH_DIR_INFORMATION)Marshal.PtrToStructure(FileInformation, typeof(FILE_BOTH_DIR_INFORMATION));

            while(true)
            {

                // the FileName always null or empty

                if ((fileInfo.FileName??"").Length > 0)
                {
                    Debug.Print("Filename Length:" + fileInfo.FileName.Length.ToString());
                }

                if (fileInfo.NextEntryOffset <= 0)
                    break;

                IntPtr fileInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(fileInfo));
                Marshal.StructureToPtr(fileInfo, fileInfoPtr, true);
                fileInfo = (FILE_BOTH_DIR_INFORMATION)Marshal.PtrToStructure(new IntPtr(fileInfoPtr.ToInt32() + (int)fileInfo.NextEntryOffset), typeof(FILE_BOTH_DIR_INFORMATION));
            }


            return result;
        }
Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,837 questions
Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,428 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,301 questions
{count} votes

2 answers

Sort by: Most helpful
  1. RLWA32 40,771 Reputation points
    2022-05-02T09:30:40.39+00:00

    This test code works for me to marshal the FILE_ID_BOTH_DIR_INFO structure. It is very similar to the structure you are attempting to marshal.

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
    using System.ComponentModel;  
    using System.Runtime.InteropServices;  
      
    namespace ConsoleApp1  
    {  
        class Program  
        {  
            [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]  
            public static extern IntPtr CreateFileW(  
                string filename,  
                uint access,  
                uint share,  
                IntPtr securityAttributes,  
                uint creationDisposition,  
                uint flagsAndAttributes,  
                IntPtr templateFile);  
      
            [DllImport("kernel32.dll", SetLastError = true)]  
            public static extern bool CloseHandle(IntPtr handle);  
      
            [StructLayout(LayoutKind.Explicit)]  
            public struct LargeInteger  
            {  
                [FieldOffset(0)]  
                public int Low;  
                [FieldOffset(4)]  
                public int High;  
                [FieldOffset(0)]  
                public long QuadPart;  
      
                // use only when QuadPart canot be passed  
                public long ToInt64()  
                {  
                    return ((long)this.High << 32) | (uint)this.Low;  
                }  
      
                // just for demonstration  
                public static LargeInteger FromInt64(long value)  
                {  
                    return new LargeInteger  
                    {  
                        Low = (int)(value),  
                        High = (int)((value >> 32))  
                    };  
                }  
      
            }  
      
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]  
            public struct FILE_ID_BOTH_DIR_INFO  
            {  
                public int NextEntryOffset;  
                public int FileIndex;  
                public LargeInteger CreationTime;  
                public LargeInteger LastAccessTime;  
                public LargeInteger LastWriteTime;  
                public LargeInteger ChangeTime;  
                public LargeInteger EndOfFile;  
                public LargeInteger AllocationSize;  
                public int FileAttributes;  
                public int FileNameLength;  
                public int EaSize;  
                public char ShortNameLength;  
                [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 12)]  
                public string ShortName;  
                public LargeInteger FileId;  
                public char FileName;  
            };  
      
            [DllImport("kernel32.dll", SetLastError = true)]  
            public static extern bool GetFileInformationByHandleEx(IntPtr hFile, int infoClass, IntPtr dirInfo, uint dwBufferSize);  
      
            const uint GENERIC_READ = 0x80000000;  
            const uint FILE_SHARE_READ = 0x00000001;  
            const uint FILE_SHARE_WRITE = 0x00000002;  
            const uint OPEN_EXISTING = 3;  
            const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;  
            const int FileIdBothDirectoryInfo = 10;  
      
      
            static void Main(string[] args)  
            {  
                IntPtr hFile = CreateFileW("C:\\Users\\RLWA32\\Documents", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero,  
                    OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero);  
      
                if (hFile != (IntPtr)(-1))  
                {  
                    IntPtr buffer = Marshal.AllocHGlobal(16384); // Arbitrary value  
                    if(GetFileInformationByHandleEx(hFile, FileIdBothDirectoryInfo, buffer, 16384))  
                    {  
                        bool bcontinue = true;  
                        IntPtr ptr = buffer;  
                        IntPtr fnameOffset = Marshal.OffsetOf<FILE_ID_BOTH_DIR_INFO>("FileName");  
                        do  
                        {  
                            FILE_ID_BOTH_DIR_INFO info = new FILE_ID_BOTH_DIR_INFO();  
                            info = Marshal.PtrToStructure<FILE_ID_BOTH_DIR_INFO>(ptr);  
                            IntPtr pfilename = ptr + (int)fnameOffset;  
                            string filename = Marshal.PtrToStringUni(pfilename, info.FileNameLength / 2); // FileNameLength in bytes, not chars  
                            Console.WriteLine(filename);  
                            if (info.NextEntryOffset != 0)  
                                ptr += info.NextEntryOffset;  
                            else  
                                bcontinue = false;  
                        } while (bcontinue);  
                    }  
      
                    Marshal.FreeHGlobal(buffer);  
      
                    CloseHandle(hFile);  
                }  
      
            }  
        }  
    }  
      
    

  2. Knife Nan 1 Reputation point
    2022-05-02T12:21:35.927+00:00

    When I call NtQueryDirectoryFile, and then I hook, all is perfect.

    But the following code can be hooked, but can not ge filename?

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Diagnostics;

    namespace Target
    {
    public partial class Form2 : Form
    {
    public Form2()
    {
    InitializeComponent();
    }

        private void button1_Click(object sender, EventArgs e)
        {
            // the hook can be raised
            openFileDialog1.ShowDialog();
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
    
        }
    }
    

    }

    0 comments No comments