hola
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
#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){
printf("error device\n");
}
NTFS_VOLUME_DATA_BUFFER ntfsData;
bresul = DeviceIoControl(hDevice,FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsData, sizeof(NTFS_VOLUME_DATA_BUFFER), &junk, (LPOVERLAPPED)NULL );
printf("Numero de serie = %ld\n", ntfsData.VolumeSerialNumber);
printf("Numero de sectores = %ld\n", ntfsData.NumberSectors);
printf("Total clusters = %ld\n", ntfsData.TotalClusters);
printf("Clusters libres = %ld\n", ntfsData.FreeClusters);
printf("Total reservados = %ld\n", ntfsData.TotalReserved);
printf("Bytes por sector = %ld\n", ntfsData.BytesPerSector);
printf("Bytes por cluster = %ld\n", ntfsData.BytesPerCluster);
printf("Bytes por segmeto de archivo = %ld\n", ntfsData.BytesPerFileRecordSegment);
printf("Cluster por segmento de archivo = %ld\n", ntfsData.ClustersPerFileRecordSegment);
printf("Longitud de datos validos MFT = %ld\n", ntfsData.MftValidDataLength);
printf("Inicio de LCN = %ld\n", ntfsData.MftStartLcn);
printf("Inicio mirror de LCN = %ld\n", ntfsData.Mft2StartLcn);
printf("Zona de Inicio MFT= %ld\n", ntfsData.MftZoneStart);
printf("Zona final MFT = %ld\n", ntfsData.MftZoneEnd);
getchar();
}
O si alguien tiene conocimientos en VB.NET que me pueda ayudar a traducir el codigo a C tambien me ayudaria bastante
Public Sub FindHDFiles(ByVal Drive As String)
Drive = Drive.TrimEnd("\")
Try
Dim dinfo = My.Computer.FileSystem.GetDriveInfo(Drive & "\")
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
ARKDDA = New DirectDriveIO(Drive & "\")
Catch
MsgBox("Could not access drive.", MsgBoxStyle.Critical, "ERROR")
Exit Sub
End Try
Drive = Drive.TrimEnd("\")
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
ToolStripStatusLabel1.Text = "Finding files in " & Drive & "\..."
Button1.Enabled = False
Button2.Enabled = False
ComboBox1.Enabled = False
Button3.Enabled = False
CheckBox2.Enabled = False
LastDrive = Drive
If CheckBox2.Checked Then Bitmap = ReadBitmap(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