git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@210 77e5149b-7576-45b1-b177-96237e5ba77b
Trog authored on 2004/01/27 01:03:45... | ... |
@@ -1,3 +1,11 @@ |
1 |
+Mon Jan 26 16:00:02 GMT 2004 (trog) |
|
2 |
+----------------------------------- |
|
3 |
+ * libclamav: VBA decoder - Fix malloc off-by-one. Add checking |
|
4 |
+ for middle and end strings in VBA project file. |
|
5 |
+ Fix compiler warnings. |
|
6 |
+ OLE2 unpacker - Remove global variables. Fix for |
|
7 |
+ nasty MacOffice docs. |
|
8 |
+ |
|
1 | 9 |
Mon Jan 26 14:14:27 GMT 2004 (njh) |
2 | 10 |
---------------------------------- |
3 | 11 |
* clamav-milter: Corrected endian problem (ntohs instead of htons) |
... | ... |
@@ -37,9 +37,6 @@ |
37 | 37 |
|
38 | 38 |
#define MIN(a, b) (((a) < (b)) ? (a) : (b)) |
39 | 39 |
|
40 |
-int big_block_size, small_block_size; |
|
41 |
-int sbat_start=-1; |
|
42 |
- |
|
43 | 40 |
typedef struct ole2_header_tag |
44 | 41 |
{ |
45 | 42 |
unsigned char magic[8]; /* should be: 0xd0cf11e0a1b11ae1 */ |
... | ... |
@@ -63,6 +60,11 @@ typedef struct ole2_header_tag |
63 | 63 |
int32_t xbat_start; |
64 | 64 |
int32_t xbat_count; |
65 | 65 |
int32_t bat_array[109]; |
66 |
+ |
|
67 |
+ /* not part of the ole2 header, but stuff we need in order to decode */ |
|
68 |
+ /* must take account of the size of variables below here when |
|
69 |
+ reading the header */ |
|
70 |
+ int sbat_root_start; |
|
66 | 71 |
} ole2_header_t __attribute__ ((packed)); |
67 | 72 |
|
68 | 73 |
typedef struct property_tag |
... | ... |
@@ -146,7 +148,7 @@ void print_property_name(char *name, int size) |
146 | 146 |
int i, count=0; |
147 | 147 |
|
148 | 148 |
if (*name == 0 || size == 0) { |
149 |
- cli_dbgmsg("[unused] "); |
|
149 |
+ cli_dbgmsg("[no name] "); |
|
150 | 150 |
return; |
151 | 151 |
} |
152 | 152 |
/* size-2 to ignore trailing NULL */ |
... | ... |
@@ -173,7 +175,7 @@ char *get_property_name(char *name, int size) |
173 | 173 |
return NULL; |
174 | 174 |
} |
175 | 175 |
|
176 |
- newname = (char *) cli_malloc(size); |
|
176 |
+ newname = (char *) cli_malloc(size*2); |
|
177 | 177 |
if (!newname) { |
178 | 178 |
return NULL; |
179 | 179 |
} |
... | ... |
@@ -191,6 +193,11 @@ char *get_property_name(char *name, int size) |
191 | 191 |
} |
192 | 192 |
} |
193 | 193 |
newname[j] = '\0'; |
194 |
+ if (strlen(newname) == 0) { |
|
195 |
+ printf ("zero sized newname\n"); |
|
196 |
+ free(newname); |
|
197 |
+ return NULL; |
|
198 |
+ } |
|
194 | 199 |
return newname; |
195 | 200 |
} |
196 | 201 |
|
... | ... |
@@ -267,7 +274,7 @@ int ole2_read_block(int fd, ole2_header_t *hdr, void *buff, int blockno) |
267 | 267 |
if (lseek(fd, offset, SEEK_SET) != offset) { |
268 | 268 |
return FALSE; |
269 | 269 |
} |
270 |
- if (readn(fd, buff, big_block_size) != big_block_size) { |
|
270 |
+ if (readn(fd, buff, (1 << hdr->log2_big_block_size)) != (1 << hdr->log2_big_block_size)) { |
|
271 | 271 |
return FALSE; |
272 | 272 |
} |
273 | 273 |
return TRUE; |
... | ... |
@@ -345,13 +352,13 @@ int ole2_get_sbat_data_block(int fd, ole2_header_t *hdr, void *buff, int sbat_in |
345 | 345 |
int block_count; |
346 | 346 |
int current_block; |
347 | 347 |
|
348 |
- if (sbat_start < 0) { |
|
348 |
+ if (hdr->sbat_root_start < 0) { |
|
349 | 349 |
cli_errmsg("No root start block\n"); |
350 | 350 |
return FALSE; |
351 | 351 |
} |
352 | 352 |
|
353 | 353 |
block_count = sbat_index / 8; // 8 small blocks per big block |
354 |
- current_block = sbat_start; |
|
354 |
+ current_block = hdr->sbat_root_start; |
|
355 | 355 |
while (block_count > 0) { |
356 | 356 |
current_block = ole2_get_next_bat_block(fd, hdr, current_block); |
357 | 357 |
block_count--; |
... | ... |
@@ -376,9 +383,9 @@ void ole2_read_property_tree(int fd, ole2_header_t *hdr, const char *dir, |
376 | 376 |
while(current_block >= 0) { |
377 | 377 |
ole2_read_block(fd, hdr, prop_block, current_block); |
378 | 378 |
for (index=0 ; index < 4 ; index++) { |
379 |
- if (prop_block[index].name[0] != 0) { |
|
379 |
+ if (prop_block[index].type > 0) { |
|
380 | 380 |
if (prop_block[index].type == 5) { |
381 |
- sbat_start = prop_block[index].start_block; |
|
381 |
+ hdr->sbat_root_start = prop_block[index].start_block; |
|
382 | 382 |
} |
383 | 383 |
print_ole2_property(&prop_block[index]); |
384 | 384 |
handler(fd, hdr, &prop_block[index], dir); |
... | ... |
@@ -401,7 +408,7 @@ void handler_null(int fd, ole2_header_t *hdr, property_t *prop, const char *dir) |
401 | 401 |
/* Write file Handler - write the contents of the entry to a file */ |
402 | 402 |
void handler_writefile(int fd, ole2_header_t *hdr, property_t *prop, const char *dir) |
403 | 403 |
{ |
404 |
- unsigned char buff[big_block_size]; |
|
404 |
+ unsigned char buff[(1 << hdr->log2_big_block_size)]; |
|
405 | 405 |
int current_block, ofd, len, offset; |
406 | 406 |
char *name, *newname; |
407 | 407 |
|
... | ... |
@@ -411,7 +418,15 @@ void handler_writefile(int fd, ole2_header_t *hdr, property_t *prop, const char |
411 | 411 |
} |
412 | 412 |
|
413 | 413 |
if (! (name = get_property_name(prop->name, prop->name_size))) { |
414 |
- return; |
|
414 |
+ /* File without a name - create a name for it */ |
|
415 |
+ int i; |
|
416 |
+ |
|
417 |
+ i = lseek(fd, 0, SEEK_CUR); |
|
418 |
+ name = malloc(11); |
|
419 |
+ if (!name) { |
|
420 |
+ return; |
|
421 |
+ } |
|
422 |
+ snprintf(name, 10, "%.10d", i + (int) prop); |
|
415 | 423 |
} |
416 | 424 |
|
417 | 425 |
newname = (char *) cli_malloc(strlen(name) + strlen(dir) + 2); |
... | ... |
@@ -449,13 +464,14 @@ void handler_writefile(int fd, ole2_header_t *hdr, property_t *prop, const char |
449 | 449 |
close(ofd); |
450 | 450 |
return; |
451 | 451 |
} |
452 |
- if (writen(ofd, &buff, MIN(len,big_block_size)) != MIN(len,big_block_size)) { |
|
452 |
+ if (writen(ofd, &buff, MIN(len,(1 << hdr->log2_big_block_size))) != |
|
453 |
+ MIN(len,(1 << hdr->log2_big_block_size))) { |
|
453 | 454 |
close(ofd); |
454 | 455 |
return; |
455 | 456 |
} |
456 | 457 |
|
457 | 458 |
current_block = ole2_get_next_block_number(fd, hdr, current_block); |
458 |
- len -= MIN(len,big_block_size); |
|
459 |
+ len -= MIN(len,(1 << hdr->log2_big_block_size)); |
|
459 | 460 |
} |
460 | 461 |
} |
461 | 462 |
close(ofd); |
... | ... |
@@ -468,7 +484,10 @@ int cli_ole2_extract(int fd, const char *dirname) |
468 | 468 |
|
469 | 469 |
cli_dbgmsg("in cli_ole2_extract()\n"); |
470 | 470 |
|
471 |
- readn(fd, &hdr, sizeof(struct ole2_header_tag)); |
|
471 |
+ /* size of header - size of other values in struct */ |
|
472 |
+ readn(fd, &hdr, sizeof(struct ole2_header_tag) - sizeof(int)); |
|
473 |
+ |
|
474 |
+ hdr.sbat_root_start = -1; |
|
472 | 475 |
|
473 | 476 |
if (strncmp(hdr.magic, magic_id, 8) != 0) { |
474 | 477 |
cli_dbgmsg("OLE2 magic failed!\n"); |
... | ... |
@@ -485,9 +504,6 @@ int cli_ole2_extract(int fd, const char *dirname) |
485 | 485 |
cli_dbgmsg("WARNING: untested sbat cutoff - please report\n\n"); |
486 | 486 |
} |
487 | 487 |
|
488 |
- big_block_size = 1 << hdr.log2_big_block_size; |
|
489 |
- small_block_size = 1 << hdr.log2_small_block_size; |
|
490 |
- |
|
491 | 488 |
print_ole2_header(&hdr); |
492 | 489 |
|
493 | 490 |
ole2_read_property_tree(fd, &hdr, dirname, handler_writefile); |
... | ... |
@@ -128,7 +128,7 @@ char *get_unicode_name(char *name, int size) |
128 | 128 |
return NULL; |
129 | 129 |
} |
130 | 130 |
|
131 |
- newname = (char *) cli_malloc(size); |
|
131 |
+ newname = (char *) cli_malloc(size*2); |
|
132 | 132 |
if (!newname) { |
133 | 133 |
return NULL; |
134 | 134 |
} |
... | ... |
@@ -147,7 +147,48 @@ char *get_unicode_name(char *name, int size) |
147 | 147 |
newname[j] = '\0'; |
148 | 148 |
return newname; |
149 | 149 |
} |
150 |
- |
|
150 |
+ |
|
151 |
+static void vba56_test_middle(int fd) |
|
152 |
+{ |
|
153 |
+ char test_middle[20]; |
|
154 |
+ static const uint8_t middle_str[20] = { |
|
155 |
+ 0x00, 0x00, 0xe1, 0x2e, 0x45, 0x0d, 0x8f, 0xe0, |
|
156 |
+ 0x1a, 0x10, 0x85, 0x2e, 0x02, 0x60, 0x8c, 0x4d, |
|
157 |
+ 0x0b, 0xb4, 0x00, 0x00 |
|
158 |
+ }; |
|
159 |
+ |
|
160 |
+ if (vba_readn(fd, &test_middle, 20) != 20) { |
|
161 |
+ return; |
|
162 |
+ } |
|
163 |
+ |
|
164 |
+ if (strncmp(test_middle, middle_str, 20) != 0) { |
|
165 |
+ lseek(fd, -20, SEEK_CUR); |
|
166 |
+ } |
|
167 |
+ return; |
|
168 |
+} |
|
169 |
+ |
|
170 |
+static void vba56_test_end(int fd) |
|
171 |
+{ |
|
172 |
+ char test_end[20]; |
|
173 |
+ static const uint8_t end_str[20] = |
|
174 |
+ { |
|
175 |
+ 0x00, 0x00, 0x2e, 0xc9, 0x27, 0x8e, 0x64, 0x12, |
|
176 |
+ 0x1c, 0x10, 0x8a, 0x2f, 0x04, 0x02, 0x24, 0x00, |
|
177 |
+ 0x9c, 0x02, 0x00, 0x00 |
|
178 |
+ }; |
|
179 |
+ |
|
180 |
+ if (vba_readn(fd, &test_end, 20) != 20) { |
|
181 |
+ return; |
|
182 |
+ } |
|
183 |
+ |
|
184 |
+ if (strncmp(test_end, end_str, 20) != 0) { |
|
185 |
+ lseek(fd, -20, SEEK_CUR); |
|
186 |
+ } |
|
187 |
+ printf("End found\n"); |
|
188 |
+ return; |
|
189 |
+} |
|
190 |
+ |
|
191 |
+ |
|
151 | 192 |
vba_project_t *vba56_dir_read(const char *dir) |
152 | 193 |
{ |
153 | 194 |
unsigned char magic[2]; |
... | ... |
@@ -176,7 +217,7 @@ vba_project_t *vba56_dir_read(const char *dir) |
176 | 176 |
|
177 | 177 |
cli_dbgmsg("in vba56_dir_read()\n"); |
178 | 178 |
|
179 |
- fullname = (char *) cli_malloc(strlen(dir) + 14); |
|
179 |
+ fullname = (char *) cli_malloc(strlen(dir) + 15); |
|
180 | 180 |
sprintf(fullname, "%s/_VBA_PROJECT", dir); |
181 | 181 |
fd = open(fullname, O_RDONLY); |
182 | 182 |
|
... | ... |
@@ -276,13 +317,17 @@ vba_project_t *vba56_dir_read(const char *dir) |
276 | 276 |
return NULL; |
277 | 277 |
}*/ |
278 | 278 |
|
279 |
- for (i=0; record_count >0 ; record_count--) { |
|
279 |
+ for (;;) { |
|
280 | 280 |
|
281 | 281 |
if (vba_readn(fd, &length, 2) != 2) { |
282 | 282 |
return NULL; |
283 | 283 |
} |
284 |
+ if (length < 6) { |
|
285 |
+ lseek(fd, -2, SEEK_CUR); |
|
286 |
+ break; |
|
287 |
+ } |
|
284 | 288 |
cli_dbgmsg ("record: %d.%d, length: %d, ", record_count, i, length); |
285 |
- buff = cli_malloc(length); |
|
289 |
+ buff = (unsigned char *) cli_malloc(length); |
|
286 | 290 |
if (!buff) { |
287 | 291 |
cli_errmsg("cli_malloc failed\n"); |
288 | 292 |
return NULL; |
... | ... |
@@ -300,7 +345,7 @@ vba_project_t *vba56_dir_read(const char *dir) |
300 | 300 |
having a 12 byte trailer */ |
301 | 301 |
/* TODO: Need to check if types H(same as G) and D(same as C) exist */ |
302 | 302 |
if (!strncmp ("*\\G", name, 3)) { |
303 |
- buff = cli_malloc(12); |
|
303 |
+ buff = (unsigned char *) cli_malloc(12); |
|
304 | 304 |
if (vba_readn(fd, buff, 12) != 12) { |
305 | 305 |
cli_errmsg("failed to read blob\n"); |
306 | 306 |
free(buff); |
... | ... |
@@ -310,7 +355,7 @@ vba_project_t *vba56_dir_read(const char *dir) |
310 | 310 |
free(buff); |
311 | 311 |
} else if (!strncmp("*\\C", name, 3)) { |
312 | 312 |
if (i == 1) { |
313 |
- buff = cli_malloc(12); |
|
313 |
+ buff = (unsigned char *) cli_malloc(12); |
|
314 | 314 |
if (vba_readn(fd, buff, 12) != 12) { |
315 | 315 |
cli_errmsg("failed to read blob\n"); |
316 | 316 |
free(buff); |
... | ... |
@@ -324,12 +369,16 @@ vba_project_t *vba56_dir_read(const char *dir) |
324 | 324 |
record_count++; |
325 | 325 |
} |
326 | 326 |
} else { |
327 |
- cli_errmsg("unknown record type!!\n\n"); |
|
327 |
+ /* Unknown type - probably ran out of strings - rewind */ |
|
328 |
+ lseek(fd, -(length+2), SEEK_CUR); |
|
329 |
+ break; |
|
328 | 330 |
} |
329 | 331 |
free(name); |
332 |
+ vba56_test_middle(fd); |
|
330 | 333 |
} |
331 | 334 |
|
332 |
- /* TODO: may need to seek forward 20 bytes here. Bleh! */ |
|
335 |
+ /* may need to seek forward 20 bytes here. Bleh! */ |
|
336 |
+ vba56_test_end(fd); |
|
333 | 337 |
|
334 | 338 |
if (vba_readn(fd, &record_count, 2) != 2) { |
335 | 339 |
return NULL; |
... | ... |
@@ -343,7 +392,7 @@ vba_project_t *vba56_dir_read(const char *dir) |
343 | 343 |
lseek(fd, 4, SEEK_CUR); |
344 | 344 |
|
345 | 345 |
/* Read fixed octet */ |
346 |
- buff = cli_malloc(8); |
|
346 |
+ buff = (unsigned char *) cli_malloc(8); |
|
347 | 347 |
if (!buff) { |
348 | 348 |
return NULL; |
349 | 349 |
} |
... | ... |
@@ -396,7 +445,7 @@ vba_project_t *vba56_dir_read(const char *dir) |
396 | 396 |
if (vba_readn(fd, &length, 2) != 2) { |
397 | 397 |
return NULL; |
398 | 398 |
} |
399 |
- buff = cli_malloc(length); |
|
399 |
+ buff = (unsigned char *) cli_malloc(length); |
|
400 | 400 |
if (!buff) { |
401 | 401 |
cli_dbgmsg("cli_malloc failed\n"); |
402 | 402 |
return NULL; |
... | ... |
@@ -462,7 +511,7 @@ vba_project_t *vba56_dir_read(const char *dir) |
462 | 462 |
void byte_array_append(byte_array_t *array, unsigned char *src, unsigned int len) |
463 | 463 |
{ |
464 | 464 |
if (array->length == 0) { |
465 |
- array->data = cli_malloc(len); |
|
465 |
+ array->data = (unsigned char *) cli_malloc(len); |
|
466 | 466 |
array->length = len; |
467 | 467 |
strncpy(array->data, src, len); |
468 | 468 |
} else { |