Win32 Windows Volume Program and Code Example 23

 

 

 

Listing the Deleted Files from Master File Table (MFT)

 

The following program example uses undocumented Windows types that can be found in the Internet domain and a complete version is available as an open source used by Linux/UNIX to read the Windows NTFS MFT.

Create a new Win32 console application project and give a suitable project name.

 

Listing the Deleted Files from Master File Table (MFT) - creating a new Win32 console mode application project

 

Add the source file and give a suitable name.

 

 

 

Listing the Deleted Files from Master File Table (MFT) - adding a new C++ source file

 

Add the following source code.

 

// Not using winioctl.h lol!

#include <windows.h>

#include <stdlib.h>

#include <stdio.h>

#include ntfs.h

 

// Global variables

ULONG BytesPerFileRecord;

HANDLE hVolume;

BOOT_BLOCK bootb;

PFILE_RECORD_HEADER MFT;

 

// Template for padding

template <class T1, class T2> inline T1* Padd(T1* p, T2 n)

{

      return (T1*)((char *)p + n);

}

 

ULONG RunLength(PUCHAR run)

{

      wprintf(LIn RunLength()...\n);

      return (*run & 0xf) + ((*run >> 4) & 0xf) + 1;

}

 

LONGLONG RunLCN(PUCHAR run)

{

      LONG i = 0;

      UCHAR n1 = 0 , n2 = 0;

      LONGLONG lcn = 0;

 

      wprintf(LIn RunLCN()...\n);

      n1 = *run & 0xf;

      n2 = (*run >> 4) & 0xf;

 

      lcn = n2 == 0 ? 0 : CHAR(run[n1 + n2]);

     

      for (i = n1 + n2 - 1; i > n1; i--)

            lcn = (lcn << 8) + run[i];

      return lcn;

}

 

ULONGLONG RunCount(PUCHAR run)

{

      UCHAR n = *run & 0xf;

      ULONGLONG count = 0;

      ULONG i;

 

      wprintf(LIn RunCount()...\n);

     

      for (i = n; i > 0; i--)

            count = (count << 8) + run[i];

 

      return count;

}

 

BOOL FindRun(PNONRESIDENT_ATTRIBUTE attr, ULONGLONG vcn, PULONGLONG lcn, PULONGLONG count)

{

      PUCHAR run = NULL;

      *lcn = 0;

      ULONGLONG base = attr->LowVcn;

 

      wprintf(LIn FindRun()...\n);

 

      if (vcn < attr->LowVcn || vcn > attr->HighVcn)

            return FALSE;

 

      for(run = PUCHAR(Padd(attr, attr->RunArrayOffset));   *run != 0;  run += RunLength(run))

      {

            *lcn += RunLCN(run);

            *count = RunCount(run);

 

            if (base <= vcn && vcn < base + *count)

            {

                  *lcn = RunLCN(run) == 0 ? 0 : *lcn + vcn - base;

                  *count -= ULONG(vcn - base);

                  return TRUE;

            }

            else

                  base += *count;

      }

      return FALSE;

}

 

PATTRIBUTE FindAttribute(PFILE_RECORD_HEADER file,ATTRIBUTE_TYPE type, PWSTR name)

{

      PATTRIBUTE attr = NULL;

 

      wprintf(LFindAttribute() - Finding attributes...\n);

 

      for (attr = PATTRIBUTE(Padd(file, file->AttributesOffset));

            attr->AttributeType != -1;attr = Padd(attr, attr->Length))

      {

            if (attr->AttributeType == type)

            {

                  if (name == 0 && attr->NameLength == 0)

                        return attr;

                  if (name != 0 && wcslen(name) == attr->NameLength && _wcsicmp(name,

                        PWSTR(Padd(attr, attr->NameOffset))) == 0)

                  return attr;

            }

      }

      return 0;

}

 

VOID FixupUpdateSequenceArray(PFILE_RECORD_HEADER file)

{

      ULONG i = 0;

      PUSHORT usa = PUSHORT(Padd(file, file->Ntfs.UsaOffset));

      PUSHORT sector = PUSHORT(file);

     

      wprintf(LIn FixupUpdateSequenceArray()...\n);

      for (i = 1; i < file->Ntfs.UsaCount; i++)

      {

            sector[255] = usa[i];

            sector += 256;

      }

}

 

VOID ReadSector(ULONGLONG sector, ULONG count, PVOID buffer)

