由于实验需要写一个分区表的分析程序,时间比较多就写了个适用于GPT和 MBR分区的通用程序

没啥特别的亮点,主要还是可以通用地分析磁盘分区以及适用两种磁盘格式 本程序是字符界面,之前的是图形化界面,规划得有点丑,就不献丑了 自带分析、提取数据函数,若想继续分析其他也可在此基础上添加。在此只演示GPT下的FAT32分区分析 注:需管理员权限运行,否则无法得到分区信息

分区/驱动器Drive类

#pragma once
#include<string>
#include<string.h>
#include<windows.h>
using namespace std;
enum DriveType {
    NTFS, FAT32, GPT, UNKNOWN
};
class Drive {
public:
//通用属性

    DriveType type;
    int cluster;        //单位:扇区
    int sector;
    string label;       //卷标
    bool active;

    //Bytes
    long long offset;
    long long size;
    TCHAR msg[512];
//FAT32属性
    int reversedSector;
    int FATSector;

    //Bytes
    long long rootOffset;
    long long FATOffest;
//NTFS属性
    //待补充
    Drive(void) {
        active = false;
        memset(msg, -1, sizeof(msg));
    }
    ~Drive(void) {
    }
};

主程序

#include <stdio.h>
#include<windows.h>
#include<String>
#include<Vector>
#include"Drive.h"

using namespace std;

#define NULL_16 (unsigned char *)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
#define NULL_8  (unsigned char *)"\x00\x00\x00\x00\x00\x00\x00\x00"
#define NULL_4 (unsigned char *)"\x00\x00\x00\x00"
#define NULL_2 (unsigned char *)"\x00\x00"


//读取磁盘在此修改
#define __READ "\\\\.\\PHYSICALDRIVE0"

#define EFI_FLAG (unsigned char *)"EFI PART"
#define NTFS_SYMBOL (unsigned char *)"NTFS    "
#define FAT32_SYMBOL (unsigned char *)"MSDOS5.0"

#define PARTITION_FLAG_LEN 8
#define OFFSET_DPT 446
#define SECTOR_LEN  512

long LODWORD(long long a);
long HIDWORD(long long a);
double ConvertToGB(long long size);
double ConvertToMB(long long size);
double ConvertToKB(long long size);
void ComfortableDataExpress(long long a,TCHAR * str);
double ComfortableData(long long a);
unsigned long long HexStringToLong(unsigned char * a,int len);

void TranslateData(unsigned char * a,int len, unsigned char * b,bool Remove_zero=0);

void Analysis_GPT(long long offset ,int show_analysis=0);
DriveType Analysis_Partition_Type(unsigned char *a ,int show_analysis=0);
void Analysis_DPT(unsigned char *a ,int show_analysis=0,bool extendFlag=0,long long posOffset=0);
DWORD ReadDisk(unsigned char* &out,long start,long High,DWORD size,int pos=0);
bool Check(unsigned char * a,unsigned char *  str,int len=4);

static vector<Drive>DriveList;
static bool GPT_FLAG=0,MBR_FLAG=0,exFlag=1;;    //磁盘类型
static long long MainExtenedOffset=0;


int main()
{
    char buff[512];
    unsigned char* a;
    ReadDisk(a,NULL,NULL,512);
    printf("\n主分区DPT分析:\n");
    Analysis_DPT(&a[OFFSET_DPT],1,0,NULL);
    printf("分区个数:%d\n",DriveList.size());
    printf("FAT32磁盘信息如下:\n");
    printf("    -------------------------------------------\n");
    for(int i=0;i<DriveList.size();i++)
        {
            if(DriveList[i].type==FAT32)
            {
                printf("    分区序号:%d\n",i);
                ComfortableDataExpress(DriveList[i].size,buff);
                printf("    分区大小: %s  \n",buff );
                printf("    分区偏移:%I64d 字节\n",DriveList[i].offset);
                printf("    簇:%d 个扇区\n",DriveList[i].cluster);
                printf("    保留扇区:%d 个\n",DriveList[i].reversedSector);
                printf("    FAT表偏移:%I64d 字节\n",DriveList[i].FATOffest);
                printf("    FAT表扇区:%d 个\n",DriveList[i].FATSector);
                printf("    根目录偏移:%I64d 字节\n",DriveList[i].rootOffset);
                printf("    -------------------------------------------\n");

            }
        }
    return 0;
}



