Browse code

libclamav: added MBR parsing for raw DMGs

Kevin Lin authored on 2014/02/07 09:00:00
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,552 @@
0
+/*
1
+ *  Copyright (C) 2014 Sourcefire, Inc.
2
+ *
3
+ *  Authors: Kevin Lin <klin@sourcefire.com>
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#if HAVE_CONFIG_H
21
+#include "clamav-config.h"
22
+#endif
23
+
24
+#include <stdio.h>
25
+#include <errno.h>
26
+#if HAVE_STRING_H
27
+#include <string.h>
28
+#endif
29
+#include <ctype.h>
30
+#include <fcntl.h>
31
+#include <zlib.h>
32
+
33
+#include "cltypes.h"
34
+#include "others.h"
35
+#include "mbr.h"
36
+#include "prtn_intxn.h"
37
+#include "scanners.h"
38
+
39
+//#define DEBUG_MBR_PARSE
40
+//#define DEBUG_EBR_PARSE
41
+
42
+#ifdef DEBUG_MBR_PARSE
43
+#  define mbr_parsemsg(...) cli_dbgmsg( __VA_ARGS__)
44
+#else
45
+#  define mbr_parsemsg(...) ;
46
+#endif
47
+
48
+#ifdef DEBUG_EBR_PARSE
49
+#  define ebr_parsemsg(...) cli_dbgmsg( __VA_ARGS__)
50
+#else
51
+#  define ebr_parsemsg(...) ;
52
+#endif
53
+
54
+enum MBR_STATE {
55
+    SEEN_NOTHING,
56
+    SEEN_PARTITION,
57
+    SEEN_EXTENDED,
58
+    SEEN_EMPTY
59
+};
60
+
61
+static int mbr_scanebr(cli_ctx *ctx, off_t *exloff, off_t exoff, size_t sectorsize);
62
+static void mbr_printbr(struct mbr_boot_record *record);
63
+static void mbr_convert_to_host(struct mbr_boot_record *record);
64
+static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen);
65
+static int mbr_check_ebr(struct mbr_boot_record *record);
66
+static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize);
67
+static int mbr_extended_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize);
68
+
69
+
70
+int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen) {
71
+    struct mbr_boot_record mbr;
72
+
73
+    if (len < 512) {
74
+        return CL_EFORMAT;
75
+    }
76
+
77
+    memcpy(&mbr, buff+MBR_BASE_OFFSET, sizeof(mbr));
78
+    mbr_convert_to_host(&mbr);
79
+
80
+    //mbr_printbr(&mbr);
81
+
82
+    return mbr_check_mbr(&mbr, maplen);
83
+}
84
+
85
+int cli_scanmbr(cli_ctx *ctx)
86
+{
87
+    struct mbr_boot_record mbr;
88
+    enum MBR_STATE state = SEEN_NOTHING;
89
+    int ret = 0;
90
+    size_t sectorsize, maplen, partsize;
91
+    off_t pos = 0, partoff = 0;
92
+    off_t exoff, exloff, exlcheck[CL_MAX_LOGICAL_PARTITIONS];
93
+    unsigned i, j, k, prtncount;
94
+
95
+    mbr_parsemsg("The start of something magnificant: MBR parsing\n");
96
+
97
+    if (!ctx || !ctx->fmap) {
98
+        cli_errmsg("cli_scanmbr: Invalid context\n");
99
+        return CL_ENULLARG;
100
+    }
101
+
102
+    /* sector size calculation */
103
+    sectorsize = MBR_SECTOR_SIZE;
104
+
105
+    /* size of total file must be a multiple of the sector size */
106
+    maplen = (*ctx->fmap)->real_len;
107
+    if ((maplen % sectorsize) != 0) {
108
+        cli_dbgmsg("cli_scanmbr: File sized %u is not a multiple of sector size %u\n",
109
+                   maplen, sectorsize);
110
+        return CL_EFORMAT;
111
+    }
112
+
113
+    /* sector 0 (first sector) is the master boot record */
114
+    pos = (MBR_SECTOR * sectorsize) + MBR_BASE_OFFSET;
115
+
116
+    /* read the master boot record */
117
+    if (fmap_readn(*ctx->fmap, &mbr, pos, sizeof(mbr)) != sizeof(mbr)) {
118
+        cli_dbgmsg("cli_scanmbr: Invalid master boot record\n");
119
+        return CL_EFORMAT;
120
+    }
121
+
122
+    /* convert the little endian to host, include the internal  */
123
+    mbr_convert_to_host(&mbr);
124
+
125
+    /* MBR checks */
126
+    ret = mbr_check_mbr(&mbr, maplen);
127
+    if (ret != CL_CLEAN) {
128
+        return ret;
129
+    }
130
+
131
+    /* check that the partition table has no intersections - HEURISTICS */
132
+    if (ctx->options & CL_SCAN_PARTITION_INTXN) {
133
+        ret = mbr_primary_prtn_intxn(ctx, mbr, sectorsize);
134
+        if ((ret != CL_CLEAN) &&
135
+            !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
136
+        
137
+            return ret;
138
+        }
139
+        ret = mbr_extended_prtn_intxn(ctx, mbr, sectorsize);
140
+        if ((ret != CL_CLEAN) &&
141
+            !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
142
+        
143
+            return ret;
144
+        }
145
+    }
146
+
147
+    /* MBR is valid, examine partitions */
148
+    prtncount = 0;
149
+    cli_dbgmsg("MBR Signature: %x\n", mbr.signature);
150
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
151
+        cli_dbgmsg("MBR Partition Entry %u:\n", i);
152
+        cli_dbgmsg("Status: %u\n", mbr.entries[i].status);
153
+        cli_dbgmsg("Type: %x\n", mbr.entries[i].type);
154
+        cli_dbgmsg("Blocks: [%u, +%u), ([%u, +%u))\n",
155
+                   mbr.entries[i].firstLBA, mbr.entries[i].numSectors,
156
+                   (mbr.entries[i].firstLBA * sectorsize),
157
+                   (mbr.entries[i].numSectors * sectorsize));
158
+
159
+        /* Handle MBR entry based on type */
160
+        if (mbr.entries[i].type == MBR_EMPTY) {
161
+            /* empty partiton entry */
162
+            prtncount++;
163
+        }
164
+        else if (mbr.entries[i].type == MBR_EXTENDED) {
165
+            if (state == SEEN_EXTENDED) {
166
+                cli_dbgmsg("cli_scanmbr: detected a master boot record "
167
+                           "with multiple extended partitions\n");
168
+            }
169
+            state = SEEN_EXTENDED; /* used only to detect mutiple extended partitions */
170
+
171
+            exoff = mbr.entries[i].firstLBA;
172
+            exloff = 0; j = 0;
173
+            do {
174
+                prtncount++;
175
+                /* check if a logical partition has been seen before */
176
+                for (k = 0; k < j; ++k) {
177
+                    if (exloff == exlcheck[k]) {
178
+                        cli_dbgmsg("cli_scanmbr: found a logical partition "
179
+                                   "that was previously seen!\n");
180
+                        /* do things! */
181
+                        return CL_EFORMAT;
182
+                    }
183
+                }
184
+                exlcheck[j] = exloff;
185
+
186
+                cli_dbgmsg("EBR Partition Entry %u:\n", j);
187
+                ret = mbr_scanebr(ctx, &exloff, exoff, sectorsize);
188
+                if ((ret != CL_CLEAN) &&
189
+                    !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
190
+                        return ret;
191
+                }
192
+
193
+                ++j;
194
+            } while (exloff != 0 && prtncount < ctx->engine->maxpartitions);
195
+
196
+            cli_dbgmsg("cli_scanmbr: examined %u logical partitions\n", j);
197
+        }
198
+        else {
199
+            prtncount++;
200
+
201
+            partoff = mbr.entries[i].firstLBA * sectorsize;
202
+            partsize = mbr.entries[i].numSectors * sectorsize;
203
+            mbr_parsemsg("cli_map_scan: [%u, +%u)\n", partoff, partsize);
204
+            ret = cli_map_scan(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY);
205
+            if ((ret != CL_CLEAN) &&
206
+                !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
207
+                    return ret;
208
+            }
209
+        }
210
+
211
+        if (prtncount >= ctx->engine->maxpartitions) {
212
+            cli_dbgmsg("cli_scanmbr: maximum partitions reached\n");
213
+            break;
214
+        }
215
+    }
216
+
217
+    return ret;
218
+}
219
+
220
+int mbr_scanebr(cli_ctx *ctx, off_t *exloff, off_t exoff, size_t sectorsize) {
221
+    struct mbr_boot_record ebr;
222
+    enum MBR_STATE state = SEEN_NOTHING;
223
+    int ret = 0;
224
+    off_t pos = 0, partoff = 0;
225
+    size_t partsize;
226
+    unsigned i;
227
+
228
+    ebr_parsemsg("The start of something excellent: EBR parsing\n");
229
+
230
+    pos = exoff * sectorsize; /* start of extended partition */
231
+    partoff = (exoff + *exloff) * sectorsize; /* start of logical partition */
232
+
233
+    /* read the extended boot record */
234
+    pos += (*exloff * sectorsize) + MBR_BASE_OFFSET;
235
+    if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) {
236
+        cli_dbgmsg("cli_scanebr: Invalid extended boot record\n");
237
+        return CL_EFORMAT;
238
+    }
239
+
240
+    /* convert the little endian to host */
241
+    mbr_convert_to_host(&ebr);
242
+
243
+    /* EBR checks */
244
+    ret = mbr_check_ebr(&ebr);
245
+    if (ret != CL_CLEAN) {
246
+        return ret;
247
+    }
248
+
249
+    /* EBR is valid, examine partitions */
250
+    cli_dbgmsg("EBR Signature: %x\n", ebr.signature);
251
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
252
+        if (i < 2) {
253
+            cli_dbgmsg("Logical Partition Entry %u:\n", i);
254
+            cli_dbgmsg("Status: %u\n", ebr.entries[i].status);
255
+            cli_dbgmsg("Type: %x\n", ebr.entries[i].type);
256
+            cli_dbgmsg("Blocks: [%u, +%u), ([%u, +%u))\n",
257
+                       ebr.entries[i].firstLBA, ebr.entries[i].numSectors,
258
+                       (ebr.entries[i].firstLBA * sectorsize),
259
+                       (ebr.entries[i].numSectors * sectorsize));
260
+
261
+            if (ebr.entries[i].type == MBR_EMPTY) {
262
+                /* empty partiton entry */
263
+                switch(state) {
264
+                case SEEN_NOTHING:
265
+                    state = SEEN_EMPTY;
266
+                    break;
267
+                case SEEN_PARTITION:
268
+                    *exloff = 0;
269
+                    break;
270
+                case SEEN_EMPTY:
271
+                    *exloff = 0;
272
+                    /* fall-through */
273
+                case SEEN_EXTENDED:
274
+                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
275
+                               "without a partition record\n");
276
+                    break;
277
+                default:
278
+                    cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n");
279
+                    return CL_EPARSE;
280
+                }
281
+            }
282
+            else if (ebr.entries[i].type == MBR_EXTENDED) {
283
+                switch(state) {
284
+                case SEEN_NOTHING:
285
+                    state = SEEN_EXTENDED;
286
+                    break;
287
+                case SEEN_PARTITION:
288
+                    break;
289
+                case SEEN_EMPTY:
290
+                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
291
+                               "without a partition record\n");
292
+                    break;
293
+                case SEEN_EXTENDED:
294
+                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
295
+                               "with multiple extended partition records\n");
296
+                    return CL_EFORMAT;
297
+                default:
298
+                    cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n");
299
+                    return CL_EPARSE;
300
+                }
301
+
302
+                *exloff = ebr.entries[i].firstLBA;
303
+            }
304
+            else {
305
+                switch(state) {
306
+                case SEEN_NOTHING:
307
+                    state = SEEN_PARTITION;
308
+                    break;
309
+                case SEEN_PARTITION:
310
+                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
311
+                               "with multiple partition records\n");
312
+                    *exloff = 0; /* no extended partitions are possible */
313
+                    break;
314
+                case SEEN_EXTENDED:
315
+                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
316
+                               "with extended partition record first\n");
317
+                    break;
318
+                case SEEN_EMPTY:
319
+                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
320
+                               "with empty partition record first\n");
321
+                    *exloff = 0; /* no extended partitions are possible */
322
+                    break;
323
+                default:
324
+                    cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n");
325
+                    return CL_EPARSE;
326
+                }
327
+
328
+                partoff += (ebr.entries[i].firstLBA * sectorsize);
329
+                partsize = ebr.entries[i].numSectors * sectorsize;
330
+                ret = cli_map_scan(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY);
331
+                if ((ret != CL_CLEAN) &&
332
+                    !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
333
+                        return ret;
334
+                }
335
+            }
336
+        }
337
+        else {
338
+            /* check the last two entries to be empty */
339
+            if (ebr.entries[i].type != MBR_EMPTY) {
340
+                cli_dbgmsg("cli_scanebr: detected a logical boot record "
341
+                           "with an entry at index %u\n", i);
342
+                /* should we attepmt to use these entries? */
343
+                return CL_EFORMAT;
344
+            }
345
+        }
346
+    }
347
+
348
+    return ret;
349
+}
350
+
351
+static void mbr_printbr(struct mbr_boot_record *record)
352
+{
353
+    unsigned i;
354
+
355
+    cli_dbgmsg("signature: %x\n", record->signature);
356
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
357
+        cli_dbgmsg("entry %u:\n", i);
358
+        cli_dbgmsg("\tstatus: %x\n", record->entries[i].status);
359
+        cli_dbgmsg("\tfirstCHS: [%u, %u, %u]\n", record->entries[i].firstCHS[0],
360
+                   record->entries[i].firstCHS[1], record->entries[i].firstCHS[2]);
361
+        cli_dbgmsg("\ttype: %x\n", record->entries[i].type);
362
+        cli_dbgmsg("\tlastCHS: [%u, %u, %u]\n", record->entries[i].lastCHS[0],
363
+                   record->entries[i].lastCHS[1], record->entries[i].lastCHS[2]);
364
+        cli_dbgmsg("\tfirstLBA: %u\n", record->entries[i].firstLBA);
365
+        cli_dbgmsg("\tnumSectors: %u\n", record->entries[i].numSectors);
366
+    }
367
+}
368
+
369
+static void mbr_convert_to_host(struct mbr_boot_record *record)
370
+{
371
+    struct mbr_partition_entry *entry;
372
+    unsigned i;
373
+ 
374
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
375
+        entry = &record->entries[i];
376
+ 
377
+        entry->firstLBA = le32_to_host(entry->firstLBA);
378
+        entry->numSectors = le32_to_host(entry->numSectors);
379
+    }
380
+    record->signature = be16_to_host(record->signature);
381
+}
382
+
383
+static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen)
384
+{
385
+    unsigned i = 0;
386
+    off_t partoff = 0;
387
+    size_t partsize = 0, sectorsize = MBR_SECTOR_SIZE;
388
+
389
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
390
+        /* check status */
391
+        if ((record->entries[i].status != MBR_STATUS_INACTIVE) && 
392
+            (record->entries[i].status != MBR_STATUS_ACTIVE)) {
393
+            cli_dbgmsg("cli_scanmbr: Invalid boot record status\n");
394
+            return CL_EFORMAT;
395
+        }
396
+
397
+        partoff = record->entries[i].firstLBA * sectorsize;
398
+        partsize = record->entries[i].numSectors * sectorsize;
399
+        if (partoff + partsize > maplen) {
400
+            cli_dbgmsg("cli_scanmbr: Invalid partition entry\n");
401
+            return CL_EFORMAT;
402
+        }
403
+    }
404
+
405
+    /* check the signature */
406
+    if (record->signature != MBR_SIGNATURE) {
407
+        cli_dbgmsg("cli_scanmbr: Invalid boot record signature\n");
408
+        return CL_EFORMAT;
409
+    }
410
+
411
+    return CL_CLEAN;
412
+}
413
+
414
+static int mbr_check_ebr(struct mbr_boot_record *record)
415
+{
416
+    unsigned i = 0;
417
+
418
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
419
+        /* check status */
420
+        if ((record->entries[i].status != MBR_STATUS_INACTIVE) && 
421
+            (record->entries[i].status != MBR_STATUS_ACTIVE)) {
422
+            cli_dbgmsg("cli_scanmbr: Invalid boot record status\n");
423
+            return CL_EFORMAT;
424
+        }
425
+    }
426
+
427
+    /* check the signature */
428
+    if (record->signature != MBR_SIGNATURE) {
429
+        cli_dbgmsg("cli_scanmbr: Invalid boot record signature\n");
430
+        return CL_EFORMAT;
431
+    }
432
+
433
+    return CL_CLEAN;
434
+}
435
+
436
+/* this includes the overall bounds of extended partitions */
437
+static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize)
438
+{
439
+    prtn_intxn_list_t prtncheck;
440
+    unsigned i, pitxn;
441
+    int ret = 0, tmp = 0;
442
+
443
+    prtn_intxn_list_init(&prtncheck);
444
+
445
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
446
+        if (mbr.entries[i].type != MBR_EMPTY) {
447
+            tmp = prtn_intxn_list_check(&prtncheck, &pitxn, mbr.entries[i].firstLBA, 
448
+                                        mbr.entries[i].numSectors);
449
+            if (tmp != CL_CLEAN) {
450
+                if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) {
451
+                    cli_dbgmsg("cli_scanmbr: detected intersection with partitions "
452
+                               "[%u, %u]\n", pitxn, i);
453
+                    cli_append_virus(ctx, "Heuristic.PartitionIntersection");
454
+                    ret = tmp;
455
+                    tmp = 0;
456
+                }
457
+                else if (tmp == CL_VIRUS) {
458
+                    cli_dbgmsg("cli_scanmbr: detected intersection with partitions "
459
+                               "[%u, %u]\n", pitxn, i);
460
+                    cli_append_virus(ctx, "Heuristic.PartitionIntersection");
461
+                    prtn_intxn_list_free(&prtncheck);
462
+                    return CL_VIRUS;
463
+                }
464
+                else {
465
+                    prtn_intxn_list_free(&prtncheck);
466
+                    return tmp;
467
+                }
468
+            }
469
+        }
470
+    }
471
+
472
+    prtn_intxn_list_free(&prtncheck);
473
+    return ret;
474
+}
475
+
476
+/* checks internal logical partitions */
477
+static int mbr_extended_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize)
478
+{
479
+    struct mbr_boot_record ebr;
480
+    prtn_intxn_list_t prtncheck;
481
+    unsigned i, j, pitxn;
482
+    int ret = 0, tmp = 0;
483
+    off_t pos = 0, exoff = 0, exloff = 0;
484
+
485
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
486
+        if (mbr.entries[i].type == MBR_EXTENDED) {
487
+
488
+            prtn_intxn_list_init(&prtncheck);
489
+
490
+            exoff = mbr.entries[i].firstLBA;
491
+            exloff = 0; j = 0;
492
+            do {
493
+                pos = exoff * sectorsize; /* start of extended partition */
494
+
495
+                /* read the extended boot record */
496
+                pos += (exloff * sectorsize) + MBR_BASE_OFFSET;
497
+                if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) {
498
+                    cli_dbgmsg("cli_scanebr: Invalid extended boot record\n");
499
+                    prtn_intxn_list_free(&prtncheck);
500
+                    return CL_EFORMAT;
501
+                }
502
+
503
+                /* convert the little endian to host */
504
+                mbr_convert_to_host(&ebr);
505
+
506
+                /* assume that logical record is first and extended is second */
507
+                tmp = prtn_intxn_list_check(&prtncheck, &pitxn, exloff, ebr.entries[0].numSectors);
508
+                if (tmp != CL_CLEAN) {
509
+                    if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) {
510
+                        cli_dbgmsg("cli_scanebr: detected intersection with partitions "
511
+                                   "[%u, %u]\n", pitxn, i);
512
+                        cli_append_virus(ctx, "Heuristic.PartitionIntersection");
513
+                        ret = tmp;
514
+                        tmp = 0;
515
+                    }
516
+                    else if (tmp == CL_VIRUS) {
517
+                        cli_dbgmsg("cli_scanebr: detected intersection with partitions "
518
+                                   "[%u, %u]\n", pitxn, i);
519
+                        cli_append_virus(ctx, "Heuristic.PartitionIntersection");
520
+                        prtn_intxn_list_free(&prtncheck);
521
+                        return CL_VIRUS;
522
+                    }
523
+                    else {
524
+                        prtn_intxn_list_free(&prtncheck);
525
+                        return tmp;
526
+                    }
527
+                }
528
+
529
+                /* assume extended is second entry */
530
+                if (ebr.entries[1].type != MBR_EXTENDED) {
531
+                    cli_dbgmsg("cli_scanebr: second entry for EBR is not an extended partition\n");
532
+                    break;
533
+                }
534
+
535
+                exloff = ebr.entries[1].firstLBA;
536
+
537
+                ++j;
538
+            } while (exloff != 0 && j < CL_MAX_LOGICAL_PARTITIONS);
539
+
540
+            if (j == CL_MAX_LOGICAL_PARTITIONS) {
541
+                cli_dbgmsg("cli_scanebr: reached maximum number of scanned logical partitions\n");
542
+            }
543
+
544
+            prtn_intxn_list_free(&prtncheck);    
545
+        }
546
+    }
547
+
548
+
549
+    return ret;
550
+
551
+}
0 552
new file mode 100644
... ...
@@ -0,0 +1,89 @@
0
+/*
1
+ *  Copyright (C) 2014 Sourcefire, Inc.
2
+ *
3
+ *  Authors: Kevin Lin <klin@sourcefire.com>
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#ifndef __MBR_H
21
+#define __MBR_H
22
+
23
+#if HAVE_CONFIG_H
24
+#include "clamav-config.h"
25
+#endif
26
+
27
+#include "cltypes.h"
28
+#include "others.h"
29
+
30
+#define MBR_SECTOR_SIZE 512
31
+#define MBR_MAX_PARTITION_ENTRIES 4
32
+#define CL_MAX_LOGICAL_PARTITIONS 50
33
+
34
+#define MBR_SIGNATURE 0x55aa
35
+#define MBR_BASE_OFFSET 446
36
+#define MBR_SECTOR 0
37
+
38
+/* MBR Status */
39
+#define MBR_STATUS_INACTIVE 0x00
40
+/* other values are invalid status */
41
+#define MBR_STATUS_ACTIVE   0x80
42
+/* End MBR Status */
43
+
44
+/* MBR Partition Types */
45
+#define MBR_EMPTY      0x00
46
+#define MBR_EXTENDED   0x05
47
+/* End Partition Types */
48
+
49
+#ifndef HAVE_ATTRIB_PACKED
50
+#define __attribute__(x)
51
+#endif
52
+
53
+#ifdef HAVE_PRAGMA_PACK
54
+#pragma pack(1)
55
+#endif
56
+
57
+#ifdef HAVE_PRAGMA_PACK_HPPA
58
+#pragma pack 1
59
+#endif
60
+
61
+/* 16-byte MBR partition entry, little-endian */
62
+struct mbr_partition_entry {
63
+    uint8_t status; /* 0x80 = active, 0x00 = inactive */
64
+    uint8_t firstCHS[3];
65
+    uint8_t type;
66
+    uint8_t lastCHS[3];
67
+    uint32_t firstLBA  __attribute__ ((packed));
68
+    uint32_t numSectors  __attribute__ ((packed));
69
+};
70
+
71
+struct mbr_boot_record {
72
+    /* 446 bytes of reserved, implementation-based data */
73
+    struct mbr_partition_entry entries[4];
74
+    uint16_t signature  __attribute__ ((packed));
75
+};
76
+
77
+#ifdef HAVE_PRAGMA_PACK
78
+#pragma pack()
79
+#endif
80
+
81
+#ifdef HAVE_PRAGMA_PACK_HPPA
82
+#pragma pack
83
+#endif
84
+
85
+int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen);
86
+int cli_scanmbr(cli_ctx *ctx);
87
+
88
+#endif