Esempio n. 1
0
        public WorkbookStream(string filePath)
        {
            using (var fs = new FileStream(filePath, FileMode.Open))
            {
                StructuredStorageReader ssr = new StructuredStorageReader(fs);
                try
                {
                    var    wbStream = ssr.GetStream("Workbook");
                    byte[] wbBytes  = new byte[wbStream.Length];
                    wbStream.Read(wbBytes, 0, wbBytes.Length, 0);
                    _biffRecords = RecordHelper.ParseBiffStreamBytes(wbBytes);
                }
                catch (StreamNotFoundException)
                {
                    var wbStream = ssr.GetStream("Book");
                    Console.WriteLine("WARNING: Main stream is in a Book record indicating legacy Excel 5 BIFF format. This may not parse correctly.");

                    byte[] wbBytes = new byte[wbStream.Length];
                    wbStream.Read(wbBytes, 0, wbBytes.Length, 0);
                    try
                    {
                        _biffRecords = RecordHelper.ParseBiffStreamBytes(wbBytes);
                    }
                    catch (Exception)
                    {
                        throw new NotImplementedException("Error parsing Book stream: Macrome currently doesn't support the Excel 5 BIFF format.");
                    }
                }
            }
        }
Esempio n. 2
0
        public static string GetRelevantRecordDumpString(WorkbookStream wbs, bool dumpHexBytes = false, bool showAttrInfo = false)
        {
            int numBytesToDump = 0;

            if (dumpHexBytes)
            {
                numBytesToDump = 0x1000;
            }

            List <BiffRecord> relevantRecords = wbs.Records.Where(rec => RecordHelper.RelevantTypes.Contains(rec.Id)).ToList();

            relevantRecords = RecordHelper.ConvertToSpecificRecords(relevantRecords);

            relevantRecords = PtgHelper.UpdateGlobalsStreamReferences(relevantRecords);

            string dumpString = "";

            foreach (var record in relevantRecords)
            {
                dumpString += record.ToHexDumpString(numBytesToDump, showAttrInfo);
                dumpString += "\n";
            }

            return(dumpString);
        }
Esempio n. 3
0
        public static string GetRelevantRecordDumpString(WorkbookStream wbs, bool dumpHexBytes = false, bool showAttrInfo = false)
        {
            int numBytesToDump = 0;

            if (dumpHexBytes)
            {
                numBytesToDump = 0x1000;
            }

            bool hasPassword = wbs.HasPasswordToOpen();

            List <BiffRecord> relevantRecords = wbs.Records.Where(rec => RecordHelper.RelevantTypes.Contains(rec.Id)).ToList();

            //We can only interpret the data of these records if they are not encrypted
            if (!hasPassword)
            {
                relevantRecords = RecordHelper.ConvertToSpecificRecords(relevantRecords);
                relevantRecords = PtgHelper.UpdateGlobalsStreamReferences(relevantRecords);
            }

            string dumpString = "";

            foreach (var record in relevantRecords)
            {
                dumpString += record.ToHexDumpString(numBytesToDump, showAttrInfo);
                dumpString += "\n";
            }

            return(dumpString);
        }
Esempio n. 4
0
 public WorkbookStream(string filePath)
 {
     using (var fs = new FileStream(filePath, FileMode.Open))
     {
         StructuredStorageReader ssr = new StructuredStorageReader(fs);
         var    wbStream             = ssr.GetStream("Workbook");
         byte[] wbBytes = new byte[wbStream.Length];
         wbStream.Read(wbBytes, 0, wbBytes.Length, 0);
         _biffRecords = RecordHelper.ParseBiffStreamBytes(wbBytes);
     }
 }
