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;
}
}
我可以看到以下错误:
- 您没有检查
CreateFile
的返回值是否成功或失败。 - 您将错误的东西传递给
ReadFile
的第一个参数。您需要将句柄传递给文件。 - 您使用了您不想要的重叠I/O,并且不能与编组的
byte[]
缓冲区一起工作。将IntPtr.Zero
传递给lpOverlapped
或null
,这取决于您的P/invoke是如何声明的。 -
ReadFile
不返回句柄,它返回一个布尔值,表示函数调用成功。 你绝对不能从托管代码中调用
GetLastError
。而是调用Marshal.GetLastWin32Error
。在该方法的文档中解释了原因。除非之前的API调用失败,否则不要调用Marshal.GetLastWin32Error
。您没有检查SetFilePointerEx
是否成功。和ReadFile
一样,它返回一个布尔值来指示成功或失败。根据文档(Physical Disks and Volumes),如果要访问分区表,必须使用DeviceIoControl
。限制和要求适用于Windows Vista。
从文档链接的一个例子:调用DeviceIoControl.