Commit 1fa960ff2d7a1515a8068399c54d8de49259c315

Authored by c1fe
Committed by Philippe Lagadec
1 parent 6d02dcee

Fixed issue with Mac files and REFERENCENAME not conforming to spec (#135)

Showing 1 changed file with 33 additions and 29 deletions
oletools/olevba.py
... ... @@ -1456,18 +1456,24 @@ def _extract_vba(ole, vba_root, project_path, dir_path, relaxed=False):
1456 1456 reference_sizeof_name = struct.unpack("<L", dir_stream.read(4))[0]
1457 1457 reference_name = dir_stream.read(reference_sizeof_name)
1458 1458 reference_reserved = struct.unpack("<H", dir_stream.read(2))[0]
1459   - # According to [MS-OVBA] 2.3.4.2.2.2 REFERENCENAME Record:
1460   - # "Reserved (2 bytes): MUST be 0x003E. MUST be ignored."
1461   - # So let's ignore it, otherwise it crashes on some files (issue #132)
1462   - # if reference_reserved not in (0x003E, 0x000D):
1463   - # raise UnexpectedDataError(dir_path, 'REFERENCE_Reserved',
1464   - # (0x003E, 0x000D), reference_reserved)
1465   - reference_sizeof_name_unicode = struct.unpack("<L", dir_stream.read(4))[0]
1466   - reference_name_unicode = dir_stream.read(reference_sizeof_name_unicode)
1467   - unused = reference_id
1468   - unused = reference_name
1469   - unused = reference_name_unicode
1470   - continue
  1459 +
  1460 + # contrary to the specification I think that the unicode name
  1461 + # is optional. if reference_reserved is not 0x003E I think it
  1462 + # is actually the start of another REFERENCE record
  1463 + # at least when projectsyskind_syskind == 0x02 (Macintosh)
  1464 + if reference_reserved == 0x003E:
  1465 + #if reference_reserved not in (0x003E, 0x000D):
  1466 + # raise UnexpectedDataError(dir_path, 'REFERENCE_Reserved',
  1467 + # 0x0003E, reference_reserved)
  1468 + reference_sizeof_name_unicode = struct.unpack("<L", dir_stream.read(4))[0]
  1469 + reference_name_unicode = dir_stream.read(reference_sizeof_name_unicode)
  1470 + unused = reference_id
  1471 + unused = reference_name
  1472 + unused = reference_name_unicode
  1473 + continue
  1474 + else:
  1475 + check = reference_reserved
  1476 + log.debug("reference type = {0:04X}".format(check))
1471 1477  
1472 1478 if check == 0x0033:
1473 1479 # REFERENCEORIGINAL (followed by REFERENCECONTROL)
... ... @@ -1485,11 +1491,9 @@ def _extract_vba(ole, vba_root, project_path, dir_path, relaxed=False):
1485 1491 referencecontrol_sizeof_libidtwiddled = struct.unpack("<L", dir_stream.read(4))[0]
1486 1492 referencecontrol_libidtwiddled = dir_stream.read(referencecontrol_sizeof_libidtwiddled)
1487 1493 referencecontrol_reserved1 = struct.unpack("<L", dir_stream.read(4))[0] # ignore
1488   - # MS-OVBA: "Reserved1 (4 bytes): MUST be 0x00000000. MUST be ignored."
1489   - # check_value('REFERENCECONTROL_Reserved1', 0x0000, referencecontrol_reserved1)
  1494 + check_value('REFERENCECONTROL_Reserved1', 0x0000, referencecontrol_reserved1)
1490 1495 referencecontrol_reserved2 = struct.unpack("<H", dir_stream.read(2))[0] # ignore
1491   - # MS-OVBA: "Reserved2 (2 bytes): MUST be 0x0000. MUST be ignored."
1492   - # check_value('REFERENCECONTROL_Reserved2', 0x0000, referencecontrol_reserved2)
  1496 + check_value('REFERENCECONTROL_Reserved2', 0x0000, referencecontrol_reserved2)
1493 1497 unused = referencecontrol_id
1494 1498 unused = referencecontrol_sizetwiddled
1495 1499 unused = referencecontrol_libidtwiddled
... ... @@ -1501,20 +1505,20 @@ def _extract_vba(ole, vba_root, project_path, dir_path, relaxed=False):
1501 1505 referencecontrol_namerecordextended_name = dir_stream.read(
1502 1506 referencecontrol_namerecordextended_sizeof_name)
1503 1507 referencecontrol_namerecordextended_reserved = struct.unpack("<H", dir_stream.read(2))[0]
1504   - # check_value('REFERENCECONTROL_NameRecordExtended_Reserved', 0x003E,
1505   - # referencecontrol_namerecordextended_reserved)
1506   - referencecontrol_namerecordextended_sizeof_name_unicode = struct.unpack("<L", dir_stream.read(4))[0]
1507   - referencecontrol_namerecordextended_name_unicode = dir_stream.read(
1508   - referencecontrol_namerecordextended_sizeof_name_unicode)
1509   - referencecontrol_reserved3 = struct.unpack("<H", dir_stream.read(2))[0]
1510   - unused = referencecontrol_namerecordextended_id
1511   - unused = referencecontrol_namerecordextended_name
1512   - unused = referencecontrol_namerecordextended_name_unicode
  1508 + if referencecontrol_namerecordextended_reserved == 0x003E:
  1509 + referencecontrol_namerecordextended_sizeof_name_unicode = struct.unpack("<L", dir_stream.read(4))[0]
  1510 + referencecontrol_namerecordextended_name_unicode = dir_stream.read(
  1511 + referencecontrol_namerecordextended_sizeof_name_unicode)
  1512 + referencecontrol_reserved3 = struct.unpack("<H", dir_stream.read(2))[0]
  1513 + unused = referencecontrol_namerecordextended_id
  1514 + unused = referencecontrol_namerecordextended_name
  1515 + unused = referencecontrol_namerecordextended_name_unicode
  1516 + else:
  1517 + referencecontrol_reserved3 = referencecontrol_namerecordextended_reserved
1513 1518 else:
1514 1519 referencecontrol_reserved3 = check2
1515 1520  
1516   - # MS-OVBA: "Reserved3 (2 bytes): MUST be 0x0030. MUST be ignored."
1517   - # check_value('REFERENCECONTROL_Reserved3', 0x0030, referencecontrol_reserved3)
  1521 + check_value('REFERENCECONTROL_Reserved3', 0x0030, referencecontrol_reserved3)
1518 1522 referencecontrol_sizeextended = struct.unpack("<L", dir_stream.read(4))[0]
1519 1523 referencecontrol_sizeof_libidextended = struct.unpack("<L", dir_stream.read(4))[0]
1520 1524 referencecontrol_libidextended = dir_stream.read(referencecontrol_sizeof_libidextended)
... ... @@ -1537,9 +1541,9 @@ def _extract_vba(ole, vba_root, project_path, dir_path, relaxed=False):
1537 1541 referenceregistered_sizeof_libid = struct.unpack("<L", dir_stream.read(4))[0]
1538 1542 referenceregistered_libid = dir_stream.read(referenceregistered_sizeof_libid)
1539 1543 referenceregistered_reserved1 = struct.unpack("<L", dir_stream.read(4))[0]
1540   - # check_value('REFERENCEREGISTERED_Reserved1', 0x0000, referenceregistered_reserved1)
  1544 + check_value('REFERENCEREGISTERED_Reserved1', 0x0000, referenceregistered_reserved1)
1541 1545 referenceregistered_reserved2 = struct.unpack("<H", dir_stream.read(2))[0]
1542   - # check_value('REFERENCEREGISTERED_Reserved2', 0x0000, referenceregistered_reserved2)
  1546 + check_value('REFERENCEREGISTERED_Reserved2', 0x0000, referenceregistered_reserved2)
1543 1547 unused = referenceregistered_id
1544 1548 unused = referenceregistered_size
1545 1549 unused = referenceregistered_libid
... ...