{

      ULARGE_INTEGER offset;

      OVERLAPPED overlap = {0};

      ULONG n;

 

      wprintf(LReadSector() - Reading the sector...\n);

      wprintf(LSector: %lu\n, sector);

 

      offset.QuadPart = sector * bootb.BytesPerSector;

      overlap.Offset = offset.LowPart;

      overlap.OffsetHigh = offset.HighPart;

      ReadFile(hVolume, buffer, count * bootb.BytesPerSector, &n, &overlap);

}

 

VOID ReadLCN(ULONGLONG lcn, ULONG count, PVOID buffer)

{

      wprintf(L\nReadLCN() - Reading the LCN, LCN: 0X%.8X\n, lcn);

      ReadSector(lcn * bootb.SectorsPerCluster,count * bootb.SectorsPerCluster, buffer);

}

 

// Non resident attributes

VOID ReadExternalAttribute(PNONRESIDENT_ATTRIBUTE attr,ULONGLONG vcn, ULONG count, PVOID buffer)

{

      ULONGLONG lcn, runcount;

      ULONG readcount, left;

      PUCHAR bytes = PUCHAR(buffer);

 

      wprintf(LReadExternalAttribute() - Reading the Non resident attributes...\n);

 

      for(left = count; left > 0; left -= readcount)

      {

            FindRun(attr, vcn, &lcn, &runcount);

            readcount = ULONG(min(runcount, left));

            ULONG n = readcount * bootb.BytesPerSector * bootb.SectorsPerCluster;

 

            if(lcn == 0)

                  memset(bytes, 0, n);

            else

            {

                  ReadLCN(lcn, readcount, bytes);

                  wprintf(LLCN: 0X%.8X\n, lcn);

            }          

            vcn += readcount;

            bytes += n;

      }

}

 

ULONG AttributeLength(PATTRIBUTE attr)

{

      wprintf(LIn AttributeLength()...\n);

      return attr->Nonresident == FALSE ? PRESIDENT_ATTRIBUTE(attr)->ValueLength : ULONG(PNONRESIDENT_ATTRIBUTE(attr)->DataSize);

}

 

ULONG AttributeLengthAllocated(PATTRIBUTE attr)

{

      wprintf(L\nIn AttributeLengthAllocated()...\n);

      return attr->Nonresident == FALSE ? PRESIDENT_ATTRIBUTE(attr)->ValueLength : ULONG(PNONRESIDENT_ATTRIBUTE(attr)->AllocatedSize);

}

 

VOID ReadAttribute(PATTRIBUTE attr, PVOID buffer)

{

      PRESIDENT_ATTRIBUTE rattr = NULL;

      PNONRESIDENT_ATTRIBUTE nattr = NULL;

 

      wprintf(LReadAttribute() - Reading the attributes...\n);

      if (attr->Nonresident == FALSE)

      {

            wprintf(LResident attribute...\n);

            rattr = PRESIDENT_ATTRIBUTE(attr);

            memcpy(buffer, Padd(rattr, rattr->ValueOffset), rattr->ValueLength);

      }

      else

      {

            wprintf(LNon-resident attribute...\n);

            nattr = PNONRESIDENT_ATTRIBUTE(attr);

            ReadExternalAttribute(nattr, 0, ULONG(nattr->HighVcn) + 1, buffer);

      }

}

 

VOID ReadVCN(PFILE_RECORD_HEADER file, ATTRIBUTE_TYPE type,ULONGLONG vcn, ULONG count, PVOID buffer)

{

      PATTRIBUTE attrlist = NULL;

      PNONRESIDENT_ATTRIBUTE attr = PNONRESIDENT_ATTRIBUTE(FindAttribute(file, type, 0));

 

      wprintf(LIn ReadVCN()...\n);

      if (attr == 0 || (vcn < attr->LowVcn || vcn > attr->HighVcn))

      {

            // Support for huge files

            attrlist = FindAttribute(file, AttributeAttributeList, 0);

            DebugBreak();

      }

      ReadExternalAttribute(attr, vcn, count, buffer);

}

 

VOID ReadFileRecord(ULONG index, PFILE_RECORD_HEADER file)

{

      ULONG clusters = bootb.ClustersPerFileRecord;

 

      wprintf(LReadFileRecord() - Reading the file records..\n);

      if (clusters > 0x80)

            clusters = 1;

 

      PUCHAR p = new UCHAR[bootb.BytesPerSector* bootb.SectorsPerCluster * clusters];

      ULONGLONG vcn = ULONGLONG(index) * BytesPerFileRecord/bootb.BytesPerSector/bootb.SectorsPerCluster;

      ReadVCN(MFT, AttributeData, vcn, clusters, p);

      LONG m = (bootb.SectorsPerCluster * bootb.BytesPerSector/BytesPerFileRecord) - 1;

      ULONG n = m > 0 ? (index & m) : 0;

      memcpy(file, p + n * BytesPerFileRecord, BytesPerFileRecord);

      delete [] p;

      FixupUpdateSequenceArray(file);

}

 

