Apis para leer disco en forma RAW y acceder a archivos eliminados

Iniciado por achernar_, 24 Junio 2011, 22:28 PM

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

achernar_

Esta es mi duda hace un tiempo que estoy buscando y no termino de dar en el clavo. Hasta donde se los archivos no desaparecen por completo de un disco cuando son eliminados. Quiero acceder al disco en forma RAW para buscar archivos eliminados. No quiero un programa para hacerlo, quiero programarlo yo. Se que con el api CreateFile() se puede acceder a una unidad de disco, después estoy dando vueltas y no termino de leer nada del disco. Busco info sobre DeviceIOControl() pero no me termina siendo clara y hay muchas constantes para las que no encuentro los valores numericos ni muchos ejemplos de codigo (eso seria lo mejor) después creo haber visto y perdido un ejemplo donde utilizaba las mismas funciones para leer un fichero pero con el disco. En fin un ejemplo seria lo mejor pero una ayuda cualquiera sea no seria despreciada. Gracias.
Tengo una habilidad sorprendente para hacer cosas que no sorprenden.

[Zero]

#1
Muevo el tema a programación C/C++ que creo que encaja mejor. No tengo mucha idea sobre como hacer lo que pides, pero creo que en modo usuario no sería posible, y digo creo. A ver si en programación pueden ayudarte mejor.

No sé si lo viste, pero alomejor te puede ayudar esto:
http://msdn.microsoft.com/en-us/library/aa363147(v=vs.85).aspx

Saludos

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche

Karman

#2
fijate esta clase, la saqué no recuerdo de donde... je  :P

#include <windows.h>
#include <stdio.h>
#include <ctype.h>

#define VWIN32_DIOC_DOS_IOCTL     1 // specified MS-DOS device I/O ctl - Interrupt 21h Function 4400h - 4411h
#define VWIN32_DIOC_DOS_INT25     2 // Absolute Disk Read command - Interrupt 25h
#define VWIN32_DIOC_DOS_INT26     3 // Absolute Disk Write command - Interrupt 25h
#define VWIN32_DIOC_DOS_INT13     4 // Interrupt 13h commands
#define VWIN32_DIOC_SIMCTRLC      5 // Simulate Ctrl-C
#define VWIN32_DIOC_DOS_DRIVEINFO 6 // Interrupt 21h Function 730X commands

#define CARRY_FLAG 1

#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER (DWORD)-1
#endif

typedef struct _DISKIO {
 DWORD  dwStartSector;   // starting logical sector number
 WORD   wSectors;        // number of sectors
 DWORD  dwBuffer;        // address of read/write buffer
} DISKIO, * PDISKIO;

typedef struct _DIOC_REGISTERS
{
 DWORD reg_EBX;
 DWORD reg_EDX;
 DWORD reg_ECX;
 DWORD reg_EAX;
 DWORD reg_EDI;
 DWORD reg_ESI;
 DWORD reg_Flags;
} DIOC_REGISTERS, *PDIOC_REGISTERS;

struct partial_boot_sector_info{
 LPSTR Fs;
 DWORD FsOffs;
 DWORD SerialOffs;
};

class DiskSectorRW{
public:
 virtual bool Open(char *vol) = 0;
 virtual void Close() = 0;
 virtual bool ReadSector(DWORD sector, char *Buffer, int sectorSize = 512) = 0;
 virtual bool WriteSector(DWORD sector, char *buffer, int sectorSize = 512) = 0;
};

class DiskSectorWinNT : public DiskSectorRW
{
private:
 HANDLE m_hDisk;
public:
 bool Open(char *vol);
 void Close();
 bool ReadSector (DWORD sector, char *Buffer, int sectorSize = 512);
 bool WriteSector(DWORD sector, char *Buffer, int sectorSize = 512);
};

class DiskSectorWin9x : public DiskSectorRW
{
private:
 HANDLE m_hVmm32;
 bool m_bOpened;
 char m_chDrive;
 BYTE m_nDriveNo;
 bool m_bW9xOsr2AndAbove;
 bool m_bUseLocking;
public:

 DiskSectorWin9x() : m_bUseLocking(false) { }
 bool Open(char *vol);
 void Close();

 bool ReadSector (DWORD sector, char *Buffer, int sectorSize = 512);
 bool WriteSector(DWORD sector, char *Buffer, int sectorSize = 512);

 static bool LockLogicalVolume (HANDLE hVWin32, BYTE   bDriveNum, BYTE   bLockLevel, WORD wPermissions);
 static bool UnlockLogicalVolume(HANDLE hVWin32, BYTE bDriveNum);

