necesito ayuda sobre MFT y su analisis en C

Iniciado por Belial & Grimoire, 26 Enero 2014, 06:33 AM

0 Miembros y 1 Visitante están viendo este tema.

Belial & Grimoire

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

Código (vbnet) [Seleccionar]
  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

.