VOID LoadMFT()

{

      wprintf(LIn LoadMFT() - Loading MFT...\n);

 

      BytesPerFileRecord = bootb.ClustersPerFileRecord < 0x80

            ? bootb.ClustersPerFileRecord* bootb.SectorsPerCluster

            * bootb.BytesPerSector: 1 << (0x100 - bootb.ClustersPerFileRecord);

 

      wprintf(L\nBytes Per File Record = %u\n\n, BytesPerFileRecord);

      wprintf(L======THESE INFO ARE NOT ACCURATE FOR DISPLAY LOL!=====\n);

      wprintf(Lbootb.BootSectors = %u\n, bootb.BootSectors);

      wprintf(Lbootb.BootSignature = %u\n, bootb.BootSignature);

      wprintf(Lbootb.BytesPerSector = %u\n, bootb.BytesPerSector);

      wprintf(Lbootb.ClustersPerFileRecord = %u\n, bootb.ClustersPerFileRecord);

      wprintf(Lbootb.ClustersPerIndexBlock = %u\n, bootb.ClustersPerIndexBlock);

      wprintf(Lbootb.Code = %u\n, bootb.Code);

      wprintf(Lbootb.Format = %u\n, bootb.Format);

      wprintf(Lbootb.Jump = %u\n, bootb.Jump);

      wprintf(Lbootb.Mbz1 = %u\n, bootb.Mbz1);

      wprintf(Lbootb.Mbz2 = %u\n, bootb.Mbz2);

      wprintf(Lbootb.Mbz3 = %u\n, bootb.Mbz3);

      wprintf(Lbootb.MediaType = 0X%X\n, bootb.MediaType);

      wprintf(Lbootb.Mft2StartLcn = 0X%.8X\n, bootb.Mft2StartLcn);

      wprintf(Lbootb.MftStartLcn = 0X%.8X\n, bootb.MftStartLcn);

      wprintf(Lbootb.NumberOfHeads = %u\n, bootb.NumberOfHeads);

      wprintf(Lbootb.PartitionOffset = %lu\n, bootb.PartitionOffset);

      wprintf(Lbootb.SectorsPerCluster = %u\n, bootb.SectorsPerCluster);

      wprintf(Lbootb.SectorsPerTrack = %u\n, bootb.SectorsPerTrack);

      wprintf(Lbootb.TotalSectors = %lu\n, bootb.TotalSectors);

      wprintf(Lbootb.VolumeSerialNumber = 0X%.8X%.8X\n\n, bootb.VolumeSerialNumber.HighPart, bootb.VolumeSerialNumber.HighPart);

 

 

      MFT = PFILE_RECORD_HEADER(new UCHAR[BytesPerFileRecord]);

 

      ReadSector((bootb.MftStartLcn)*(bootb.SectorsPerCluster), (BytesPerFileRecord)/(bootb.BytesPerSector), MFT);

      FixupUpdateSequenceArray(MFT);

}

 

BOOL bitset(PUCHAR bitmap, ULONG i)

{

      return (bitmap[i >> 3] & (1 << (i & 7))) != 0;

}

 

VOID FindDeleted()

{

      PATTRIBUTE attr = FindAttribute(MFT, AttributeBitmap, 0);

      PUCHAR bitmap = new UCHAR[AttributeLengthAllocated(attr)];

      ReadAttribute(attr, bitmap);

      ULONG n = AttributeLength(FindAttribute(MFT, AttributeData, 0))/BytesPerFileRecord;

 

      wprintf(LFindDeleted() - Finding the deleted files...\n);

 

      PFILE_RECORD_HEADER file = PFILE_RECORD_HEADER(new UCHAR[BytesPerFileRecord]);

 

      for(ULONG i = 0; i < n; i++)

      {

            if (bitset(bitmap, i))

                  continue;

 

            ReadFileRecord(i, file);

 

            if (file->Ntfs.Type == 'ELIF' && (file->Flags & 1) == 0)

            {

                  attr = FindAttribute(file, AttributeFileName, 0);

                  if (attr == 0)

                        continue;

 

                  PFILENAME_ATTRIBUTE name = PFILENAME_ATTRIBUTE(Padd(attr,PRESIDENT_ATTRIBUTE(attr)->ValueOffset));

 

                  // * means the width/precision was supplied in the argument list

                  // ws ~ wide character string

                  wprintf(L\n%10u %u %.*s\n\n, i, int(name->NameLength), int(name->NameLength), name->Name);

                  // To see the very long output short, uncomment the following line

                  // _getwch();

            }

      }

}

 