 static bool ReadLogicalSectors (HANDLE hDev, BYTE   bDrive, DWORD  dwStartSector, WORD wSectors, LPBYTE lpSectBuff);
 static bool WriteLogicalSectors (HANDLE hDev, BYTE   bDrive, DWORD  dwStartSector, WORD   wSectors, LPBYTE lpSectBuff);

 static bool NewReadSectors(HANDLE hDev, BYTE   bDrive, DWORD  dwStartSector, WORD   wSectors, LPBYTE lpSectBuff);
 static bool NewWriteSectors(HANDLE hDev, BYTE   bDrive, DWORD  dwStartSector, WORD   wSectors, LPBYTE lpSectBuff);

};

class DiskSector
{
private:
 DiskSectorRW *util;
public:
 DiskSector();
 ~DiskSector();
 bool Open(char *vol);
 void Close();
 bool ReadSector(DWORD sector, char *Buffer, int sectorSize = 512);
 bool WriteSector(DWORD sector, char *buffer, int sectorSize = 512);
};


#include "disk.h"

DiskSector::DiskSector()
{
 if (GetVersion() > 0x80000000)
   util = new DiskSectorWin9x;
 else
   util = new DiskSectorWinNT;
}

void DiskSector::Close()
{
 util->Close();
}

bool DiskSector::Open(char *vol)
{
 return util->Open(vol);
}

bool DiskSector::WriteSector(DWORD sector, char *Buffer, int sectorSize)
{
 return util->WriteSector(sector, Buffer, sectorSize);
}

bool DiskSector::ReadSector(DWORD sector, char *Buffer, int sectorSize)
{
 return util->ReadSector(sector, Buffer, sectorSize);
}

DiskSector::~DiskSector()
{
 delete util;
}

/***********************************************************/

bool DiskSectorWinNT::Open(char *vol)
{
 char szDrive[10];
 sprintf(szDrive, "\\\\.\\%c:", vol[0]);
 m_hDisk = ::CreateFile(
   szDrive,
   GENERIC_READ | GENERIC_WRITE,
   FILE_SHARE_READ | FILE_SHARE_WRITE,
   NULL,
   OPEN_EXISTING,
   0,
   NULL);
 return m_hDisk != INVALID_HANDLE_VALUE;
}

void DiskSectorWinNT::Close()
{
 if (m_hDisk != INVALID_HANDLE_VALUE)
   ::CloseHandle(m_hDisk);
}