/*------------------------------------------------------------------------------------------------*/
//进制转换
double ConvertToGB(long long size)
 {
     return size/1024.0/1024.0/1024.0;
 }
 double ConvertToMB(long long size)
 {
     return size/1024.0/1024.0;
 }
 double ConvertToKB(long long size)
 {
     return size/1024.0;
 }

void ComfortableDataExpress(long long a,TCHAR * str)
{
    if(ConvertToGB(a)>=1)sprintf(str,TEXT("%.2lf GB"),ConvertToGB(a));
    else if(ConvertToMB(a)>=1)sprintf(str,TEXT("%.2lf MB"),ConvertToMB(a));
    else sprintf(str,TEXT("%.2lf KB"),ConvertToKB(a));
}

double ComfortableData(long long a)
{
    if(ConvertToGB(a)>=1)return ConvertToGB(a);
    else if(ConvertToMB(a)>=1)return ConvertToMB(a);
    else return ConvertToKB(a);
}
long LODWORD(long long a)
{
    return (DWORD)a;
}
long HIDWORD(long long a)
{
    return (a>>32);
}


/*------------------------------------------------------------------------------------------------*/
//读取硬盘

DWORD ReadDisk(unsigned char* &out,long start,long High,DWORD size,int pos)
{
    /*OVERLAPPED over = { 0 };
    over.Offset = start;  */

    HANDLE handle = CreateFile(
        TEXT(__READ),
        GENERIC_READ,
        FILE_SHARE_READ|FILE_SHARE_WRITE,
        0,
        OPEN_EXISTING,
        0,
        0);
    if (handle == INVALID_HANDLE_VALUE)return 0;
    unsigned char* buffer = new unsigned char[size + 1];
    SetFilePointer(handle, start, &High, pos);
    DWORD readsize;
    if (ReadFile(handle, buffer, size, &readsize, NULL) == 0)
    {
        CloseHandle(handle);
        return 0;
    }
    buffer[size] = 0;
    out = buffer;


    return size;
}
/*------------------------------------------------------------------------------------------------*/



/*------------------------------------------------------------------------------------------------*/
//判断字符

 bool Check(unsigned char * a,unsigned char * str,int len)
 {
     for(int i=0;i<len;i++)
     {
         if(a[i]!=str[i])return false;
     }
     return true;
 }

/*------------------------------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------------------------*/
//十六进制字符转十进制数字
 unsigned long long HexStringToLong(unsigned char * a,int len)
 {
    unsigned long long num=0,t=0;
    for(int i =0;i<len;i++)
    {
        t=a[i];
        for(int j=i;j>0;j--){
            t*=256;
        }
        num+=t;
    }
    return num;
 }

//获取字符信息
 void TranslateData(unsigned char * a,int len, unsigned char * b,bool Remove_zero)
   {
        int zero_num=0;
        int char_num=0;
        if (len){
            for (int i = 0; i < len; i++){
                if (Remove_zero)
                {
                    if(a[i]==0)
                    {zero_num++;
                    continue;
                    }
                }
                char_num++;
                b[i-zero_num]=a[i];
            }
        }
        b[char_num]=0;
        sprintf((char *)b,"%s",b);
  }

 /*------------------------------------------------------------------------------------------------*/