VOID DumpData(ULONG index, WCHAR* filename)

{

      PATTRIBUTE attr = NULL;

      HANDLE hFile = NULL;

      PFILE_RECORD_HEADER file = PFILE_RECORD_HEADER(new UCHAR[BytesPerFileRecord]);

      ULONG n;

 

 

      ReadFileRecord(index, file);

 

      wprintf(LDumping the data...\n);

 

      if (file->Ntfs.Type != 'ELIF')

            return;

 

      attr = FindAttribute(file, AttributeData, 0);

      if (attr == 0)

            return;

 

      PUCHAR buf = new UCHAR[AttributeLengthAllocated(attr)];

      ReadAttribute(attr, buf);

     

      hFile = CreateFile((LPCWSTR)filename, GENERIC_WRITE, 0, 0,CREATE_ALWAYS, 0, 0);

     

      if(hFile == INVALID_HANDLE_VALUE)

      {

            wprintf(LCreateFile() failed, error %u\n, GetLastError());

            return;

      }

     

      if(WriteFile(hFile, buf, AttributeLength(attr), &n, 0) == 0)

      {

            wprintf(LWriteFile() failed, error %u\n, GetLastError());

            return;

      }

 

      CloseHandle(hFile);

      delete [] buf;

}

 

int wmain(int argc, WCHAR **argv)

{

      // Default primary partition

      WCHAR drive[] = L\\\\.\\C:;

      ULONG n;

     

      // No argument supplied

      if (argc < 2)

      {

            wprintf(LUsage:\n);

            wprintf(LFind deleted files: %s <primary_partition>\n, argv[0]);

            wprintf(LRead the file records: %s <primary_partition> <index> <file_name>\n, argv[0]);

            // Just exit

            exit(1);

      }    

      // More code to stop the user from entering the non-primary partition

 

      // Read the user input

      drive[4] = *argv[1];

     

      // Get the handle to the primary partition/volume/physical disk

      hVolume = CreateFile(

            drive,

            GENERIC_READ,

            FILE_SHARE_READ | FILE_SHARE_WRITE,

            0,

            OPEN_EXISTING,

            0,

            0);

 

      if(hVolume == INVALID_HANDLE_VALUE)

      {

            wprintf(LCreateFile() failed, error %u\n, GetLastError());

            exit(1);

      }

 

      // Reads data from the specified input/output (I/O) device - volume/physical disk

      if(ReadFile(hVolume, &bootb, sizeof bootb, &n, 0) == 0)

      {

            wprintf(LReadFile() failed, error %u\n, GetLastError());

            exit(1);

      }

 

      LoadMFT();

     

      // The primary partition supplied else

      // default C:\ will be used

      if (argc == 2)

            FindDeleted();

     

      // Need to convert the recovered filename to long file name

      // Not implemented here. It is 8.3 file name format

 

      // The primary partition, index and file name to be recovered

      // are supplied

      if (argc == 4)

            DumpData(wcstoul(argv[2], 0, 0), argv[3]);

 

      CloseHandle(hVolume);

      return 0;

}

 

Add the ntfs.h header file.

 

 

Listing the Deleted Files from Master File Table (MFT) - adding ntfs.h header file to the existing project

 

Add the following source code.

 

///ntfs.h

// These types are not available in MSDN documentation

// It is taken from Internet and Linux documentation

// and not the whole code...

// Copyrights and trademarks must go to the original

// authors and/or publishers

typedef struct {

      ULONG Type;

      USHORT UsaOffset;

      USHORT UsaCount;

      USN Usn;

} NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER;

 

typedef struct {

      NTFS_RECORD_HEADER Ntfs;

      USHORT SequenceNumber;

      USHORT LinkCount;

      USHORT AttributesOffset;

      USHORT Flags; // 0x0001 = InUse, 0x0002= Directory

      ULONG BytesInUse;

      ULONG BytesAllocated;

      ULONGLONG BaseFileRecord;

      USHORT NextAttributeNumber;

} FILE_RECORD_HEADER, *PFILE_RECORD_HEADER;

 

