Exemple #1
0
 public void SetRgce(Stack <AbstractPtg> rgce)
 {
     _rgce = rgce;
     byte[] rgceBytes = PtgHelper.GetBytes(rgce);
     cce     = Convert.ToUInt16(rgceBytes.Length);
     _length = CalculateLength();
 }
Exemple #2
0
        public override byte[] GetBytes()
        {
            using (BinaryWriter bw = new BinaryWriter(new MemoryStream()))
            {
                bw.Write(GetHeaderBytes());
                bw.Write(Convert.ToUInt16(rw));
                bw.Write(Convert.ToUInt16(col));
                bw.Write(Convert.ToUInt16(ixfe));
                bw.Write(val);
                bw.Write(Convert.ToUInt16(grbit));
                bw.Write(Convert.ToUInt32(chn));
                bw.Write(Convert.ToUInt16(cce));

                if (!this.fShrFmla)
                {
                    byte[] ptgBytes = PtgHelper.GetBytes(ptgStack);
                    bw.Write(ptgBytes);
                }
                else
                {
                    throw new NotImplementedException();
                }

                return(bw.GetBytesWritten());
            }
        }
Exemple #3
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);
        }
Exemple #4
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);
        }
Exemple #5
0
 public CellParsedFormula(Stack <AbstractPtg> ptgStack)
 {
     rgce     = PtgHelper.GetBytes(ptgStack);
     PtgStack = ptgStack;
     rgcb     = new byte[] { };
     cce      = Convert.ToUInt16(rgce.Length);
 }
Exemple #6
0
        public override string ToString()
        {
            string name = Name.Value;

            if (fBuiltin)
            {
                string builtinName = ExcelHelperClass.getNameStringfromBuiltInFunctionID(Name.Value);

                if (Name.Value.Length > 1)
                {
                    builtinName += new String(Name.Value.Skip(1).ToArray());
                }
                name = builtinName;
            }

            string labelString = string.Format(
                "Lbl (0x{0} bytes) - flags: 0x{1} | fBuiltin: {2} | fHidden: {3} | Name [unicode={4}]: {5}",
                Length.ToString("X"),
                Flags.ToString("X"),
                fBuiltin,
                fHidden,
                Name.fHighByte,
                name);

            if (rgce != null && rgce.Count > 0)
            {
                string labelRgceContent = "";

                switch (rgce.First())
                {
                //When we reference a different name
                case PtgName ptgName:
                    labelRgceContent = ptgName.ToString();
                    break;

                case PtgRef3d ptgRef3d:
                    labelRgceContent = ptgRef3d.ToString();
                    break;

                default:
                    labelRgceContent = PtgHelper.GetFormulaString(rgce);
                    break;
                }

                if (IsAutoOpenLabel())
                {
                    labelString += " !AUTO_OPEN!";
                }

                labelString += " | Formula: " + labelRgceContent;
            }

            return(labelString);
        }
Exemple #7
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);
                }
            }
        }
Exemple #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.</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);
            }
        }
Exemple #9
0
        public void TestFormulaToStringConversion()
        {
            WorkbookStream wbs = TestHelpers.GetMacroLoopWorkbookStream();

            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
            };

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

            relevantRecords = RecordHelper.ConvertToSpecificRecords(relevantRecords);

            relevantRecords = PtgHelper.UpdateGlobalsStreamReferences(relevantRecords);

            List <string> results = relevantRecords.Select(r => r.ToHexDumpString()).ToList();


            string b1formula = results.Where(res => res.StartsWith("Formula[B1]")).First();

            Assert.AreEqual("Formula[B1]: invokeChar=A11", b1formula);

            string b2formula = results.Where(res => res.StartsWith("Formula[B2]")).First();

            Assert.AreEqual("Formula[B2]: var=999", b2formula);

            string b5formula = results.Where(res => res.StartsWith("Formula[B5]")).First();

            Assert.AreEqual("Formula[B5]: InvokeFormula(\"=HALT()\",A1)", b5formula);

            string b6formula = results.Where(res => res.StartsWith("Formula[B6]")).First();

            Assert.AreEqual("Formula[B6]: WProcessMemory(-1,B2+(D1*255),ACTIVE.CELL(),LEN(ACTIVE.CELL()),0)", b6formula);

            string a11formula = results.Where(res => res.StartsWith("Formula[A11]")).First();

            Assert.AreEqual("Formula[A11]: RETURN(CHAR(var))", a11formula);

            string a12formula = results.Where(res => res.StartsWith("Formula[A12]")).First();

            Assert.AreEqual("Formula[A12]: RETURN(FORMULA(arg1,arg2))", a12formula);

            string d13formula = results.Where(res => res.StartsWith("Formula[D13]")).First();

            Assert.AreEqual("Formula[D13]: stringToBuild=stringToBuild&invokeChar()", d13formula);

            string d14formula = results.Where(res => res.StartsWith("Formula[D14]")).First();

            Assert.AreEqual("Formula[D14]: curCell=ABSREF(\"R[1]C\",curCell)", d14formula);
        }
Exemple #10
0
        public override byte[] GetBytes()
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryWriter bw = new BinaryWriter(stream);

                byte[] headerBytes = base.GetHeaderBytes();
                bw.Write(headerBytes);

                uint flags = 0;
                flags = flags | Utils.BoolToBitmask(this.fHidden, 0x0001);
                flags = flags | Utils.BoolToBitmask(this.fFunc, 0x0002);
                flags = flags | Utils.BoolToBitmask(this.fOB, 0x0004);
                flags = flags | Utils.BoolToBitmask(this.fProc, 0x0008);
                flags = flags | Utils.BoolToBitmask(this.fCalcExp, 0x0010);
                flags = flags | Utils.BoolToBitmask(this.fBuiltin, 0x0020);
                flags = flags | Utils.ByteToBitmask(this.fGrp, 0x0FC0);
                flags = flags | Utils.BoolToBitmask(this.fReserved1, 0x1000);
                flags = flags | Utils.BoolToBitmask(this.fPublished, 0x2000);
                flags = flags | Utils.BoolToBitmask(this.fWorkbookParam, 0x4000);
                flags = flags | Utils.BoolToBitmask(this.fReserved2, 0x8000);
                bw.Write(Convert.ToUInt16(flags));

                bw.Write(this.chKey);
                bw.Write(this.cch);
                bw.Write(Convert.ToUInt16(this.cce));
                bw.Write(Convert.ToUInt16(this.fReserved3));
                bw.Write(Convert.ToUInt16(this.itab));
                bw.Write(Convert.ToUInt32(this.fReserved4));

                if (RawLblBytes != null)
                {
                    bw.Write(RawLblBytes);
                }
                else
                {
                    bw.Write(this.Name.Bytes);

                    if (this.rgce != null)
                    {
                        byte[] ptgBytes = PtgHelper.GetBytes(this.rgce);
                        bw.Write(ptgBytes);
                    }
                }

                return(bw.GetBytesWritten());
            }
        }
Exemple #11
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);
            }
        }
Exemple #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);
            }
        }
Exemple #13
0
 public string ToFormulaString(bool showAttributes = false)
 {
     return(string.Format("Formula[{0}]", GetCellName()) + ": " + PtgHelper.GetFormulaString(ptgStack, showAttributes));
 }