Esempio n. 5
0
        /// <summary>
        /// Dumps information about BIFF records that are relevant for analysis. Defaults to sheet, label, and formula data.
        /// </summary>
        /// <param name="path">Path to the XLS file to dump</param>
        /// <param name="dumpAll">Dump all BIFF records, not the most commonly used by maldocs</param>
        /// <param name="showAttrInfo">Explicitly display PtgAttr information in Formula strings. Defaults to False.</param>
        /// <param name="dumpHexBytes">Dump the byte content of each BIFF record in addition to its content summary. Defaults to False.</param>
        public static void Dump(FileInfo path, bool dumpAll = false, bool showAttrInfo = false, bool dumpHexBytes = false)
        {
            if (path == null)
            {
                Console.WriteLine("path argument must be specified in Dump mode. Run dump -h for usage instructions.");
                return;
            }

            if (path.Exists == false)
            {
                Console.WriteLine("path file does not exist.");
                return;
            }

            WorkbookStream wbs = new WorkbookStream(path.FullName);

            List <RecordType> relevantTypes = new List <RecordType>()
            {
                RecordType.BoundSheet8,     //Sheet definitions (Defines macro sheets + hides them)
                RecordType.Lbl,             //Named Cells (Contains Auto_Start)
                RecordType.Formula,         //The meat of most cell content
                RecordType.SupBook,         //Contains information for cross-sheet references
                RecordType.ExternSheet      //Contains the XTI records mapping ixti values to BoundSheet8
            };

            int numBytesToDump = 0;

            if (dumpHexBytes)
            {
                numBytesToDump = 0x1000;
            }

            if (dumpAll)
            {
                WorkbookStream fullStream = new WorkbookStream(PtgHelper.UpdateGlobalsStreamReferences(wbs.Records));
                foreach (var record in fullStream.Records)
                {
                    Console.WriteLine(record.ToHexDumpString(numBytesToDump, showAttrInfo));
                }
            }
            else
            {
                List <BiffRecord> relevantRecords = wbs.Records.Where(rec => relevantTypes.Contains(rec.Id)).ToList();
                relevantRecords = RecordHelper.ConvertToSpecificRecords(relevantRecords);

                relevantRecords = PtgHelper.UpdateGlobalsStreamReferences(relevantRecords);
                foreach (var record in relevantRecords)
                {
                    string dumpString = "";
                    dumpString += record.ToHexDumpString(numBytesToDump, showAttrInfo);
                    Console.WriteLine(dumpString);
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Dumps information about BIFF records that are relevant for analysis. Defaults to sheet, label, and formula data.
        /// </summary>
        /// <param name="path">Path to the XLS file to dump</param>
        /// <param name="dumpAll">Dump all BIFF records, not the most commonly used by maldocs</param>
        /// <param name="showAttrInfo">Explicitly display PtgAttr information in Formula strings. Defaults to False.</param>
        /// <param name="dumpHexBytes">Dump the byte content of each BIFF record in addition to its content summary.</param>
        /// <param name="password">XOR Obfuscation decryption password to try. Defaults to VelvetSweatshop if FilePass record is found.</param>
        /// <param name="disableDecryption">Use this flag in order to skip decryption of the file before dumping.</param>
        public static void Dump(FileInfo path, bool dumpAll = false, bool showAttrInfo = false, bool dumpHexBytes = false, string password = "******", bool disableDecryption = false)
        {
            if (path == null)
            {
                Console.WriteLine("path argument must be specified in Dump mode. Run dump -h for usage instructions.");
                return;
            }

            if (path.Exists == false)
            {
                Console.WriteLine("path file does not exist.");
                return;
            }

            WorkbookStream wbs = new WorkbookStream(path.FullName);

            if (wbs.HasPasswordToOpen() && !disableDecryption)
            {
                Console.WriteLine("FilePass record found - attempting to decrypt with password " + password);
                XorObfuscation xorObfuscation = new XorObfuscation();
                try
                {
                    wbs = xorObfuscation.DecryptWorkbookStream(wbs, password);
                }
                catch (ArgumentException argEx)
                {
                    Console.WriteLine("Password " + password + " does not match the verifier value of the document FilePass. Try a different password.");
                    return;
                }
            }

            int numBytesToDump = 0;

            if (dumpHexBytes)
            {
                numBytesToDump = 0x1000;
            }

            if (dumpAll)
            {
                List <BiffRecord> records;
                WorkbookStream    fullStream = new WorkbookStream(PtgHelper.UpdateGlobalsStreamReferences(wbs.Records));
                records = fullStream.Records;
                foreach (var record in records)
                {
                    Console.WriteLine(record.ToHexDumpString(numBytesToDump, showAttrInfo));
                }
            }
            else
            {
                string dumpString = RecordHelper.GetRelevantRecordDumpString(wbs, dumpHexBytes, showAttrInfo);
                Console.WriteLine(dumpString);
            }
        }
Esempio n. 7
0
        public WorkbookStream AddSheet(BoundSheet8 sheetHeader, byte[] sheetBytes)
        {
            WorkbookStream     newStream           = new WorkbookStream(Records);
            List <BoundSheet8> existingBoundSheets = newStream.GetAllRecordsByType <BoundSheet8>();
            BoundSheet8        lastSheet8          = existingBoundSheets.Last();

            newStream = newStream.InsertRecord(sheetHeader, lastSheet8);

            List <BiffRecord> sheetRecords = RecordHelper.ParseBiffStreamBytes(sheetBytes);

            newStream = newStream.InsertRecords(sheetRecords);

            newStream = newStream.FixBoundSheetOffsets();

            return(newStream);
        }
Esempio n. 8
0
        /// <summary>
        /// Dumps information about BIFF records that are relevant for analysis. Defaults to sheet, label, and formula data.
        /// </summary>
        /// <param name="path">Path to the XLS file to dump</param>
        /// <param name="dumpAll">Dump all BIFF records, not the most commonly used by maldocs</param>
        /// <param name="showAttrInfo">Explicitly display PtgAttr information in Formula strings. Defaults to False.</param>
        /// <param name="dumpHexBytes">Dump the byte content of each BIFF record in addition to its content summary. Defaults to False.</param>
        public static void Dump(FileInfo path, bool dumpAll = false, bool showAttrInfo = false, bool dumpHexBytes = false)
        {
            if (path == null)
            {
                Console.WriteLine("path argument must be specified in Dump mode. Run dump -h for usage instructions.");
                return;
            }

            if (path.Exists == false)
            {
                Console.WriteLine("path file does not exist.");
                return;
            }

            WorkbookStream wbs = new WorkbookStream(path.FullName);



            int numBytesToDump = 0;

            if (dumpHexBytes)
            {
                numBytesToDump = 0x1000;
            }

            if (dumpAll)
            {
                WorkbookStream fullStream = new WorkbookStream(PtgHelper.UpdateGlobalsStreamReferences(wbs.Records));
                foreach (var record in fullStream.Records)
                {
                    Console.WriteLine(record.ToHexDumpString(numBytesToDump, showAttrInfo));
                }
            }
            else
            {
                string dumpString = RecordHelper.GetRelevantRecordDumpString(wbs, dumpHexBytes, showAttrInfo);
                Console.WriteLine(dumpString);
            }
        }
Esempio n. 9
0
 public WorkbookStream(byte[] workbookBytes)
 {
     _biffRecords = RecordHelper.ParseBiffStreamBytes(workbookBytes);
 }
Esempio n. 10
0
 public byte[] ToBytes()
 {
     return(RecordHelper.ConvertBiffRecordsToBytes(_biffRecords));
 }
Esempio n. 11
0
 public WorkbookStream AddSheet(BoundSheet8 sheetHeader, List <BiffRecord> records)
 {
     return(AddSheet(sheetHeader, RecordHelper.ConvertBiffRecordsToBytes(records)));
 }
Esempio n. 12
0
        /// <summary>
        /// Dumps information about BIFF records that are relevant for analysis. Defaults to sheet, label, and formula data.
        /// </summary>
        /// <param name="path">Path to the XLS file to dump</param>
        /// <param name="dumpAll">Dump all BIFF records, not the most commonly used by maldocs</param>
        /// <param name="showAttrInfo">Explicitly display PtgAttr information in Formula strings. Defaults to False.</param>
        /// <param name="dumpHexBytes">Dump the byte content of each BIFF record in addition to its content summary.</param>
        /// <param name="password">XOR Obfuscation decryption password to try. Defaults to VelvetSweatshop if FilePass record is found.</param>
        /// <param name="disableDecryption">Use this flag in order to skip decryption of the file before dumping.</param>
        public static void Dump(FileInfo path, bool dumpAll = false, bool showAttrInfo = false, bool dumpHexBytes = false, string password = "******", bool disableDecryption = false)
        {
            if (path == null)
            {
                Console.WriteLine("path argument must be specified in Dump mode. Run dump -h for usage instructions.");
                return;
            }

            if (path.Exists == false)
            {
                Console.WriteLine("path file does not exist.");
                return;
            }

            WorkbookStream wbs = new WorkbookStream(path.FullName);

            if (wbs.HasPasswordToOpen() && !disableDecryption)
            {
                FilePass fpRecord = wbs.GetAllRecordsByType <FilePass>().First();

                if (fpRecord.wEncryptionType == 0 && fpRecord.xorObfuscationKey != 0)
                {
                    XorObfuscation xorObfuscation = new XorObfuscation();
                    Console.WriteLine("FilePass record found - attempting to decrypt with password " + password);
                    try
                    {
                        wbs = xorObfuscation.DecryptWorkbookStream(wbs, password);
                    }
                    catch (ArgumentException argEx)
                    {
                        Console.WriteLine("Password " + password + " does not match the verifier value of the document FilePass. Try a different password.");
                        return;
                    }
                }
                else if (fpRecord.wEncryptionType == 1 && fpRecord.vMajor > 1)
                {
                    Console.WriteLine("FilePass record for CryptoAPI Found - Currently Unsupported.");
                    string verifierSalt = BitConverter.ToString(fpRecord.encryptionVerifier.Salt).Replace("-", "");
                    string verifier     = BitConverter.ToString(fpRecord.encryptionVerifier.EncryptedVerifier).Replace("-", "");
                    string verifierHash = BitConverter.ToString(fpRecord.encryptionVerifier.EncryptedVerifierHash).Replace("-", "");
                    Console.WriteLine("Salt is: " + verifierSalt);
                    Console.WriteLine("Vrfy is: " + verifier);
                    Console.WriteLine("vHsh is: " + verifierHash);
                    Console.WriteLine("Algo is: " + string.Format("{0:x8}", fpRecord.encryptionHeader.AlgID));
                }

                else if (fpRecord.wEncryptionType == 1 && fpRecord.vMajor == 1)
                {
                    Console.WriteLine("FilePass record for RC4 Binary Document Encryption Found - Currently Unsupported.");
                }
            }

            int numBytesToDump = 0;

            if (dumpHexBytes)
            {
                numBytesToDump = 0x1000;
            }

            if (dumpAll)
            {
                List <BiffRecord> records;
                WorkbookStream    fullStream = new WorkbookStream(PtgHelper.UpdateGlobalsStreamReferences(wbs.Records));
                records = fullStream.Records;
                foreach (var record in records)
                {
                    Console.WriteLine(record.ToHexDumpString(numBytesToDump, showAttrInfo));
                }
            }
            else
            {
                string dumpString = RecordHelper.GetRelevantRecordDumpString(wbs, dumpHexBytes, showAttrInfo);
                Console.WriteLine(dumpString);
            }
        }