... | ... |
@@ -40,6 +40,7 @@ |
40 | 40 |
#include "default.h" |
41 | 41 |
#include "iowrap.h" |
42 | 42 |
#include "mbr.h" |
43 |
+#include "gpt.h" |
|
43 | 44 |
|
44 | 45 |
#include "htmlnorm.h" |
45 | 46 |
#include "entconv.h" |
... | ... |
@@ -312,7 +313,7 @@ cli_file_t cli_filetype2(fmap_t *map, const struct cl_engine *engine, cli_file_t |
312 | 312 |
/* raw dmgs must be a multiple of 512 */ |
313 | 313 |
if ((map->len % 512) == 0 && map->len > 512) { |
314 | 314 |
/* check if detected MBR is protective on GPT */ |
315 |
- if (0 == memcmp(rbuff, "EFI PART", 8)) { |
|
315 |
+ if (gpt_detect_size(map) != 0) { |
|
316 | 316 |
cli_dbgmsg("Recognized GUID Partition Table file\n"); |
317 | 317 |
return CL_TYPE_GPT; |
318 | 318 |
} |
... | ... |
@@ -68,12 +68,37 @@ static void gpt_printName(uint16_t name[], const char* msg); |
68 | 68 |
static void gpt_printGUID(uint8_t GUID[], const char* msg); |
69 | 69 |
static int gpt_prtn_intxn(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize); |
70 | 70 |
|
71 |
-int cli_scangpt(cli_ctx *ctx) |
|
71 |
+/* returns 0 on failing to detect sectorsize */ |
|
72 |
+size_t gpt_detect_size(fmap_t *map) |
|
73 |
+{ |
|
74 |
+ unsigned char *buff; |
|
75 |
+ |
|
76 |
+ buff = (unsigned char*)fmap_need_off_once(map, 512, 8); |
|
77 |
+ if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8)) |
|
78 |
+ return 512; |
|
79 |
+ |
|
80 |
+ buff = (unsigned char*)fmap_need_off_once(map, 1024, 8); |
|
81 |
+ if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8)) |
|
82 |
+ return 1024; |
|
83 |
+ |
|
84 |
+ buff = (unsigned char*)fmap_need_off_once(map, 2048, 8); |
|
85 |
+ if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8)) |
|
86 |
+ return 2048; |
|
87 |
+ |
|
88 |
+ buff = (unsigned char*)fmap_need_off_once(map, 4096, 8); |
|
89 |
+ if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8)) |
|
90 |
+ return 4096; |
|
91 |
+ |
|
92 |
+ return 0; |
|
93 |
+} |
|
94 |
+ |
|
95 |
+/* attempts to detect sector size is input as 0 */ |
|
96 |
+int cli_scangpt(cli_ctx *ctx, size_t sectorsize) |
|
72 | 97 |
{ |
73 | 98 |
struct gpt_header phdr, shdr; |
74 | 99 |
enum GPT_SCANSTATE state = INVALID; |
75 | 100 |
int ret = 0; |
76 |
- size_t sectorsize, maplen; |
|
101 |
+ size_t maplen; |
|
77 | 102 |
off_t pos = 0; |
78 | 103 |
|
79 | 104 |
gpt_parsemsg("The beginning of something big: GPT parsing\n"); |
... | ... |
@@ -84,7 +109,14 @@ int cli_scangpt(cli_ctx *ctx) |
84 | 84 |
} |
85 | 85 |
|
86 | 86 |
/* sector size calculatation */ |
87 |
- sectorsize = GPT_DEFAULT_SECTOR_SIZE; |
|
87 |
+ if (sectorsize == 0) { |
|
88 |
+ sectorsize = gpt_detect_size((*ctx->fmap)); |
|
89 |
+ cli_errmsg("cli_scangpt: detected %u sector size\n", sectorsize); |
|
90 |
+ } |
|
91 |
+ if (sectorsize == 0) { |
|
92 |
+ cli_errmsg("cli_scangpt: could not detemine sector size\n"); |
|
93 |
+ return CL_EFORMAT; |
|
94 |
+ } |
|
88 | 95 |
|
89 | 96 |
/* size of total file must be a multiple of the sector size */ |
90 | 97 |
maplen = (*ctx->fmap)->real_len; |
... | ... |
@@ -395,7 +427,7 @@ static int gpt_validate_header(cli_ctx *ctx, struct gpt_header hdr, size_t secto |
395 | 395 |
} |
396 | 396 |
|
397 | 397 |
/* check that valid table entry size */ |
398 |
- if (hdr.tableEntrySize != GPT_PARTITION_ENTRY_SIZE) { |
|
398 |
+ if (hdr.tableEntrySize != sizeof(struct gpt_partition_entry)) { |
|
399 | 399 |
cli_dbgmsg("cli_scangpt: cannot parse gpt with partition entry sized %u\n", |
400 | 400 |
hdr.tableEntrySize); |
401 | 401 |
return CL_EFORMAT; |
... | ... |
@@ -32,10 +32,8 @@ |
32 | 32 |
* values. Sector size for GPT can be found by the offset the GPT header |
33 | 33 |
* signature is located (marking the beginning of the second sector. |
34 | 34 |
*/ |
35 |
-#define GPT_DEFAULT_SECTOR_SIZE 512 |
|
36 |
-#define GPT_PARTITION_ENTRY_SIZE 128 |
|
37 |
- |
|
38 | 35 |
#define GPT_SIGNATURE 0x4546492050415254ULL |
36 |
+#define GPT_SIGNATURE_STR "EFI PART" |
|
39 | 37 |
#define GPT_PRIMARY_HDR_LBA 1 |
40 | 38 |
#define GPT_HDR_RESERVED 0 |
41 | 39 |
|
... | ... |
@@ -95,6 +93,7 @@ struct gpt_partition_entry { |
95 | 95 |
#pragma pack |
96 | 96 |
#endif |
97 | 97 |
|
98 |
-int cli_scangpt(cli_ctx *ctx); |
|
98 |
+size_t gpt_detect_size(fmap_t *map); |
|
99 |
+int cli_scangpt(cli_ctx *ctx, size_t sectorsize); |
|
99 | 100 |
|
100 | 101 |
#endif |
... | ... |
@@ -75,27 +75,31 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl |
75 | 75 |
|
76 | 76 |
int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen) { |
77 | 77 |
struct mbr_boot_record mbr; |
78 |
+ off_t mbr_base = 0; |
|
79 |
+ size_t sectorsize = 512; |
|
78 | 80 |
|
79 |
- if (len < 512) { |
|
81 |
+ if (len < sectorsize) { |
|
80 | 82 |
return CL_EFORMAT; |
81 | 83 |
} |
82 | 84 |
|
83 |
- memcpy(&mbr, buff+MBR_BASE_OFFSET, sizeof(mbr)); |
|
85 |
+ mbr_base = sectorsize - sizeof(struct mbr_boot_record); |
|
86 |
+ memcpy(&mbr, buff+mbr_base, sizeof(mbr)); |
|
84 | 87 |
mbr_convert_to_host(&mbr); |
85 | 88 |
|
86 | 89 |
//mbr_printbr(&mbr); |
87 | 90 |
|
88 |
- return mbr_check_mbr(&mbr, maplen, MBR_SECTOR_SIZE); |
|
91 |
+ return mbr_check_mbr(&mbr, maplen, sectorsize); |
|
89 | 92 |
} |
90 | 93 |
|
91 |
-int cli_scanmbr(cli_ctx *ctx) |
|
94 |
+/* sets sectorsize to default value if specfied to be 0 */ |
|
95 |
+int cli_scanmbr(cli_ctx *ctx, size_t sectorsize) |
|
92 | 96 |
{ |
93 | 97 |
struct mbr_boot_record mbr; |
94 | 98 |
enum MBR_STATE state = SEEN_NOTHING; |
95 | 99 |
int ret = CL_CLEAN; |
96 |
- off_t pos = 0, partoff = 0; |
|
100 |
+ off_t pos = 0, mbr_base = 0, partoff = 0; |
|
97 | 101 |
unsigned i = 0, prtncount = 0; |
98 |
- size_t sectorsize, maplen, partsize; |
|
102 |
+ size_t maplen, partsize; |
|
99 | 103 |
|
100 | 104 |
mbr_parsemsg("The start of something magnificant: MBR parsing\n"); |
101 | 105 |
|
... | ... |
@@ -105,7 +109,10 @@ int cli_scanmbr(cli_ctx *ctx) |
105 | 105 |
} |
106 | 106 |
|
107 | 107 |
/* sector size calculation, actual value is OS dependent */ |
108 |
- sectorsize = MBR_SECTOR_SIZE; |
|
108 |
+ if (sectorsize == 0) |
|
109 |
+ sectorsize = MBR_SECTOR_SIZE; |
|
110 |
+ |
|
111 |
+ mbr_base = sectorsize - sizeof(struct mbr_boot_record); |
|
109 | 112 |
|
110 | 113 |
/* size of total file must be a multiple of the sector size */ |
111 | 114 |
maplen = (*ctx->fmap)->real_len; |
... | ... |
@@ -116,7 +123,7 @@ int cli_scanmbr(cli_ctx *ctx) |
116 | 116 |
} |
117 | 117 |
|
118 | 118 |
/* sector 0 (first sector) is the master boot record */ |
119 |
- pos = (MBR_SECTOR * sectorsize) + MBR_BASE_OFFSET; |
|
119 |
+ pos = (MBR_SECTOR * sectorsize) + mbr_base; |
|
120 | 120 |
|
121 | 121 |
/* read the master boot record */ |
122 | 122 |
if (fmap_readn(*ctx->fmap, &mbr, pos, sizeof(mbr)) != sizeof(mbr)) { |
... | ... |
@@ -134,7 +141,7 @@ int cli_scanmbr(cli_ctx *ctx) |
134 | 134 |
} |
135 | 135 |
|
136 | 136 |
/* MBR is valid, examine bootstrap code */ |
137 |
- ret = cli_map_scan(*ctx->fmap, 0, MBR_BASE_OFFSET, ctx, CL_TYPE_FILE_ANY); |
|
137 |
+ ret = cli_map_scan(*ctx->fmap, 0, sectorsize, ctx, CL_TYPE_ANY); |
|
138 | 138 |
if ((ret != CL_CLEAN) && |
139 | 139 |
!((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) { |
140 | 140 |
return ret; |
... | ... |
@@ -206,12 +213,14 @@ static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size |
206 | 206 |
struct mbr_boot_record ebr; |
207 | 207 |
enum MBR_STATE state = SEEN_NOTHING; |
208 | 208 |
int ret = CL_CLEAN; |
209 |
- off_t pos = 0, logiclba = 0, extoff = 0, partoff = 0; |
|
209 |
+ off_t pos = 0, mbr_base = 0, logiclba = 0, extoff = 0, partoff = 0; |
|
210 | 210 |
size_t partsize, extsize; |
211 | 211 |
unsigned i = 0, j = 0; |
212 | 212 |
|
213 | 213 |
ebr_parsemsg("The start of something exhausting: EBR parsing\n"); |
214 | 214 |
|
215 |
+ mbr_base = sectorsize - sizeof(struct mbr_boot_record); |
|
216 |
+ |
|
215 | 217 |
logiclba = 0; |
216 | 218 |
extoff = extlba * sectorsize; |
217 | 219 |
extsize = extlbasize * sectorsize; |
... | ... |
@@ -219,7 +228,7 @@ static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size |
219 | 219 |
pos = extlba * sectorsize; /* start of extended partition */ |
220 | 220 |
|
221 | 221 |
/* read the extended boot record */ |
222 |
- pos += (logiclba * sectorsize) + MBR_BASE_OFFSET; |
|
222 |
+ pos += (logiclba * sectorsize) + mbr_base; |
|
223 | 223 |
if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) { |
224 | 224 |
cli_dbgmsg("cli_scanebr: Invalid extended boot record\n"); |
225 | 225 |
return CL_EFORMAT; |
... | ... |
@@ -506,9 +515,11 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl |
506 | 506 |
struct mbr_boot_record ebr; |
507 | 507 |
prtn_intxn_list_t prtncheck; |
508 | 508 |
unsigned i, pitxn; |
509 |
- int ret = 0, tmp = 0; |
|
509 |
+ int ret = 0, mbr_base = 0, tmp = 0; |
|
510 | 510 |
off_t pos = 0, logiclba = 0; |
511 | 511 |
|
512 |
+ mbr_base = sectorsize - sizeof(struct mbr_boot_record); |
|
513 |
+ |
|
512 | 514 |
prtn_intxn_list_init(&prtncheck); |
513 | 515 |
|
514 | 516 |
logiclba = 0; i = 0; |
... | ... |
@@ -516,7 +527,7 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl |
516 | 516 |
pos = extlba * sectorsize; /* start of extended partition */ |
517 | 517 |
|
518 | 518 |
/* read the extended boot record */ |
519 |
- pos += (logiclba * sectorsize) + MBR_BASE_OFFSET; |
|
519 |
+ pos += (logiclba * sectorsize) + mbr_base; |
|
520 | 520 |
if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) { |
521 | 521 |
cli_dbgmsg("cli_scanebr: Invalid extended boot record\n"); |
522 | 522 |
prtn_intxn_list_free(&prtncheck); |
... | ... |
@@ -33,7 +33,6 @@ |
33 | 33 |
#define CL_MAX_LOGICAL_PARTITIONS 50 |
34 | 34 |
|
35 | 35 |
#define MBR_SIGNATURE 0x55aa |
36 |
-#define MBR_BASE_OFFSET 446 |
|
37 | 36 |
#define MBR_SECTOR 0 |
38 | 37 |
|
39 | 38 |
/* MBR Status */ |
... | ... |
@@ -84,6 +83,6 @@ struct mbr_boot_record { |
84 | 84 |
#endif |
85 | 85 |
|
86 | 86 |
int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen); |
87 |
-int cli_scanmbr(cli_ctx *ctx); |
|
87 |
+int cli_scanmbr(cli_ctx *ctx, size_t sectorsize); |
|
88 | 88 |
|
89 | 89 |
#endif |
... | ... |
@@ -2587,12 +2587,12 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type) |
2587 | 2587 |
|
2588 | 2588 |
case CL_TYPE_MBR: |
2589 | 2589 |
//if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_MBR)) |
2590 |
- ret = cli_scanmbr(ctx); |
|
2590 |
+ ret = cli_scanmbr(ctx, 0); |
|
2591 | 2591 |
break; |
2592 | 2592 |
|
2593 | 2593 |
case CL_TYPE_GPT: |
2594 | 2594 |
//if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_GPT)) |
2595 |
- ret = cli_scangpt(ctx); |
|
2595 |
+ ret = cli_scangpt(ctx, 0); |
|
2596 | 2596 |
break; |
2597 | 2597 |
|
2598 | 2598 |
case CL_TYPE_APM: |