#include <stdio.h>
#include <stdlib.h>
#include <stdint.h> // 包含用于定义定宽整数类型的头文件
#include <iostream>
#ifdef _WIN32 // Windows平台
#include <windows.h>
#define FILE_HANDLE HANDLE
#define OPEN_FILE(path) CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)
#define CLOSE_FILE(handle) CloseHandle(handle)
#define READ_FILE(handle, buffer, size, bytesRead, offset) ReadFile(handle, buffer, size, bytesRead, NULL)
#define SEEK_FILE(handle, offset) SetFilePointerEx(handle, offset, NULL, FILE_BEGIN)
#else // Linux平台
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#define FILE_HANDLE int
#define OPEN_FILE(path) open(path, O_RDONLY)
#define CLOSE_FILE(handle) close(handle)
#define READ_FILE(handle, buffer, size, offset) pread(handle, buffer, size, offset)
#define SEEK_FILE(handle, offset) lseek(handle, offset, SEEK_SET)
#endif
class FileIO {
public:
FILE_HANDLE file;
bool Open(const char* path) {
file = OPEN_FILE(path);
if (file == NULL) {
perror("Failed to open file");
return false;
}
return true;
}
void Close() {
if (file != NULL) {
CLOSE_FILE(file);
file = NULL;
}
}
bool Read(char* buffer, size_t size, uint64_t offset) {
#ifdef _WIN32
LARGE_INTEGER offsetInt;
offsetInt.QuadPart = offset;
if (!SEEK_FILE(file, offsetInt)) {
perror("Failed to seek file");
return false;
}
#else
if (SEEK_FILE(file, offset) == (off_t)-1) {
perror("Failed to seek file");
return false;
}
#endif
uint64_t bytesRead = 0;
#ifdef _WIN32
if (!READ_FILE(file, buffer, size, (DWORD*)&bytesRead, NULL)) {
#else
bytesRead = READ_FILE(file, buffer, size, offset);
if (bytesRead == -1) {
#endif
perror("Failed to read from file");
return false;
}
return true;
}
};
int CheckGPT(char *pBuff)
{
if ((pBuff[0x400] != 0) && (pBuff[0x410] != 0))
{
return 1;
}
return 0;
}
uint64_t GetDBROffset(char *pBuff)
{
if (CheckGPT(pBuff))
{
return *(uint64_t*)(pBuff+0x420);
}
else
{
return *(int*)(pBuff+0x1C6);
}
}
int GetSctSize(char *pBuff)
{
return *(short*)(pBuff+0x0B);
}
int GetSctOfCluster(char *pBuff)
{
return *(char*)(pBuff+0x0D);
}
uint64_t GetMFTOffset(char *pBuff)
{
uint64_t mftClusterAddr = *(uint64_t*)(pBuff+0x30);
return mftClusterAddr*GetSctOfCluster(pBuff);
}
uint64_t GetInfoByMFTNo(const char *pBuff, int nSctSize, int nSctOfCluster, int mftNo, int* pBitmapSize)
{
// mft size = 1K.
uint64_t bitmapMFTOffset = mftNo * 1024;
// Find bitmap run list, sizeof(MFT_HEADER)=0x38
uint64_t attrOffset = bitmapMFTOffset + 0x38;
while (*(unsigned char*)(pBuff+attrOffset) != 0x80)
{
int attrSize = *(int*)(pBuff+attrOffset+4);
attrOffset += attrSize;
}
int runListOffset = *(short*)(pBuff + attrOffset + 0x20);
int buffSizeBytes = (*(unsigned char*)(pBuff + attrOffset + runListOffset))&0x0F;
int buffCluserAddrBytes =(*(unsigned char*)(pBuff + attrOffset + runListOffset))>>4;
int dataBuffSize = 0;
for (int i = 0; i < buffSizeBytes; i++)
{
int val = *(unsigned char*)(pBuff + attrOffset + runListOffset + 1 + i);
dataBuffSize += (val<<(i*8));
}
*pBitmapSize = dataBuffSize*nSctOfCluster;
uint64_t dataClusterOffset = 0;
for (int i = 0; i < buffCluserAddrBytes; i++)
{
int val = *(unsigned char*)(pBuff + attrOffset + runListOffset + 1 + buffSizeBytes + i);
dataClusterOffset += (val<<(i*8));
}
return dataClusterOffset*nSctOfCluster;
}
int main(int argc, char* argv[])
{
FileIO file;
#ifdef _WIN32
const char* filePath = "\\\\.\\PhysicalDrive1";
#else
const char* filePath = "/dev/sda";
#endif
if (!file.Open(filePath)) {
return 1;
}
const int bufferSize = 40960;
char* pBuff = new char[bufferSize]();
// Read GPT/MBR
if (!file.Read(pBuff, bufferSize, 0))
{
printf("Failed to read disk");
return 1;
}
std::cout<<(CheckGPT(pBuff) ? "It is GPT" : "It is MBR" )<<std::endl;
std::cout<<"DBROffset:"<<GetDBROffset(pBuff)<<std::endl;
// Read DBR
int dbrOffset = GetDBROffset(pBuff);
if (!file.Read(pBuff, bufferSize, dbrOffset*512))
{
printf("Failed to read disk");
return 2;
}
uint64_t mftOffset = GetMFTOffset(pBuff);
int nSctSize = GetSctSize(pBuff);
int nSctOfCluster = GetSctOfCluster(pBuff);
std::cout<<"Sector Size:"<<nSctSize<<std::endl;
std::cout<<"Sector of Cluster:"<<nSctOfCluster<<std::endl;
std::cout<<"MFT Sector offset:"<<mftOffset<<std::endl;
// Read MFT
if (!file.Read(pBuff, bufferSize, (mftOffset + dbrOffset)*nSctSize))
{
printf("Failed to read disk");
return 2;
}
int nLogFileSize = 0;
int mftNoOfLogFile = 2;
uint64_t logFileOffset = GetInfoByMFTNo(pBuff, nSctSize, nSctOfCluster, mftNoOfLogFile, &nLogFileSize);
std::cout<<"LogFile sector offset:"<<logFileOffset<<std::endl;
std::cout<<"LogFile size:"<<nLogFileSize*nSctSize<<std::endl;
int nBitmapSize = 0;
int mftNoOfBitmap = 6;
uint64_t bitmapOffset = GetInfoByMFTNo(pBuff, nSctSize, nSctOfCluster, mftNoOfBitmap, &nBitmapSize);
std::cout<<"Bitmap sector offset:"<<bitmapOffset<<std::endl;
std::cout<<"Bitmap size:"<<nBitmapSize*nSctSize<<std::endl;
return 0;
}