/*------------------------------------------------------------------------------------------------*/
//分析DPT

 void Analysis_DPT(unsigned char *a ,int show_analysis,bool extenedFlag,long long posOffset)
 {
     TCHAR buff[512];
     unsigned char * BUFFER;
     long long offset=0;
     unsigned char * partition_sector;
     for (int i=0;i<4;i++)
     {
         if(Check(&a[i*16],NULL_16,16))break;
         else
         {
              if (show_analysis)
            {
                printf(" 活动分区标志: %02x |", a[0+i*16]);

                printf(" 分区类型标志: %02x |", a[4+i*16]);

                printf(" 偏移扇区: %I64d |", HexStringToLong(&a[8+i*16],4));

                ComfortableDataExpress(512*HexStringToLong(&a[12+i*16],4),buff);
                printf(" 磁盘大小: %s  |\n",buff );
            }

             offset=512*HexStringToLong(&a[8+i*16],4);
             if(Check(&a[4+i*16],(unsigned char *)"\x0f",1) || (i==1 && extenedFlag))
             {

                 if(exFlag){
                    MainExtenedOffset = 512*HexStringToLong(&a[8+i*16],4);
                    exFlag=0;
                 }
                 if(extenedFlag)offset+=MainExtenedOffset;

                 printf(" 偏移扇区: %I64d |\n", HexStringToLong(&a[8+i*16],4));

                 ReadDisk(partition_sector,LODWORD(offset),HIDWORD(offset),SECTOR_LEN);
                 Analysis_DPT(&partition_sector[OFFSET_DPT],1,1,offset);
                 return ;
             }


             if(extenedFlag)offset+=posOffset;
             ReadDisk(partition_sector,LODWORD(offset),HIDWORD(offset),SECTOR_LEN);
             //ShowData(partition_sector,512);
             if(Analysis_Partition_Type(partition_sector)!=GPT)
             {
                 printf("\n检测到该磁盘为MBR磁盘!\n\n");
                 Drive drive;
                 //活动分区标志
                 if(a[0+i*16]==0x80)drive.active=true;
                 //盘位移
                 if(!extenedFlag)
                 offset=512*HexStringToLong(&a[8+i*16],4);//计算逻辑分区的位移
                 drive.offset=offset;//存入位移
                 drive.size=512*HexStringToLong(&a[12+i*16],4);//盘大小

                 //开始跳转至盘分析

                 ReadDisk(BUFFER,LODWORD(offset),HIDWORD(offset),1*SECTOR_LEN);
                 drive.type = Analysis_Partition_Type(BUFFER);
                 switch(drive.type)
                 {
                 case NTFS:
                     break;
                 case FAT32:
                    drive.cluster = HexStringToLong(&BUFFER[0x0d],1);
                    drive.reversedSector=HexStringToLong(&BUFFER[0x0e],2);
                    drive.FATOffest = drive.reversedSector * SECTOR_LEN;
                    drive.FATSector = HexStringToLong(&BUFFER[0x24],4);
                    drive.rootOffset = drive.FATOffest + SECTOR_LEN * drive.FATSector *2;
                    break;
                 case UNKNOWN:
                     break;
                 }
                 DriveList.push_back(drive);
             }

             else
             {
                 printf("\n检测到该磁盘为GPT磁盘!\n\n");
                 Analysis_GPT(offset,1);
             }
         }
     }
  }


 /*------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------*/


 DriveType Analysis_Partition_Type(unsigned char *a ,int show_analysis)
 {

         if(Check(a,EFI_FLAG,PARTITION_FLAG_LEN))
         {
             GPT_FLAG=1;
             if(show_analysis)printf(" 磁盘为GPT磁盘!\n");
             return GPT;
         }
         else if(Check(&a[3],NTFS_SYMBOL,PARTITION_FLAG_LEN))
         {
             if(show_analysis)printf("分区格式:%-10s|","NTFS");
             return NTFS;
         }
         else if(Check(&a[3],FAT32_SYMBOL,PARTITION_FLAG_LEN))
         {
             if(show_analysis)printf("分区格式:%-10s|","FAT32");
             return FAT32;
         }
         else
         {
             if(show_analysis)printf("分区格式:%-10s|","UNKNOWN");
             return UNKNOWN;
         }
     }

/*------------------------------------------------------------------------------------------------*/