typedef enum {

      AttributeStandardInformation = 0x10,

      AttributeAttributeList = 0x20,

      AttributeFileName = 0x30,

      AttributeObjectId = 0x40,

      AttributeSecurityDescriptor = 0x50,

      AttributeVolumeName = 0x60,

      AttributeVolumeInformation = 0x70,

      AttributeData = 0x80,

      AttributeIndexRoot = 0x90,

      AttributeIndexAllocation = 0xA0,

      AttributeBitmap = 0xB0,

      AttributeReparsePoint = 0xC0,

      AttributeEAInformation = 0xD0,

      AttributeEA = 0xE0,

      AttributePropertySet = 0xF0,

      AttributeLoggedUtilityStream = 0x100

} ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE;

 

typedef struct {

      ATTRIBUTE_TYPE AttributeType;

      ULONG Length;

      BOOLEAN Nonresident;

      UCHAR NameLength;

      USHORT NameOffset;

      USHORT Flags; // 0x0001 = Compressed

      USHORT AttributeNumber;

} ATTRIBUTE, *PATTRIBUTE;

 

typedef struct {

      ATTRIBUTE Attribute;

      ULONG ValueLength;

      USHORT ValueOffset;

      USHORT Flags; // 0x0001 = Indexed

} RESIDENT_ATTRIBUTE, *PRESIDENT_ATTRIBUTE;

 

typedef struct {

      ATTRIBUTE Attribute;

      ULONGLONG LowVcn;

      ULONGLONG HighVcn;

      USHORT RunArrayOffset;

      UCHAR CompressionUnit;

      UCHAR AlignmentOrReserved[5];

      ULONGLONG AllocatedSize;

      ULONGLONG DataSize;

      ULONGLONG InitializedSize;

      ULONGLONG CompressedSize; // Only when compressed

} NONRESIDENT_ATTRIBUTE, *PNONRESIDENT_ATTRIBUTE;

 

typedef struct {

      ULONGLONG CreationTime;

      ULONGLONG ChangeTime;

      ULONGLONG LastWriteTime;

      ULONGLONG LastAccessTime;

      ULONG FileAttributes;

      ULONG AlignmentOrReservedOrUnknown[3];

      ULONG QuotaId;                // NTFS 3.0

      ULONG SecurityId;       // NTFS 3.0

      ULONGLONG QuotaCharge;  // NTFS 3.0

      USN Usn;                      // NTFS 3.0

} STANDARD_INFORMATION, *PSTANDARD_INFORMATION;

 

typedef struct {

      ATTRIBUTE_TYPE AttributeType;

      USHORT Length;

      UCHAR NameLength;

      UCHAR NameOffset;

      ULONGLONG LowVcn;

      ULONGLONG FileReferenceNumber;

      USHORT AttributeNumber;

      USHORT AlignmentOrReserved[3];

} ATTRIBUTE_LIST, *PATTRIBUTE_LIST;

 

typedef struct {

      ULONGLONG DirectoryFileReferenceNumber;         //

      ULONGLONG CreationTime;       // Saved when filename last changed

      ULONGLONG ChangeTime;         //

      ULONGLONG LastWriteTime;      //

      ULONGLONG LastAccessTime;     //

      ULONGLONG AllocatedSize;      //

      ULONGLONG DataSize;                 //

      ULONG FileAttributes;         //

      ULONG AlignmentOrReserved;    //

      UCHAR NameLength;             //

      UCHAR NameType;                     // 0x01 = Long, 0x02 = Short

      WCHAR Name[1];                      //

} FILENAME_ATTRIBUTE, *PFILENAME_ATTRIBUTE;

 

typedef struct {

      GUID ObjectId;

      union {

            struct {

                  GUID BirthVolumeId;

                  GUID BirthObjectId;

                  GUID DomainId;

            };

            UCHAR ExtendedInfo[48];

      };

} OBJECTID_ATTRIBUTE, *POBJECTID_ATTRIBUTE;

 

typedef struct {

      ULONG Unknown[2];

      UCHAR MajorVersion;

      UCHAR MinorVersion;

      USHORT Flags;

} VOLUME_INFORMATION, *PVOLUME_INFORMATION;

 

typedef struct {

      ULONG EntriesOffset;

      ULONG IndexBlockLength;

      ULONG AllocatedSize;

      ULONG Flags; // 0x00 = Small directory, 0x01 = Large directory

} DIRECTORY_INDEX, *PDIRECTORY_INDEX;

 

