SetFilePointerEx API to read MFT

本文关键字:MFT read to API SetFilePointerEx | 更新日期: 2023-09-27 18:16:41

我想从分区上的MFT偏移量中读取一些字节。我得到了分区句柄并成功地读取了前1K字节,但是SetFilePointerEx返回了一个错误。请帮我一下。

int nread = 0;
IntPtr handle = IntPtr.Zero;
byte[] buff = new byte[1024];
IntPtr newaddress = IntPtr.Zero;
long MFTAddress = bytepersector * sectorpercluster * (long)MFTStart;
string driveRoot = "''''.''c:";
IntPtr hRoot = CreateFile(driveRoot,
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    IntPtr.Zero,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    IntPtr.Zero);
SetFilePointerEx(hRoot, MFTAddress, ref newaddress, 0);
int error = GetLastError();
if (hRoot != IntPtr.Zero)
    handle = ReadFile(newaddress, buff, 1024,ref nread, new System.Threading.NativeOverlapped());

这是找到MFTOffset和其他信息的代码。

            uint nread = 0;
        IntPtr handle;
        byte[] buff = new byte[1024];
        string driveRoot = string.Concat("''''.''", driveLetter);
        IntPtr hRoot = CreateFile(driveRoot,
            GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            IntPtr.Zero,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            IntPtr.Zero);
        if (hRoot != IntPtr.Zero)
             ReadFile(hRoot, buff, 1024,out nread, IntPtr.Zero);
        string SystemFile = Convert.ToString(LittleEndian(4, new byte[] { buff[3], buff[4], buff[5], buff[6] }, typeof(string)));
        int BytePerSector = 0;
        int SectorPerCluster = 0;
        double MFTStart = 0;
        if (SystemFile == "NTFS")
        {
            listBox1.Items.Add(SystemFile);
            BytePerSector = (int)LittleEndian(2, new byte[] { buff[11], buff[12] }, BytePerSector.GetType());
            listBox1.Items.Add("Byte per Sector : " + BytePerSector);
            SectorPerCluster = (int)LittleEndian(1, new byte[] { buff[13] }, typeof(int));
            listBox1.Items.Add("Sector per Cluster : " + SectorPerCluster.ToString());
            MFTStart = (long)LittleEndian(8, new byte[]{
                buff[48],buff[49],buff[50],buff[51],buff[52],buff[53],buff[54],buff[55]}, typeof(long));
            listBox1.Items.Add("MFT LCN : " + MFTStart);
        }
        else
            listBox1.Items.Add("No NTFS Valoume");

我想读MFT。我找到了它在分区上的偏移量。我用CreateFile API获得分区句柄,然后用ReadFile API从MBR获得MFT偏移量。我将结果与WinHex进行比较,结果是正确的。现在我想转移到分区上的MFT地址。我发现SetFilePointer API来做它。我使用SetFilePointer,但我得到了错误,而使用ReadFile(newAddress)

public static void ReadMFT(string DriveLetter, ulong MFTStart, int bytepersector, int sectorpercluster)
    {
        IntPtr handle = IntPtr.Zero;
        IntPtr newaddress = IntPtr.Zero;
        long MFTAddress = bytepersector * sectorpercluster * (long)MFTStart;
        string driveRoot = string.Concat("''''.''", DriveLetter);
        IntPtr hRoot = CreateFile(driveRoot,
            GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            IntPtr.Zero,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            IntPtr.Zero);
        **newaddress = SetFilePointer(hRoot, (ulong)MFTAddress, IntPtr.Zero, 0);**
        Console.WriteLine("hroot : " + hRoot.ToString());
        Console.WriteLine("MFTAddress : " + MFTAddress.ToString());
        Console.WriteLine("NewAddress : " + newaddress.ToString());
        if (hRoot.ToInt64() != INVALID_HANDLE_VALUE)
        {
            uint nread;
            byte[] buff = new byte[1024];
            if (**ReadFile(newaddress, buff, (uint)buff.Length, out nread, IntPtr.Zero)**)
                Console.WriteLine("Read successful");
            else
                Console.WriteLine("Read unsuccessful");
        }
        while (true)
        {
            //read other MFT Record
            break;
        }
    }

SetFilePointerEx API to read MFT

我可以看到以下错误:

  • 您没有检查CreateFile的返回值是否成功或失败。
  • 您将错误的东西传递给ReadFile的第一个参数。您需要将句柄传递给文件。
  • 您使用了您不想要的重叠I/O,并且不能与编组的byte[]缓冲区一起工作。将IntPtr.Zero传递给lpOverlappednull,这取决于您的P/invoke是如何声明的。
  • ReadFile不返回句柄,它返回一个布尔值,表示函数调用成功。
  • 你绝对不能从托管代码中调用GetLastError。而是调用Marshal.GetLastWin32Error。在该方法的文档中解释了原因。除非之前的API调用失败,否则不要调用Marshal.GetLastWin32Error。您没有检查SetFilePointerEx是否成功。和ReadFile一样,它返回一个布尔值来指示成功或失败。

根据文档(Physical Disks and Volumes),如果要访问分区表,必须使用DeviceIoControl。限制和要求适用于Windows Vista。

从文档链接的一个例子:调用DeviceIoControl.