...
|
...
|
@@ -81,7 +81,7 @@ typedef struct ole2_header_tag
|
81
|
81
|
int16_t byte_order __attribute__ ((packed)); /* -2=intel */
|
82
|
82
|
|
83
|
83
|
uint16_t log2_big_block_size __attribute__ ((packed)); /* usually 9 (2^9 = 512) */
|
84
|
|
- uint32_t log2_small_block_size __attribute__ ((packed)); /* usually 6 (2^6 = 128) */
|
|
84
|
+ uint32_t log2_small_block_size __attribute__ ((packed)); /* usually 6 (2^6 = 64) */
|
85
|
85
|
|
86
|
86
|
int32_t reserved[2] __attribute__ ((packed));
|
87
|
87
|
int32_t bat_count __attribute__ ((packed));
|
...
|
...
|
@@ -288,7 +288,7 @@ static void print_ole2_header(ole2_header_t *hdr)
|
288
|
288
|
return;
|
289
|
289
|
}
|
290
|
290
|
|
291
|
|
-static int ole2_read_block(int fd, ole2_header_t *hdr, void *buff, int32_t blockno)
|
|
291
|
+static int ole2_read_block(int fd, ole2_header_t *hdr, void *buff, unsigned int size, int32_t blockno)
|
292
|
292
|
{
|
293
|
293
|
off_t offset, offend;
|
294
|
294
|
|
...
|
...
|
@@ -297,21 +297,21 @@ static int ole2_read_block(int fd, ole2_header_t *hdr, void *buff, int32_t block
|
297
|
297
|
}
|
298
|
298
|
|
299
|
299
|
/* other methods: (blockno+1) * 512 or (blockno * block_size) + 512; */
|
300
|
|
- offset = (blockno << hdr->log2_big_block_size) + 512; /* 512 is header size */
|
|
300
|
+ offset = (blockno << hdr->log2_big_block_size) + MAX(512, 1 << hdr->log2_big_block_size); /* 512 is header size */
|
301
|
301
|
|
302
|
302
|
if (hdr->m_area == NULL) {
|
303
|
303
|
if (lseek(fd, offset, SEEK_SET) != offset) {
|
304
|
304
|
return FALSE;
|
305
|
305
|
}
|
306
|
|
- if (cli_readn(fd, buff, (1 << hdr->log2_big_block_size)) != (1 << hdr->log2_big_block_size)) {
|
|
306
|
+ if (cli_readn(fd, buff, size) != size) {
|
307
|
307
|
return FALSE;
|
308
|
308
|
}
|
309
|
309
|
} else {
|
310
|
|
- offend = offset + (1 << hdr->log2_big_block_size);
|
|
310
|
+ offend = offset + size;
|
311
|
311
|
if ((offend <= 0) || (offend > hdr->m_length)) {
|
312
|
312
|
return FALSE;
|
313
|
313
|
}
|
314
|
|
- memcpy(buff, hdr->m_area+offset, (1 << hdr->log2_big_block_size));
|
|
314
|
+ memcpy(buff, hdr->m_area+offset, size);
|
315
|
315
|
}
|
316
|
316
|
return TRUE;
|
317
|
317
|
}
|
...
|
...
|
@@ -330,7 +330,7 @@ static int32_t ole2_get_next_bat_block(int fd, ole2_header_t *hdr, int32_t curre
|
330
|
330
|
cli_dbgmsg("bat_array index error\n");
|
331
|
331
|
return -10;
|
332
|
332
|
}
|
333
|
|
- if (!ole2_read_block(fd, hdr, &bat,
|
|
333
|
+ if (!ole2_read_block(fd, hdr, &bat, 512,
|
334
|
334
|
ole2_endian_convert_32(hdr->bat_array[bat_array_index]))) {
|
335
|
335
|
return -1;
|
336
|
336
|
}
|
...
|
...
|
@@ -356,20 +356,20 @@ static int32_t ole2_get_next_xbat_block(int fd, ole2_header_t *hdr, int32_t curr
|
356
|
356
|
|
357
|
357
|
bat_index = current_block % 128;
|
358
|
358
|
|
359
|
|
- if (!ole2_read_block(fd, hdr, &xbat, hdr->xbat_start)) {
|
|
359
|
+ if (!ole2_read_block(fd, hdr, &xbat, 512, hdr->xbat_start)) {
|
360
|
360
|
return -1;
|
361
|
361
|
}
|
362
|
362
|
|
363
|
363
|
/* Follow the chain of XBAT blocks */
|
364
|
364
|
while (xbat_block_index > 0) {
|
365
|
|
- if (!ole2_read_block(fd, hdr, &xbat,
|
|
365
|
+ if (!ole2_read_block(fd, hdr, &xbat, 512,
|
366
|
366
|
ole2_endian_convert_32(xbat[127]))) {
|
367
|
367
|
return -1;
|
368
|
368
|
}
|
369
|
369
|
xbat_block_index--;
|
370
|
370
|
}
|
371
|
371
|
|
372
|
|
- if (!ole2_read_block(fd, hdr, &bat, ole2_endian_convert_32(xbat[bat_blockno]))) {
|
|
372
|
+ if (!ole2_read_block(fd, hdr, &bat, 512, ole2_endian_convert_32(xbat[bat_blockno]))) {
|
373
|
373
|
return -1;
|
374
|
374
|
}
|
375
|
375
|
|
...
|
...
|
@@ -404,7 +404,7 @@ static int32_t ole2_get_next_sbat_block(int fd, ole2_header_t *hdr, int32_t curr
|
404
|
404
|
current_bat_block = ole2_get_next_block_number(fd, hdr, current_bat_block);
|
405
|
405
|
iter--;
|
406
|
406
|
}
|
407
|
|
- if (!ole2_read_block(fd, hdr, &sbat, current_bat_block)) {
|
|
407
|
+ if (!ole2_read_block(fd, hdr, &sbat, 512, current_bat_block)) {
|
408
|
408
|
return -1;
|
409
|
409
|
}
|
410
|
410
|
return ole2_endian_convert_32(sbat[current_block % 128]);
|
...
|
...
|
@@ -424,7 +424,7 @@ static int32_t ole2_get_sbat_data_block(int fd, ole2_header_t *hdr, void *buff,
|
424
|
424
|
return FALSE;
|
425
|
425
|
}
|
426
|
426
|
|
427
|
|
- block_count = sbat_index / 8; /* 8 small blocks per big block */
|
|
427
|
+ block_count = sbat_index / (1 << (hdr->log2_big_block_size - hdr->log2_small_block_size));
|
428
|
428
|
current_block = hdr->sbat_root_start;
|
429
|
429
|
while (block_count > 0) {
|
430
|
430
|
current_block = ole2_get_next_block_number(fd, hdr, current_block);
|
...
|
...
|
@@ -433,62 +433,9 @@ static int32_t ole2_get_sbat_data_block(int fd, ole2_header_t *hdr, void *buff,
|
433
|
433
|
/* current_block now contains the block number of the sbat array
|
434
|
434
|
containing the entry for the required small block */
|
435
|
435
|
|
436
|
|
- return(ole2_read_block(fd, hdr, buff, current_block));
|
|
436
|
+ return(ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block));
|
437
|
437
|
}
|
438
|
438
|
|
439
|
|
-/* Read the property tree.
|
440
|
|
- It is read as just an array rather than a tree */
|
441
|
|
-/*
|
442
|
|
-static void ole2_read_property_tree(int fd, ole2_header_t *hdr, const char *dir,
|
443
|
|
- int (*handler)(int fd, ole2_header_t *hdr, property_t *prop, const char *dir))
|
444
|
|
-{
|
445
|
|
- property_t prop_block[4];
|
446
|
|
- int32_t index, current_block, count=0;
|
447
|
|
-
|
448
|
|
- current_block = hdr->prop_start;
|
449
|
|
-
|
450
|
|
- while(current_block >= 0) {
|
451
|
|
- if (!ole2_read_block(fd, hdr, prop_block,
|
452
|
|
- current_block)) {
|
453
|
|
- return;
|
454
|
|
- }
|
455
|
|
- for (index=0 ; index < 4 ; index++) {
|
456
|
|
- if (prop_block[index].type > 0) {
|
457
|
|
- prop_block[index].name_size = ole2_endian_convert_16(prop_block[index].name_size);
|
458
|
|
- prop_block[index].prev = ole2_endian_convert_32(prop_block[index].prev);
|
459
|
|
- prop_block[index].next = ole2_endian_convert_32(prop_block[index].next);
|
460
|
|
- prop_block[index].child = ole2_endian_convert_32(prop_block[index].child);
|
461
|
|
- prop_block[index].user_flags = ole2_endian_convert_32(prop_block[index].user_flags);
|
462
|
|
- prop_block[index].create_lowdate = ole2_endian_convert_32(prop_block[index].create_lowdate);
|
463
|
|
- prop_block[index].create_highdate = ole2_endian_convert_32(prop_block[index].create_highdate);
|
464
|
|
- prop_block[index].mod_lowdate = ole2_endian_convert_32(prop_block[index].mod_lowdate);
|
465
|
|
- prop_block[index].mod_highdate = ole2_endian_convert_32(prop_block[index].mod_highdate);
|
466
|
|
- prop_block[index].start_block = ole2_endian_convert_32(prop_block[index].start_block);
|
467
|
|
- prop_block[index].size = ole2_endian_convert_32(prop_block[index].size);
|
468
|
|
- if (prop_block[index].type > 5) {
|
469
|
|
- cli_dbgmsg("ERROR: invalid property type: %d\n", prop_block[index].type);
|
470
|
|
- return;
|
471
|
|
- }
|
472
|
|
- if (prop_block[index].type == 5) {
|
473
|
|
- hdr->sbat_root_start = prop_block[index].start_block;
|
474
|
|
- }
|
475
|
|
- print_ole2_property(&prop_block[index]);
|
476
|
|
- if (!handler(fd, hdr, &prop_block[index], dir)) {
|
477
|
|
- cli_dbgmsg("ERROR: handler failed\n");
|
478
|
|
- return;
|
479
|
|
- }
|
480
|
|
- }
|
481
|
|
- }
|
482
|
|
- current_block = ole2_get_next_block_number(fd, hdr, current_block);
|
483
|
|
- if (++count > 100000) {
|
484
|
|
- cli_dbgmsg("ERROR: loop detected\n");
|
485
|
|
- return;
|
486
|
|
- }
|
487
|
|
- }
|
488
|
|
- return;
|
489
|
|
-}
|
490
|
|
-*/
|
491
|
|
-
|
492
|
439
|
static int ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir, int32_t prop_index,
|
493
|
440
|
int (*handler)(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx),
|
494
|
441
|
unsigned int rec_level, unsigned int *file_count, cli_ctx *ctx, unsigned long *scansize)
|
...
|
...
|
@@ -522,7 +469,7 @@ static int ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir,
|
522
|
522
|
}
|
523
|
523
|
}
|
524
|
524
|
idx = prop_index % 4;
|
525
|
|
- if (!ole2_read_block(fd, hdr, prop_block,
|
|
525
|
+ if (!ole2_read_block(fd, hdr, prop_block, 512,
|
526
|
526
|
current_block)) {
|
527
|
527
|
return CL_SUCCESS;
|
528
|
528
|
}
|
...
|
...
|
@@ -664,6 +611,7 @@ static int handler_writefile(int fd, ole2_header_t *hdr, property_t *prop, const
|
664
|
664
|
if (!blk_bitset) {
|
665
|
665
|
cli_errmsg("OLE2 [handler_writefile]: init bitset failed\n");
|
666
|
666
|
close(ofd);
|
|
667
|
+ free(buff);
|
667
|
668
|
return CL_BREAK;
|
668
|
669
|
}
|
669
|
670
|
while((current_block >= 0) && (len > 0)) {
|
...
|
...
|
@@ -698,20 +646,21 @@ static int handler_writefile(int fd, ole2_header_t *hdr, property_t *prop, const
|
698
|
698
|
cli_bitset_free(blk_bitset);
|
699
|
699
|
return CL_SUCCESS;
|
700
|
700
|
}
|
701
|
|
- /* buff now contains the block with 8 small blocks in it */
|
702
|
|
- offset = 64 * (current_block % 8);
|
703
|
|
- if (cli_writen(ofd, &buff[offset], MIN(len,64)) != MIN(len,64)) {
|
|
701
|
+ /* buff now contains the block with N small blocks in it */
|
|
702
|
+ offset = (1 << hdr->log2_small_block_size) * (current_block % (1 << (hdr->log2_big_block_size - hdr->log2_small_block_size)));
|
|
703
|
+
|
|
704
|
+ if (cli_writen(ofd, &buff[offset], MIN(len,1 << hdr->log2_small_block_size)) != MIN(len,1 << hdr->log2_small_block_size)) {
|
704
|
705
|
close(ofd);
|
705
|
706
|
free(buff);
|
706
|
707
|
cli_bitset_free(blk_bitset);
|
707
|
708
|
return CL_BREAK;
|
708
|
709
|
}
|
709
|
710
|
|
710
|
|
- len -= MIN(len,64);
|
|
711
|
+ len -= MIN(len,1 << hdr->log2_small_block_size);
|
711
|
712
|
current_block = ole2_get_next_sbat_block(fd, hdr, current_block);
|
712
|
713
|
} else {
|
713
|
714
|
/* Big block file */
|
714
|
|
- if (!ole2_read_block(fd, hdr, buff, current_block)) {
|
|
715
|
+ if (!ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
|
715
|
716
|
close(ofd);
|
716
|
717
|
free(buff);
|
717
|
718
|
cli_bitset_free(blk_bitset);
|
...
|
...
|
@@ -821,9 +770,9 @@ static int handler_otf(int fd, ole2_header_t *hdr, property_t *prop, const char
|
821
|
821
|
cli_dbgmsg("ole2_get_sbat_data_block failed\n");
|
822
|
822
|
break;
|
823
|
823
|
}
|
824
|
|
- /* buff now contains the block with 8 small blocks in it */
|
825
|
|
- offset = 64 * (current_block % 8);
|
826
|
|
- if (cli_writen(ofd, &buff[offset], MIN(len,64)) != MIN(len,64)) {
|
|
824
|
+ /* buff now contains the block with N small blocks in it */
|
|
825
|
+ offset = (1 << hdr->log2_small_block_size) * (current_block % (1 << (hdr->log2_big_block_size - hdr->log2_small_block_size)));
|
|
826
|
+ if (cli_writen(ofd, &buff[offset], MIN(len,1 << hdr->log2_small_block_size)) != MIN(len,1 << hdr->log2_small_block_size)) {
|
827
|
827
|
close(ofd);
|
828
|
828
|
free(buff);
|
829
|
829
|
cli_bitset_free(blk_bitset);
|
...
|
...
|
@@ -835,11 +784,11 @@ static int handler_otf(int fd, ole2_header_t *hdr, property_t *prop, const char
|
835
|
835
|
return CL_BREAK;
|
836
|
836
|
}
|
837
|
837
|
|
838
|
|
- len -= MIN(len,64);
|
|
838
|
+ len -= MIN(len,1 << hdr->log2_small_block_size);
|
839
|
839
|
current_block = ole2_get_next_sbat_block(fd, hdr, current_block);
|
840
|
840
|
} else {
|
841
|
841
|
/* Big block file */
|
842
|
|
- if (!ole2_read_block(fd, hdr, buff, current_block)) {
|
|
842
|
+ if (!ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
|
843
|
843
|
break;
|
844
|
844
|
}
|
845
|
845
|
if (cli_writen(ofd, buff, MIN(len,(1 << hdr->log2_big_block_size))) !=
|
...
|
...
|
@@ -1020,22 +969,22 @@ int cli_ole2_extract(int fd, const char *dirname, cli_ctx *ctx, struct uniq **vb
|
1020
|
1020
|
goto abort;
|
1021
|
1021
|
}
|
1022
|
1022
|
|
1023
|
|
- if (hdr.log2_big_block_size != 9) {
|
1024
|
|
- cli_errmsg("WARNING: not scanned; untested big block size - please report\n");
|
|
1023
|
+ if (hdr.log2_big_block_size < 6 || hdr.log2_big_block_size > 30) {
|
|
1024
|
+ cli_dbgmsg("CAN'T PARSE: Invalid big block size (2^%u)\n", hdr.log2_big_block_size);
|
1025
|
1025
|
goto abort;
|
1026
|
1026
|
}
|
1027
|
|
- if (hdr.log2_small_block_size != 6) {
|
1028
|
|
- cli_errmsg("WARNING: not scanned; untested small block size - please report\n");
|
|
1027
|
+ if (!hdr.log2_small_block_size || hdr.log2_small_block_size > hdr.log2_big_block_size) {
|
|
1028
|
+ cli_dbgmsg("CAN'T PARSE: Invalid small block size (2^%u)\n", hdr.log2_small_block_size);
|
1029
|
1029
|
goto abort;
|
1030
|
1030
|
}
|
|
1031
|
+
|
1031
|
1032
|
if (hdr.sbat_cutoff != 4096) {
|
1032
|
|
- cli_errmsg("WARNING: not scanned; untested sbat cutoff - please report\n");
|
1033
|
|
- goto abort;
|
|
1033
|
+ cli_dbgmsg("WARNING: Untested sbat cutoff (%u); data may not extract correctly\n", hdr.sbat_cutoff);
|
1034
|
1034
|
}
|
1035
|
1035
|
|
1036
|
1036
|
/* 8 SBAT blocks per file block */
|
1037
|
|
- hdr.max_block_no = ((statbuf.st_size / hdr.log2_big_block_size) + 1) * 8;
|
1038
|
|
-
|
|
1037
|
+ hdr.max_block_no = (statbuf.st_size - MAX(512, 1 << hdr.log2_big_block_size)) / (1 << hdr.log2_small_block_size);
|
|
1038
|
+
|
1039
|
1039
|
print_ole2_header(&hdr);
|
1040
|
1040
|
cli_dbgmsg("Max block number: %lu\n", (unsigned long int) hdr.max_block_no);
|
1041
|
1041
|
|