typedef struct {

      ULONGLONG FileReferenceNumber;

      USHORT Length;

      USHORT AttributeLength;

      ULONG Flags; // 0x01 = Has trailing VCN, 0x02 = Last entry

      // FILENAME_ATTRIBUTE Name;

      // ULONGLONG Vcn; // VCN in IndexAllocation of earlier entries

} DIRECTORY_ENTRY, *PDIRECTORY_ENTRY;

 

typedef struct {

      ATTRIBUTE_TYPE Type;

      ULONG CollationRule;

      ULONG BytesPerIndexBlock;

      ULONG ClustersPerIndexBlock;

      DIRECTORY_INDEX DirectoryIndex;

} INDEX_ROOT, *PINDEX_ROOT;

 

typedef struct {

      NTFS_RECORD_HEADER Ntfs;

      ULONGLONG IndexBlockVcn;

      DIRECTORY_INDEX DirectoryIndex;

} INDEX_BLOCK_HEADER, *PINDEX_BLOCK_HEADER;

 

typedef struct {

      ULONG ReparseTag;

      USHORT ReparseDataLength;

      USHORT Reserved;

      UCHAR ReparseData[1];

} REPARSE_POINT, *PREPARSE_POINT;

 

typedef struct {

      ULONG EaLength;

      ULONG EaQueryLength;

} EA_INFORMATION, *PEA_INFORMATION;

 

typedef struct {

      ULONG NextEntryOffset;

      UCHAR Flags;

      UCHAR EaNameLength;

      USHORT EaValueLength;

      CHAR EaName[1];

      // UCHAR EaData[];

} EA_ATTRIBUTE, *PEA_ATTRIBUTE;

 

typedef struct {

      WCHAR AttributeName[64];

      ULONG AttributeNumber;

      ULONG Unknown[2];

      ULONG Flags;

      ULONGLONG MinimumSize;

      ULONGLONG MaximumSize;

} ATTRIBUTE_DEFINITION, *PATTRIBUTE_DEFINITION;

 

#pragma pack(push, 1)

 

typedef struct {

      UCHAR Jump[3];

      UCHAR Format[8];

      USHORT BytesPerSector;

      UCHAR SectorsPerCluster;

      USHORT BootSectors;

      UCHAR Mbz1;

      USHORT Mbz2;

      USHORT Reserved1;

      UCHAR MediaType;

      USHORT Mbz3;

      USHORT SectorsPerTrack;

      USHORT NumberOfHeads;

      ULONG PartitionOffset;

      ULONG Reserved2[2];

      ULONGLONG TotalSectors;

      ULONGLONG MftStartLcn;

      ULONGLONG Mft2StartLcn;

      ULONG ClustersPerFileRecord;

      ULONG ClustersPerIndexBlock;

      LARGE_INTEGER VolumeSerialNumber;

      UCHAR Code[0x1AE];

      USHORT BootSignature;

 

} BOOT_BLOCK, *PBOOT_BLOCK;

 

#pragma pack(pop)

 

 

Build and run the project. The following screenshot is an output sample.

 

Listing the Deleted Files from Master File Table (MFT) - sample output without any argument supplied

 

The following sample outputs run with the primary partition supplied as an argument.

 

Listing the Deleted Files from Master File Table (MFT) - sample output with primary partition as the argument

 

Listing the Deleted Files from Master File Table (MFT) - sample output showing the deleted files found in MFT

 

To save all the deleted file names you may want to redirect the output into a text file as shown below.

 

Listing the Deleted Files from Master File Table (MFT) - redirecting output into a text file

 

 

Then open the text file using any unformatted text editor such as WordPad.

 

Listing the Deleted Files from Master File Table (MFT) - text file that contains the console application output

 

 

Listing the Deleted Files from Master File Table (MFT) - sample output with MFT information and list of deleted files

 

Next we will try to recover a file. We got the file name and index from the previous output.

 

Listing the Deleted Files from Master File Table (MFT) - sample program running to recover a text file

 

The following is a sample output.

 

Listing the Deleted Files from Master File Table (MFT) - the text file should be recovered

 

Next, the recovered file should be stored in the project’s Debug folder.

 

Listing the Deleted Files from Master File Table (MFT) - the recovered file stored under the project's Debug folder

 

 

Listing the Deleted Files from Master File Table (MFT) - the content of the recovered text file

 

 

  < Windows Volume 22 | Win32 Programming Index | Windows Volume Index | Windows Volume 24 >