Commit 0fd8f06bfa03126fbdfa80df2f4e092e7f5918c3
Committed by
GitHub
1 parent
eb330067
Update plugin to latest version
The current version has severe performance issues when analyzing some binary xls files. Updating to the latest plugin version solves the problem.
Showing
1 changed file
with
362 additions
and
466 deletions
oletools/thirdparty/oledump/plugin_biff.py
| @@ -2,8 +2,8 @@ | @@ -2,8 +2,8 @@ | ||
| 2 | 2 | ||
| 3 | __description__ = 'BIFF plugin for oledump.py' | 3 | __description__ = 'BIFF plugin for oledump.py' |
| 4 | __author__ = 'Didier Stevens' | 4 | __author__ = 'Didier Stevens' |
| 5 | -__version__ = '0.0.5' | ||
| 6 | -__date__ = '2019/03/06' | 5 | +__version__ = '0.0.6' |
| 6 | +__date__ = '2019/11/05' | ||
| 7 | 7 | ||
| 8 | # Slightly modified version by Philippe Lagadec to be imported into olevba | 8 | # Slightly modified version by Philippe Lagadec to be imported into olevba |
| 9 | 9 | ||
| @@ -24,6 +24,7 @@ History: | @@ -24,6 +24,7 @@ History: | ||
| 24 | 2018/10/26: continue | 24 | 2018/10/26: continue |
| 25 | 2019/01/05: 0.0.4 added option -x | 25 | 2019/01/05: 0.0.4 added option -x |
| 26 | 2019/03/06: 0.0.5 enhanced parsing of formula expressions | 26 | 2019/03/06: 0.0.5 enhanced parsing of formula expressions |
| 27 | + 2019/11/05: 0.0.6 Python 3 support | ||
| 27 | 28 | ||
| 28 | Todo: | 29 | Todo: |
| 29 | """ | 30 | """ |
| @@ -31,51 +32,68 @@ Todo: | @@ -31,51 +32,68 @@ Todo: | ||
| 31 | import struct | 32 | import struct |
| 32 | import re | 33 | import re |
| 33 | import optparse | 34 | import optparse |
| 34 | -import binascii | ||
| 35 | -import sys | ||
| 36 | 35 | ||
| 37 | -# from olevba: | 36 | +def CombineHexASCII(hexDump, asciiDump, length): |
| 37 | + if hexDump == '': | ||
| 38 | + return '' | ||
| 39 | + return hexDump + ' ' + (' ' * (3 * (length - len(asciiDump)))) + asciiDump | ||
| 40 | + | ||
| 41 | +def HexASCII(data, length=16): | ||
| 42 | + result = [] | ||
| 43 | + if len(data) > 0: | ||
| 44 | + hexDump = '' | ||
| 45 | + asciiDump = '' | ||
| 46 | + for i, b in enumerate(data): | ||
| 47 | + if i % length == 0: | ||
| 48 | + if hexDump != '': | ||
| 49 | + result.append(CombineHexASCII(hexDump, asciiDump, length)) | ||
| 50 | + hexDump = '%08X:' % i | ||
| 51 | + asciiDump = '' | ||
| 52 | + hexDump += ' %02X' % P23Ord(b) | ||
| 53 | + asciiDump += IFF(P23Ord(b) >= 32, b, '.') | ||
| 54 | + result.append(CombineHexASCII(hexDump, asciiDump, length)) | ||
| 55 | + return result | ||
| 38 | 56 | ||
| 39 | -if sys.version_info[0] <= 2: | ||
| 40 | - # Python 2.x | ||
| 41 | - PYTHON2 = True | ||
| 42 | -else: | ||
| 43 | - # Python 3.x+ | ||
| 44 | - PYTHON2 = False | 57 | +def StringsASCII(data): |
| 58 | + return re.findall(b'[^\x00-\x08\x0A-\x1F\x7F-\xFF]{4,}', data) | ||
| 45 | 59 | ||
| 46 | -def unicode2str(unicode_string): | ||
| 47 | - """ | ||
| 48 | - convert a unicode string to a native str: | ||
| 49 | - - on Python 3, it returns the same string | ||
| 50 | - - on Python 2, the string is encoded with UTF-8 to a bytes str | ||
| 51 | - :param unicode_string: unicode string to be converted | ||
| 52 | - :return: the string converted to str | ||
| 53 | - :rtype: str | ||
| 54 | - """ | ||
| 55 | - if PYTHON2: | ||
| 56 | - return unicode_string.encode('utf8', errors='replace') | ||
| 57 | - else: | ||
| 58 | - return unicode_string | 60 | +def StringsUNICODE(data): |
| 61 | + return [foundunicodestring.replace('\x00', '') for foundunicodestring, dummy in re.findall(b'(([^\x00-\x08\x0A-\x1F\x7F-\xFF]\x00){4,})', data)] | ||
| 59 | 62 | ||
| 63 | +def Strings(data, encodings='sL'): | ||
| 64 | + dStrings = {} | ||
| 65 | + for encoding in encodings: | ||
| 66 | + if encoding == 's': | ||
| 67 | + dStrings[encoding] = StringsASCII(data) | ||
| 68 | + elif encoding == 'L': | ||
| 69 | + dStrings[encoding] = StringsUNICODE(data) | ||
| 70 | + return dStrings | ||
| 60 | 71 | ||
| 61 | -def bytes2str(bytes_string, encoding='utf8'): | ||
| 62 | - """ | ||
| 63 | - convert a bytes string to a native str: | ||
| 64 | - - on Python 2, it returns the same string (bytes=str) | ||
| 65 | - - on Python 3, the string is decoded using the provided encoding | ||
| 66 | - (UTF-8 by default) to a unicode str | ||
| 67 | - :param bytes_string: bytes string to be converted | ||
| 68 | - :param encoding: codec to be used for decoding | ||
| 69 | - :return: the string converted to str | ||
| 70 | - :rtype: str | ||
| 71 | - """ | ||
| 72 | - if PYTHON2: | ||
| 73 | - return bytes_string | ||
| 74 | - else: | ||
| 75 | - return bytes_string.decode(encoding, errors='replace') | 72 | +def ContainsWP23Ord(word, expression): |
| 73 | + return struct.pack('<H', word) in expression | ||
| 76 | 74 | ||
| 75 | +#https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/6e5eed10-5b77-43d6-8dd0-37345f8654ad | ||
| 76 | +def ParseLoc(expression): | ||
| 77 | + formatcodes = 'HH' | ||
| 78 | + formatsize = struct.calcsize(formatcodes) | ||
| 79 | + row, column = struct.unpack(formatcodes, expression[0:formatsize]) | ||
| 80 | + rowRelative = column & 0x8000 | ||
| 81 | + colRelative = column & 0x4000 | ||
| 82 | + column = column & 0x3FFF | ||
| 83 | + if rowRelative: | ||
| 84 | + rowindicator = '~' | ||
| 85 | + else: | ||
| 86 | + rowindicator = '' | ||
| 87 | + row += 1 | ||
| 88 | + if colRelative: | ||
| 89 | + colindicator = '~' | ||
| 90 | + else: | ||
| 91 | + colindicator = '' | ||
| 92 | + column += 1 | ||
| 93 | + return 'R%s%dC%s%d' % (rowindicator, row, colindicator, column) | ||
| 77 | 94 | ||
| 78 | -dTokens = { | 95 | +def ParseExpression(expression): |
| 96 | + dTokens = { | ||
| 79 | 0x01: 'ptgExp', | 97 | 0x01: 'ptgExp', |
| 80 | 0x02: 'ptgTbl', | 98 | 0x02: 'ptgTbl', |
| 81 | 0x03: 'ptgAdd', | 99 | 0x03: 'ptgAdd', |
| @@ -174,7 +192,7 @@ dTokens = { | @@ -174,7 +192,7 @@ dTokens = { | ||
| 174 | } | 192 | } |
| 175 | 193 | ||
| 176 | #https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/00b5dd7d-51ca-4938-b7b7-483fe0e5933b | 194 | #https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/00b5dd7d-51ca-4938-b7b7-483fe0e5933b |
| 177 | -dFunctions = { | 195 | + dFunctions = { |
| 178 | 0x0000: 'COUNT', | 196 | 0x0000: 'COUNT', |
| 179 | 0x0001: 'IF', | 197 | 0x0001: 'IF', |
| 180 | 0x0002: 'ISNA', | 198 | 0x0002: 'ISNA', |
| @@ -550,436 +568,62 @@ dFunctions = { | @@ -550,436 +568,62 @@ dFunctions = { | ||
| 550 | 0x017B: 'RTD', | 568 | 0x017B: 'RTD', |
| 551 | 569 | ||
| 552 | 0x8076: 'ALERT', | 570 | 0x8076: 'ALERT', |
| 553 | -} | ||
| 554 | - | ||
| 555 | -dOpcodes = { | ||
| 556 | - 0x06: 'FORMULA : Cell Formula', | ||
| 557 | - 0x0A: 'EOF : End of File', | ||
| 558 | - 0x0C: 'CALCCOUNT : Iteration Count', | ||
| 559 | - 0x0D: 'CALCMODE : Calculation Mode', | ||
| 560 | - 0x0E: 'PRECISION : Precision', | ||
| 561 | - 0x0F: 'REFMODE : Reference Mode', | ||
| 562 | - 0x10: 'DELTA : Iteration Increment', | ||
| 563 | - 0x11: 'ITERATION : Iteration Mode', | ||
| 564 | - 0x12: 'PROTECT : Protection Flag', | ||
| 565 | - 0x13: 'PASSWORD : Protection Password', | ||
| 566 | - 0x14: 'HEADER : Print Header on Each Page', | ||
| 567 | - 0x15: 'FOOTER : Print Footer on Each Page', | ||
| 568 | - 0x16: 'EXTERNCOUNT : Number of External References', | ||
| 569 | - 0x17: 'EXTERNSHEET : External Reference', | ||
| 570 | - 0x18: 'LABEL : Cell Value, String Constant', | ||
| 571 | - 0x19: 'WINDOWPROTECT : Windows Are Protected', | ||
| 572 | - 0x1A: 'VERTICALPAGEBREAKS : Explicit Column Page Breaks', | ||
| 573 | - 0x1B: 'HORIZONTALPAGEBREAKS : Explicit Row Page Breaks', | ||
| 574 | - 0x1C: 'NOTE : Comment Associated with a Cell', | ||
| 575 | - 0x1D: 'SELECTION : Current Selection', | ||
| 576 | - 0x22: '1904 : 1904 Date System', | ||
| 577 | - 0x26: 'LEFTMARGIN : Left Margin Measurement', | ||
| 578 | - 0x27: 'RIGHTMARGIN : Right Margin Measurement', | ||
| 579 | - 0x28: 'TOPMARGIN : Top Margin Measurement', | ||
| 580 | - 0x29: 'BOTTOMMARGIN : Bottom Margin Measurement', | ||
| 581 | - 0x2A: 'PRINTHEADERS : Print Row/Column Labels', | ||
| 582 | - 0x2B: 'PRINTGRIDLINES : Print Gridlines Flag', | ||
| 583 | - 0x2F: 'FILEPASS : File Is Password-Protected', | ||
| 584 | - 0x3C: 'CONTINUE : Continues Long Records', | ||
| 585 | - 0x3D: 'WINDOW1 : Window Information', | ||
| 586 | - 0x40: 'BACKUP : Save Backup Version of the File', | ||
| 587 | - 0x41: 'PANE : Number of Panes and Their Position', | ||
| 588 | - 0x42: 'CODENAME : VBE Object Name', | ||
| 589 | - 0x42: 'CODEPAGE : Default Code Page', | ||
| 590 | - 0x4D: 'PLS : Environment-Specific Print Record', | ||
| 591 | - 0x50: 'DCON : Data Consolidation Information', | ||
| 592 | - 0x51: 'DCONREF : Data Consolidation References', | ||
| 593 | - 0x52: 'DCONNAME : Data Consolidation Named References', | ||
| 594 | - 0x55: 'DEFCOLWIDTH : Default Width for Columns', | ||
| 595 | - 0x59: 'XCT : CRN Record Count', | ||
| 596 | - 0x5A: 'CRN : Nonresident Operands', | ||
| 597 | - 0x5B: 'FILESHARING : File-Sharing Information', | ||
| 598 | - 0x5C: 'WRITEACCESS : Write Access User Name', | ||
| 599 | - 0x5D: 'OBJ : Describes a Graphic Object', | ||
| 600 | - 0x5E: 'UNCALCED : Recalculation Status', | ||
| 601 | - 0x5F: 'SAVERECALC : Recalculate Before Save', | ||
| 602 | - 0x60: 'TEMPLATE : Workbook Is a Template', | ||
| 603 | - 0x63: 'OBJPROTECT : Objects Are Protected', | ||
| 604 | - 0x7D: 'COLINFO : Column Formatting Information', | ||
| 605 | - 0x7E: 'RK : Cell Value, RK Number', | ||
| 606 | - 0x7F: 'IMDATA : Image Data', | ||
| 607 | - 0x80: 'GUTS : Size of Row and Column Gutters', | ||
| 608 | - 0x81: 'WSBOOL : Additional Workspace Information', | ||
| 609 | - 0x82: 'GRIDSET : State Change of Gridlines Option', | ||
| 610 | - 0x83: 'HCENTER : Center Between Horizontal Margins', | ||
| 611 | - 0x84: 'VCENTER : Center Between Vertical Margins', | ||
| 612 | - 0x85: 'BOUNDSHEET : Sheet Information', | ||
| 613 | - 0x86: 'WRITEPROT : Workbook Is Write-Protected', | ||
| 614 | - 0x87: 'ADDIN : Workbook Is an Add-in Macro', | ||
| 615 | - 0x88: 'EDG : Edition Globals', | ||
| 616 | - 0x89: 'PUB : Publisher', | ||
| 617 | - 0x8C: 'COUNTRY : Default Country and WIN.INI Country', | ||
| 618 | - 0x8D: 'HIDEOBJ : Object Display Options', | ||
| 619 | - 0x90: 'SORT : Sorting Options', | ||
| 620 | - 0x91: 'SUB : Subscriber', | ||
| 621 | - 0x92: 'PALETTE : Color Palette Definition', | ||
| 622 | - 0x94: 'LHRECORD : .WK? File Conversion Information', | ||
| 623 | - 0x95: 'LHNGRAPH : Named Graph Information', | ||
| 624 | - 0x96: 'SOUND : Sound Note', | ||
| 625 | - 0x98: 'LPR : Sheet Was Printed Using LINE.PRINT(', | ||
| 626 | - 0x99: 'STANDARDWIDTH : Standard Column Width', | ||
| 627 | - 0x9A: 'FNGROUPNAME : Function Group Name', | ||
| 628 | - 0x9B: 'FILTERMODE : Sheet Contains Filtered List', | ||
| 629 | - 0x9C: 'FNGROUPCOUNT : Built-in Function Group Count', | ||
| 630 | - 0x9D: 'AUTOFILTERINFO : Drop-Down Arrow Count', | ||
| 631 | - 0x9E: 'AUTOFILTER : AutoFilter Data', | ||
| 632 | - 0xA0: 'SCL : Window Zoom Magnification', | ||
| 633 | - 0xA1: 'SETUP : Page Setup', | ||
| 634 | - 0xA9: 'COORDLIST : Polygon Object Vertex Coordinates', | ||
| 635 | - 0xAB: 'GCW : Global Column-Width Flags', | ||
| 636 | - 0xAE: 'SCENMAN : Scenario Output Data', | ||
| 637 | - 0xAF: 'SCENARIO : Scenario Data', | ||
| 638 | - 0xB0: 'SXVIEW : View Definition', | ||
| 639 | - 0xB1: 'SXVD : View Fields', | ||
| 640 | - 0xB2: 'SXVI : View Item', | ||
| 641 | - 0xB4: 'SXIVD : Row/Column Field IDs', | ||
| 642 | - 0xB5: 'SXLI : Line Item Array', | ||
| 643 | - 0xB6: 'SXPI : Page Item', | ||
| 644 | - 0xB8: 'DOCROUTE : Routing Slip Information', | ||
| 645 | - 0xB9: 'RECIPNAME : Recipient Name', | ||
| 646 | - 0xBC: 'SHRFMLA : Shared Formula', | ||
| 647 | - 0xBD: 'MULRK : Multiple RK Cells', | ||
| 648 | - 0xBE: 'MULBLANK : Multiple Blank Cells', | ||
| 649 | - 0xC1: 'MMS : ADDMENU / DELMENU Record Group Count', | ||
| 650 | - 0xC2: 'ADDMENU : Menu Addition', | ||
| 651 | - 0xC3: 'DELMENU : Menu Deletion', | ||
| 652 | - 0xC5: 'SXDI : Data Item', | ||
| 653 | - 0xC6: 'SXDB : PivotTable Cache Data', | ||
| 654 | - 0xCD: 'SXSTRING : String', | ||
| 655 | - 0xD0: 'SXTBL : Multiple Consolidation Source Info', | ||
| 656 | - 0xD1: 'SXTBRGIITM : Page Item Name Count', | ||
| 657 | - 0xD2: 'SXTBPG : Page Item Indexes', | ||
| 658 | - 0xD3: 'OBPROJ : Visual Basic Project', | ||
| 659 | - 0xD5: 'SXIDSTM : Stream ID', | ||
| 660 | - 0xD6: 'RSTRING : Cell with Character Formatting', | ||
| 661 | - 0xD7: 'DBCELL : Stream Offsets', | ||
| 662 | - 0xDA: 'BOOKBOOL : Workbook Option Flag', | ||
| 663 | - 0xDC: 'PARAMQRY : Query Parameters', | ||
| 664 | - 0xDC: 'SXEXT : External Source Information', | ||
| 665 | - 0xDD: 'SCENPROTECT : Scenario Protection', | ||
| 666 | - 0xDE: 'OLESIZE : Size of OLE Object', | ||
| 667 | - 0xDF: 'UDDESC : Description String for Chart Autoformat', | ||
| 668 | - 0xE0: 'XF : Extended Format', | ||
| 669 | - 0xE1: 'INTERFACEHDR : Beginning of User Interface Records', | ||
| 670 | - 0xE2: 'INTERFACEEND : End of User Interface Records', | ||
| 671 | - 0xE3: 'SXVS : View Source', | ||
| 672 | - 0xE5: 'MERGECELLS : Merged Cells', | ||
| 673 | - 0xEA: 'TABIDCONF : Sheet Tab ID of Conflict History', | ||
| 674 | - 0xEB: 'MSODRAWINGGROUP : Microsoft Office Drawing Group', | ||
| 675 | - 0xEC: 'MSODRAWING : Microsoft Office Drawing', | ||
| 676 | - 0xED: 'MSODRAWINGSELECTION : Microsoft Office Drawing Selection', | ||
| 677 | - 0xF0: 'SXRULE : PivotTable Rule Data', | ||
| 678 | - 0xF1: 'SXEX : PivotTable View Extended Information', | ||
| 679 | - 0xF2: 'SXFILT : PivotTable Rule Filter', | ||
| 680 | - 0xF4: 'SXDXF : Pivot Table Formatting', | ||
| 681 | - 0xF5: 'SXITM : Pivot Table Item Indexes', | ||
| 682 | - 0xF6: 'SXNAME : PivotTable Name', | ||
| 683 | - 0xF7: 'SXSELECT : PivotTable Selection Information', | ||
| 684 | - 0xF8: 'SXPAIR : PivotTable Name Pair', | ||
| 685 | - 0xF9: 'SXFMLA : Pivot Table Parsed Expression', | ||
| 686 | - 0xFB: 'SXFORMAT : PivotTable Format Record', | ||
| 687 | - 0xFC: 'SST : Shared String Table', | ||
| 688 | - 0xFD: 'LABELSST : Cell Value, String Constant/ SST', | ||
| 689 | - 0xFF: 'EXTSST : Extended Shared String Table', | ||
| 690 | - 0x100: 'SXVDEX : Extended PivotTable View Fields', | ||
| 691 | - 0x103: 'SXFORMULA : PivotTable Formula Record', | ||
| 692 | - 0x122: 'SXDBEX : PivotTable Cache Data', | ||
| 693 | - 0x13D: 'TABID : Sheet Tab Index Array', | ||
| 694 | - 0x160: 'USESELFS : Natural Language Formulas Flag', | ||
| 695 | - 0x161: 'DSF : Double Stream File', | ||
| 696 | - 0x162: 'XL5MODIFY : Flag for DSF', | ||
| 697 | - 0x1A5: 'FILESHARING2 : File-Sharing Information for Shared Lists', | ||
| 698 | - 0x1A9: 'USERBVIEW : Workbook Custom View Settings', | ||
| 699 | - 0x1AA: 'USERSVIEWBEGIN : Custom View Settings', | ||
| 700 | - 0x1AB: 'USERSVIEWEND : End of Custom View Records', | ||
| 701 | - 0x1AD: 'QSI : External Data Range', | ||
| 702 | - 0x1AE: 'SUPBOOK : Supporting Workbook', | ||
| 703 | - 0x1AF: 'PROT4REV : Shared Workbook Protection Flag', | ||
| 704 | - 0x1B0: 'CONDFMT : Conditional Formatting Range Information', | ||
| 705 | - 0x1B1: 'CF : Conditional Formatting Conditions', | ||
| 706 | - 0x1B2: 'DVAL : Data Validation Information', | ||
| 707 | - 0x1B5: 'DCONBIN : Data Consolidation Information', | ||
| 708 | - 0x1B6: 'TXO : Text Object', | ||
| 709 | - 0x1B7: 'REFRESHALL : Refresh Flag', | ||
| 710 | - 0x1B8: 'HLINK : Hyperlink', | ||
| 711 | - 0x1BB: 'SXFDBTYPE : SQL Datatype Identifier', | ||
| 712 | - 0x1BC: 'PROT4REVPASS : Shared Workbook Protection Password', | ||
| 713 | - 0x1BE: 'DV : Data Validation Criteria', | ||
| 714 | - 0x1C0: 'EXCEL9FILE : Excel 9 File', | ||
| 715 | - 0x1C1: 'RECALCID : Recalc Information', | ||
| 716 | - 0x200: 'DIMENSIONS : Cell Table Size', | ||
| 717 | - 0x201: 'BLANK : Cell Value, Blank Cell', | ||
| 718 | - 0x203: 'NUMBER : Cell Value, Floating-Point Number', | ||
| 719 | - 0x204: 'LABEL : Cell Value, String Constant', | ||
| 720 | - 0x205: 'BOOLERR : Cell Value, Boolean or Error', | ||
| 721 | - 0x207: 'STRING : String Value of a Formula', | ||
| 722 | - 0x208: 'ROW : Describes a Row', | ||
| 723 | - 0x20B: 'INDEX : Index Record', | ||
| 724 | - 0x218: 'NAME : Defined Name', | ||
| 725 | - 0x221: 'ARRAY : Array-Entered Formula', | ||
| 726 | - 0x223: 'EXTERNNAME : Externally Referenced Name', | ||
| 727 | - 0x225: 'DEFAULTROWHEIGHT : Default Row Height', | ||
| 728 | - 0x231: 'FONT : Font Description', | ||
| 729 | - 0x236: 'TABLE : Data Table', | ||
| 730 | - 0x23E: 'WINDOW2 : Sheet Window Information', | ||
| 731 | - 0x293: 'STYLE : Style Information', | ||
| 732 | - 0x406: 'FORMULA : Cell Formula', | ||
| 733 | - 0x41E: 'FORMAT : Number Format', | ||
| 734 | - 0x800: 'HLINKTOOLTIP : Hyperlink Tooltip', | ||
| 735 | - 0x801: 'WEBPUB : Web Publish Item', | ||
| 736 | - 0x802: 'QSISXTAG : PivotTable and Query Table Extensions', | ||
| 737 | - 0x803: 'DBQUERYEXT : Database Query Extensions', | ||
| 738 | - 0x804: 'EXTSTRING : FRT String', | ||
| 739 | - 0x805: 'TXTQUERY : Text Query Information', | ||
| 740 | - 0x806: 'QSIR : Query Table Formatting', | ||
| 741 | - 0x807: 'QSIF : Query Table Field Formatting', | ||
| 742 | - 0x809: 'BOF : Beginning of File', | ||
| 743 | - 0x80A: 'OLEDBCONN : OLE Database Connection', | ||
| 744 | - 0x80B: 'WOPT : Web Options', | ||
| 745 | - 0x80C: 'SXVIEWEX : Pivot Table OLAP Extensions', | ||
| 746 | - 0x80D: 'SXTH : PivotTable OLAP Hierarchy', | ||
| 747 | - 0x80E: 'SXPIEX : OLAP Page Item Extensions', | ||
| 748 | - 0x80F: 'SXVDTEX : View Dimension OLAP Extensions', | ||
| 749 | - 0x810: 'SXVIEWEX9 : Pivot Table Extensions', | ||
| 750 | - 0x812: 'CONTINUEFRT : Continued FRT', | ||
| 751 | - 0x813: 'REALTIMEDATA : Real-Time Data (RTD)', | ||
| 752 | - 0x862: 'SHEETEXT : Extra Sheet Info', | ||
| 753 | - 0x863: 'BOOKEXT : Extra Book Info', | ||
| 754 | - 0x864: 'SXADDL : Pivot Table Additional Info', | ||
| 755 | - 0x865: 'CRASHRECERR : Crash Recovery Error', | ||
| 756 | - 0x866: 'HFPicture : Header / Footer Picture', | ||
| 757 | - 0x867: 'FEATHEADR : Shared Feature Header', | ||
| 758 | - 0x868: 'FEAT : Shared Feature Record', | ||
| 759 | - 0x86A: 'DATALABEXT : Chart Data Label Extension', | ||
| 760 | - 0x86B: 'DATALABEXTCONTENTS : Chart Data Label Extension Contents', | ||
| 761 | - 0x86C: 'CELLWATCH : Cell Watch', | ||
| 762 | - 0x86d: 'FEATINFO : Shared Feature Info Record', | ||
| 763 | - 0x871: 'FEATHEADR11 : Shared Feature Header 11', | ||
| 764 | - 0x872: 'FEAT11 : Shared Feature 11 Record', | ||
| 765 | - 0x873: 'FEATINFO11 : Shared Feature Info 11 Record', | ||
| 766 | - 0x874: 'DROPDOWNOBJIDS : Drop Down Object', | ||
| 767 | - 0x875: 'CONTINUEFRT11 : Continue FRT 11', | ||
| 768 | - 0x876: 'DCONN : Data Connection', | ||
| 769 | - 0x877: 'LIST12 : Extra Table Data Introduced in Excel 2007', | ||
| 770 | - 0x878: 'FEAT12 : Shared Feature 12 Record', | ||
| 771 | - 0x879: 'CONDFMT12 : Conditional Formatting Range Information 12', | ||
| 772 | - 0x87A: 'CF12 : Conditional Formatting Condition 12', | ||
| 773 | - 0x87B: 'CFEX : Conditional Formatting Extension', | ||
| 774 | - 0x87C: 'XFCRC : XF Extensions Checksum', | ||
| 775 | - 0x87D: 'XFEXT : XF Extension', | ||
| 776 | - 0x87E: 'EZFILTER12 : AutoFilter Data Introduced in Excel 2007', | ||
| 777 | - 0x87F: 'CONTINUEFRT12 : Continue FRT 12', | ||
| 778 | - 0x881: 'SXADDL12 : Additional Workbook Connections Information', | ||
| 779 | - 0x884: 'MDTINFO : Information about a Metadata Type', | ||
| 780 | - 0x885: 'MDXSTR : MDX Metadata String', | ||
| 781 | - 0x886: 'MDXTUPLE : Tuple MDX Metadata', | ||
| 782 | - 0x887: 'MDXSET : Set MDX Metadata', | ||
| 783 | - 0x888: 'MDXPROP : Member Property MDX Metadata', | ||
| 784 | - 0x889: 'MDXKPI : Key Performance Indicator MDX Metadata', | ||
| 785 | - 0x88A: 'MDTB : Block of Metadata Records', | ||
| 786 | - 0x88B: 'PLV : Page Layout View Settings in Excel 2007', | ||
| 787 | - 0x88C: 'COMPAT12 : Compatibility Checker 12', | ||
| 788 | - 0x88D: 'DXF : Differential XF', | ||
| 789 | - 0x88E: 'TABLESTYLES : Table Styles', | ||
| 790 | - 0x88F: 'TABLESTYLE : Table Style', | ||
| 791 | - 0x890: 'TABLESTYLEELEMENT : Table Style Element', | ||
| 792 | - 0x892: 'STYLEEXT : Named Cell Style Extension', | ||
| 793 | - 0x893: 'NAMEPUBLISH : Publish To Excel Server Data for Name', | ||
| 794 | - 0x894: 'NAMECMT : Name Comment', | ||
| 795 | - 0x895: 'SORTDATA12 : Sort Data 12', | ||
| 796 | - 0x896: 'THEME : Theme', | ||
| 797 | - 0x897: 'GUIDTYPELIB : VB Project Typelib GUID', | ||
| 798 | - 0x898: 'FNGRP12 : Function Group', | ||
| 799 | - 0x899: 'NAMEFNGRP12 : Extra Function Group', | ||
| 800 | - 0x89A: 'MTRSETTINGS : Multi-Threaded Calculation Settings', | ||
| 801 | - 0x89B: 'COMPRESSPICTURES : Automatic Picture Compression Mode', | ||
| 802 | - 0x89C: 'HEADERFOOTER : Header Footer', | ||
| 803 | - 0x8A3: 'FORCEFULLCALCULATION : Force Full Calculation Settings', | ||
| 804 | - 0x8c1: 'LISTOBJ : List Object', | ||
| 805 | - 0x8c2: 'LISTFIELD : List Field', | ||
| 806 | - 0x8c3: 'LISTDV : List Data Validation', | ||
| 807 | - 0x8c4: 'LISTCONDFMT : List Conditional Formatting', | ||
| 808 | - 0x8c5: 'LISTCF : List Cell Formatting', | ||
| 809 | - 0x8c6: 'FMQRY : Filemaker queries', | ||
| 810 | - 0x8c7: 'FMSQRY : File maker queries', | ||
| 811 | - 0x8c8: 'PLV : Page Layout View in Mac Excel 11', | ||
| 812 | - 0x8c9: 'LNEXT : Extension information for borders in Mac Office 11', | ||
| 813 | - 0x8ca: 'MKREXT : Extension information for markers in Mac Office 11' | ||
| 814 | -} | ||
| 815 | - | ||
| 816 | - | ||
| 817 | -# CIC: Call If Callable | ||
| 818 | -def CIC(expression): | ||
| 819 | - if callable(expression): | ||
| 820 | - return expression() | ||
| 821 | - else: | ||
| 822 | - return expression | ||
| 823 | - | ||
| 824 | - | ||
| 825 | -# IFF: IF Function | ||
| 826 | -def IFF(expression, valueTrue, valueFalse): | ||
| 827 | - if expression: | ||
| 828 | - return CIC(valueTrue) | ||
| 829 | - else: | ||
| 830 | - return CIC(valueFalse) | ||
| 831 | - | 571 | + } |
| 832 | 572 | ||
| 833 | -def CombineHexASCII(hexDump, asciiDump, length): | ||
| 834 | - if hexDump == '': | ||
| 835 | - return '' | ||
| 836 | - return hexDump + ' ' + (' ' * (3 * (length - len(asciiDump)))) + asciiDump | ||
| 837 | - | ||
| 838 | -def HexASCII(data, length=16): | ||
| 839 | - result = [] | ||
| 840 | - if len(data) > 0: | ||
| 841 | - hexDump = '' | ||
| 842 | - asciiDump = '' | ||
| 843 | - for i, b in enumerate(data): | ||
| 844 | - if i % length == 0: | ||
| 845 | - if hexDump != '': | ||
| 846 | - result.append(CombineHexASCII(hexDump, asciiDump, length)) | ||
| 847 | - hexDump = '%08X:' % i | ||
| 848 | - asciiDump = '' | ||
| 849 | - hexDump += ' %02X' % ord(b) | ||
| 850 | - asciiDump += IFF(ord(b) >= 32, b, '.') | ||
| 851 | - result.append(CombineHexASCII(hexDump, asciiDump, length)) | ||
| 852 | - return result | ||
| 853 | - | ||
| 854 | -def StringsASCII(data): | ||
| 855 | - """ | ||
| 856 | - Extract a list of plain ASCII strings of 4+ chars found in data. | ||
| 857 | - :param data: bytearray or bytes | ||
| 858 | - :return: list of str (converted to unicode on Python 3) | ||
| 859 | - """ | ||
| 860 | - # list of bytes strings: | ||
| 861 | - bytes_strings = re.findall(b'[^\x00-\x08\x0A-\x1F\x7F-\xFF]{4,}', bytes(data)) | ||
| 862 | - return [bytes2str(bs) for bs in bytes_strings] | ||
| 863 | - | ||
| 864 | -def StringsUNICODE(data): | ||
| 865 | - """ | ||
| 866 | - Extract a list of Unicode strings (made of 4+ plain ASCII characters only) found in data. | ||
| 867 | - :param data: bytearray or bytes | ||
| 868 | - :return: list of str (converted to unicode on Python 3) | ||
| 869 | - """ | ||
| 870 | - # list of bytes strings: | ||
| 871 | - # TODO: check if the null byte should be before or after the ascii byte | ||
| 872 | - bytes_strings = [foundunicodestring.replace(b'\x00', b'') for foundunicodestring, dummy in re.findall(b'(([^\x00-\x08\x0A-\x1F\x7F-\xFF]\x00){4,})', bytes(data))] | ||
| 873 | - return [bytes2str(bs) for bs in bytes_strings] | ||
| 874 | - | ||
| 875 | -def Strings(data, encodings='sL'): | ||
| 876 | - """ | ||
| 877 | - | ||
| 878 | - :param data bytearray: bytearray, data to be scanned for strings | ||
| 879 | - :param encodings: | ||
| 880 | - :return: dict with key = 's' or 'L', values = list of str | ||
| 881 | - """ | ||
| 882 | - dStrings = {} | ||
| 883 | - for encoding in encodings: | ||
| 884 | - if encoding == 's': | ||
| 885 | - dStrings[encoding] = StringsASCII(data) | ||
| 886 | - elif encoding == 'L': | ||
| 887 | - dStrings[encoding] = StringsUNICODE(data) | ||
| 888 | - return dStrings | ||
| 889 | - | ||
| 890 | -def ContainsWord(word, expression): | ||
| 891 | - return struct.pack('<H', word) in expression | ||
| 892 | - | ||
| 893 | -# https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-xls/6e5eed10-5b77-43d6-8dd0-37345f8654ad | ||
| 894 | -def ParseLoc(expression): | ||
| 895 | - """ | ||
| 896 | - | ||
| 897 | - :param expression bytearray: bytearray, data to be parsed | ||
| 898 | - :return: | ||
| 899 | - :rtype: str | ||
| 900 | - """ | ||
| 901 | - formatcodes = 'HH' | ||
| 902 | - formatsize = struct.calcsize(formatcodes) | ||
| 903 | - row, column = struct.unpack(formatcodes, expression[0:formatsize]) | ||
| 904 | - rowRelative = column & 0x8000 | ||
| 905 | - colRelative = column & 0x4000 | ||
| 906 | - column = column & 0x3FFF | ||
| 907 | - if rowRelative: | ||
| 908 | - rowindicator = '~' | ||
| 909 | - else: | ||
| 910 | - rowindicator = '' | ||
| 911 | - row += 1 | ||
| 912 | - if colRelative: | ||
| 913 | - colindicator = '~' | ||
| 914 | - else: | ||
| 915 | - colindicator = '' | ||
| 916 | - column += 1 | ||
| 917 | - return 'R%s%dC%s%d' % (rowindicator, row, colindicator, column) | ||
| 918 | - | ||
| 919 | -def ParseExpression(expression): | ||
| 920 | - ''' | ||
| 921 | - Parse an expression into a human readable string. | ||
| 922 | - | ||
| 923 | - :param expression bytearray: bytearray, expression data to be parsed | ||
| 924 | - :return: str, parsed expression as a string (bytes on Python 2, unicode on python 3) | ||
| 925 | - :rtype: str | ||
| 926 | - ''' | ||
| 927 | result = '' | 573 | result = '' |
| 928 | while len(expression) > 0: | 574 | while len(expression) > 0: |
| 929 | - ptgid = expression[0] # int | ||
| 930 | - expression = expression[1:] # bytearray | 575 | + ptgid = P23Ord(expression[0]) |
| 576 | + expression = expression[1:] | ||
| 931 | if ptgid in dTokens: | 577 | if ptgid in dTokens: |
| 932 | result += dTokens[ptgid] + ' ' | 578 | result += dTokens[ptgid] + ' ' |
| 933 | - if ptgid == 0x17: # ptgStr | ||
| 934 | - length = expression[0] # int | 579 | + if ptgid == 0x17: |
| 580 | + length = P23Ord(expression[0]) | ||
| 935 | expression = expression[1:] | 581 | expression = expression[1:] |
| 936 | - if expression[0] == 0: # probably BIFF8 -> UNICODE (compressed) | 582 | + if expression[0] == '\x00': # probably BIFF8 -> UNICODE (compressed) |
| 937 | expression = expression[1:] | 583 | expression = expression[1:] |
| 938 | - result += '"%s" ' % bytes2str(expression[:length]) | 584 | + result += '"%s" ' % expression[:length] |
| 939 | expression = expression[length:] | 585 | expression = expression[length:] |
| 940 | - elif ptgid == 0x19: # ptgAttr | ||
| 941 | - grbit = expression[0] # int | 586 | + elif ptgid == 0x19: |
| 587 | + grbit = P23Ord(expression[0]) | ||
| 942 | expression = expression[1:] | 588 | expression = expression[1:] |
| 943 | if grbit & 0x04: | 589 | if grbit & 0x04: |
| 944 | result += 'CHOOSE ' | 590 | result += 'CHOOSE ' |
| 945 | break | 591 | break |
| 946 | else: | 592 | else: |
| 947 | expression = expression[2:] | 593 | expression = expression[2:] |
| 948 | - elif ptgid == 0x16 or ptgid == 0x0e: # 0x0E: 'ptgNE', 0x16: 'ptgMissArg' | 594 | + elif ptgid == 0x16 or ptgid == 0x0e: |
| 949 | pass | 595 | pass |
| 950 | - elif ptgid == 0x1e: # ptgInt | ||
| 951 | - result += '%d ' % (expression[0] + expression[1] * 0x100) | 596 | + elif ptgid == 0x1e: |
| 597 | + result += '%d ' % (P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100) | ||
| 952 | expression = expression[2:] | 598 | expression = expression[2:] |
| 953 | - elif ptgid == 0x41: # ptgFuncV | ||
| 954 | - functionid = expression[0] + expression[1] * 0x100 | 599 | + elif ptgid == 0x41: |
| 600 | + functionid = P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100 | ||
| 955 | result += '%s (0x%04x) ' % (dFunctions.get(functionid, '*UNKNOWN FUNCTION*'), functionid) | 601 | result += '%s (0x%04x) ' % (dFunctions.get(functionid, '*UNKNOWN FUNCTION*'), functionid) |
| 956 | expression = expression[2:] | 602 | expression = expression[2:] |
| 957 | - elif ptgid == 0x22 or ptgid == 0x42: # 0x22: 'ptgFuncVar', 0x42: 'ptgFuncVarV' | ||
| 958 | - functionid = expression[1] + expression[2] * 0x100 | ||
| 959 | - result += 'args %d func %s (0x%04x) ' % (expression[0], dFunctions.get(functionid, '*UNKNOWN FUNCTION*'), functionid) | 603 | + elif ptgid == 0x22 or ptgid == 0x42: |
| 604 | + functionid = P23Ord(expression[1]) + P23Ord(expression[2]) * 0x100 | ||
| 605 | + result += 'args %d func %s (0x%04x) ' % (P23Ord(expression[0]), dFunctions.get(functionid, '*UNKNOWN FUNCTION*'), functionid) | ||
| 960 | expression = expression[3:] | 606 | expression = expression[3:] |
| 961 | - elif ptgid == 0x23: # ptgName | ||
| 962 | - result += '%04x ' % (expression[0] + expression[1] * 0x100) | ||
| 963 | - # TODO: looks like we're skipping quite a few bytes | 607 | + elif ptgid == 0x23: |
| 608 | + result += '%04x ' % (P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100) | ||
| 964 | expression = expression[14:] | 609 | expression = expression[14:] |
| 965 | - elif ptgid == 0x1f: # ptgNum | 610 | + elif ptgid == 0x1f: |
| 966 | result += 'FLOAT ' | 611 | result += 'FLOAT ' |
| 967 | - # TODO: looks like we're skipping quite a few bytes | ||
| 968 | expression = expression[8:] | 612 | expression = expression[8:] |
| 969 | - elif ptgid == 0x26: # ptgMemArea | ||
| 970 | - expression = expression[4:] # skipping 4 bytes | ||
| 971 | - expression = expression[expression[0] + expression[1] * 0x100:] | 613 | + elif ptgid == 0x26: |
| 614 | + expression = expression[4:] | ||
| 615 | + expression = expression[P23Ord(expression[0]) + P23Ord(expression[1]) * 0x100:] | ||
| 972 | result += 'REFERENCE-EXPRESSION ' | 616 | result += 'REFERENCE-EXPRESSION ' |
| 973 | - elif ptgid == 0x01: # ptgExp | 617 | + elif ptgid == 0x01: |
| 974 | formatcodes = 'HH' | 618 | formatcodes = 'HH' |
| 975 | formatsize = struct.calcsize(formatcodes) | 619 | formatsize = struct.calcsize(formatcodes) |
| 976 | row, column = struct.unpack(formatcodes, expression[0:formatsize]) | 620 | row, column = struct.unpack(formatcodes, expression[0:formatsize]) |
| 977 | expression = expression[formatsize:] | 621 | expression = expression[formatsize:] |
| 978 | result += 'R%dC%d ' % (row + 1, column + 1) | 622 | result += 'R%dC%d ' % (row + 1, column + 1) |
| 979 | - elif ptgid == 0x24 or ptgid == 0x44: # 0x24: 'ptgRef', 0x44: 'ptgRefV' | 623 | + elif ptgid == 0x24 or ptgid == 0x44: |
| 980 | result += '%s ' % ParseLoc(expression) | 624 | result += '%s ' % ParseLoc(expression) |
| 981 | expression = expression[4:] | 625 | expression = expression[4:] |
| 982 | - elif ptgid == 0x3A or ptgid == 0x5A: # 0x3A: 'ptgRef3d', 0x5A: 'ptgRef3dV' | 626 | + elif ptgid == 0x3A or ptgid == 0x5A: |
| 983 | result += '%s ' % ParseLoc(expression[2:]) | 627 | result += '%s ' % ParseLoc(expression[2:]) |
| 984 | expression = expression[6:] | 628 | expression = expression[6:] |
| 985 | else: | 629 | else: |
| @@ -987,11 +631,10 @@ def ParseExpression(expression): | @@ -987,11 +631,10 @@ def ParseExpression(expression): | ||
| 987 | else: | 631 | else: |
| 988 | result += '*UNKNOWN TOKEN* ' | 632 | result += '*UNKNOWN TOKEN* ' |
| 989 | break | 633 | break |
| 990 | - if len(expression) == 0: | 634 | + if expression == b'': |
| 991 | return result | 635 | return result |
| 992 | else: | 636 | else: |
| 993 | - # 0x006E: 'EXEC', 0x0095: 'REGISTER' | ||
| 994 | - functions = [dFunctions[functionid] for functionid in [0x6E, 0x95] if ContainsWord(functionid, expression)] | 637 | + functions = [dFunctions[functionid] for functionid in [0x6E, 0x95] if ContainsWP23Ord(functionid, expression)] |
| 995 | if functions != []: | 638 | if functions != []: |
| 996 | message = ' Could contain following functions: ' + ','.join(functions) + ' -' | 639 | message = ' Could contain following functions: ' + ','.join(functions) + ' -' |
| 997 | else: | 640 | else: |
| @@ -999,7 +642,7 @@ def ParseExpression(expression): | @@ -999,7 +642,7 @@ def ParseExpression(expression): | ||
| 999 | return result + ' *INCOMPLETE FORMULA PARSING*' + message + ' Remaining, unparsed expression: ' + repr(expression) | 642 | return result + ' *INCOMPLETE FORMULA PARSING*' + message + ' Remaining, unparsed expression: ' + repr(expression) |
| 1000 | 643 | ||
| 1001 | 644 | ||
| 1002 | -class cBIFF(object): # cPluginParent): | 645 | +class cBIFF(object): # cPluginParent): |
| 1003 | macroOnly = False | 646 | macroOnly = False |
| 1004 | name = 'BIFF plugin' | 647 | name = 'BIFF plugin' |
| 1005 | 648 | ||
| @@ -1012,10 +655,270 @@ class cBIFF(object): # cPluginParent): | @@ -1012,10 +655,270 @@ class cBIFF(object): # cPluginParent): | ||
| 1012 | def Analyze(self): | 655 | def Analyze(self): |
| 1013 | result = [] | 656 | result = [] |
| 1014 | macros4Found = False | 657 | macros4Found = False |
| 658 | + dOpcodes = { | ||
| 659 | + 0x06: 'FORMULA : Cell Formula', | ||
| 660 | + 0x0A: 'EOF : End of File', | ||
| 661 | + 0x0C: 'CALCCOUNT : Iteration Count', | ||
| 662 | + 0x0D: 'CALCMODE : Calculation Mode', | ||
| 663 | + 0x0E: 'PRECISION : Precision', | ||
| 664 | + 0x0F: 'REFMODE : Reference Mode', | ||
| 665 | + 0x10: 'DELTA : Iteration Increment', | ||
| 666 | + 0x11: 'ITERATION : Iteration Mode', | ||
| 667 | + 0x12: 'PROTECT : Protection Flag', | ||
| 668 | + 0x13: 'PASSWORD : Protection Password', | ||
| 669 | + 0x14: 'HEADER : Print Header on Each Page', | ||
| 670 | + 0x15: 'FOOTER : Print Footer on Each Page', | ||
| 671 | + 0x16: 'EXTERNCOUNT : Number of External References', | ||
| 672 | + 0x17: 'EXTERNSHEET : External Reference', | ||
| 673 | + 0x18: 'LABEL : Cell Value, String Constant', | ||
| 674 | + 0x19: 'WINDOWPROTECT : Windows Are Protected', | ||
| 675 | + 0x1A: 'VERTICALPAGEBREAKS : Explicit Column Page Breaks', | ||
| 676 | + 0x1B: 'HORIZONTALPAGEBREAKS : Explicit Row Page Breaks', | ||
| 677 | + 0x1C: 'NOTE : Comment Associated with a Cell', | ||
| 678 | + 0x1D: 'SELECTION : Current Selection', | ||
| 679 | + 0x22: '1904 : 1904 Date System', | ||
| 680 | + 0x26: 'LEFTMARGIN : Left Margin Measurement', | ||
| 681 | + 0x27: 'RIGHTMARGIN : Right Margin Measurement', | ||
| 682 | + 0x28: 'TOPMARGIN : Top Margin Measurement', | ||
| 683 | + 0x29: 'BOTTOMMARGIN : Bottom Margin Measurement', | ||
| 684 | + 0x2A: 'PRINTHEADERS : Print Row/Column Labels', | ||
| 685 | + 0x2B: 'PRINTGRIDLINES : Print Gridlines Flag', | ||
| 686 | + 0x2F: 'FILEPASS : File Is Password-Protected', | ||
| 687 | + 0x3C: 'CONTINUE : Continues Long Records', | ||
| 688 | + 0x3D: 'WINDOW1 : Window Information', | ||
| 689 | + 0x40: 'BACKUP : Save Backup Version of the File', | ||
| 690 | + 0x41: 'PANE : Number of Panes and Their Position', | ||
| 691 | + 0x42: 'CODENAME : VBE Object Name', | ||
| 692 | + 0x42: 'CODEPAGE : Default Code Page', | ||
| 693 | + 0x4D: 'PLS : Environment-Specific Print Record', | ||
| 694 | + 0x50: 'DCON : Data Consolidation Information', | ||
| 695 | + 0x51: 'DCONREF : Data Consolidation References', | ||
| 696 | + 0x52: 'DCONNAME : Data Consolidation Named References', | ||
| 697 | + 0x55: 'DEFCOLWIDTH : Default Width for Columns', | ||
| 698 | + 0x59: 'XCT : CRN Record Count', | ||
| 699 | + 0x5A: 'CRN : Nonresident Operands', | ||
| 700 | + 0x5B: 'FILESHARING : File-Sharing Information', | ||
| 701 | + 0x5C: 'WRITEACCESS : Write Access User Name', | ||
| 702 | + 0x5D: 'OBJ : Describes a Graphic Object', | ||
| 703 | + 0x5E: 'UNCALCED : Recalculation Status', | ||
| 704 | + 0x5F: 'SAVERECALC : Recalculate Before Save', | ||
| 705 | + 0x60: 'TEMPLATE : Workbook Is a Template', | ||
| 706 | + 0x63: 'OBJPROTECT : Objects Are Protected', | ||
| 707 | + 0x7D: 'COLINFO : Column Formatting Information', | ||
| 708 | + 0x7E: 'RK : Cell Value, RK Number', | ||
| 709 | + 0x7F: 'IMDATA : Image Data', | ||
| 710 | + 0x80: 'GUTS : Size of Row and Column Gutters', | ||
| 711 | + 0x81: 'WSBOOL : Additional Workspace Information', | ||
| 712 | + 0x82: 'GRIDSET : State Change of Gridlines Option', | ||
| 713 | + 0x83: 'HCENTER : Center Between Horizontal Margins', | ||
| 714 | + 0x84: 'VCENTER : Center Between Vertical Margins', | ||
| 715 | + 0x85: 'BOUNDSHEET : Sheet Information', | ||
| 716 | + 0x86: 'WRITEPROT : Workbook Is Write-Protected', | ||
| 717 | + 0x87: 'ADDIN : Workbook Is an Add-in Macro', | ||
| 718 | + 0x88: 'EDG : Edition Globals', | ||
| 719 | + 0x89: 'PUB : Publisher', | ||
| 720 | + 0x8C: 'COUNTRY : Default Country and WIN.INI Country', | ||
| 721 | + 0x8D: 'HIDEOBJ : Object Display Options', | ||
| 722 | + 0x90: 'SORT : Sorting Options', | ||
| 723 | + 0x91: 'SUB : Subscriber', | ||
| 724 | + 0x92: 'PALETTE : Color Palette Definition', | ||
| 725 | + 0x94: 'LHRECORD : .WK? File Conversion Information', | ||
| 726 | + 0x95: 'LHNGRAPH : Named Graph Information', | ||
| 727 | + 0x96: 'SOUND : Sound Note', | ||
| 728 | + 0x98: 'LPR : Sheet Was Printed Using LINE.PRINT(', | ||
| 729 | + 0x99: 'STANDARDWIDTH : Standard Column Width', | ||
| 730 | + 0x9A: 'FNGROUPNAME : Function Group Name', | ||
| 731 | + 0x9B: 'FILTERMODE : Sheet Contains Filtered List', | ||
| 732 | + 0x9C: 'FNGROUPCOUNT : Built-in Function Group Count', | ||
| 733 | + 0x9D: 'AUTOFILTERINFO : Drop-Down Arrow Count', | ||
| 734 | + 0x9E: 'AUTOFILTER : AutoFilter Data', | ||
| 735 | + 0xA0: 'SCL : Window Zoom Magnification', | ||
| 736 | + 0xA1: 'SETUP : Page Setup', | ||
| 737 | + 0xA9: 'COORDLIST : Polygon Object Vertex Coordinates', | ||
| 738 | + 0xAB: 'GCW : Global Column-Width Flags', | ||
| 739 | + 0xAE: 'SCENMAN : Scenario Output Data', | ||
| 740 | + 0xAF: 'SCENARIO : Scenario Data', | ||
| 741 | + 0xB0: 'SXVIEW : View Definition', | ||
| 742 | + 0xB1: 'SXVD : View Fields', | ||
| 743 | + 0xB2: 'SXVI : View Item', | ||
| 744 | + 0xB4: 'SXIVD : Row/Column Field IDs', | ||
| 745 | + 0xB5: 'SXLI : Line Item Array', | ||
| 746 | + 0xB6: 'SXPI : Page Item', | ||
| 747 | + 0xB8: 'DOCROUTE : Routing Slip Information', | ||
| 748 | + 0xB9: 'RECIPNAME : Recipient Name', | ||
| 749 | + 0xBC: 'SHRFMLA : Shared Formula', | ||
| 750 | + 0xBD: 'MULRK : Multiple RK Cells', | ||
| 751 | + 0xBE: 'MULBLANK : Multiple Blank Cells', | ||
| 752 | + 0xC1: 'MMS : ADDMENU / DELMENU Record Group Count', | ||
| 753 | + 0xC2: 'ADDMENU : Menu Addition', | ||
| 754 | + 0xC3: 'DELMENU : Menu Deletion', | ||
| 755 | + 0xC5: 'SXDI : Data Item', | ||
| 756 | + 0xC6: 'SXDB : PivotTable Cache Data', | ||
| 757 | + 0xCD: 'SXSTRING : String', | ||
| 758 | + 0xD0: 'SXTBL : Multiple Consolidation Source Info', | ||
| 759 | + 0xD1: 'SXTBRGIITM : Page Item Name Count', | ||
| 760 | + 0xD2: 'SXTBPG : Page Item Indexes', | ||
| 761 | + 0xD3: 'OBPROJ : Visual Basic Project', | ||
| 762 | + 0xD5: 'SXIDSTM : Stream ID', | ||
| 763 | + 0xD6: 'RSTRING : Cell with Character Formatting', | ||
| 764 | + 0xD7: 'DBCELL : Stream Offsets', | ||
| 765 | + 0xDA: 'BOOKBOOL : Workbook Option Flag', | ||
| 766 | + 0xDC: 'PARAMQRY : Query Parameters', | ||
| 767 | + 0xDC: 'SXEXT : External Source Information', | ||
| 768 | + 0xDD: 'SCENPROTECT : Scenario Protection', | ||
| 769 | + 0xDE: 'OLESIZE : Size of OLE Object', | ||
| 770 | + 0xDF: 'UDDESC : Description String for Chart Autoformat', | ||
| 771 | + 0xE0: 'XF : Extended Format', | ||
| 772 | + 0xE1: 'INTERFACEHDR : Beginning of User Interface Records', | ||
| 773 | + 0xE2: 'INTERFACEEND : End of User Interface Records', | ||
| 774 | + 0xE3: 'SXVS : View Source', | ||
| 775 | + 0xE5: 'MERGECELLS : Merged Cells', | ||
| 776 | + 0xEA: 'TABIDCONF : Sheet Tab ID of Conflict History', | ||
| 777 | + 0xEB: 'MSODRAWINGGROUP : Microsoft Office Drawing Group', | ||
| 778 | + 0xEC: 'MSODRAWING : Microsoft Office Drawing', | ||
| 779 | + 0xED: 'MSODRAWINGSELECTION : Microsoft Office Drawing Selection', | ||
| 780 | + 0xF0: 'SXRULE : PivotTable Rule Data', | ||
| 781 | + 0xF1: 'SXEX : PivotTable View Extended Information', | ||
| 782 | + 0xF2: 'SXFILT : PivotTable Rule Filter', | ||
| 783 | + 0xF4: 'SXDXF : Pivot Table Formatting', | ||
| 784 | + 0xF5: 'SXITM : Pivot Table Item Indexes', | ||
| 785 | + 0xF6: 'SXNAME : PivotTable Name', | ||
| 786 | + 0xF7: 'SXSELECT : PivotTable Selection Information', | ||
| 787 | + 0xF8: 'SXPAIR : PivotTable Name Pair', | ||
| 788 | + 0xF9: 'SXFMLA : Pivot Table Parsed Expression', | ||
| 789 | + 0xFB: 'SXFORMAT : PivotTable Format Record', | ||
| 790 | + 0xFC: 'SST : Shared String Table', | ||
| 791 | + 0xFD: 'LABELSST : Cell Value, String Constant/ SST', | ||
| 792 | + 0xFF: 'EXTSST : Extended Shared String Table', | ||
| 793 | + 0x100: 'SXVDEX : Extended PivotTable View Fields', | ||
| 794 | + 0x103: 'SXFORMULA : PivotTable Formula Record', | ||
| 795 | + 0x122: 'SXDBEX : PivotTable Cache Data', | ||
| 796 | + 0x13D: 'TABID : Sheet Tab Index Array', | ||
| 797 | + 0x160: 'USESELFS : Natural Language Formulas Flag', | ||
| 798 | + 0x161: 'DSF : Double Stream File', | ||
| 799 | + 0x162: 'XL5MODIFY : Flag for DSF', | ||
| 800 | + 0x1A5: 'FILESHARING2 : File-Sharing Information for Shared Lists', | ||
| 801 | + 0x1A9: 'USERBVIEW : Workbook Custom View Settings', | ||
| 802 | + 0x1AA: 'USERSVIEWBEGIN : Custom View Settings', | ||
| 803 | + 0x1AB: 'USERSVIEWEND : End of Custom View Records', | ||
| 804 | + 0x1AD: 'QSI : External Data Range', | ||
| 805 | + 0x1AE: 'SUPBOOK : Supporting Workbook', | ||
| 806 | + 0x1AF: 'PROT4REV : Shared Workbook Protection Flag', | ||
| 807 | + 0x1B0: 'CONDFMT : Conditional Formatting Range Information', | ||
| 808 | + 0x1B1: 'CF : Conditional Formatting Conditions', | ||
| 809 | + 0x1B2: 'DVAL : Data Validation Information', | ||
| 810 | + 0x1B5: 'DCONBIN : Data Consolidation Information', | ||
| 811 | + 0x1B6: 'TXO : Text Object', | ||
| 812 | + 0x1B7: 'REFRESHALL : Refresh Flag', | ||
| 813 | + 0x1B8: 'HLINK : Hyperlink', | ||
| 814 | + 0x1BB: 'SXFDBTYPE : SQL Datatype Identifier', | ||
| 815 | + 0x1BC: 'PROT4REVPASS : Shared Workbook Protection Password', | ||
| 816 | + 0x1BE: 'DV : Data Validation Criteria', | ||
| 817 | + 0x1C0: 'EXCEL9FILE : Excel 9 File', | ||
| 818 | + 0x1C1: 'RECALCID : Recalc Information', | ||
| 819 | + 0x200: 'DIMENSIONS : Cell Table Size', | ||
| 820 | + 0x201: 'BLANK : Cell Value, Blank Cell', | ||
| 821 | + 0x203: 'NUMBER : Cell Value, Floating-Point Number', | ||
| 822 | + 0x204: 'LABEL : Cell Value, String Constant', | ||
| 823 | + 0x205: 'BOOLERR : Cell Value, Boolean or Error', | ||
| 824 | + 0x207: 'STRING : String Value of a Formula', | ||
| 825 | + 0x208: 'ROW : Describes a Row', | ||
| 826 | + 0x20B: 'INDEX : Index Record', | ||
| 827 | + 0x218: 'NAME : Defined Name', | ||
| 828 | + 0x221: 'ARRAY : Array-Entered Formula', | ||
| 829 | + 0x223: 'EXTERNNAME : Externally Referenced Name', | ||
| 830 | + 0x225: 'DEFAULTROWHEIGHT : Default Row Height', | ||
| 831 | + 0x231: 'FONT : Font Description', | ||
| 832 | + 0x236: 'TABLE : Data Table', | ||
| 833 | + 0x23E: 'WINDOW2 : Sheet Window Information', | ||
| 834 | + 0x293: 'STYLE : Style Information', | ||
| 835 | + 0x406: 'FORMULA : Cell Formula', | ||
| 836 | + 0x41E: 'FORMAT : Number Format', | ||
| 837 | + 0x800: 'HLINKTOOLTIP : Hyperlink Tooltip', | ||
| 838 | + 0x801: 'WEBPUB : Web Publish Item', | ||
| 839 | + 0x802: 'QSISXTAG : PivotTable and Query Table Extensions', | ||
| 840 | + 0x803: 'DBQUERYEXT : Database Query Extensions', | ||
| 841 | + 0x804: 'EXTSTRING : FRT String', | ||
| 842 | + 0x805: 'TXTQUERY : Text Query Information', | ||
| 843 | + 0x806: 'QSIR : Query Table Formatting', | ||
| 844 | + 0x807: 'QSIF : Query Table Field Formatting', | ||
| 845 | + 0x809: 'BOF : Beginning of File', | ||
| 846 | + 0x80A: 'OLEDBCONN : OLE Database Connection', | ||
| 847 | + 0x80B: 'WOPT : Web Options', | ||
| 848 | + 0x80C: 'SXVIEWEX : Pivot Table OLAP Extensions', | ||
| 849 | + 0x80D: 'SXTH : PivotTable OLAP Hierarchy', | ||
| 850 | + 0x80E: 'SXPIEX : OLAP Page Item Extensions', | ||
| 851 | + 0x80F: 'SXVDTEX : View Dimension OLAP Extensions', | ||
| 852 | + 0x810: 'SXVIEWEX9 : Pivot Table Extensions', | ||
| 853 | + 0x812: 'CONTINUEFRT : Continued FRT', | ||
| 854 | + 0x813: 'REALTIMEDATA : Real-Time Data (RTD)', | ||
| 855 | + 0x862: 'SHEETEXT : Extra Sheet Info', | ||
| 856 | + 0x863: 'BOOKEXT : Extra Book Info', | ||
| 857 | + 0x864: 'SXADDL : Pivot Table Additional Info', | ||
| 858 | + 0x865: 'CRASHRECERR : Crash Recovery Error', | ||
| 859 | + 0x866: 'HFPicture : Header / Footer Picture', | ||
| 860 | + 0x867: 'FEATHEADR : Shared Feature Header', | ||
| 861 | + 0x868: 'FEAT : Shared Feature Record', | ||
| 862 | + 0x86A: 'DATALABEXT : Chart Data Label Extension', | ||
| 863 | + 0x86B: 'DATALABEXTCONTENTS : Chart Data Label Extension Contents', | ||
| 864 | + 0x86C: 'CELLWATCH : Cell Watch', | ||
| 865 | + 0x86d: 'FEATINFO : Shared Feature Info Record', | ||
| 866 | + 0x871: 'FEATHEADR11 : Shared Feature Header 11', | ||
| 867 | + 0x872: 'FEAT11 : Shared Feature 11 Record', | ||
| 868 | + 0x873: 'FEATINFO11 : Shared Feature Info 11 Record', | ||
| 869 | + 0x874: 'DROPDOWNOBJIDS : Drop Down Object', | ||
| 870 | + 0x875: 'CONTINUEFRT11 : Continue FRT 11', | ||
| 871 | + 0x876: 'DCONN : Data Connection', | ||
| 872 | + 0x877: 'LIST12 : Extra Table Data Introduced in Excel 2007', | ||
| 873 | + 0x878: 'FEAT12 : Shared Feature 12 Record', | ||
| 874 | + 0x879: 'CONDFMT12 : Conditional Formatting Range Information 12', | ||
| 875 | + 0x87A: 'CF12 : Conditional Formatting Condition 12', | ||
| 876 | + 0x87B: 'CFEX : Conditional Formatting Extension', | ||
| 877 | + 0x87C: 'XFCRC : XF Extensions Checksum', | ||
| 878 | + 0x87D: 'XFEXT : XF Extension', | ||
| 879 | + 0x87E: 'EZFILTER12 : AutoFilter Data Introduced in Excel 2007', | ||
| 880 | + 0x87F: 'CONTINUEFRT12 : Continue FRT 12', | ||
| 881 | + 0x881: 'SXADDL12 : Additional Workbook Connections Information', | ||
| 882 | + 0x884: 'MDTINFO : Information about a Metadata Type', | ||
| 883 | + 0x885: 'MDXSTR : MDX Metadata String', | ||
| 884 | + 0x886: 'MDXTUPLE : Tuple MDX Metadata', | ||
| 885 | + 0x887: 'MDXSET : Set MDX Metadata', | ||
| 886 | + 0x888: 'MDXPROP : Member Property MDX Metadata', | ||
| 887 | + 0x889: 'MDXKPI : Key Performance Indicator MDX Metadata', | ||
| 888 | + 0x88A: 'MDTB : Block of Metadata Records', | ||
| 889 | + 0x88B: 'PLV : Page Layout View Settings in Excel 2007', | ||
| 890 | + 0x88C: 'COMPAT12 : Compatibility Checker 12', | ||
| 891 | + 0x88D: 'DXF : Differential XF', | ||
| 892 | + 0x88E: 'TABLESTYLES : Table Styles', | ||
| 893 | + 0x88F: 'TABLESTYLE : Table Style', | ||
| 894 | + 0x890: 'TABLESTYLEELEMENT : Table Style Element', | ||
| 895 | + 0x892: 'STYLEEXT : Named Cell Style Extension', | ||
| 896 | + 0x893: 'NAMEPUBLISH : Publish To Excel Server Data for Name', | ||
| 897 | + 0x894: 'NAMECMT : Name Comment', | ||
| 898 | + 0x895: 'SORTDATA12 : Sort Data 12', | ||
| 899 | + 0x896: 'THEME : Theme', | ||
| 900 | + 0x897: 'GUIDTYPELIB : VB Project Typelib GUID', | ||
| 901 | + 0x898: 'FNGRP12 : Function Group', | ||
| 902 | + 0x899: 'NAMEFNGRP12 : Extra Function Group', | ||
| 903 | + 0x89A: 'MTRSETTINGS : Multi-Threaded Calculation Settings', | ||
| 904 | + 0x89B: 'COMPRESSPICTURES : Automatic Picture Compression Mode', | ||
| 905 | + 0x89C: 'HEADERFOOTER : Header Footer', | ||
| 906 | + 0x8A3: 'FORCEFULLCALCULATION : Force Full Calculation Settings', | ||
| 907 | + 0x8c1: 'LISTOBJ : List Object', | ||
| 908 | + 0x8c2: 'LISTFIELD : List Field', | ||
| 909 | + 0x8c3: 'LISTDV : List Data Validation', | ||
| 910 | + 0x8c4: 'LISTCONDFMT : List Conditional Formatting', | ||
| 911 | + 0x8c5: 'LISTCF : List Cell Formatting', | ||
| 912 | + 0x8c6: 'FMQRY : Filemaker queries', | ||
| 913 | + 0x8c7: 'FMSQRY : File maker queries', | ||
| 914 | + 0x8c8: 'PLV : Page Layout View in Mac Excel 11', | ||
| 915 | + 0x8c9: 'LNEXT : Extension information for borders in Mac Office 11', | ||
| 916 | + 0x8ca: 'MKREXT : Extension information for markers in Mac Office 11' | ||
| 917 | + } | ||
| 918 | + | ||
| 1015 | if self.streamname in [['Workbook'], ['Book']]: | 919 | if self.streamname in [['Workbook'], ['Book']]: |
| 1016 | self.ran = True | 920 | self.ran = True |
| 1017 | - # use a bytearray to have Python 2+3 compatibility with the same code (no need for ord()) | ||
| 1018 | - stream = bytearray(self.stream) | 921 | + stream = self.stream |
| 1019 | 922 | ||
| 1020 | oParser = optparse.OptionParser() | 923 | oParser = optparse.OptionParser() |
| 1021 | oParser.add_option('-s', '--strings', action='store_true', default=False, help='Dump strings') | 924 | oParser.add_option('-s', '--strings', action='store_true', default=False, help='Dump strings') |
| @@ -1028,12 +931,10 @@ class cBIFF(object): # cPluginParent): | @@ -1028,12 +931,10 @@ class cBIFF(object): # cPluginParent): | ||
| 1028 | if options.find.startswith('0x'): | 931 | if options.find.startswith('0x'): |
| 1029 | options.find = binascii.a2b_hex(options.find[2:]) | 932 | options.find = binascii.a2b_hex(options.find[2:]) |
| 1030 | 933 | ||
| 1031 | - while len(stream)>0: | 934 | + while len(stream) > 0: |
| 1032 | formatcodes = 'HH' | 935 | formatcodes = 'HH' |
| 1033 | formatsize = struct.calcsize(formatcodes) | 936 | formatsize = struct.calcsize(formatcodes) |
| 1034 | - # print('formatsize=%d' % formatsize) | ||
| 1035 | opcode, length = struct.unpack(formatcodes, stream[0:formatsize]) | 937 | opcode, length = struct.unpack(formatcodes, stream[0:formatsize]) |
| 1036 | - # print('opcode=%d length=%d len(stream)=%d' % (opcode, length, len(stream))) | ||
| 1037 | stream = stream[formatsize:] | 938 | stream = stream[formatsize:] |
| 1038 | data = stream[:length] | 939 | data = stream[:length] |
| 1039 | stream = stream[length:] | 940 | stream = stream[length:] |
| @@ -1043,7 +944,6 @@ class cBIFF(object): # cPluginParent): | @@ -1043,7 +944,6 @@ class cBIFF(object): # cPluginParent): | ||
| 1043 | else: | 944 | else: |
| 1044 | opcodename = '' | 945 | opcodename = '' |
| 1045 | line = '%04x %6d %s' % (opcode, length, opcodename) | 946 | line = '%04x %6d %s' % (opcode, length, opcodename) |
| 1046 | - # print(line) | ||
| 1047 | 947 | ||
| 1048 | # FORMULA record | 948 | # FORMULA record |
| 1049 | if opcode == 0x06 and len(data) >= 21: | 949 | if opcode == 0x06 and len(data) >= 21: |
| @@ -1055,42 +955,38 @@ class cBIFF(object): # cPluginParent): | @@ -1055,42 +955,38 @@ class cBIFF(object): # cPluginParent): | ||
| 1055 | length = struct.unpack(formatcodes, data[20:20 + formatsize])[0] | 955 | length = struct.unpack(formatcodes, data[20:20 + formatsize])[0] |
| 1056 | expression = data[22:] | 956 | expression = data[22:] |
| 1057 | line += ' - R%dC%d len=%d %s' % (row + 1, column + 1, length, ParseExpression(expression)) | 957 | line += ' - R%dC%d len=%d %s' % (row + 1, column + 1, length, ParseExpression(expression)) |
| 1058 | - # print(line) | ||
| 1059 | 958 | ||
| 1060 | # FORMULA record #a# difference BIFF4 and BIFF5+ | 959 | # FORMULA record #a# difference BIFF4 and BIFF5+ |
| 1061 | if opcode == 0x18 and len(data) >= 16: | 960 | if opcode == 0x18 and len(data) >= 16: |
| 1062 | - if data[0] & 0x20: | 961 | + if P23Ord(data[0]) & 0x20: |
| 1063 | dBuildInNames = {1: 'Auto_Open', 2: 'Auto_Close'} | 962 | dBuildInNames = {1: 'Auto_Open', 2: 'Auto_Close'} |
| 1064 | - code = data[14] | 963 | + code = P23Ord(data[14]) |
| 1065 | if code == 0: #a# hack with BIFF8 Unicode | 964 | if code == 0: #a# hack with BIFF8 Unicode |
| 1066 | - code = data[15] | 965 | + code = P23Ord(data[15]) |
| 1067 | line += ' - build-in-name %d %s' % (code, dBuildInNames.get(code, '?')) | 966 | line += ' - build-in-name %d %s' % (code, dBuildInNames.get(code, '?')) |
| 1068 | else: | 967 | else: |
| 1069 | pass | 968 | pass |
| 1070 | - line += ' - %s' % bytes2str(data[14:14+data[3]]) | ||
| 1071 | - # print(line) | 969 | + line += ' - %s' % (data[14:14+P23Ord(data[3])]) |
| 1072 | 970 | ||
| 1073 | # BOUNDSHEET record | 971 | # BOUNDSHEET record |
| 1074 | if opcode == 0x85 and len(data) >= 6: | 972 | if opcode == 0x85 and len(data) >= 6: |
| 1075 | dSheetType = {0: 'worksheet or dialog sheet', 1: 'Excel 4.0 macro sheet', 2: 'chart', 6: 'Visual Basic module'} | 973 | dSheetType = {0: 'worksheet or dialog sheet', 1: 'Excel 4.0 macro sheet', 2: 'chart', 6: 'Visual Basic module'} |
| 1076 | - if data[5] == 1: | 974 | + if P23Ord(data[5]) == 1: |
| 1077 | macros4Found = True | 975 | macros4Found = True |
| 1078 | dSheetState = {0: 'visible', 1: 'hidden', 2: 'very hidden'} | 976 | dSheetState = {0: 'visible', 1: 'hidden', 2: 'very hidden'} |
| 1079 | - line += ' - %s, %s' % (dSheetType.get(data[5], '%02x' % data[5]), dSheetState.get(data[4], '%02x' % data[4])) | ||
| 1080 | - # print(line) | 977 | + line += ' - %s, %s' % (dSheetType.get(P23Ord(data[5]), '%02x' % P23Ord(data[5])), dSheetState.get(P23Ord(data[4]), '%02x' % P23Ord(data[4]))) |
| 1081 | 978 | ||
| 1082 | # STRING record | 979 | # STRING record |
| 1083 | if opcode == 0x207 and len(data) >= 4: | 980 | if opcode == 0x207 and len(data) >= 4: |
| 1084 | values = list(Strings(data[3:]).values()) | 981 | values = list(Strings(data[3:]).values()) |
| 1085 | - strings = '' | 982 | + strings = b'' |
| 1086 | if values[0] != []: | 983 | if values[0] != []: |
| 1087 | - strings += ' '.join(values[0]) | 984 | + strings += b' '.join(values[0]) |
| 1088 | if values[1] != []: | 985 | if values[1] != []: |
| 1089 | - if strings != '': | ||
| 1090 | - strings += ' ' | ||
| 1091 | - strings += ' '.join(values[1]) | 986 | + if strings != b'': |
| 987 | + strings += b' ' | ||
| 988 | + strings += b' '.join(values[1]) | ||
| 1092 | line += ' - %s' % strings | 989 | line += ' - %s' % strings |
| 1093 | - # print(line) | ||
| 1094 | 990 | ||
| 1095 | if options.find == '' and options.opcode == '' and not options.xlm or options.opcode != '' and options.opcode.lower() in line.lower() or options.find != '' and options.find in data or options.xlm and opcode in [0x06, 0x18, 0x85, 0x207]: | 991 | if options.find == '' and options.opcode == '' and not options.xlm or options.opcode != '' and options.opcode.lower() in line.lower() or options.find != '' and options.find in data or options.xlm and opcode in [0x06, 0x18, 0x85, 0x207]: |
| 1096 | result.append(line) | 992 | result.append(line) |