public void SetRgce(Stack <AbstractPtg> rgce) { _rgce = rgce; byte[] rgceBytes = PtgHelper.GetBytes(rgce); cce = Convert.ToUInt16(rgceBytes.Length); _length = CalculateLength(); }
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()); } }
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); }
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); }
public CellParsedFormula(Stack <AbstractPtg> ptgStack) { rgce = PtgHelper.GetBytes(ptgStack); PtgStack = ptgStack; rgcb = new byte[] { }; cce = Convert.ToUInt16(rgce.Length); }
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); }
/// <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); } } }
/// <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); } }
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); }
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()); } }
/// <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); } }
/// <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); } }
public string ToFormulaString(bool showAttributes = false) { return(string.Format("Formula[{0}]", GetCellName()) + ": " + PtgHelper.GetFormulaString(ptgStack, showAttributes)); }