bool DiskSectorWinNT::ReadSector (DWORD sector, char *Buffer, int sectorSize)
{
 DWORD read = 0;

 if (::SetFilePointer(m_hDisk, sector, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
   return false;

 if (!::ReadFile(m_hDisk, Buffer, sectorSize, &read, NULL))
   return false;
 return true;
}

bool DiskSectorWinNT::WriteSector(DWORD sector, char *Buffer, int sectorSize)
{
 DWORD wrote = 0;

 if (::SetFilePointer(m_hDisk, sector, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
   return false;

 if (!::WriteFile(m_hDisk, Buffer, sectorSize, &wrote, NULL))
   return false;

 return true;
}

/***********************************************************/

bool DiskSectorWin9x::Open(char *vol){
 m_bOpened = false;
 
 OSVERSIONINFOEX osvi = {0};
 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
 if (!::GetVersionEx((OSVERSIONINFO *)&osvi)){
   osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
   if (!::GetVersionEx ((OSVERSIONINFO *)&osvi))
     return false;
 }
 if (osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
   return false;

 m_chDrive  = toupper(vol[0]);
 m_nDriveNo = m_chDrive - 'A' + 1;

 char temp[10] = {0};
 sprintf(temp, "%c:\\", m_chDrive);

 if (::GetDriveType(temp) != DRIVE_FIXED)
   return false;

 m_bW9xOsr2AndAbove = (osvi.dwMajorVersion >= 4 && osvi.dwMinorVersion >= 10)
   ||
   (
     (osvi.dwBuildNumber == 4 && osvi.dwMinorVersion == 0) &&
     (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B')
   );

 m_hVmm32 = ::CreateFile(
   "\\\\.\\VWIN32",      // name
   0,                      // access mode
   0,                      // share mode
   NULL,           // security descriptor
   0,                   // ho to create
   FILE_FLAG_DELETE_ON_CLOSE, // file attributes
   NULL);          // handle to file with att to copy

 m_bOpened = (m_hVmm32 != INVALID_HANDLE_VALUE);

 return m_bOpened;
}

void DiskSectorWin9x::Close()
{
 if (m_bOpened)
   ::CloseHandle(m_hVmm32);
 m_bOpened = false;
}


bool DiskSectorWin9x::ReadLogicalSectors (HANDLE hDev,
                        BYTE   bDrive,
                        DWORD  dwStartSector,
                        WORD   wSectors,
                        LPBYTE lpSectBuff)
{
 BOOL           fResult;
 DWORD          cb;
 DIOC_REGISTERS reg = {0};
 DISKIO         dio = {0};

 dio.dwStartSector = dwStartSector;
 dio.wSectors      = wSectors;
 dio.dwBuffer      = (DWORD)lpSectBuff;

 reg.reg_EAX = bDrive - 1;    // Int 25h drive numbers are 0-based.
 reg.reg_EBX = (DWORD)&dio;   // Drive letter 0 = A, 1 = B  2 = C ect..
 reg.reg_ECX = 0xFFFF;        // use DISKIO struct

 fResult = ::DeviceIoControl(hDev, VWIN32_DIOC_DOS_INT25,
   &reg, sizeof(reg),
   &reg, sizeof(reg), &cb, 0);

 // Determine if the DeviceIoControl call and the read succeeded.
 fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);

 return fResult == TRUE;
}

bool DiskSectorWin9x::WriteLogicalSectors (HANDLE hDev,
                         BYTE   bDrive,
                         DWORD  dwStartSector,
                         WORD   wSectors,
                         LPBYTE lpSectBuff)
{
 BOOL           fResult;
 DWORD          cb;
 DIOC_REGISTERS reg = {0};
 DISKIO         dio = {0};

 dio.dwStartSector = dwStartSector;
 dio.wSectors      = wSectors;
 dio.dwBuffer      = (DWORD)lpSectBuff;

 reg.reg_EAX = bDrive - 1;    // Int 26h drive numbers are 0-based.
 reg.reg_EBX = (DWORD)&dio;
 reg.reg_ECX = 0xFFFF;        // use DISKIO struct

 fResult = ::DeviceIoControl(hDev, VWIN32_DIOC_DOS_INT26,
   &reg, sizeof(reg),
   &reg, sizeof(reg), &cb, 0);

 // Determine if the DeviceIoControl call and the write succeeded.
 fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);

 return fResult == TRUE;
}


bool DiskSectorWin9x::NewReadSectors(HANDLE hDev,
                   BYTE   bDrive,
                   DWORD  dwStartSector,
                   WORD   wSectors,
                   LPBYTE lpSectBuff)
{
 BOOL           fResult;
 DWORD          cb;
 DIOC_REGISTERS reg = {0};
 DISKIO         dio;

 dio.dwStartSector = dwStartSector;
 dio.wSectors      = wSectors;
 dio.dwBuffer      = (DWORD)lpSectBuff;

 reg.reg_EAX = 0x7305;   // Ext_ABSDiskReadWrite
 reg.reg_EBX = (DWORD)&dio;
 reg.reg_ECX = (DWORD)-1;
 reg.reg_EDX = bDrive;   // Int 21h, fn 7305h drive numbers are 1-based

 fResult = ::DeviceIoControl(hDev, VWIN32_DIOC_DOS_DRIVEINFO,
   &reg, sizeof(reg),
   &reg, sizeof(reg), &cb, 0);

 // Determine if the DeviceIoControl call and the read succeeded.
 fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);

 return fResult == TRUE;
}


bool DiskSectorWin9x::NewWriteSectors(HANDLE hDev,
                    BYTE   bDrive,
                    DWORD  dwStartSector,
                    WORD   wSectors,
                    LPBYTE lpSectBuff)
{
 BOOL           fResult;
 DWORD          cb;
 DIOC_REGISTERS reg = {0};
 DISKIO         dio;

 dio.dwStartSector = dwStartSector;
 dio.wSectors      = wSectors;
 dio.dwBuffer      = (DWORD)lpSectBuff;

 reg.reg_EAX = 0x7305;   // Ext_ABSDiskReadWrite
 reg.reg_EBX = (DWORD)&dio;
 reg.reg_ECX = (DWORD)-1;
 reg.reg_EDX = bDrive;   // Int 21h, fn 7305h drive numbers are 1-based

 reg.reg_ESI = 0x6001;   // Normal file data/write (See function
 // documentation for other values)


 fResult = ::DeviceIoControl(hDev, VWIN32_DIOC_DOS_DRIVEINFO,
   &reg, sizeof(reg),
   &reg, sizeof(reg), &cb, 0);

 // Determine if the DeviceIoControl call and the write succeeded.
 fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);

 return fResult == TRUE;
}

bool DiskSectorWin9x::LockLogicalVolume (HANDLE hVWin32,
                              BYTE   bDriveNum,
                              BYTE   bLockLevel,
                              WORD   wPermissions)
{
 BOOL           fResult;
 DIOC_REGISTERS regs = {0};
 BYTE           bDeviceCat;  // can be either 0x48 or 0x08
 DWORD          cb;

 bDeviceCat = 0x48;

ATTEMPT_AGAIN:
 // Set up the parameters for the call.
 regs.reg_EAX = 0x440D;
 regs.reg_EBX = MAKEWORD(bDriveNum, bLockLevel);
 regs.reg_ECX = MAKEWORD(0x4A, bDeviceCat);
 regs.reg_EDX = wPermissions;

 fResult = ::DeviceIoControl (hVWin32, VWIN32_DIOC_DOS_IOCTL,
   &regs, sizeof(regs), &regs, sizeof(regs),
   &cb, 0);

 fResult = fResult && !(regs.reg_Flags & CARRY_FLAG);
 if (!fResult && (bDeviceCat != 0x08)){
   bDeviceCat = 0x08;
   goto ATTEMPT_AGAIN;
 }

 return fResult == TRUE;
}

bool DiskSectorWin9x::UnlockLogicalVolume (HANDLE hVWin32, BYTE bDriveNum)
{
 BOOL           fResult;
 DIOC_REGISTERS regs = {0};
 BYTE           bDeviceCat;  // can be either 0x48 or 0x08
 DWORD          cb;
 bDeviceCat = 0x48;

ATTEMPT_AGAIN:
 regs.reg_EAX = 0x440D;
 regs.reg_EBX = bDriveNum;
 regs.reg_ECX = MAKEWORD(0x6A, bDeviceCat);
 fResult = ::DeviceIoControl (hVWin32, VWIN32_DIOC_DOS_IOCTL,
   &regs, sizeof(regs), &regs, sizeof(regs),
   &cb, 0);
 fResult = fResult && !(regs.reg_Flags & CARRY_FLAG);
 if (!fResult && (bDeviceCat != 0x08)){
   bDeviceCat = 0x08;
   goto ATTEMPT_AGAIN;
 }
 return fResult == TRUE;
}


bool DiskSectorWin9x::ReadSector (DWORD sector, char *Buffer, int sectorSize)
{
 if (!m_bOpened)
   return false;

 if (m_bUseLocking)
 {
   if (!LockLogicalVolume(m_hVmm32, m_nDriveNo, 1, 1))
     return false;

   if (!LockLogicalVolume(m_hVmm32, m_nDriveNo, 2, 0))
   {
     UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
     return false;
   }
 }

 bool bRet;
 if (m_bW9xOsr2AndAbove)
   bRet = NewReadSectors(m_hVmm32, m_nDriveNo, sector, 1, (LPBYTE)Buffer);
 else
   bRet = ReadLogicalSectors(m_hVmm32, m_nDriveNo, sector, 1, (LPBYTE)Buffer);

 if (m_bUseLocking)
 {
   UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
   UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
 }
 return bRet;
}

bool DiskSectorWin9x::WriteSector (DWORD sector, char *Buffer, int sectorSize)
{
 if (!m_bOpened)
   return false;

 if (!LockLogicalVolume(m_hVmm32, m_nDriveNo, 1, 1))
   return false;

 if (!LockLogicalVolume(m_hVmm32, m_nDriveNo, 2, 0))
 {
   UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
   return false;
 }

 if (!LockLogicalVolume(m_hVmm32, m_nDriveNo, 3, 0))
 {
   UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
   UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
   return false;
 }

 bool bRet;

 if (m_bW9xOsr2AndAbove)
   bRet = NewWriteSectors(m_hVmm32, m_nDriveNo, sector, 1, (LPBYTE) Buffer);
 else
   bRet = WriteLogicalSectors(m_hVmm32, m_nDriveNo, sector, 1, (LPBYTE) Buffer);

 UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
 UnlockLogicalVolume(m_hVmm32, m_nDriveNo);
 UnlockLogicalVolume(m_hVmm32, m_nDriveNo);

 return bRet;
}


S2

PD: cabe aclarar que tenes que tener permisos administrativos al usar el código.
PD2: con esto solo accedes al los datos raw del disco, luego tenes que analizar la cabecera de las particiones, detectar el tipo (FAT, NTFS) y según eso ver la lista de nodos de archivos... en google había visto algunos ejemplos hace un tiempo.

achernar_

Gracias. Voy a ver si puedo crear una dll y subirla en agradecimiento.  ;-)
Tengo una habilidad sorprendente para hacer cosas que no sorprenden.