Browse code

Mon Jan 26 16:00:02 GMT 2004 (trog) ----------------------------------- * libclamav: VBA decoder - Fix malloc off-by-one. Add checking for middle and end strings in VBA project file. Fix compiler warnings. OLE2 unpacker - Remove global variables. Fix for nasty MacOffice docs.

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
Showing 3 changed files
... ...
@@ -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 {