... | ... |
@@ -40,6 +40,10 @@ |
40 | 40 |
//#define DEBUG_MBR_PARSE |
41 | 41 |
//#define DEBUG_EBR_PARSE |
42 | 42 |
|
43 |
+#ifndef PRTN_INTXN_DETECTION |
|
44 |
+# define PRTN_INTXN_DETECTION "heuristic.mbrprtnintersect" |
|
45 |
+#endif |
|
46 |
+ |
|
43 | 47 |
#ifdef DEBUG_MBR_PARSE |
44 | 48 |
# define mbr_parsemsg(...) cli_dbgmsg( __VA_ARGS__) |
45 | 49 |
#else |
... | ... |
@@ -59,14 +63,14 @@ enum MBR_STATE { |
59 | 59 |
SEEN_EMPTY |
60 | 60 |
}; |
61 | 61 |
|
62 |
-static int mbr_scanebr(cli_ctx *ctx, off_t *exloff, off_t exoff, size_t sectorsize); |
|
62 |
+static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, |
|
63 |
+ size_t extlbasize, size_t sectorsize); |
|
63 | 64 |
static void mbr_printbr(struct mbr_boot_record *record); |
64 | 65 |
static void mbr_convert_to_host(struct mbr_boot_record *record); |
65 |
-static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen); |
|
66 |
+static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen, size_t sectorsize); |
|
66 | 67 |
static int mbr_check_ebr(struct mbr_boot_record *record); |
67 | 68 |
static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize); |
68 |
-static int mbr_extended_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize); |
|
69 |
- |
|
69 |
+static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size_t sectorsize); |
|
70 | 70 |
|
71 | 71 |
int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen) { |
72 | 72 |
struct mbr_boot_record mbr; |
... | ... |
@@ -80,18 +84,17 @@ int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen) { |
80 | 80 |
|
81 | 81 |
//mbr_printbr(&mbr); |
82 | 82 |
|
83 |
- return mbr_check_mbr(&mbr, maplen); |
|
83 |
+ return mbr_check_mbr(&mbr, maplen, MBR_SECTOR_SIZE); |
|
84 | 84 |
} |
85 | 85 |
|
86 | 86 |
int cli_scanmbr(cli_ctx *ctx) |
87 | 87 |
{ |
88 | 88 |
struct mbr_boot_record mbr; |
89 | 89 |
enum MBR_STATE state = SEEN_NOTHING; |
90 |
- int ret = 0; |
|
91 |
- size_t sectorsize, maplen, partsize; |
|
90 |
+ int ret = CL_CLEAN; |
|
92 | 91 |
off_t pos = 0, partoff = 0; |
93 |
- off_t exoff, exloff, exlcheck[CL_MAX_LOGICAL_PARTITIONS]; |
|
94 |
- unsigned i, j, k, prtncount; |
|
92 |
+ unsigned i = 0, prtncount = 0; |
|
93 |
+ size_t sectorsize, maplen, partsize; |
|
95 | 94 |
|
96 | 95 |
mbr_parsemsg("The start of something magnificant: MBR parsing\n"); |
97 | 96 |
|
... | ... |
@@ -124,7 +127,7 @@ int cli_scanmbr(cli_ctx *ctx) |
124 | 124 |
mbr_convert_to_host(&mbr); |
125 | 125 |
|
126 | 126 |
/* MBR checks */ |
127 |
- ret = mbr_check_mbr(&mbr, maplen); |
|
127 |
+ ret = mbr_check_mbr(&mbr, maplen, sectorsize); |
|
128 | 128 |
if (ret != CL_CLEAN) { |
129 | 129 |
return ret; |
130 | 130 |
} |
... | ... |
@@ -137,25 +140,19 @@ int cli_scanmbr(cli_ctx *ctx) |
137 | 137 |
|
138 | 138 |
return ret; |
139 | 139 |
} |
140 |
- ret = mbr_extended_prtn_intxn(ctx, mbr, sectorsize); |
|
141 |
- if ((ret != CL_CLEAN) && |
|
142 |
- !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) { |
|
143 |
- |
|
144 |
- return ret; |
|
145 |
- } |
|
146 | 140 |
} |
147 | 141 |
|
148 | 142 |
/* MBR is valid, examine partitions */ |
149 | 143 |
prtncount = 0; |
150 | 144 |
cli_dbgmsg("MBR Signature: %x\n", mbr.signature); |
151 |
- for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) { |
|
145 |
+ for (i = 0; i < MBR_MAX_PARTITION_ENTRIES && prtncount < ctx->engine->maxpartitions; ++i) { |
|
152 | 146 |
cli_dbgmsg("MBR Partition Entry %u:\n", i); |
153 | 147 |
cli_dbgmsg("Status: %u\n", mbr.entries[i].status); |
154 | 148 |
cli_dbgmsg("Type: %x\n", mbr.entries[i].type); |
155 | 149 |
cli_dbgmsg("Blocks: [%u, +%u), ([%u, +%u))\n", |
156 |
- mbr.entries[i].firstLBA, mbr.entries[i].numSectors, |
|
150 |
+ mbr.entries[i].firstLBA, mbr.entries[i].numLBA, |
|
157 | 151 |
(mbr.entries[i].firstLBA * sectorsize), |
158 |
- (mbr.entries[i].numSectors * sectorsize)); |
|
152 |
+ (mbr.entries[i].numLBA * sectorsize)); |
|
159 | 153 |
|
160 | 154 |
/* Handle MBR entry based on type */ |
161 | 155 |
if (mbr.entries[i].type == MBR_EMPTY) { |
... | ... |
@@ -169,38 +166,18 @@ int cli_scanmbr(cli_ctx *ctx) |
169 | 169 |
} |
170 | 170 |
state = SEEN_EXTENDED; /* used only to detect mutiple extended partitions */ |
171 | 171 |
|
172 |
- exoff = mbr.entries[i].firstLBA; |
|
173 |
- exloff = 0; j = 0; |
|
174 |
- do { |
|
175 |
- prtncount++; |
|
176 |
- /* check if a logical partition has been seen before */ |
|
177 |
- for (k = 0; k < j; ++k) { |
|
178 |
- if (exloff == exlcheck[k]) { |
|
179 |
- cli_dbgmsg("cli_scanmbr: found a logical partition " |
|
180 |
- "that was previously seen!\n"); |
|
181 |
- /* do things! */ |
|
182 |
- return CL_EFORMAT; |
|
183 |
- } |
|
184 |
- } |
|
185 |
- exlcheck[j] = exloff; |
|
186 |
- |
|
187 |
- cli_dbgmsg("EBR Partition Entry %u:\n", j); |
|
188 |
- ret = mbr_scanebr(ctx, &exloff, exoff, sectorsize); |
|
189 |
- if ((ret != CL_CLEAN) && |
|
190 |
- !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) { |
|
191 |
- return ret; |
|
192 |
- } |
|
193 |
- |
|
194 |
- ++j; |
|
195 |
- } while (exloff != 0 && prtncount < ctx->engine->maxpartitions); |
|
196 |
- |
|
197 |
- cli_dbgmsg("cli_scanmbr: examined %u logical partitions\n", j); |
|
172 |
+ ret = mbr_scanextprtn(ctx, &prtncount, mbr.entries[i].firstLBA, |
|
173 |
+ mbr.entries[i].numLBA, sectorsize); |
|
174 |
+ if ((ret != CL_CLEAN) && |
|
175 |
+ !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) { |
|
176 |
+ return ret; |
|
177 |
+ } |
|
198 | 178 |
} |
199 | 179 |
else { |
200 | 180 |
prtncount++; |
201 | 181 |
|
202 | 182 |
partoff = mbr.entries[i].firstLBA * sectorsize; |
203 |
- partsize = mbr.entries[i].numSectors * sectorsize; |
|
183 |
+ partsize = mbr.entries[i].numLBA * sectorsize; |
|
204 | 184 |
mbr_parsemsg("cli_map_scan: [%u, +%u)\n", partoff, partsize); |
205 | 185 |
ret = cli_map_scan(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY); |
206 | 186 |
if ((ret != CL_CLEAN) && |
... | ... |
@@ -208,144 +185,158 @@ int cli_scanmbr(cli_ctx *ctx) |
208 | 208 |
return ret; |
209 | 209 |
} |
210 | 210 |
} |
211 |
- |
|
212 |
- if (prtncount >= ctx->engine->maxpartitions) { |
|
213 |
- cli_dbgmsg("cli_scanmbr: maximum partitions reached\n"); |
|
214 |
- break; |
|
215 |
- } |
|
216 | 211 |
} |
217 | 212 |
|
213 |
+ if (prtncount >= ctx->engine->maxpartitions) { |
|
214 |
+ cli_dbgmsg("cli_scanmbr: maximum partitions reached\n"); |
|
215 |
+ } |
|
218 | 216 |
return ret; |
219 | 217 |
} |
220 | 218 |
|
221 |
-int mbr_scanebr(cli_ctx *ctx, off_t *exloff, off_t exoff, size_t sectorsize) { |
|
219 |
+static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size_t extlbasize, size_t sectorsize) |
|
220 |
+{ |
|
222 | 221 |
struct mbr_boot_record ebr; |
223 | 222 |
enum MBR_STATE state = SEEN_NOTHING; |
224 |
- int ret = 0; |
|
225 |
- off_t pos = 0, partoff = 0; |
|
226 |
- size_t partsize; |
|
227 |
- unsigned i; |
|
228 |
- |
|
229 |
- ebr_parsemsg("The start of something excellent: EBR parsing\n"); |
|
230 |
- |
|
231 |
- pos = exoff * sectorsize; /* start of extended partition */ |
|
232 |
- partoff = (exoff + *exloff) * sectorsize; /* start of logical partition */ |
|
233 |
- |
|
234 |
- /* read the extended boot record */ |
|
235 |
- pos += (*exloff * sectorsize) + MBR_BASE_OFFSET; |
|
236 |
- if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) { |
|
237 |
- cli_dbgmsg("cli_scanebr: Invalid extended boot record\n"); |
|
238 |
- return CL_EFORMAT; |
|
239 |
- } |
|
223 |
+ int ret = CL_CLEAN; |
|
224 |
+ off_t pos = 0, logiclba = 0, extoff = 0, partoff = 0; |
|
225 |
+ size_t partsize, extsize; |
|
226 |
+ unsigned i = 0, j = 0; |
|
227 |
+ |
|
228 |
+ ebr_parsemsg("The start of something exhausting: EBR parsing\n"); |
|
229 |
+ |
|
230 |
+ logiclba = 0; |
|
231 |
+ extoff = extlba * sectorsize; |
|
232 |
+ extsize = extlbasize * sectorsize; |
|
233 |
+ do { |
|
234 |
+ pos = extlba * sectorsize; /* start of extended partition */ |
|
235 |
+ |
|
236 |
+ /* read the extended boot record */ |
|
237 |
+ pos += (logiclba * sectorsize) + MBR_BASE_OFFSET; |
|
238 |
+ if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) { |
|
239 |
+ cli_dbgmsg("cli_scanebr: Invalid extended boot record\n"); |
|
240 |
+ return CL_EFORMAT; |
|
241 |
+ } |
|
240 | 242 |
|
241 |
- /* convert the little endian to host */ |
|
242 |
- mbr_convert_to_host(&ebr); |
|
243 |
+ /* convert the little endian to host */ |
|
244 |
+ mbr_convert_to_host(&ebr); |
|
243 | 245 |
|
244 |
- /* EBR checks */ |
|
245 |
- ret = mbr_check_ebr(&ebr); |
|
246 |
- if (ret != CL_CLEAN) { |
|
247 |
- return ret; |
|
248 |
- } |
|
246 |
+ /* EBR checks */ |
|
247 |
+ ret = mbr_check_ebr(&ebr); |
|
248 |
+ if (ret != CL_CLEAN) { |
|
249 |
+ return ret; |
|
250 |
+ } |
|
249 | 251 |
|
250 |
- /* EBR is valid, examine partitions */ |
|
251 |
- cli_dbgmsg("EBR Signature: %x\n", ebr.signature); |
|
252 |
- for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) { |
|
253 |
- if (i < 2) { |
|
254 |
- cli_dbgmsg("Logical Partition Entry %u:\n", i); |
|
255 |
- cli_dbgmsg("Status: %u\n", ebr.entries[i].status); |
|
256 |
- cli_dbgmsg("Type: %x\n", ebr.entries[i].type); |
|
257 |
- cli_dbgmsg("Blocks: [%u, +%u), ([%u, +%u))\n", |
|
258 |
- ebr.entries[i].firstLBA, ebr.entries[i].numSectors, |
|
259 |
- (ebr.entries[i].firstLBA * sectorsize), |
|
260 |
- (ebr.entries[i].numSectors * sectorsize)); |
|
261 |
- |
|
262 |
- if (ebr.entries[i].type == MBR_EMPTY) { |
|
263 |
- /* empty partiton entry */ |
|
264 |
- switch(state) { |
|
265 |
- case SEEN_NOTHING: |
|
266 |
- state = SEEN_EMPTY; |
|
267 |
- break; |
|
268 |
- case SEEN_PARTITION: |
|
269 |
- *exloff = 0; |
|
270 |
- break; |
|
271 |
- case SEEN_EMPTY: |
|
272 |
- *exloff = 0; |
|
273 |
- /* fall-through */ |
|
274 |
- case SEEN_EXTENDED: |
|
275 |
- cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
276 |
- "without a partition record\n"); |
|
277 |
- break; |
|
278 |
- default: |
|
279 |
- cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n"); |
|
280 |
- return CL_EPARSE; |
|
281 |
- } |
|
282 |
- } |
|
283 |
- else if (ebr.entries[i].type == MBR_EXTENDED) { |
|
284 |
- switch(state) { |
|
285 |
- case SEEN_NOTHING: |
|
286 |
- state = SEEN_EXTENDED; |
|
287 |
- break; |
|
288 |
- case SEEN_PARTITION: |
|
289 |
- break; |
|
290 |
- case SEEN_EMPTY: |
|
291 |
- cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
292 |
- "without a partition record\n"); |
|
293 |
- break; |
|
294 |
- case SEEN_EXTENDED: |
|
295 |
- cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
296 |
- "with multiple extended partition records\n"); |
|
297 |
- return CL_EFORMAT; |
|
298 |
- default: |
|
299 |
- cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n"); |
|
300 |
- return CL_EPARSE; |
|
252 |
+ /* update state */ |
|
253 |
+ state = SEEN_NOTHING; |
|
254 |
+ (*prtncount)++; |
|
255 |
+ |
|
256 |
+ /* EBR is valid, examine partitions */ |
|
257 |
+ cli_dbgmsg("EBR Partition Entry %u:\n", i++); |
|
258 |
+ cli_dbgmsg("EBR Signature: %x\n", ebr.signature); |
|
259 |
+ for (j = 0; j < MBR_MAX_PARTITION_ENTRIES; ++j) { |
|
260 |
+ if (j < 2) { |
|
261 |
+ cli_dbgmsg("Logical Partition Entry %u:\n", j); |
|
262 |
+ cli_dbgmsg("Status: %u\n", ebr.entries[j].status); |
|
263 |
+ cli_dbgmsg("Type: %x\n", ebr.entries[j].type); |
|
264 |
+ cli_dbgmsg("Blocks: [%u, +%u), ([%u, +%u))\n", |
|
265 |
+ ebr.entries[j].firstLBA, ebr.entries[j].numLBA, |
|
266 |
+ (ebr.entries[j].firstLBA * sectorsize), |
|
267 |
+ (ebr.entries[j].numLBA * sectorsize)); |
|
268 |
+ |
|
269 |
+ if (ebr.entries[j].type == MBR_EMPTY) { |
|
270 |
+ /* empty partiton entry */ |
|
271 |
+ switch(state) { |
|
272 |
+ case SEEN_NOTHING: |
|
273 |
+ state = SEEN_EMPTY; |
|
274 |
+ break; |
|
275 |
+ case SEEN_PARTITION: |
|
276 |
+ logiclba = 0; |
|
277 |
+ break; |
|
278 |
+ case SEEN_EMPTY: |
|
279 |
+ logiclba = 0; |
|
280 |
+ /* fall-through */ |
|
281 |
+ case SEEN_EXTENDED: |
|
282 |
+ cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
283 |
+ "without a partition record\n"); |
|
284 |
+ break; |
|
285 |
+ default: |
|
286 |
+ cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n"); |
|
287 |
+ return CL_EPARSE; |
|
288 |
+ } |
|
301 | 289 |
} |
290 |
+ else if (ebr.entries[j].type == MBR_EXTENDED) { |
|
291 |
+ switch(state) { |
|
292 |
+ case SEEN_NOTHING: |
|
293 |
+ state = SEEN_EXTENDED; |
|
294 |
+ break; |
|
295 |
+ case SEEN_PARTITION: |
|
296 |
+ break; |
|
297 |
+ case SEEN_EMPTY: |
|
298 |
+ cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
299 |
+ "without a partition record\n"); |
|
300 |
+ break; |
|
301 |
+ case SEEN_EXTENDED: |
|
302 |
+ cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
303 |
+ "with multiple extended partition records\n"); |
|
304 |
+ return CL_EFORMAT; |
|
305 |
+ default: |
|
306 |
+ cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n"); |
|
307 |
+ return CL_EPARSE; |
|
308 |
+ } |
|
302 | 309 |
|
303 |
- *exloff = ebr.entries[i].firstLBA; |
|
304 |
- } |
|
305 |
- else { |
|
306 |
- switch(state) { |
|
307 |
- case SEEN_NOTHING: |
|
308 |
- state = SEEN_PARTITION; |
|
309 |
- break; |
|
310 |
- case SEEN_PARTITION: |
|
311 |
- cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
312 |
- "with multiple partition records\n"); |
|
313 |
- *exloff = 0; /* no extended partitions are possible */ |
|
314 |
- break; |
|
315 |
- case SEEN_EXTENDED: |
|
316 |
- cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
317 |
- "with extended partition record first\n"); |
|
318 |
- break; |
|
319 |
- case SEEN_EMPTY: |
|
320 |
- cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
321 |
- "with empty partition record first\n"); |
|
322 |
- *exloff = 0; /* no extended partitions are possible */ |
|
323 |
- break; |
|
324 |
- default: |
|
325 |
- cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n"); |
|
326 |
- return CL_EPARSE; |
|
310 |
+ logiclba = ebr.entries[j].firstLBA; |
|
327 | 311 |
} |
312 |
+ else { |
|
313 |
+ switch(state) { |
|
314 |
+ case SEEN_NOTHING: |
|
315 |
+ state = SEEN_PARTITION; |
|
316 |
+ break; |
|
317 |
+ case SEEN_PARTITION: |
|
318 |
+ cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
319 |
+ "with multiple partition records\n"); |
|
320 |
+ logiclba = 0; /* no extended partitions are possible */ |
|
321 |
+ break; |
|
322 |
+ case SEEN_EXTENDED: |
|
323 |
+ cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
324 |
+ "with extended partition record first\n"); |
|
325 |
+ break; |
|
326 |
+ case SEEN_EMPTY: |
|
327 |
+ cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
328 |
+ "with empty partition record first\n"); |
|
329 |
+ logiclba = 0; /* no extended partitions are possible */ |
|
330 |
+ break; |
|
331 |
+ default: |
|
332 |
+ cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n"); |
|
333 |
+ return CL_EPARSE; |
|
334 |
+ } |
|
328 | 335 |
|
329 |
- partoff += (ebr.entries[i].firstLBA * sectorsize); |
|
330 |
- partsize = ebr.entries[i].numSectors * sectorsize; |
|
331 |
- ret = cli_map_scan(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY); |
|
332 |
- if ((ret != CL_CLEAN) && |
|
333 |
- !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) { |
|
336 |
+ partoff = (extlba + logiclba + ebr.entries[j].firstLBA) * sectorsize; |
|
337 |
+ partsize = ebr.entries[j].numLBA * sectorsize; |
|
338 |
+ if (extoff + partsize > extsize) { |
|
339 |
+ cli_dbgmsg("cli_scanmbr: Invalid partition entry\n"); |
|
340 |
+ return CL_EFORMAT; |
|
341 |
+ } |
|
342 |
+ |
|
343 |
+ ret = cli_map_scan(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY); |
|
344 |
+ if ((ret != CL_CLEAN) && |
|
345 |
+ !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) { |
|
334 | 346 |
return ret; |
347 |
+ } |
|
335 | 348 |
} |
336 | 349 |
} |
337 |
- } |
|
338 |
- else { |
|
339 |
- /* check the last two entries to be empty */ |
|
340 |
- if (ebr.entries[i].type != MBR_EMPTY) { |
|
341 |
- cli_dbgmsg("cli_scanebr: detected a logical boot record " |
|
342 |
- "with an entry at index %u\n", i); |
|
343 |
- /* should we attepmt to use these entries? */ |
|
344 |
- return CL_EFORMAT; |
|
350 |
+ else { |
|
351 |
+ /* check the last two entries to be empty */ |
|
352 |
+ if (ebr.entries[j].type != MBR_EMPTY) { |
|
353 |
+ cli_dbgmsg("cli_scanebr: detected a non-empty partition " |
|
354 |
+ "entry at index %u\n", j); |
|
355 |
+ /* should we attempt to use these entries? */ |
|
356 |
+ return CL_EFORMAT; |
|
357 |
+ } |
|
345 | 358 |
} |
346 | 359 |
} |
347 |
- } |
|
360 |
+ } while (logiclba != 0 && (*prtncount) < ctx->engine->maxpartitions); |
|
348 | 361 |
|
362 |
+ cli_dbgmsg("cli_scanmbr: examined %u logical partitions\n", i); |
|
349 | 363 |
return ret; |
350 | 364 |
} |
351 | 365 |
|
... | ... |
@@ -363,7 +354,7 @@ static void mbr_printbr(struct mbr_boot_record *record) |
363 | 363 |
cli_dbgmsg("\tlastCHS: [%u, %u, %u]\n", record->entries[i].lastCHS[0], |
364 | 364 |
record->entries[i].lastCHS[1], record->entries[i].lastCHS[2]); |
365 | 365 |
cli_dbgmsg("\tfirstLBA: %u\n", record->entries[i].firstLBA); |
366 |
- cli_dbgmsg("\tnumSectors: %u\n", record->entries[i].numSectors); |
|
366 |
+ cli_dbgmsg("\tnumLBA: %u\n", record->entries[i].numLBA); |
|
367 | 367 |
} |
368 | 368 |
} |
369 | 369 |
|
... | ... |
@@ -376,16 +367,16 @@ static void mbr_convert_to_host(struct mbr_boot_record *record) |
376 | 376 |
entry = &record->entries[i]; |
377 | 377 |
|
378 | 378 |
entry->firstLBA = le32_to_host(entry->firstLBA); |
379 |
- entry->numSectors = le32_to_host(entry->numSectors); |
|
379 |
+ entry->numLBA = le32_to_host(entry->numLBA); |
|
380 | 380 |
} |
381 | 381 |
record->signature = be16_to_host(record->signature); |
382 | 382 |
} |
383 | 383 |
|
384 |
-static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen) |
|
384 |
+static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen, size_t sectorsize) |
|
385 | 385 |
{ |
386 | 386 |
unsigned i = 0; |
387 | 387 |
off_t partoff = 0; |
388 |
- size_t partsize = 0, sectorsize = MBR_SECTOR_SIZE; |
|
388 |
+ size_t partsize = 0; |
|
389 | 389 |
|
390 | 390 |
for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) { |
391 | 391 |
/* check status */ |
... | ... |
@@ -396,7 +387,7 @@ static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen) |
396 | 396 |
} |
397 | 397 |
|
398 | 398 |
partoff = record->entries[i].firstLBA * sectorsize; |
399 |
- partsize = record->entries[i].numSectors * sectorsize; |
|
399 |
+ partsize = record->entries[i].numLBA * sectorsize; |
|
400 | 400 |
if (partoff + partsize > maplen) { |
401 | 401 |
cli_dbgmsg("cli_scanmbr: Invalid partition entry\n"); |
402 | 402 |
return CL_EFORMAT; |
... | ... |
@@ -416,7 +407,7 @@ static int mbr_check_ebr(struct mbr_boot_record *record) |
416 | 416 |
{ |
417 | 417 |
unsigned i = 0; |
418 | 418 |
|
419 |
- for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) { |
|
419 |
+ for (i = 0; i < MBR_MAX_PARTITION_ENTRIES-2; ++i) { |
|
420 | 420 |
/* check status */ |
421 | 421 |
if ((record->entries[i].status != MBR_STATUS_INACTIVE) && |
422 | 422 |
(record->entries[i].status != MBR_STATUS_ACTIVE)) { |
... | ... |
@@ -438,27 +429,31 @@ static int mbr_check_ebr(struct mbr_boot_record *record) |
438 | 438 |
static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize) |
439 | 439 |
{ |
440 | 440 |
prtn_intxn_list_t prtncheck; |
441 |
- unsigned i, pitxn; |
|
441 |
+ unsigned i = 0, pitxn = 0, prtncount = 0; |
|
442 | 442 |
int ret = 0, tmp = 0; |
443 | 443 |
|
444 | 444 |
prtn_intxn_list_init(&prtncheck); |
445 | 445 |
|
446 |
- for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) { |
|
447 |
- if (mbr.entries[i].type != MBR_EMPTY) { |
|
448 |
- tmp = prtn_intxn_list_check(&prtncheck, &pitxn, mbr.entries[i].firstLBA, |
|
449 |
- mbr.entries[i].numSectors); |
|
446 |
+ for (i = 0; i < MBR_MAX_PARTITION_ENTRIES && prtncount < ctx->engine->maxpartitions; ++i) { |
|
447 |
+ if (mbr.entries[i].type == MBR_EMPTY) { |
|
448 |
+ /* empty partiton entry */ |
|
449 |
+ prtncount++; |
|
450 |
+ } |
|
451 |
+ else { |
|
452 |
+ tmp = prtn_intxn_list_check(&prtncheck, &pitxn, mbr.entries[i].firstLBA, |
|
453 |
+ mbr.entries[i].numLBA); |
|
450 | 454 |
if (tmp != CL_CLEAN) { |
451 | 455 |
if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) { |
452 | 456 |
cli_dbgmsg("cli_scanmbr: detected intersection with partitions " |
453 | 457 |
"[%u, %u]\n", pitxn, i); |
454 |
- cli_append_virus(ctx, "Heuristic.PartitionIntersection"); |
|
458 |
+ cli_append_virus(ctx, PRTN_INTXN_DETECTION); |
|
455 | 459 |
ret = tmp; |
456 | 460 |
tmp = 0; |
457 | 461 |
} |
458 | 462 |
else if (tmp == CL_VIRUS) { |
459 | 463 |
cli_dbgmsg("cli_scanmbr: detected intersection with partitions " |
460 | 464 |
"[%u, %u]\n", pitxn, i); |
461 |
- cli_append_virus(ctx, "Heuristic.PartitionIntersection"); |
|
465 |
+ cli_append_virus(ctx, PRTN_INTXN_DETECTION); |
|
462 | 466 |
prtn_intxn_list_free(&prtncheck); |
463 | 467 |
return CL_VIRUS; |
464 | 468 |
} |
... | ... |
@@ -467,57 +462,17 @@ static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size |
467 | 467 |
return tmp; |
468 | 468 |
} |
469 | 469 |
} |
470 |
- } |
|
471 |
- } |
|
472 |
- |
|
473 |
- prtn_intxn_list_free(&prtncheck); |
|
474 |
- return ret; |
|
475 |
-} |
|
476 |
- |
|
477 |
-/* checks internal logical partitions */ |
|
478 |
-static int mbr_extended_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize) |
|
479 |
-{ |
|
480 |
- struct mbr_boot_record ebr; |
|
481 |
- prtn_intxn_list_t prtncheck; |
|
482 |
- unsigned i, j, pitxn; |
|
483 |
- int ret = 0, tmp = 0; |
|
484 |
- off_t pos = 0, exoff = 0, exloff = 0; |
|
485 |
- |
|
486 |
- for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) { |
|
487 |
- if (mbr.entries[i].type == MBR_EXTENDED) { |
|
488 |
- |
|
489 |
- prtn_intxn_list_init(&prtncheck); |
|
490 |
- |
|
491 |
- exoff = mbr.entries[i].firstLBA; |
|
492 |
- exloff = 0; j = 0; |
|
493 |
- do { |
|
494 |
- pos = exoff * sectorsize; /* start of extended partition */ |
|
495 |
- |
|
496 |
- /* read the extended boot record */ |
|
497 |
- pos += (exloff * sectorsize) + MBR_BASE_OFFSET; |
|
498 |
- if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) { |
|
499 |
- cli_dbgmsg("cli_scanebr: Invalid extended boot record\n"); |
|
500 |
- prtn_intxn_list_free(&prtncheck); |
|
501 |
- return CL_EFORMAT; |
|
502 |
- } |
|
503 | 470 |
|
504 |
- /* convert the little endian to host */ |
|
505 |
- mbr_convert_to_host(&ebr); |
|
506 |
- |
|
507 |
- /* assume that logical record is first and extended is second */ |
|
508 |
- tmp = prtn_intxn_list_check(&prtncheck, &pitxn, exloff, ebr.entries[0].numSectors); |
|
471 |
+ if (mbr.entries[i].type == MBR_EXTENDED) { |
|
472 |
+ /* check the logical partitions */ |
|
473 |
+ tmp = mbr_extended_prtn_intxn(ctx, &prtncount, |
|
474 |
+ mbr.entries[i].firstLBA, sectorsize); |
|
509 | 475 |
if (tmp != CL_CLEAN) { |
510 | 476 |
if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) { |
511 |
- cli_dbgmsg("cli_scanebr: detected intersection with partitions " |
|
512 |
- "[%u, %u]\n", pitxn, i); |
|
513 |
- cli_append_virus(ctx, "Heuristic.PartitionIntersection"); |
|
514 | 477 |
ret = tmp; |
515 | 478 |
tmp = 0; |
516 | 479 |
} |
517 | 480 |
else if (tmp == CL_VIRUS) { |
518 |
- cli_dbgmsg("cli_scanebr: detected intersection with partitions " |
|
519 |
- "[%u, %u]\n", pitxn, i); |
|
520 |
- cli_append_virus(ctx, "Heuristic.PartitionIntersection"); |
|
521 | 481 |
prtn_intxn_list_free(&prtncheck); |
522 | 482 |
return CL_VIRUS; |
523 | 483 |
} |
... | ... |
@@ -526,27 +481,80 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, siz |
526 | 526 |
return tmp; |
527 | 527 |
} |
528 | 528 |
} |
529 |
+ } |
|
530 |
+ else { |
|
531 |
+ prtncount++; |
|
532 |
+ } |
|
533 |
+ } |
|
534 |
+ } |
|
529 | 535 |
|
530 |
- /* assume extended is second entry */ |
|
531 |
- if (ebr.entries[1].type != MBR_EXTENDED) { |
|
532 |
- cli_dbgmsg("cli_scanebr: second entry for EBR is not an extended partition\n"); |
|
533 |
- break; |
|
534 |
- } |
|
536 |
+ prtn_intxn_list_free(&prtncheck); |
|
537 |
+ return ret; |
|
538 |
+} |
|
539 |
+ |
|
540 |
+/* checks internal logical partitions */ |
|
541 |
+static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size_t sectorsize) |
|
542 |
+{ |
|
543 |
+ struct mbr_boot_record ebr; |
|
544 |
+ prtn_intxn_list_t prtncheck; |
|
545 |
+ unsigned i, pitxn; |
|
546 |
+ int ret = 0, tmp = 0; |
|
547 |
+ off_t pos = 0, logiclba = 0; |
|
548 |
+ |
|
549 |
+ prtn_intxn_list_init(&prtncheck); |
|
535 | 550 |
|
536 |
- exloff = ebr.entries[1].firstLBA; |
|
551 |
+ logiclba = 0; i = 0; |
|
552 |
+ do { |
|
553 |
+ pos = extlba * sectorsize; /* start of extended partition */ |
|
537 | 554 |
|
538 |
- ++j; |
|
539 |
- } while (exloff != 0 && j < CL_MAX_LOGICAL_PARTITIONS); |
|
555 |
+ /* read the extended boot record */ |
|
556 |
+ pos += (logiclba * sectorsize) + MBR_BASE_OFFSET; |
|
557 |
+ if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) { |
|
558 |
+ cli_dbgmsg("cli_scanebr: Invalid extended boot record\n"); |
|
559 |
+ prtn_intxn_list_free(&prtncheck); |
|
560 |
+ return CL_EFORMAT; |
|
561 |
+ } |
|
540 | 562 |
|
541 |
- if (j == CL_MAX_LOGICAL_PARTITIONS) { |
|
542 |
- cli_dbgmsg("cli_scanebr: reached maximum number of scanned logical partitions\n"); |
|
563 |
+ /* convert the little endian to host */ |
|
564 |
+ mbr_convert_to_host(&ebr); |
|
565 |
+ |
|
566 |
+ /* update state */ |
|
567 |
+ (*prtncount)++; |
|
568 |
+ |
|
569 |
+ /* assume that logical record is first and extended is second */ |
|
570 |
+ tmp = prtn_intxn_list_check(&prtncheck, &pitxn, logiclba, ebr.entries[0].numLBA); |
|
571 |
+ if (tmp != CL_CLEAN) { |
|
572 |
+ if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) { |
|
573 |
+ cli_dbgmsg("cli_scanebr: detected intersection with partitions " |
|
574 |
+ "[%u, %u]\n", pitxn, i); |
|
575 |
+ cli_append_virus(ctx, PRTN_INTXN_DETECTION); |
|
576 |
+ ret = tmp; |
|
577 |
+ tmp = 0; |
|
578 |
+ } |
|
579 |
+ else if (tmp == CL_VIRUS) { |
|
580 |
+ cli_dbgmsg("cli_scanebr: detected intersection with partitions " |
|
581 |
+ "[%u, %u]\n", pitxn, i); |
|
582 |
+ cli_append_virus(ctx, PRTN_INTXN_DETECTION); |
|
583 |
+ prtn_intxn_list_free(&prtncheck); |
|
584 |
+ return CL_VIRUS; |
|
543 | 585 |
} |
586 |
+ else { |
|
587 |
+ prtn_intxn_list_free(&prtncheck); |
|
588 |
+ return tmp; |
|
589 |
+ } |
|
590 |
+ } |
|
544 | 591 |
|
545 |
- prtn_intxn_list_free(&prtncheck); |
|
592 |
+ /* assume extended is second entry */ |
|
593 |
+ if (ebr.entries[1].type != MBR_EXTENDED) { |
|
594 |
+ cli_dbgmsg("cli_scanebr: second entry for EBR is not an extended partition\n"); |
|
595 |
+ break; |
|
546 | 596 |
} |
547 |
- } |
|
548 | 597 |
|
598 |
+ logiclba = ebr.entries[1].firstLBA; |
|
549 | 599 |
|
550 |
- return ret; |
|
600 |
+ ++i; |
|
601 |
+ } while (logiclba != 0 && (*prtncount) < ctx->engine->maxpartitions); |
|
551 | 602 |
|
603 |
+ prtn_intxn_list_free(&prtncheck); |
|
604 |
+ return ret; |
|
552 | 605 |
} |