Estoy tratando de crear un codigo para recuperar archivos borrados, vengo leyendo varios documentos y viendo varios codigos, poco a poco estoy comprendiendo como funciona, hasta ahora he logrado comprender en donde se encuentra la informacion de los archivos, sobre NTFS, MFT y clusters, y mas o menos como encontrar los archivos borrados, sobre sus atributos y despues de eso me faltaria saber como restaurar los archivos
he practicado y mas abajo pondre un codigo que hice analizando codigos que hay en la red, desafortunadamente para mi, la mayoria en funcionamiento los encuentro para VB, hay otros pero son muy elaborados usando incluso clases, pero a la mayoria he visto lo mismo
Ahora... mi problema es el siguiente, ¿de que forma puedo leer los datos de MFT?, ya tengo una forma de acceso pero no logro entender como hacen ese escaneo por los datos del archivo MFT para analizar los archivos que se encuentran en mi computadora, asi como los borrados
espero alguien me pueda ayudar diciendo que API, estructura o que operacion tendria que usar ahora para empezar el analisis en MFT, porfavor, porque ya no se por donde seguir o que mas se deba hacer
dejo el codigo que mencione, pero despues de aprender esto, que mas sigue?, perdon si estan mal escrito los printf pero los escribi asi de mal porque solo fue para entender de que sirve la estructura
por cierto, he visto que algunos utilizan DISK_GEOMETRY pero yo no lo vi necesario
tambien hay unas API que vi que utilizan por ejemplo FSCTL_ENUM_USN_DATA, FSCTL_QUERY_USN_JOURNAL
Esto es lo que he logrado entender y es parecido a una parte de VB.net
Código
#include <Windows.h> #include <winioctl.h> #include <stdio.h> #define FSCTL_GET_NTFS_VOLUME_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 25, METHOD_BUFFERED, FILE_ANY_ACCESS) #define zwpath L"\\\\.\\PhysicalDrive0" int main(int argc, char *argv[]){ HANDLE hDevice = INVALID_HANDLE_VALUE; BOOL bresul = FALSE; DWORD junk = 0; hDevice = CreateFileW(zwpath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(hDevice == INVALID_HANDLE_VALUE){ } NTFS_VOLUME_DATA_BUFFER ntfsData; bresul = DeviceIoControl(hDevice,FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsData, sizeof(NTFS_VOLUME_DATA_BUFFER), &junk, (LPOVERLAPPED)NULL ); }
O si alguien tiene conocimientos en VB.NET que me pueda ayudar a traducir el codigo a C tambien me ayudaria bastante
Código
Try If Not dinfo.IsReady Then MsgBox("Drive not ready.", MsgBoxStyle.Critical, "ERROR") Exit Sub End If If dinfo.DriveFormat <> "NTFS" Then MsgBox("This feature only works on NTFS volumes.", MsgBoxStyle.Critical, "ERROR") Exit Sub End If Catch MsgBox("Could not access drive.", MsgBoxStyle.Critical, "ERROR") Exit Sub End Try Dim diskhandle = CreateFile("\\?\" & Drive, EFileAccess.GENERIC_READ + EFileAccess.GENERIC_WRITE, EFileShare.FILE_SHARE_READ + EFileShare.FILE_SHARE_WRITE, Nothing, ECreationDisposition.OPEN_EXISTING, 0, Nothing) If diskhandle = 0 Then diskhandle = CreateFile("\\.\" & Drive, EFileAccess.GENERIC_READ + EFileAccess.GENERIC_WRITE, EFileShare.FILE_SHARE_READ + EFileShare.FILE_SHARE_WRITE, Nothing, ECreationDisposition.OPEN_EXISTING, 0, Nothing) If diskhandle = 0 Then MsgBox("Could not access drive.", MsgBoxStyle.Critical, "ERROR") Exit Sub End If End If Dim FSCTL_GET_NFTS_VOLUME_DATA = CTL_CODE(FILE_DEVICE.FILE_DEVICE_FILE_SYSTEM, 25, METHOD_BUFFERED, FILE_ANY_ACCESS) Dim buffer As NTFS_VOLUME_DATA_BUFFER DeviceIoControlNTFS(diskhandle, FSCTL_GET_NFTS_VOLUME_DATA, 0, 0, buffer, SizeOf(buffer), 0, 0) CloseHandle(diskhandle) Dim MFTAddress As Long = buffer.MftStartLcn * CLng(buffer.BytesPerCluster / buffer.BytesPerSector) Dim MFTEntrySize As Integer = buffer.BytesPerFileRecordSegment / buffer.BytesPerSector Dim NumberOfEntries As Long = buffer.MftValidDataLength / MFTEntrySize Dim Bytes(buffer.BytesPerCluster) As Byte Dim CurrEntryBytes(MFTEntrySize * buffer.BytesPerSector) As Byte Dim CurrEntry As New STANDARD_MFT_ENTRY Dim Type As Byte Dim Name As String Dim BaseAddr As Long Dim Parent As Integer Dim DoEventsCounter As Integer = 0 ListView1.Items.Clear() ListView2.Items.Clear() ProgressBar1.Value = 0 ProgressBar1.Maximum = buffer.MftValidDataLength / buffer.BytesPerFileRecordSegment Button1.Enabled = False Button2.Enabled = False ComboBox1.Enabled = False Button3.Enabled = False CheckBox2.Enabled = False LastDrive = Drive Dim BitmapBase As Long = MFTAddress + (MFTEntrySize * 0) Bytes = ARKDDA.ReadSectors(BitmapBase, MFTEntrySize) BaseAddr = MergeToInt(Bytes, &H14, &H15) 'The offset the the first attribute While Bytes(baseaddr) <> &H80 baseaddr = baseaddr + MergeToInt(Bytes, baseaddr + &H4, baseaddr + &H7) 'Add the length of the attribute to the base address to find the next attribute End While baseaddr = baseaddr + &H40 Dim Length As ULong = 0 Dim LenLen As Byte = 0 Dim Offset As ULong = 0 Dim OffLen As Byte = 0 Dim Path As String = "" Dim BaseAddr2 As ULong = 0 Dim FileSize As ULong = 0 Dim LoopCount As Integer = 0 Dim PartNum As Integer = 0 While Bytes(baseaddr) > 0 LenLen = Bytes(BaseAddr) And &HF OffLen = (Bytes(BaseAddr) And &HF0) / &H10 Length = MergeToInt(Bytes, BaseAddr + 1, BaseAddr + LenLen) Offset = Offset + MergeToInt(Bytes, BaseAddr + 1 + LenLen, BaseAddr + LenLen + OffLen) For Record = 0 To ((Length * buffer.BytesPerCluster) / buffer.BytesPerFileRecordSegment) - 1 DoEventsCounter = DoEventsCounter + 1 If DoEventsCounter >= 100 Then Application.DoEvents() DoEventsCounter = 0 End If Try If (PartNum + 1) >= (CurrEntryBytes.Count / buffer.BytesPerFileRecordSegment) Then CurrEntryBytes = ARKDDA.ReadSectors((Record * MFTEntrySize) + (Offset * (buffer.BytesPerCluster / buffer.BytesPerSector)), MFTEntrySize * 1024) BaseAddr2 = 0 PartNum = 0 Else 'CurrEntryBytes = ByteArrayPart(CurrEntryBytes, buffer.BytesPerFileRecordSegment, UBound(CurrEntryBytes)) 'BaseAddr2 = (((BaseAddr2 \ buffer.BytesPerFileRecordSegment) + 1) * buffer.BytesPerFileRecordSegment) PartNum = PartNum + 1 BaseAddr2 = PartNum * buffer.BytesPerFileRecordSegment End If If CurrEntryBytes(BaseAddr2) <> Asc("F") Then 'If CurrEntryBytes(0) <> Asc("F") Then GoTo dn End If Name = "" Parent = 5 Path = "" FileSize = 0 'Type = CurrEntryBytes(&H16) Type = CurrEntryBytes(&H16 + BaseAddr2) 'If Type = MFT_ENTRY_FILE_TYPE_FLAGS.DeletedDirectory Or Type = MFT_ENTRY_FILE_TYPE_FLAGS.DeletedFile Then If Type = MFT_ENTRY_FILE_TYPE_FLAGS.DeletedFile Then 'BaseAddr2 = BaseAddr2 + MergeToInt(CurrEntryBytes, &H14, &H15) 'The offset the the first attribute BaseAddr2 = BaseAddr2 + MergeToInt(CurrEntryBytes, BaseAddr2 + &H14, BaseAddr2 + &H15) 'The offset the the first attribute BaseAddr2 = BaseAddr2 + MergeToInt(CurrEntryBytes, BaseAddr2 + &H4, BaseAddr2 + &H7) 'Add the length of the attribute to the base address to find the next attribute Try Parent = MergeToInt(CurrEntryBytes, BaseAddr2 + &H18, BaseAddr2 + &H1D) Catch End Try Try If FileSize = 0 Then FileSize = MergeToInt(CurrEntryBytes, BaseAddr2 + &H48, BaseAddr2 + &H4F) If FileSize > 2 ^ 30 Then FileSize = 0 'If FileSize = 0 Then FileSize = MergeToInt(CurrEntryBytes, BaseAddr2 + &H40, BaseAddr2 + &H47) Catch End Try Try Name = System.Text.UnicodeEncoding.Unicode.GetString(ByteArrayPart(CurrEntryBytes, BaseAddr2 + &H5A, (BaseAddr2 + &H5A) + ((2 * CurrEntryBytes(BaseAddr2 + &H58)) - 2))) Catch End Try Try If Name.Contains("~") Then BaseAddr2 = BaseAddr2 + MergeToInt(CurrEntryBytes, BaseAddr2 + &H4, BaseAddr2 + &H7) 'Add the length of the attribute to the base address to find the next attribute If FileSize = 0 Then FileSize = MergeToInt(CurrEntryBytes, BaseAddr2 + &H48, BaseAddr2 + &H4F) If FileSize > 2 ^ 30 Then FileSize = 0 'If FileSize = 0 Then FileSize = MergeToInt(CurrEntryBytes, BaseAddr2 + &H40, BaseAddr2 + &H47) Name = System.Text.UnicodeEncoding.Unicode.GetString(ByteArrayPart(CurrEntryBytes, BaseAddr2 + &H5A, (BaseAddr2 + &H5A) + ((2 * CurrEntryBytes(BaseAddr2 + &H58)) - 2))) End If Catch End Try If Name.Length >= 75 Then Name = Mid(Name, 1, 74) & Mid(Name, 76, Name.Length - 75) If CheckBox1.Checked Then Try Path = GetFullPath2(Parent, MFTAddress, MFTEntrySize, buffer.BytesPerCluster) & "\" & Name Catch End Try End If If FileSize = 0 Then Try LoopCount = 0 While CurrEntryBytes(BaseAddr2) <> &H80 And LoopCount < 5 LoopCount = LoopCount + 1 BaseAddr2 = BaseAddr2 + MergeToInt(CurrEntryBytes, BaseAddr2 + &H4, BaseAddr2 + &H7) 'Add the length of the attribute to the base address to find the next attribute End While 'FileSize = MergeToInt(CurrEntryBytes, BaseAddr2 + &H28, BaseAddr2 + &H2F) 'If FileSize > 2 ^ 30 Then FileSize = MergeToInt(CurrEntryBytes, BaseAddr2 + &H38, BaseAddr2 + &H3F) If MergeToInt(CurrEntryBytes, BaseAddr2 + &HE, BaseAddr2 + &HF) = 1 Then 'It is recycled (filename at offset 0x30,file size at offset 0x10) FileSize = MergeToInt(CurrEntryBytes, BaseAddr2 + &H10, BaseAddr2 + &H13) 'Path = "" 'BaseAddr2 = BaseAddr2 + &H30 'While CurrEntryBytes(BaseAddr2) > 0 'Path = Path + ChrW(MergeToInt(CurrEntryBytes, BaseAddr2, BaseAddr2 + 1)) 'Path = Path + ChrW(CurrEntryBytes(BaseAddr2)) 'BaseAddr2 = BaseAddr2 + 2 'End While Else 'FileSize = 0 FileSize = MergeToInt(CurrEntryBytes, BaseAddr2 + &H30, BaseAddr2 + &H37) End If If FileSize > 2 ^ 30 Then FileSize = 0 Catch End Try End If If FileSize > 0 Then With ListView1.Items.Add(Name) If Not Path.Contains("SKIPTHISFILE") Then .SubItems.Add(Path) Else .SubItems.Add("") End If .SubItems.Add(FileSize) .SubItems.Add((Record * MFTEntrySize) + (Offset * (buffer.BytesPerCluster / buffer.BytesPerSector))) If CheckBox2.Checked Then Try .SubItems.Add(GetFileIntegrity((Record * MFTEntrySize) + (Offset * (buffer.BytesPerCluster / buffer.BytesPerSector)), buffer.BytesPerSector, buffer.BytesPerFileRecordSegment)) Catch .SubItems.Add("Unknown") End Try Else .SubItems.Add("") End If ListView2.Items.Add(.Clone) End With End If GoTo dn End If Catch End Try dn: Try ProgressBar1.Value = ProgressBar1.Value + 1 Catch End Try Next Record BaseAddr = BaseAddr + (1 + LenLen + OffLen) End While ProgressBar1.Value = 0 ToolStripStatusLabel1.Text = "" Button1.Enabled = True Button2.Enabled = True ComboBox1.Enabled = True Button3.Enabled = True CheckBox2.Enabled = True End Sub