/*------------------------------------------------------------------------------------------------*/
 //解析GPT头

 void Analysis_GPT(long  long offset,int show_analysis)
 {

    TCHAR buff[512];
    unsigned char * GPT_PT;
    unsigned char * BUFFER;
    ReadDisk(GPT_PT,LODWORD(offset),HIDWORD(offset),32*SECTOR_LEN);
    long long GPT_Offset =  HexStringToLong(&GPT_PT[0x48],8)*512;
    long long Offset=0;
    ReadDisk(GPT_PT,LODWORD(GPT_Offset),HIDWORD(GPT_Offset),32*SECTOR_LEN);

    for(int i=0;i<128;i++)
    {
        if(Check(&GPT_PT[i*128],NULL_16,16))break;
        Drive drive;
        //初始化GPT磁盘的分区属性

        //分区大小
        drive.size = 512*(HexStringToLong(&GPT_PT[i*128+0x28],8)-HexStringToLong(&GPT_PT[i*128+0x20],8) );
        //GPT头自带72字节的分区信息
        TranslateData(&GPT_PT[i*128+0x38],72,(unsigned char *)drive.msg,true);
        //分区偏移
        Offset=512*(HexStringToLong(&GPT_PT[i*128+0x20],8));
        drive.offset = Offset;
        ReadDisk(BUFFER,LODWORD(Offset),HIDWORD(Offset),1*SECTOR_LEN);
        drive.type = Analysis_Partition_Type(BUFFER);
        switch(drive.type)
        {
        case NTFS:
            break;
        case FAT32:

            drive.cluster = HexStringToLong(&BUFFER[0x0d],1);
            drive.reversedSector=HexStringToLong(&BUFFER[0x0e],2);
            drive.FATOffest = drive.reversedSector * SECTOR_LEN;
            drive.FATSector = HexStringToLong(&BUFFER[0x24],4);
            drive.rootOffset = drive.FATOffest + SECTOR_LEN * drive.FATSector *2;
            break;
        case UNKNOWN:
            break;

        }

        DriveList.push_back(drive);

        if(show_analysis)
            {

                ComfortableDataExpress(512*(HexStringToLong(&GPT_PT[i*128+0x28],8)-HexStringToLong(&GPT_PT[i*128+0x20],8) ),buff );
                printf(" 磁盘大小: %-10s  |",buff );
                TranslateData(&GPT_PT[i*128+0x38],72,(unsigned char *)buff,true);
                Offset=512*(HexStringToLong(&GPT_PT[i*128+0x20],8));
                ReadDisk(BUFFER,LODWORD(Offset),HIDWORD(Offset),1*SECTOR_LEN);
                Analysis_Partition_Type(BUFFER,1);
                printf(" GPT磁盘分区信息: %-30s |\n",buff);

            }
    }
    printf("\n");
 }

 /*------------------------------------------------------------------------------------------------*/

输出展示

输出结果:

主分区DPT分析:
 活动分区标志: 00 | 分区类型标志: ee | 偏移扇区: 1 | 磁盘大小: 465.76 GB  |

检测到该磁盘为GPT磁盘!

 磁盘大小: 500.00 MB   |分区格式:FAT32     | GPT磁盘分区信息: EFI system partition           |
 磁盘大小: 40.00 MB    |分区格式:FAT32     | GPT磁盘分区信息: Basic data partition           |
 磁盘大小: 128.00 MB   |分区格式:UNKNOWN   | GPT磁盘分区信息: Microsoft reserved partition   |
 磁盘大小: 750.00 MB   |分区格式:NTFS      | GPT磁盘分区信息: Basic data partition           |
 磁盘大小: 188.96 GB   |分区格式:NTFS      | GPT磁盘分区信息: Basic data partition           |
 磁盘大小: 126.95 GB   |分区格式:NTFS      | GPT磁盘分区信息: Basic data partition           |
 磁盘大小: 69.71 GB    |分区格式:NTFS      | GPT磁盘分区信息: Basic data partition           |
 磁盘大小: 1023.50 KB  |分区格式:NTFS      | GPT磁盘分区信息:                                |
 磁盘大小: 40.00 GB    |分区格式:UNKNOWN   | GPT磁盘分区信息: Basic data partition           |
 磁盘大小: 300.00 MB   |分区格式:UNKNOWN   | GPT磁盘分区信息: Basic data partition           |
 磁盘大小: 8.46 GB     |分区格式:NTFS      | GPT磁盘分区信息: Microsoft recovery partition   |
 磁盘大小: 30.00 GB    |分区格式:UNKNOWN   | GPT磁盘分区信息:                                |

分区个数:12
FAT32磁盘信息如下:
    -------------------------------------------
    分区序号:0
    分区大小: 500.00 MB  
    分区偏移:1048576 字节
    簇:8 个扇区
    保留扇区:6206
    FAT表偏移:3177472 字节
    FAT表扇区:993
    根目录偏移:4194304 字节
    -------------------------------------------
    分区序号:1
    分区大小: 40.00 MB  
    分区偏移:525336576 字节
    簇:1 个扇区
    保留扇区:7038
    FAT表偏移:3603456 字节
    FAT表扇区:577
    根目录偏移:4194304 字节
    -------------------------------------------