用C实现磁盘分析

20171010010507711.jpg

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

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

分区/驱动器Drive类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#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) {
}
};

主程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
#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");
}
/*------------------------------------------------------------------------------------------------*/

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
主分区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 字节
-------------------------------------------



----- 感谢阅读 -----