Exemplo n.º 1
0
        public void Test_COMPRESS_SPACE()
        {
            String FILENAME = "MultipleStorage3.cfs"; // 22Kb

            FileInfo srcFile = new FileInfo(FILENAME);

            File.Copy(FILENAME, "MultipleStorage_Deleted_Compress.cfs", true);

            CompoundFile cf = new CompoundFile("MultipleStorage_Deleted_Compress.cfs", CFSUpdateMode.Update, CFSConfiguration.SectorRecycle | CFSConfiguration.EraseFreeSectors);

            CFStorage st = cf.RootStorage.GetStorage("MyStorage");

            st = st.GetStorage("AnotherStorage");

            Assert.IsNotNull(st);
            st.Delete("Another2Stream");
            cf.Commit();
            cf.Close();

            CompoundFile.ShrinkCompoundFile("MultipleStorage_Deleted_Compress.cfs"); // -> 7Kb

            FileInfo dstFile = new FileInfo("MultipleStorage_Deleted_Compress.cfs");

            Assert.IsTrue(srcFile.Length > dstFile.Length);
        }
Exemplo n.º 2
0
        public static VBAInfo FromCompoundFile(CompoundFile cf, List <string> moduleNames)
        {
            VBAInfo info = new VBAInfo();

            try
            {
                CFStorage projectStorage = cf.RootStorage.GetStorage("_VBA_PROJECT_CUR");
                CFStorage vbaStorage     = projectStorage.GetStorage("VBA");

                info.ProjectWmStream = projectStorage.GetStream("PROJECTwm");
                info.ProjectStream   = projectStorage.GetStream("PROJECT");

                info.ThisWorkbookStream = vbaStorage.GetStream("ThisWorkbook");
                info.VbaProjectStream   = vbaStorage.GetStream("_VBA_PROJECT");
                info.dirStream          = vbaStorage.GetStream("dir");
                info.ModuleStreams      = new List <CFStream>();
                foreach (var moduleName in moduleNames)
                {
                    try
                    {
                        info.ModuleStreams.Add(vbaStorage.GetStream(moduleName));
                    }
                    catch (CFItemNotFound)
                    {
                    }
                }
            }
            catch (CFItemNotFound)
            {
                // If we don't have any VBA directory then just return null
                return(null);
            }

            return(info);
        }
        public void LoadRpmsgDataFromEmbeddedAttachment(CFStorage msgStorage)
        {
            LogUtils.Log("");
            try
            {
                CFStorage firstAttachmentStorage = msgStorage.GetStorage(FIRST_MSG_ATTACHMENT_STORAGE_NAME);
                string    fileName = Encoding.Unicode.GetString(firstAttachmentStorage.GetStream(PidTagAttachLongFilename).GetData());
                if (fileName.Equals(RPMSG_ATTACHMENT_NAME))
                {
                    Content   = firstAttachmentStorage.GetStream(PidTagAttachDataBinary).GetData();
                    Extension = ".rpmsg";
                    //embedded messages do not have an extension in the attachment props
                    Name    += ".msg";
                    MimeType = Encoding.Unicode.GetString(firstAttachmentStorage.GetStream(MIME_TYPE_STREAM_NAME).GetData());
                    return;
                }

                throw new CFItemNotFound("");
            }
            catch (CFItemNotFound)
            {
                LogUtils.Log("Embedded message is not protected");
                Content = new byte[0];
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Получить ссылку на поток из файла MCDF по его пути
        /// </summary>
        /// <param name="file">Файл - хранилище</param>
        /// <param name="streamPath">Путь к потоку в файле</param>
        /// <returns></returns>
        public static CFStream GetFileStream(CompoundFile file, string streamPath)
        {
            string[]  path   = streamPath.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
            CFStorage curDir = file.RootStorage;

            for (int i = 0; i < path.Length - 1; i++)
            {
                curDir = curDir.GetStorage(path[i]);
            }
            return(curDir.GetStream(path[path.Length - 1]));
        }
Exemplo n.º 5
0
        /// <summary>
        ///     Writes the properties to the <see cref="CFStorage" />
        /// </summary>
        /// <param name="storage"></param>
        /// <param name="messageSize"></param>
        /// <remarks>
        ///     Unfortunately this is going to have to be used after we already written the top level properties.
        /// </remarks>
        internal void WriteProperties(CFStorage storage, long messageSize = 0)
        {
            // Grab the nameIdStorage, 3.1 on the SPEC
            storage = storage.GetStorage(PropertyTags.NameIdStorage);

            var entryStream         = new EntryStream(storage);
            var stringStream        = new StringStream(storage);
            var guidStream          = new GuidStream(storage);
            var nameIdMappingStream = new EntryStream(storage);

            ushort propertyIndex = 0;

            foreach (var guid in Guids.Where(g => g != PropertySets.PS_MAPI && g != PropertySets.PS_PUBLIC_STRINGS))
            {
                guidStream.Add(guid);
            }

            foreach (var namedProperty in this)
            {
                var guidIndex = GetGuidIndex(namedProperty);

                var indexAndKind = new IndexAndKindInformation(propertyIndex, guidIndex, namedProperty.Kind);

                if (namedProperty.Kind == PropertyKind.Name)
                {
                    var stringStreamItem = new StringStreamItem(namedProperty.Name);
                    stringStream.Add(stringStreamItem);
                    entryStream.Add(new EntryStreamItem(stringStream.GetItemByteOffset(stringStreamItem), indexAndKind));
                }
                else
                {
                    entryStream.Add(new EntryStreamItem(namedProperty.NameIdentifier, indexAndKind));
                }

                nameIdMappingStream.Add(new EntryStreamItem(GenerateNameIdentifier(namedProperty), indexAndKind));
                nameIdMappingStream.Write(storage, GenerateStreamName(namedProperty));

                // Dependign on the property type. This is doing name.
                //entryStream.Add(new EntryStreamItem(namedProperty.NameIdentifier, new IndexAndKindInformation(propertyIndex, guidIndex, PropertyKind.Lid))); //+3 as per spec.
                //entryStream2.Add(new EntryStreamItem(namedProperty.NameIdentifier, new IndexAndKindInformation(propertyIndex, guidIndex, PropertyKind.Lid)));



                // 3.2.2 of the SPEC Needs to be written, because the stream changes as per named object.
                nameIdMappingStream.Clear();
                propertyIndex++;
            }

            guidStream.Write(storage);
            entryStream.Write(storage);
            stringStream.Write(storage);
        }
        private CFStorage GetStorage(CFStorage cfstorage, string storagename)
        {
            CFStorage storage = null;

            try
            {
                storage = cfstorage.GetStorage(storagename);
            }
            catch (Exception)
            {
            }

            return(storage);
        }
Exemplo n.º 7
0
 public static CFStorage GetStorage(List <string> pathList, ref CFStorage storage)
 {
     if (pathList == null || pathList[0] == "")
     {
         return(storage);
     }
     if (pathList.Count <string>() > 1)
     {
         int    index       = pathList.Count <string>() - 1;
         string storageName = pathList[index];
         pathList.RemoveAt(index);
         return(CFUtil.GetStorage(pathList, ref storage).GetStorage(storageName));
     }
     return(storage.GetStorage(pathList[0]));
 }
Exemplo n.º 8
0
 static void CopyCfStreamsExcept(CFStorage src, CFStorage dest, string excludeName)
 {
     src.VisitEntries(i => {
         if (i.Name?.Equals(excludeName, StringComparison.InvariantCultureIgnoreCase) ?? false)
         {
             return;
         }
         if (i.IsStorage)
         {
             dest.AddStorage(i.Name);
             CopyCfStreamsExcept((CFStorage)i, dest.GetStorage(i.Name), null);
         }
         else
         {
             dest.AddStream(i.Name);
             dest.GetStream(i.Name).SetData(((CFStream)i).GetData());
         }
     }, false);
 }
Exemplo n.º 9
0
        static string GetPrepend(Module mod, CFStorage vbaProject, Encoding enc)
        {
            switch (mod.Type)
            {
            case ModuleType.Class:
            case ModuleType.StaticClass:
                return("VERSION 1.0 CLASS\r\nBEGIN\r\n  MultiUse = -1  'True\r\nEND\r\n");

            case ModuleType.Form:
                var vbFrameLines = enc.GetString(vbaProject.GetStorage(mod.StreamName).GetStream("\x0003VBFrame").GetData())
                                   .Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();
                vbFrameLines.Insert(2, $"   OleObjectBlob   =   \"{mod.Name}.frx\":0000");
                return(string.Join("\r\n", vbFrameLines) + "\r\n");

            case ModuleType.Standard:
                return("");

            default:
                throw new ApplicationException("Unrecognized module type");
            }
        }
Exemplo n.º 10
0
        /// <summary>
        ///     Writes the properties to the <see cref="CFStorage" />
        /// </summary>
        /// <param name="storage"></param>
        /// <param name="messageSize"></param>
        /// <remarks>
        ///     Unfortunately this is going to have to be used after we already written the top level properties.
        /// </remarks>
        internal void WriteProperties(CFStorage storage, long messageSize = 0)
        {
            // Grab the nameIdStorage, 3.1 on the SPEC
            storage = storage.GetStorage(PropertyTags.NameIdStorage);

            var entryStream  = new EntryStream(storage);
            var stringStream = new StringStream(storage);
            var guidStream   = new GuidStream(storage);
            var entryStream2 = new EntryStream(storage);

            ushort propertyIndex = 0;
            var    guids         = this.Select(x => x.Guid).Distinct().ToList();

            foreach (var guid in guids)
            {
                guidStream.Add(guid);
            }

            foreach (var namedProperty in this)
            {
                var guidIndex = (ushort)(guids.IndexOf(namedProperty.Guid) + 3);

                // Dependign on the property type. This is doing name.
                entryStream.Add(new EntryStreamItem(namedProperty.NameIdentifier, new IndexAndKindInformation(propertyIndex, guidIndex, PropertyKind.Lid))); //+3 as per spec.
                entryStream2.Add(new EntryStreamItem(namedProperty.NameIdentifier, new IndexAndKindInformation(propertyIndex, guidIndex, PropertyKind.Lid)));

                //3.2.2 of the SPEC [MS-OXMSG]
                entryStream2.Write(storage, GenerateStreamString(namedProperty.NameIdentifier, guidIndex, namedProperty.Kind));

                // 3.2.2 of the SPEC Needs to be written, because the stream changes as per named object.
                entryStream2.Clear();
                propertyIndex++;
            }

            guidStream.Write(storage);
            entryStream.Write(storage);
            stringStream.Write(storage);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Reads model information from the current file, and assigns it to their respective
        /// component bodies.
        /// Model information includes the model positioning parameters and its STEP data.
        /// </summary>
        /// <param name="library">Storage where to look for the models data.</param>
        private void ReadLibraryModels(CFStorage library)
        {
            BeginContext("Models");

            var models      = library.GetStorage("Models");
            var recordCount = ReadHeader(models);

            using (var reader = models.GetStream("Data").GetBinaryReader())
            {
                for (var i = 0; i < recordCount; ++i)
                {
                    var parameters          = ReadBlock(reader, size => ReadParameters(reader, size));
                    var modelId             = parameters["ID"].AsString();
                    var modelCompressedData = models.GetStream($"{i}").GetData();

                    // models are stored as ASCII STEP files but using zlib compression
                    var stepModel = ParseCompressedZlibData(modelCompressedData, stream =>
                    {
                        using (var modelReader = new StreamReader(stream, Encoding.ASCII))
                        {
                            return(modelReader.ReadToEnd());
                        }
                    });

                    // assign STEP data to component bodies
                    var bodies = Data.Items.SelectMany(c => c.GetPrimitivesOfType <PcbComponentBody>(false))
                                 .Where(body => body.ModelId.ToUpperInvariant() == modelId.ToUpperInvariant());
                    foreach (var body in bodies)
                    {
                        body.StepModel = stepModel;
                    }
                }
            }

            EndContext();
        }
Exemplo n.º 12
0
        public void Test_DELETE_WITHOUT_COMPRESSION()
        {
            String FILENAME = "MultipleStorage3.cfs";

            FileInfo srcFile = new FileInfo(FILENAME);

            CompoundFile cf = new CompoundFile(FILENAME);

            CFStorage st = cf.RootStorage.GetStorage("MyStorage");

            st = st.GetStorage("AnotherStorage");

            Assert.IsNotNull(st);

            st.Delete("Another2Stream"); //17Kb

            //cf.CompressFreeSpace();
            cf.Save("MultipleStorage_Deleted_Compress.cfs");

            cf.Close();
            FileInfo dstFile = new FileInfo("MultipleStorage_Deleted_Compress.cfs");

            Assert.IsFalse(srcFile.Length > dstFile.Length);
        }
        public void LoadAttachmentProps(CFStorage attachmentStorage)
        {
            byte[] descBytes;
            try
            {
                descBytes = attachmentStorage.GetStream("AttachDesc").GetData();
            }
            catch (CFItemNotFound ex)
            {
                throw new NotSupportedException("Attachment description stream not found", ex);
            }

            if (descBytes.Length == 0)
            {
                throw new ArgumentException("no description bytes to read");
            }

            int nextIndex = 2;             //first two bytes are the version

            StringUtils.ReadStringA(descBytes, ref nextIndex);
            StringUtils.ReadStringA(descBytes, ref nextIndex);
            string displayName = StringUtils.ReadStringA(descBytes, ref nextIndex);

            StringUtils.ReadStringA(descBytes, ref nextIndex);
            StringUtils.ReadStringA(descBytes, ref nextIndex);
            string extension = StringUtils.ReadStringA(descBytes, ref nextIndex);

            nextIndex += 16;

            AttachmentMethod = (AttachType)BitConverter.ToUInt32(descBytes, nextIndex);
            nextIndex       += 4;

            ContentID = StringUtils.ReadStringW(descBytes, ref nextIndex);
            StringUtils.ReadStringW(descBytes, ref nextIndex);
            StringUtils.ReadStringW(descBytes, ref nextIndex);
            StringUtils.ReadStringW(descBytes, ref nextIndex);
            string displayNameW = StringUtils.ReadStringW(descBytes, ref nextIndex);

            StringUtils.ReadStringW(descBytes, ref nextIndex);
            StringUtils.ReadStringW(descBytes, ref nextIndex);
            string extensionW = StringUtils.ReadStringW(descBytes, ref nextIndex);

            //there's other stuff here, but I'm not going to read it

            Name      = displayName ?? displayNameW;
            Extension = extension ?? extensionW;

#if __ANDROID__
            MimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(Extension == null ? null : Extension.Trim('.'));
#endif

            switch (AttachmentMethod)
            {
            case AttachType.afByBalue:
                Content = attachmentStorage.GetStream("AttachContents").GetData();
                return;

            case AttachType.afEmbeddedMessage:
                LoadRpmsgDataFromEmbeddedAttachment(attachmentStorage.GetStorage("MAPIMessage"));
                return;

            default:
                LogUtils.Error("unsupported attachment method: " + AttachmentMethod);
                Content = new byte[0];
                return;
            }
        }
Exemplo n.º 14
0
        private static bool CfStoragesAreDifferent(CFStorage s1, CFStorage s2, out string explain)
        {
            var s1Names = new List <Tuple <string, bool> >();
            var s2Names = new List <Tuple <string, bool> >();

            s1.VisitEntries(i => s1Names.Add(Tuple.Create(i.Name, i.IsStorage)), false);
            s2.VisitEntries(i => s2Names.Add(Tuple.Create(i.Name, i.IsStorage)), false);
            s1Names.Sort();
            s2Names.Sort();
            if (!s1Names.SequenceEqual(s2Names))
            {
                explain = string.Format(VBASyncResources.ExplainFrxDifferentFileLists, s1.Name,
                                        string.Join("', '", s1Names.Select(t => t.Item1)),
                                        string.Join("', '", s2Names.Select(t => t.Item1)));
                return(true);
            }
            FormControl fc1 = null;
            FormControl fc2 = null;

            foreach (var t in s1Names)
            {
                if (t.Item2)
                {
                    if (CfStoragesAreDifferent(s1.GetStorage(t.Item1), s2.GetStorage(t.Item1), out explain))
                    {
                        return(true);
                    }
                }
                else if (t.Item1 == "f")
                {
                    fc1 = new FormControl(s1.GetStream("f").GetData());
                    fc2 = new FormControl(s2.GetStream("f").GetData());
                    if (!fc1.Equals(fc2))
                    {
                        explain = string.Format(VBASyncResources.ExplainFrxGeneralStreamDifference, "f", s1.Name);
                        return(true);
                    }
                }
                else if (t.Item1 == "o" && fc1 != null && fc2 != null)
                {
                    var fc2SitesList = fc2.Sites.ToList();
                    var o1Controls   = DecomposeOStream(fc1.Sites, s1.GetStream("o").GetData());
                    var o2Controls   = DecomposeOStream(fc2.Sites, s2.GetStream("o").GetData());
                    for (var siteIdx1 = 0; siteIdx1 < fc1.Sites.Length; ++siteIdx1)
                    {
                        var siteIdx2 = fc2SitesList.FindIndex(s => s.Id == fc1.Sites[siteIdx1].Id);
                        if (!Equals(o1Controls[siteIdx1], o2Controls[siteIdx2]))
                        {
                            explain = string.Format(VBASyncResources.ExplainFrxOStreamDifference,
                                                    fc1.Sites[siteIdx1].Name, s1.Name);
                            return(true);
                        }
                    }
                }
                else if (!s1.GetStream(t.Item1).GetData().SequenceEqual(s2.GetStream(t.Item1).GetData()))
                {
                    explain = string.Format(VBASyncResources.ExplainFrxGeneralStreamDifference, t.Item1, s1.Name);
                    return(true);
                }
            }
            explain = "No differences found.";
            return(false);
        }
Exemplo n.º 15
0
        static void Main(string[] args)
        {
            try
            {
                if (args.Length == 0 || args.Contains("-h"))
                {
                    PrintHelp();
                    return;
                }

                Dictionary <string, string> argDict = Utils.ParseArgs(args);

                if (argDict.ContainsKey("f"))
                {
                    filename = argDict["f"];
                }
                else
                {
                    Console.WriteLine("\n[!] Missing file (-f)\n");
                    return;
                }

                if (args.Contains("-l"))
                {
                    list_modules = true;
                }
                else
                {
                    if (argDict.ContainsKey("m"))
                    {
                        module = argDict["m"];
                    }
                    else
                    {
                        Console.WriteLine("\n[.] Will automatically decide which modules to purge.");
                    }
                }

                bool is_OpenXML = false;

                // Temp path to unzip OpenXML files to
                String unzipTempPath = "";

                string outFilename = Utils.getOutFilename(filename);
                string oleFilename = outFilename;

                // VBA Purging
                try
                {
                    // Make a copy of document to VBA Purge if user is not listing  modules
                    if (!list_modules)
                    {
                        if (File.Exists(outFilename))
                        {
                            File.Delete(outFilename);
                        }
                        File.Copy(filename, outFilename);
                        filename = outFilename;
                    }

                    try
                    {
                        unzipTempPath = CreateUniqueTempDirectory();
                        ZipFile.ExtractToDirectory(filename, unzipTempPath);

                        if (File.Exists(Path.Combine(unzipTempPath, "word", "vbaProject.bin")))
                        {
                            oleFilename = Path.Combine(unzipTempPath, "word", "vbaProject.bin");
                        }
                        else if (File.Exists(Path.Combine(unzipTempPath, "xl", "vbaProject.bin")))
                        {
                            oleFilename = Path.Combine(unzipTempPath, "xl", "vbaProject.bin");
                        }

                        is_OpenXML = true;
                    }
                    catch (Exception)
                    {
                        // Not OpenXML format, Maybe 97-2003 format, Make a copy
                        if (File.Exists(outFilename))
                        {
                            File.Delete(outFilename);
                        }
                        File.Copy(filename, outFilename);
                    }

                    CompoundFile cf            = new CompoundFile(oleFilename, CFSUpdateMode.Update, 0);
                    CFStorage    commonStorage = cf.RootStorage;

                    if (cf.RootStorage.TryGetStorage("Macros") != null)
                    {
                        commonStorage = cf.RootStorage.GetStorage("Macros");
                    }

                    if (cf.RootStorage.TryGetStorage("_VBA_PROJECT_CUR") != null)
                    {
                        commonStorage = cf.RootStorage.GetStorage("_VBA_PROJECT_CUR");
                    }

                    var vbaStorage = commonStorage.GetStorage("VBA");
                    if (vbaStorage == null)
                    {
                        throw new CFItemNotFound("Cannot find item");
                    }

                    // Grab data from "dir" module stream. Used to retrieve list of module streams in document.
                    byte[] dirStream = Utils.Decompress(vbaStorage.GetStream("dir").GetData());
                    List <Utils.ModuleInformation> vbaModules = Utils.ParseModulesFromDirStream(dirStream);

                    // Only list module streams in document and return
                    if (list_modules)
                    {
                        foreach (var vbaModule in vbaModules)
                        {
                            Console.WriteLine("[*] VBA module name: " + vbaModule.moduleName);
                        }
                        Console.WriteLine("[*] Finished listing modules\n");

                        return;
                    }

                    string [] dontPurgeTheseModules =
                    {
                        "ThisDocument",
                        "ThisWorkbook",
                        "Sheet",
                    };

                    byte[] streamBytes;
                    bool   module_found = false;
                    foreach (var vbaModule in vbaModules)
                    {
                        //VBA Purging begins
                        bool purge = true;

                        if (module.Length > 0)
                        {
                            purge = vbaModule.moduleName == module;
                        }
                        else
                        {
                            foreach (string mod in dontPurgeTheseModules)
                            {
                                if (vbaModule.moduleName.StartsWith(mod))
                                {
                                    purge = false;
                                }
                            }
                        }

                        if (purge)
                        {
                            Console.WriteLine("\n[*] Purging VBA code in module: " + vbaModule.moduleName);
                            Console.WriteLine("[*] Offset for code: " + vbaModule.textOffset);

                            // Get the CompressedSourceCode from module
                            streamBytes = vbaStorage.GetStream(vbaModule.moduleName).GetData();
                            string OG_VBACode = Utils.GetVBATextFromModuleStream(streamBytes, vbaModule.textOffset);

                            // Remove P-code from module stream and set the module to only have the CompressedSourceCode
                            streamBytes = Utils.RemovePcodeInModuleStream(streamBytes, vbaModule.textOffset, OG_VBACode);
                            vbaStorage.GetStream(vbaModule.moduleName).SetData(streamBytes);
                            module_found = true;
                        }
                    }

                    if (module_found == false)
                    {
                        Console.WriteLine("\n[!] Could not find module in document (-m). List all module streams with (-l).\n");

                        if (!is_OpenXML)
                        {
                            cf.Commit();
                            cf.Close();
                            CompoundFile.ShrinkCompoundFile(oleFilename);
                            File.Delete(oleFilename);
                            if (File.Exists(outFilename))
                            {
                                File.Delete(outFilename);
                            }
                        }

                        return;
                    }

                    // Change offset to 0 so that document can find compressed source code.
                    vbaStorage.GetStream("dir").SetData(Utils.Compress(Utils.ChangeOffset(dirStream)));
                    Console.WriteLine("\n[*] Module offset changed to 0.");

                    // Remove performance cache in _VBA_PROJECT stream. Replace the entire stream with _VBA_PROJECT header.

                    string b1 = "00";
                    string b2 = "00";

                    Random rnd = new Random();
                    b1 = String.Format("{0:X2}", rnd.Next(0, 255));
                    b2 = String.Format("{0:X2}", rnd.Next(0, 255));

                    byte[] data = Utils.HexToByte(String.Format("CC-61-FF-FF-00-{0}-{1}", b1, b2));
                    vbaStorage.GetStream("_VBA_PROJECT").SetData(data);
                    Console.WriteLine("[*] PerformanceCache removed from _VBA_PROJECT stream.");

                    // Check if document contains SRPs. Must be removed for VBA Purging to work.
                    try
                    {
                        for (int i = 0; i < 10; i++)
                        {
                            string srp = String.Format("__SRP_{0}", i);
                            var    str = vbaStorage.TryGetStream(srp);
                            if (str != null)
                            {
                                vbaStorage.Delete(srp);
                            }
                        }

                        Console.WriteLine("[*] SRP streams deleted!");
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("[*] No SRP streams found.");
                    }

                    // Commit changes and close
                    cf.Commit();
                    cf.Close();
                    CompoundFile.ShrinkCompoundFile(oleFilename);

                    // Zip the file back up as a docm or xlsm
                    if (is_OpenXML)
                    {
                        if (File.Exists(outFilename))
                        {
                            File.Delete(outFilename);
                        }
                        ZipFile.CreateFromDirectory(unzipTempPath, outFilename);
                    }

                    Console.WriteLine("[+] VBA Purging completed successfully!\n");
                }

                // Error handle for file not found
                catch (FileNotFoundException ex) when(ex.Message.Contains("Could not find file"))
                {
                    Console.WriteLine("[!] Could not find path or file (-f). \n");
                }

                // Error handle when document specified and file chosen don't match
                catch (CFItemNotFound ex) when(ex.Message.Contains("Cannot find item"))
                {
                    Console.WriteLine("[!] File (-f) does not contain macros.\n");
                }

                // Error handle when document is not OLE/CFBF format
                catch (CFFileFormatException)
                {
                    Console.WriteLine("[!] Incorrect filetype (-f). OfficePurge supports documents in .docm or .xlsm format as well as .doc/.xls/.pub in the Office 97-2003 format.\n");
                }
                finally
                {
                    if (is_OpenXML)
                    {
                        Directory.Delete(unzipTempPath, true);
                    }
                }
            }
            // Error handle for incorrect use of flags
            catch (IndexOutOfRangeException)
            {
                Console.WriteLine("\n[!] Flags (-d), (-f), (-m) need an argument. Make sure you have provided these flags an argument.\n");
            }
        }
Exemplo n.º 16
0
        static bool CfStoragesAreDifferent(CFStorage s1, CFStorage s2, out string explain)
        {
            var s1Names = new List <Tuple <string, bool> >();
            var s2Names = new List <Tuple <string, bool> >();

            s1.VisitEntries(i => s1Names.Add(Tuple.Create(i.Name, i.IsStorage)), false);
            s2.VisitEntries(i => s2Names.Add(Tuple.Create(i.Name, i.IsStorage)), false);
            s1Names.Sort();
            s2Names.Sort();
            if (!s1Names.SequenceEqual(s2Names))
            {
                explain = $"Different file lists in storage '{s1.Name}'.\r\nFile 1: {{'{string.Join("', '", s1Names)}'}}\r\nFile 2: {{'{string.Join("'', '", s2Names)}'}}.";
                return(true);
            }
            FormControl fc1 = null;

            foreach (var t in s1Names)
            {
                if (t.Item2)
                {
                    if (CfStoragesAreDifferent(s1.GetStorage(t.Item1), s2.GetStorage(t.Item1), out explain))
                    {
                        return(true);
                    }
                }
                else if (t.Item1 == "f")
                {
                    fc1 = new FormControl(s1.GetStream("f").GetData());
                    var fc2 = new FormControl(s2.GetStream("f").GetData());
                    if (!fc1.Equals(fc2))
                    {
                        explain = $"Different contents of stream 'f' in storage '{s1.Name}'.";
                        return(true);
                    }
                }
                else if (t.Item1 == "o" && fc1 != null)
                {
                    var  o1  = s1.GetStream("o").GetData();
                    var  o2  = s2.GetStream("o").GetData();
                    uint idx = 0;
                    foreach (var site in fc1.Sites)
                    {
                        explain = $"Different contents of stream 'o', site '{site.Name}' in storage '{s1.Name}'.";
                        var o1Range = o1.Range(idx, site.ObjectStreamSize);
                        var o2Range = o2.Range(idx, site.ObjectStreamSize);
                        switch (site.ClsidCacheIndex)
                        {
                        case 15:     // MorphData
                        case 26:     // CheckBox
                        case 25:     // ComboBox
                        case 24:     // ListBox
                        case 27:     // OptionButton
                        case 23:     // TextBox
                        case 28:     // ToggleButton
                            if (!new MorphDataControl(o1Range).Equals(new MorphDataControl(o2Range)))
                            {
                                return(true);
                            }
                            break;

                        case 17:     // CommandButton
                            if (!new CommandButtonControl(o1Range).Equals(new CommandButtonControl(o2Range)))
                            {
                                return(true);
                            }
                            break;

                        case 21:     // Label
                            if (!new LabelControl(o1Range).Equals(new LabelControl(o2Range)))
                            {
                                return(true);
                            }
                            break;

                        default:
                            if (!o1Range.SequenceEqual(o2Range))
                            {
                                return(true);
                            }
                            break;
                        }
                        idx += site.ObjectStreamSize;
                    }
                }
                else if (!s1.GetStream(t.Item1).GetData().SequenceEqual(s2.GetStream(t.Item1).GetData()))
                {
                    explain = $"Different contents of stream '{t.Item1}' in storage '{s1.Name}'.";
                    return(true);
                }
            }
            explain = "No differences found.";
            return(false);
        }
Exemplo n.º 17
0
        public MSOfficeManipulator(string filename, string[] names)
        {
            targetModules = new List <string>();

            foreach (string s in names)
            {
                targetModules.Add(s);
            }

            // OLE Filename (make a copy so we don't overwrite the original)
            outFilename = getOutFilename(filename);
            oleFilename = outFilename;

            // Attempt to unzip as docm or xlsm OpenXML format
            try
            {
                unzipTempPath = CreateUniqueTempDirectory();
                ZipFile.ExtractToDirectory(filename, unzipTempPath);
                if (File.Exists(Path.Combine(unzipTempPath, "word", "vbaProject.bin")))
                {
                    oleFilename = Path.Combine(unzipTempPath, "word", "vbaProject.bin");
                }
                else if (File.Exists(Path.Combine(unzipTempPath, "xl", "vbaProject.bin")))
                {
                    oleFilename = Path.Combine(unzipTempPath, "xl", "vbaProject.bin");
                }
                is_OpenXML = true;
            }
            catch (Exception)
            {
                // Not OpenXML format, Maybe 97-2003 format, Make a copy
                if (File.Exists(outFilename))
                {
                    File.Delete(outFilename);
                }
                File.Copy(filename, outFilename);
            }

            // Open OLE compound file for editing
            try
            {
                cf = new CompoundFile(oleFilename, CFSUpdateMode.Update, 0);
            }
            catch (Exception e)
            {
                Console.WriteLine("ERROR: Could not open file " + filename);
                Console.WriteLine("Please make sure this file exists and is .docm or .xlsm file or a .doc in the Office 97-2003 format.");
                Console.WriteLine();
                Console.WriteLine(e.Message);
                return;
            }

            // Read relevant streams
            commonStorage = cf.RootStorage; // docm or xlsm
            if (cf.RootStorage.TryGetStorage("Macros") != null)
            {
                commonStorage = cf.RootStorage.GetStorage("Macros");                                                 // .doc
            }
            if (cf.RootStorage.TryGetStorage("_VBA_PROJECT_CUR") != null)
            {
                commonStorage = cf.RootStorage.GetStorage("_VBA_PROJECT_CUR");                                                           // xls
            }
            vbaProjectStream = commonStorage.GetStorage("VBA").GetStream("_VBA_PROJECT").GetData();
            projectStream    = commonStorage.GetStream("project").GetData();
            projectwmStream  = commonStorage.GetStream("projectwm").GetData();
            dirStream        = Decompress(commonStorage.GetStorage("VBA").GetStream("dir").GetData());

            // Read project streams as string
            projectStreamString   = Encoding.UTF8.GetString(projectStream);
            projectwmStreamString = Encoding.UTF8.GetString(projectwmStream);

            // Find all VBA modules in current file
            vbaModules = ParseModulesFromDirStream(dirStream);

            // Write streams to debug log (if verbosity enabled)
            //Console.WriteLine("Hex dump of original _VBA_PROJECT stream:\n" + Utils.HexDump(vbaProjectStream));
            //Console.WriteLine("Hex dump of original dir stream:\n" + Utils.HexDump(dirStream));
            //Console.WriteLine("Hex dump of original project stream:\n" + Utils.HexDump(projectStream));
        }
Exemplo n.º 18
0
    static public void Main(string[] args)
    {
        // List of target VBA modules to stomp, if empty => all modules will be stomped
        List <string> targetModules = new List <string>();

        // Filename that contains the VBA code used for substitution
        string VBASourceFileName = "";

        // Target MS Office version for pcode
        string targetOfficeVersion = "";

        // Option to hide modules from VBA editor GUI
        bool optionHideInGUI = false;

        // Option to start web server to serve malicious template
        int optionWebserverPort = 0;

        // Option to display help
        bool optionShowHelp = false;

        // File format is OpenXML (docm or xlsm)
        bool is_OpenXML = false;

        // Option to delete metadata from file
        bool optionDeleteMetadata = false;

        // Option to set random module names in dir stream
        bool optionSetRandomNames = false;

        // Temp path to unzip OpenXML files to
        String unzipTempPath = "";


        // Start parsing command line arguments
        var p = new OptionSet()
        {
            { "n|name=", "The target module name to stomp.\n" +
              "This argument can be repeated.",
              v => targetModules.Add(v) },
            { "s|sourcefile=", "File containing substitution VBA code (fake code).",
              v => VBASourceFileName = v },
            { "g|guihide", "Hide code from VBA editor GUI.",
              v => optionHideInGUI = v != null },
            { "t|targetversion=", "Target MS Office version the pcode will run on.",
              v => targetOfficeVersion = v },
            { "w|webserver=", "Start web server on specified port to serve malicious template.",
              (int v) => optionWebserverPort = v },
            { "d|delmetadata", "Remove metadata stream (may include your name etc.).",
              v => optionDeleteMetadata = v != null },
            { "r|randomnames", "Set random module names, confuses some analyst tools.",
              v => optionSetRandomNames = v != null },
            { "v", "Increase debug message verbosity.",
              v => { if (v != null)
                     {
                         ++verbosity;
                     }
              } },
            { "h|help", "Show this message and exit.",
              v => optionShowHelp = v != null },
        };

        List <string> extra;

        try
        {
            extra = p.Parse(args);
        }
        catch (OptionException e)
        {
            Console.WriteLine(e.Message);
            Console.WriteLine("Try '--help' for more information.");
            return;
        }

        if (extra.Count > 0)
        {
            filename = string.Join(" ", extra.ToArray());
        }
        else
        {
            optionShowHelp = true;
        }

        if (optionShowHelp)
        {
            ShowHelp(p);
            return;
        }
        // End parsing command line arguments

        // OLE Filename (make a copy so we don't overwrite the original)
        string outFilename = getOutFilename(filename);
        string oleFilename = outFilename;

        // Attempt to unzip as docm or xlsm OpenXML format
        try
        {
            unzipTempPath = CreateUniqueTempDirectory();
            ZipFile.ExtractToDirectory(filename, unzipTempPath);
            if (File.Exists(Path.Combine(unzipTempPath, "word", "vbaProject.bin")))
            {
                oleFilename = Path.Combine(unzipTempPath, "word", "vbaProject.bin");
            }
            else if (File.Exists(Path.Combine(unzipTempPath, "xl", "vbaProject.bin")))
            {
                oleFilename = Path.Combine(unzipTempPath, "xl", "vbaProject.bin");
            }
            is_OpenXML = true;
        }
        catch (Exception)
        {
            // Not OpenXML format, Maybe 97-2003 format, Make a copy
            if (File.Exists(outFilename))
            {
                File.Delete(outFilename);
            }
            File.Copy(filename, outFilename);
        }

        // Open OLE compound file for editing
        try
        {
            cf = new CompoundFile(oleFilename, CFSUpdateMode.Update, 0);
        }
        catch (Exception e)
        {
            Console.WriteLine("ERROR: Could not open file " + filename);
            Console.WriteLine("Please make sure this file exists and is .docm or .xlsm file or a .doc in the Office 97-2003 format.");
            Console.WriteLine();
            Console.WriteLine(e.Message);
            return;
        }

        // Read relevant streams
        CFStorage commonStorage = cf.RootStorage; // docm or xlsm

        if (cf.RootStorage.TryGetStorage("Macros") != null)
        {
            commonStorage = cf.RootStorage.GetStorage("Macros");                                                         // .doc
        }
        if (cf.RootStorage.TryGetStorage("_VBA_PROJECT_CUR") != null)
        {
            commonStorage = cf.RootStorage.GetStorage("_VBA_PROJECT_CUR");                                                                   // xls
        }
        vbaProjectStream = commonStorage.GetStorage("VBA").GetStream("_VBA_PROJECT").GetData();
        projectStream    = commonStorage.GetStream("project").GetData();
        dirStream        = Decompress(commonStorage.GetStorage("VBA").GetStream("dir").GetData());

        // Read project stream as string
        string projectStreamString = System.Text.Encoding.UTF8.GetString(projectStream);

        // Find all VBA modules in current file
        List <ModuleInformation> vbaModules = ParseModulesFromDirStream(dirStream);

        // Write streams to debug log (if verbosity enabled)
        DebugLog("Hex dump of original _VBA_PROJECT stream:\n" + Utils.HexDump(vbaProjectStream));
        DebugLog("Hex dump of original dir stream:\n" + Utils.HexDump(dirStream));
        DebugLog("Hex dump of original project stream:\n" + Utils.HexDump(projectStream));

        // Replace Office version in _VBA_PROJECT stream
        if (targetOfficeVersion != "")
        {
            ReplaceOfficeVersionInVBAProject(vbaProjectStream, targetOfficeVersion);
            commonStorage.GetStorage("VBA").GetStream("_VBA_PROJECT").SetData(vbaProjectStream);
        }

        // Hide modules from GUI
        if (optionHideInGUI)
        {
            foreach (var vbaModule in vbaModules)
            {
                if ((vbaModule.moduleName != "ThisDocument") && (vbaModule.moduleName != "ThisWorkbook"))
                {
                    Console.WriteLine("Hiding module: " + vbaModule.moduleName);
                    projectStreamString = projectStreamString.Replace("Module=" + vbaModule.moduleName, "");
                }
            }

            // Write changes to project stream
            commonStorage.GetStream("project").SetData(Encoding.UTF8.GetBytes(projectStreamString));
        }

        // Stomp VBA modules
        if (VBASourceFileName != "")
        {
            byte[] streamBytes;

            foreach (var vbaModule in vbaModules)
            {
                DebugLog("VBA module name: " + vbaModule.moduleName + "\nOffset for code: " + vbaModule.textOffset);

                // If this module is a target module, or if no targets are specified, then stomp
                if (targetModules.Contains(vbaModule.moduleName) || !targetModules.Any())
                {
                    Console.WriteLine("Now stomping VBA code in module: " + vbaModule.moduleName);

                    streamBytes = commonStorage.GetStorage("VBA").GetStream(vbaModule.moduleName).GetData();

                    DebugLog("Existing VBA source:\n" + GetVBATextFromModuleStream(streamBytes, vbaModule.textOffset));

                    // Get new VBA source code from specified text file. If not specified, VBA code is removed completely.
                    string newVBACode = "";
                    if (VBASourceFileName != "")
                    {
                        try
                        {
                            newVBACode = System.IO.File.ReadAllText(VBASourceFileName);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("ERROR: Could not open VBA source file " + VBASourceFileName);
                            Console.WriteLine("Please make sure this file exists and contains ASCII only characters.");
                            Console.WriteLine();
                            Console.WriteLine(e.Message);
                            return;
                        }
                    }

                    DebugLog("Replacing with VBA code:\n" + newVBACode);

                    streamBytes = ReplaceVBATextInModuleStream(streamBytes, vbaModule.textOffset, newVBACode);

                    DebugLog("Hex dump of VBA module stream " + vbaModule.moduleName + ":\n" + Utils.HexDump(streamBytes));

                    commonStorage.GetStorage("VBA").GetStream(vbaModule.moduleName).SetData(streamBytes);
                }
            }
        }

        // Set random ASCII names for VBA modules in dir stream
        if (optionSetRandomNames)
        {
            Console.WriteLine("Setting random ASCII names for VBA modules in dir stream (while leaving unicode names intact).");

            // Recompress and write to dir stream
            commonStorage.GetStorage("VBA").GetStream("dir").SetData(Compress(SetRandomNamesInDirStream(dirStream)));
        }

        // Delete metadata from document
        if (optionDeleteMetadata)
        {
            try
            {
                cf.RootStorage.Delete("\u0005SummaryInformation");
            }
            catch (Exception e)
            {
                Console.WriteLine("ERROR: metadata stream does not exist (option ignored)");
                DebugLog(e.Message);
            }
        }

        // Commit changes and close file
        cf.Commit();
        cf.Close();

        // Purge unused space in file
        CompoundFile.ShrinkCompoundFile(oleFilename);

        // Zip the file back up as a docm or xlsm
        if (is_OpenXML)
        {
            if (File.Exists(outFilename))
            {
                File.Delete(outFilename);
            }
            ZipFile.CreateFromDirectory(unzipTempPath, outFilename);
            // Delete Temporary Files
            Directory.Delete(unzipTempPath, true);
        }

        // Start web server, if option is specified
        if (optionWebserverPort != 0)
        {
            try
            {
                WebServer ws = new WebServer(SendFile, "http://*:" + optionWebserverPort.ToString() + "/");
                ws.Run();
                Console.WriteLine("Webserver starting on port " + optionWebserverPort.ToString() + ". Press a key to quit.");
                Console.ReadKey();
                ws.Stop();
                Console.WriteLine("Webserver closed. Goodbye!");
            }
            catch (Exception e)
            {
                Console.WriteLine("ERROR: could not start webserver on specified port");
                DebugLog(e.Message);
            }
        }
    }
Exemplo n.º 19
0
    static public void Main(string[] args)
    {
        // List of target VBA modules to stomp, if empty => all modules will be stomped
        List <string> targetModules = new List <string>();

        // Filename that contains the VBA code used for substitution
        string VBASourceFileName = "";

        // Target MS Office version for pcode
        string targetOfficeVersion = "";

        // Option to hide modules from VBA editor GUI
        bool optionHideInGUI = false;

        // Option to unhide modules from VBA editor GUI
        bool optionUnhideInGUI = false;

        // Option to start web server to serve malicious template
        int optionWebserverPort = 0;

        // Option to display help
        bool optionShowHelp = false;

        // File format is OpenXML (docm or xlsm)
        bool is_OpenXML = false;

        // Option to delete metadata from file
        bool optionDeleteMetadata = false;

        // Option to set random module names in dir stream
        bool optionSetRandomNames = false;

        // Option to reset module names in dir stream (undo SetRandomNames option)
        bool optionResetModuleNames = false;

        // Option to set locked/unviewable options in Project Stream
        bool optionUnviewableVBA = false;

        // Option to set unlocked/viewable options in Project Stream
        bool optionViewableVBA = false;

        // Temp path to unzip OpenXML files to
        String unzipTempPath = "";


        // Start parsing command line arguments
        var p = new OptionSet()
        {
            { "n|name=", "The target module name to stomp.\n" +
              "This argument can be repeated.",
              v => targetModules.Add(v) },
            { "s|sourcefile=", "File containing substitution VBA code (fake code).",
              v => VBASourceFileName = v },
            { "g|guihide", "Hide code from VBA editor GUI.",
              v => optionHideInGUI = v != null },
            { "gg|guiunhide", "Unhide code from VBA editor GUI.",
              v => optionUnhideInGUI = v != null },
            { "t|targetversion=", "Target MS Office version the pcode will run on.",
              v => targetOfficeVersion = v },
            { "w|webserver=", "Start web server on specified port to serve malicious template.",
              (int v) => optionWebserverPort = v },
            { "d|delmetadata", "Remove metadata stream (may include your name etc.).",
              v => optionDeleteMetadata = v != null },
            { "r|randomnames", "Set random module names, confuses some analyst tools.",
              v => optionSetRandomNames = v != null },
            { "rr|resetmodulenames", "Undo the set random module names by making the ASCII module names in the DIR stream match their Unicode counter parts",
              v => optionResetModuleNames = v != null },
            { "u|unviewableVBA", "Make VBA Project unviewable/locked.",
              v => optionUnviewableVBA = v != null },
            { "uu|viewableVBA", "Make VBA Project viewable/unlocked.",
              v => optionViewableVBA = v != null },
            { "v", "Increase debug message verbosity.",
              v => { if (v != null)
                     {
                         ++verbosity;
                     }
              } },
            { "h|help", "Show this message and exit.",
              v => optionShowHelp = v != null },
        };

        List <string> extra;

        try
        {
            extra = p.Parse(args);
        }
        catch (OptionException e)
        {
            Console.WriteLine(e.Message);
            Console.WriteLine("Try '--help' for more information.");
            return;
        }

        if (extra.Count > 0)
        {
            filename = string.Join(" ", extra.ToArray());
        }
        else
        {
            optionShowHelp = true;
        }

        if (optionShowHelp)
        {
            ShowHelp(p);
            return;
        }
        // End parsing command line arguments

        // OLE Filename (make a copy so we don't overwrite the original)
        outFilename = getOutFilename(filename);
        string oleFilename = outFilename;

        // Attempt to unzip as docm or xlsm OpenXML format
        try
        {
            unzipTempPath = CreateUniqueTempDirectory();
            ZipFile.ExtractToDirectory(filename, unzipTempPath);
            if (File.Exists(Path.Combine(unzipTempPath, "word", "vbaProject.bin")))
            {
                oleFilename = Path.Combine(unzipTempPath, "word", "vbaProject.bin");
            }
            else if (File.Exists(Path.Combine(unzipTempPath, "xl", "vbaProject.bin")))
            {
                oleFilename = Path.Combine(unzipTempPath, "xl", "vbaProject.bin");
            }
            is_OpenXML = true;
        }
        catch (Exception)
        {
            // Not OpenXML format, Maybe 97-2003 format, Make a copy
            if (File.Exists(outFilename))
            {
                File.Delete(outFilename);
            }
            File.Copy(filename, outFilename);
        }

        // Open OLE compound file for editing
        try
        {
            cf = new CompoundFile(oleFilename, CFSUpdateMode.Update, 0);
        }
        catch (Exception e)
        {
            Console.WriteLine("ERROR: Could not open file " + filename);
            Console.WriteLine("Please make sure this file exists and is .docm or .xlsm file or a .doc in the Office 97-2003 format.");
            Console.WriteLine();
            Console.WriteLine(e.Message);
            return;
        }

        // Read relevant streams
        CFStorage commonStorage = cf.RootStorage; // docm or xlsm

        if (cf.RootStorage.TryGetStorage("Macros") != null)
        {
            commonStorage = cf.RootStorage.GetStorage("Macros");                                                         // .doc
        }
        if (cf.RootStorage.TryGetStorage("_VBA_PROJECT_CUR") != null)
        {
            commonStorage = cf.RootStorage.GetStorage("_VBA_PROJECT_CUR");                                                                   // xls
        }
        vbaProjectStream = commonStorage.GetStorage("VBA").GetStream("_VBA_PROJECT").GetData();
        projectStream    = commonStorage.GetStream("project").GetData();
        projectwmStream  = commonStorage.GetStream("projectwm").GetData();
        dirStream        = Decompress(commonStorage.GetStorage("VBA").GetStream("dir").GetData());

        // Read project streams as string
        string projectStreamString   = System.Text.Encoding.UTF8.GetString(projectStream);
        string projectwmStreamString = System.Text.Encoding.UTF8.GetString(projectwmStream);

        // Find all VBA modules in current file
        List <ModuleInformation> vbaModules = ParseModulesFromDirStream(dirStream);

        // Write streams to debug log (if verbosity enabled)
        DebugLog("Hex dump of original _VBA_PROJECT stream:\n" + Utils.HexDump(vbaProjectStream));
        DebugLog("Hex dump of original dir stream:\n" + Utils.HexDump(dirStream));
        DebugLog("Hex dump of original project stream:\n" + Utils.HexDump(projectStream));

        // Replace Office version in _VBA_PROJECT stream
        if (targetOfficeVersion != "")
        {
            ReplaceOfficeVersionInVBAProject(vbaProjectStream, targetOfficeVersion);
            commonStorage.GetStorage("VBA").GetStream("_VBA_PROJECT").SetData(vbaProjectStream);
        }
        //Set ProjectProtectionState and ProjectVisibilityState to locked/unviewable see https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-ovba/dfd72140-85a6-4f25-8a17-70a89c00db8c
        if (optionUnviewableVBA)
        {
            string tmpStr = Regex.Replace(projectStreamString, "CMG=\".*\"", "CMG=\"\"");
            string newProjectStreamString = Regex.Replace(tmpStr, "GC=\".*\"", "GC=\"\"");
            // Write changes to project stream
            commonStorage.GetStream("project").SetData(Encoding.UTF8.GetBytes(newProjectStreamString));
        }

        //Set ProjectProtectionState and ProjectVisibilityState to be viewable see https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-ovba/dfd72140-85a6-4f25-8a17-70a89c00db8c
        if (optionViewableVBA)
        {
            Console.WriteLine("Making the project visible...");
            // Console.WriteLine("Stream before: " + projectStreamString);
            string tmpStr = projectStreamString;
            tmpStr = Regex.Replace(tmpStr, "CMG=\"?.*\"?", "CMG=\"CAC866BE34C234C230C630C6\"");
            tmpStr = Regex.Replace(tmpStr, "ID=\"?.*\"?", "ID=\"{00000000-0000-0000-0000-000000000000}\"");
            tmpStr = Regex.Replace(tmpStr, "DPB=\"?.*\"?", "DPB=\"94963888C84FE54FE5B01B50E59251526FE67A1CC76C84ED0DAD653FD058F324BFD9D38DED37\"");
            tmpStr = Regex.Replace(tmpStr, "GC=\"?.*\"?", "GC=\"5E5CF2C27646414741474\"");
            string newProjectStreamString = tmpStr;
            // Console.WriteLine("Stream afterw: " + newProjectStreamString);

            // Write changes to project stream
            commonStorage.GetStream("project").SetData(Encoding.UTF8.GetBytes(newProjectStreamString));
        }


        // Hide modules from GUI
        if (optionHideInGUI)
        {
            foreach (var vbaModule in vbaModules)
            {
                if ((vbaModule.moduleName != "ThisDocument") && (vbaModule.moduleName != "ThisWorkbook"))
                {
                    Console.WriteLine("Hiding module: " + vbaModule.moduleName);
                    projectStreamString = projectStreamString.Replace("Module=" + vbaModule.moduleName, "");
                }
            }

            // Write changes to project stream
            commonStorage.GetStream("project").SetData(Encoding.UTF8.GetBytes(projectStreamString));
        }

        // Undo the Hide modules from GUI effects
        if (optionUnhideInGUI)
        {
            ArrayList vbaModulesNamesFromProjectwm = getModulesNamesFromProjectwmStream(projectwmStreamString);
            Regex     theregex = new Regex(@"(Document\=.*\/.{10})([\S\s]*?)(ExeName32\=|Name\=|ID\=|Class\=|BaseClass\=|Package\=|HelpFile\=|HelpContextID\=|Description\=|VersionCompatible32\=|CMG\=|DPB\=|GC\=)");
            Match     m        = theregex.Match(projectStreamString);
            if (m.Groups.Count != 4)
            {
                Console.WriteLine("Error, could not find the location to insert module names. Not able to unhide modules");
            }
            else
            {
                string moduleString = "\r\n";

                foreach (var vbaModuleName in vbaModulesNamesFromProjectwm)
                {
                    Console.WriteLine("Unhiding module: " + vbaModuleName);
                    moduleString = moduleString.Insert(moduleString.Length, "Module=" + vbaModuleName + "\r\n");
                }

                projectStreamString = projectStreamString.Replace(m.Groups[0].Value, m.Groups[1].Value + moduleString + m.Groups[3].Value);

                // write changes to project stream
                commonStorage.GetStream("project").SetData(Encoding.UTF8.GetBytes(projectStreamString));
            }
        }

        // Stomp VBA modules
        if (VBASourceFileName != "")
        {
            byte[] streamBytes;

            foreach (var vbaModule in vbaModules)
            {
                DebugLog("VBA module name: " + vbaModule.moduleName + "\nOffset for code: " + vbaModule.textOffset);

                // If this module is a target module, or if no targets are specified, then stomp
                if (targetModules.Contains(vbaModule.moduleName) || !targetModules.Any())
                {
                    Console.WriteLine("Now stomping VBA code in module: " + vbaModule.moduleName);

                    streamBytes = commonStorage.GetStorage("VBA").GetStream(vbaModule.moduleName).GetData();

                    DebugLog("Existing VBA source:\n" + GetVBATextFromModuleStream(streamBytes, vbaModule.textOffset));

                    // Get new VBA source code from specified text file. If not specified, VBA code is removed completely.
                    string newVBACode = "";
                    if (VBASourceFileName != "")
                    {
                        try
                        {
                            newVBACode = System.IO.File.ReadAllText(VBASourceFileName);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("ERROR: Could not open VBA source file " + VBASourceFileName);
                            Console.WriteLine("Please make sure this file exists and contains ASCII only characters.");
                            Console.WriteLine();
                            Console.WriteLine(e.Message);
                            return;
                        }
                    }

                    DebugLog("Replacing with VBA code:\n" + newVBACode);

                    streamBytes = ReplaceVBATextInModuleStream(streamBytes, vbaModule.textOffset, newVBACode);

                    DebugLog("Hex dump of VBA module stream " + vbaModule.moduleName + ":\n" + Utils.HexDump(streamBytes));

                    commonStorage.GetStorage("VBA").GetStream(vbaModule.moduleName).SetData(streamBytes);
                }
            }
        }


        // Set random ASCII names for VBA modules in dir stream
        if (optionSetRandomNames)
        {
            Console.WriteLine("Setting random ASCII names for VBA modules in dir stream (while leaving unicode names intact).");

            // Recompress and write to dir stream
            commonStorage.GetStorage("VBA").GetStream("dir").SetData(Compress(SetRandomNamesInDirStream(dirStream)));
        }

        // Reset module names in dir stream so that the ASCII names match the Unicode names (undo SetRandomNames option)
        if (optionResetModuleNames)
        {
            Console.WriteLine("Resetting module names in dir stream to match names is _VBA_PROJECT stream (undo SetRandomNames option)");

            // Recompress and write to dir stream
            commonStorage.GetStorage("VBA").GetStream("dir").SetData(Compress(ResetModuleNamesInDirStream(dirStream)));
        }

        // Delete metadata from document
        if (optionDeleteMetadata)
        {
            try
            {
                cf.RootStorage.Delete("\u0005SummaryInformation");
            }
            catch (Exception e)
            {
                Console.WriteLine("ERROR: metadata stream does not exist (option ignored)");
                DebugLog(e.Message);
            }
        }

        // Commit changes and close file
        cf.Commit();
        cf.Close();

        // Purge unused space in file
        CompoundFile.ShrinkCompoundFile(oleFilename);

        // Zip the file back up as a docm or xlsm
        if (is_OpenXML)
        {
            if (File.Exists(outFilename))
            {
                File.Delete(outFilename);
            }
            ZipFile.CreateFromDirectory(unzipTempPath, outFilename);
            // Delete Temporary Files
            Directory.Delete(unzipTempPath, true);
        }

        // Start web server, if option is specified
        if (optionWebserverPort != 0)
        {
            try
            {
                WebServer ws = new WebServer(SendFile, "http://*:" + optionWebserverPort.ToString() + "/");
                ws.Run();
                Console.WriteLine("Webserver starting on port " + optionWebserverPort.ToString() + ". Press a key to quit.");
                Console.ReadKey();
                ws.Stop();
                Console.WriteLine("Webserver closed. Goodbye!");
            }
            catch (Exception e)
            {
                Console.WriteLine("ERROR: could not start webserver on specified port");
                DebugLog(e.Message);
            }
        }
    }
Exemplo n.º 20
0
        /// <summary>
        /// Gets the MAPI property value from a stream or storage in this storage.
        /// </summary>
        /// <param name="propIdentifier">The 4 char hexadecimal prop identifier.</param>
        /// <returns>The value of the MAPI property or null if not found.</returns>
        private object GetMapiPropertyFromStreamOrStorage(string propIdentifier)
        {
            //determine if the property identifier is in a stream or sub storage
            string propTag  = null;
            var    propType = PropertyType.PT_UNSPECIFIED;

            foreach (string propKey in _keys)
            {
                if (propKey.StartsWith(MapiTags.SubStgVersion1 + propIdentifier))
                {
                    propTag  = propKey.Substring(12, 8);
                    propType = (PropertyType)ushort.Parse(propKey.Substring(16, 4), System.Globalization.NumberStyles.HexNumber);
                    break;
                }
            }

            //depending on prop type use method to get property value
            string containerName = MapiTags.SubStgVersion1 + propTag;

            switch (propType)
            {
            case PropertyType.PT_UNSPECIFIED:
                return(null);

            case PropertyType.PT_STRING8:
                return(this.GetStreamAsString(containerName, Encoding.Default));

            case PropertyType.PT_UNICODE:
                return(this.GetStreamAsString(containerName, Encoding.Unicode));

            case PropertyType.PT_BINARY:
                return(_storage.GetStream(containerName).GetData());

            case PropertyType.PT_OBJECT:
                return(_storage.GetStorage(containerName));

            case PropertyType.PT_MV_STRING8:
            case PropertyType.PT_MV_UNICODE:

                // If the property is a unicode multiview item we need to read all the properties
                // again and filter out all the multivalue names, they end with -00000000, -00000001, etc..
                var multiValueContainerNames = _keys.Where(propKey => propKey.StartsWith(containerName + "-")).ToList();

                var values = new List <string>();
                foreach (var multiValueContainerName in multiValueContainerNames)
                {
                    var value = GetStreamAsString(multiValueContainerName,
                                                  propType == PropertyType.PT_MV_STRING8 ? Encoding.Default : Encoding.Unicode);

                    // Multi values always end with a null char so we need to strip that one off
                    if (value.EndsWith("/0"))
                    {
                        value = value.Substring(0, value.Length - 1);
                    }

                    values.Add(value);
                }

                return(values);

            default:
                throw new ApplicationException("MAPI property has an unsupported type and can not be retrieved.");
            }
        }
Exemplo n.º 21
0
        /**
         * Create VBA Project from file
         *
         * @param sPath path of macro enabled Excel, Powerpoint or Word file.
         */
        public VBAProject(string sPath)
        {
            //Initialize pPath
            pPath = sPath;

            //Get unzip location
            unzipTempPath = CreateUniqueTempDirectory();

            /* EvilClippy brute forces the file open, It does this in a fairly unclean manner. We will assume the file,
             * is named correctly (extension wise). This, although requiring more boiler plate will look a lot cleaner.
             */

            // Get extension of file:
            string ext = Path.GetExtension(sPath);

            //Parse extension and create sOLEFileName
            switch (ext)
            {
            case ".xlsm":
            case ".xlam":
                isOpenXML    = true;
                sOLEFileName = Path.Combine(unzipTempPath, "xl", "vbaProject.bin");
                break;

            case ".docm":
                isOpenXML    = true;
                sOLEFileName = Path.Combine(unzipTempPath, "word", "vbaProject.bin");
                break;

            case ".pptm":
                isOpenXML    = true;
                sOLEFileName = Path.Combine(unzipTempPath, "ppt", "vbaProject.bin"); //untested
                break;

            case ".xls":
            case ".doc":
            case ".ppt":
                //Copy path to sOLEFileName to prevent overwriting (we'll overrite this file directly)
                sOLEFileName = Path.Combine(unzipTempPath, Path.GetFileName(sPath));
                File.Copy(sPath, sOLEFileName);
                break;

            default:
                Console.WriteLine("ERROR: Could not open file " + sPath);
                Console.WriteLine("Please make sure this file exists, has a valid extension and is of a valid type.");
                Console.WriteLine();
                break;
            }

            //Unzip to unzipTemoPath if isOpenXML. Otherwise create compound file.
            if (isOpenXML)
            {
                ZipFile.ExtractToDirectory(sPath, unzipTempPath);
            }

            //Create Compound file from VBProject.bin or xls,doc,ppt file:
            cf = new CompoundFile(sOLEFileName, CFSUpdateMode.Update, 0);

            // Read relevant streams
            switch (ext)
            {
            case ".xlsm":
            case ".xlam":
            case ".docm":
            case ".pptm":
                commonStorage = cf.RootStorage;
                break;

            case ".doc":
                commonStorage = cf.RootStorage.GetStorage("Macros"); //Note you can also use `cf.RootStorage.TryGetStorage("Macros")` which returns null if not found.
                break;

            case ".ppt": //untested - don't know if this is the case for ppts
            case ".xls":
                commonStorage = cf.RootStorage.GetStorage("_VBA_PROJECT_CUR");
                break;
            }

            vbaProjectStream = commonStorage.GetStorage("VBA").GetStream("_VBA_PROJECT").GetData();

            //Contains VBA Project properties, including module names. Remove module names from this stream to hide them.
            //PROJECT stream:   https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-ovba/cc848a02-6f87-49a4-ad93-6edb3103f593
            //More information: https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-ovba/d88cb9d8-a475-423d-b370-cc0caaf78628
            projectStream = commonStorage.GetStream("project").GetData();

            //PROJECTwm stream contains all names of all Modules.
            //PROJECTwm stream:  https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-ovba/514acc65-ea7b-4813-aaf7-fabb1bca0ba2
            //More Information:  https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-ovba/c458f2e6-f2cc-4c2d-96c7-91a3e63f2fe1
            projectwmStream = commonStorage.GetStream("PROJECTwm").GetData();

            //Contains names of visible modules and module source code text (compressed)
            //VBA Storage:     https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-ovba/b693e0ba-489f-4ac8-ac9d-6387fb5779bb
            //VBA StorageInfo: https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-ovba/170f52a0-4cd6-4729-b51a-d08155cbd213
            //Dir Stream:      https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-ovba/672d276c-d83c-4452-993b-ca9eca3d8917
            dirStream = VbaCompression.Decompress(commonStorage.GetStorage("VBA").GetStream("dir").GetData());

            // Read project streams as string
            string projectStreamString   = System.Text.Encoding.UTF8.GetString(projectStream);
            string projectwmStreamString = System.Text.Encoding.UTF8.GetString(projectwmStream);

            Console.WriteLine(System.Text.Encoding.UTF8.GetString(projectStream));
            Console.WriteLine(System.Text.Encoding.UTF8.GetString(projectwmStream));



            // Find all VBA modules in current file
            vbaModulesEx = ParseModulesFromDirStream(dirStream);

            // Write streams to debug log (if verbosity enabled)
            Console.WriteLine("Hex dump of original _VBA_PROJECT stream:\n" + Utils.HexDump(vbaProjectStream));
            Console.WriteLine("Hex dump of original dir stream:\n" + Utils.HexDump(dirStream));
        }
Exemplo n.º 22
0
        private static bool CfStoragesAreDifferent(CFStorage s1, CFStorage s2, out string explain)
        {
            var s1Names = new List <Tuple <string, bool> >();
            var s2Names = new List <Tuple <string, bool> >();

            s1.VisitEntries(i => s1Names.Add(Tuple.Create(i.Name, i.IsStorage)), false);
            s2.VisitEntries(i => s2Names.Add(Tuple.Create(i.Name, i.IsStorage)), false);
            s1Names.Sort();
            s2Names.Sort();
            if (!s1Names.SequenceEqual(s2Names))
            {
                explain = string.Format(VBASyncResources.ExplainFrxDifferentFileLists, s1.Name,
                                        string.Join("', '", s1Names.Select(t => t.Item1)),
                                        string.Join("', '", s2Names.Select(t => t.Item1)));
                return(true);
            }
            FormControl fc1 = null;

            foreach (var t in s1Names)
            {
                if (t.Item2)
                {
                    if (CfStoragesAreDifferent(s1.GetStorage(t.Item1), s2.GetStorage(t.Item1), out explain))
                    {
                        return(true);
                    }
                }
                else if (t.Item1 == "f")
                {
                    fc1 = new FormControl(s1.GetStream("f").GetData());
                    var fc2 = new FormControl(s2.GetStream("f").GetData());
                    if (!fc1.Equals(fc2))
                    {
                        explain = string.Format(VBASyncResources.ExplainFrxGeneralStreamDifference, "f", s1.Name);
                        return(true);
                    }
                }
                else if (t.Item1 == "o" && fc1 != null)
                {
                    var  o1  = s1.GetStream("o").GetData();
                    var  o2  = s2.GetStream("o").GetData();
                    uint idx = 0;
                    foreach (var site in fc1.Sites)
                    {
                        explain = string.Format(VBASyncResources.ExplainFrxOStreamDifference, site.Name, s1.Name);
                        var o1Range = o1.Range(idx, site.ObjectStreamSize);
                        var o2Range = o2.Range(idx, site.ObjectStreamSize);
                        switch (site.ClsidCacheIndex)
                        {
                        case 15: // MorphData
                        case 26: // CheckBox
                        case 25: // ComboBox
                        case 24: // ListBox
                        case 27: // OptionButton
                        case 23: // TextBox
                        case 28: // ToggleButton
                            if (!new MorphDataControl(o1Range).Equals(new MorphDataControl(o2Range)))
                            {
                                return(true);
                            }
                            break;

                        case 17: // CommandButton
                            if (!new CommandButtonControl(o1Range).Equals(new CommandButtonControl(o2Range)))
                            {
                                return(true);
                            }
                            break;

                        case 18: // TabStrip
                            if (!new TabStripControl(o1Range).Equals(new TabStripControl(o2Range)))
                            {
                                return(true);
                            }
                            break;

                        case 21: // Label
                            if (!new LabelControl(o1Range).Equals(new LabelControl(o2Range)))
                            {
                                return(true);
                            }
                            break;

                        default:
                            if (!o1Range.SequenceEqual(o2Range))
                            {
                                return(true);
                            }
                            break;
                        }
                        idx += site.ObjectStreamSize;
                    }
                }
                else if (!s1.GetStream(t.Item1).GetData().SequenceEqual(s2.GetStream(t.Item1).GetData()))
                {
                    explain = string.Format(VBASyncResources.ExplainFrxGeneralStreamDifference, t.Item1, s1.Name);
                    return(true);
                }
            }
            explain = "No differences found.";
            return(false);
        }
Exemplo n.º 23
0
        static void Main(string[] args)
        {
            try
            {
                if (args.Length == 0 || args.Contains("-h"))
                {
                    PrintHelp();
                    return;
                }

                Dictionary <string, string> argDict = Utils.ParseArgs(args);

                if (argDict.ContainsKey("d"))
                {
                    document = argDict["d"];
                    if (document != "word" && document != "excel" && document != "publisher")
                    {
                        Console.WriteLine("\n[!] Unknown document type. Options are 'word', 'excel', or 'publisher'.\n");
                        return;
                    }
                }
                else
                {
                    Console.WriteLine("\n[!] Missing document type (-d)\n");
                    return;
                }

                if (argDict.ContainsKey("f"))
                {
                    filename = argDict["f"];
                }
                else
                {
                    Console.WriteLine("\n[!] Missing file (-f)\n");
                    return;
                }

                if (args.Contains("-l"))
                {
                    list_modules = true;
                }
                else
                {
                    if (argDict.ContainsKey("m"))
                    {
                        module = argDict["m"];
                    }
                    else
                    {
                        Console.WriteLine("\n[!] Missing module (-m)\n");
                        return;
                    }
                }

                // VBA Purging
                try
                {
                    // Make a copy of document to VBA Purge if user is not listing  modules
                    if (!list_modules)
                    {
                        string outFilename = Utils.getOutFilename(filename);
                        string oleFilename = outFilename;

                        if (File.Exists(outFilename))
                        {
                            File.Delete(outFilename);
                        }
                        File.Copy(filename, outFilename);
                        filename = outFilename;
                    }

                    CompoundFile cf            = new CompoundFile(filename, CFSUpdateMode.Update, 0);
                    CFStorage    commonStorage = cf.RootStorage;

                    if (document == "word")
                    {
                        commonStorage = cf.RootStorage.GetStorage("Macros");
                    }

                    else if (document == "excel")
                    {
                        commonStorage = cf.RootStorage.GetStorage("_VBA_PROJECT_CUR");
                    }

                    else if (document == "publisher")
                    {
                        commonStorage = cf.RootStorage.GetStorage("VBA");
                    }


                    // Grab data from "dir" module stream. Used to retrieve list of module streams in document.
                    byte[] dirStream = Utils.Decompress(commonStorage.GetStorage("VBA").GetStream("dir").GetData());
                    List <Utils.ModuleInformation> vbaModules = Utils.ParseModulesFromDirStream(dirStream);

                    // Only list module streams in document and return
                    if (list_modules)
                    {
                        foreach (var vbaModule in vbaModules)
                        {
                            Console.WriteLine("\n[*] VBA module name: " + vbaModule.moduleName);
                        }
                        Console.WriteLine("\n[*] Finished listing modules\n");
                        return;
                    }


                    byte[] streamBytes;
                    bool   module_found = false;
                    foreach (var vbaModule in vbaModules)
                    {
                        //VBA Purging begins
                        if (vbaModule.moduleName == module)
                        {
                            Console.WriteLine("\n[*] VBA module name: " + vbaModule.moduleName);
                            Console.WriteLine("\n[*] Offset for code: " + vbaModule.textOffset);
                            Console.WriteLine("\n[*] Now purging VBA code in module: " + vbaModule.moduleName);

                            // Get the CompressedSourceCode from module
                            streamBytes = commonStorage.GetStorage("VBA").GetStream(vbaModule.moduleName).GetData();
                            string OG_VBACode = Utils.GetVBATextFromModuleStream(streamBytes, vbaModule.textOffset);

                            // Remove P-code from module stream and set the module to only have the CompressedSourceCode
                            streamBytes = Utils.RemovePcodeInModuleStream(streamBytes, vbaModule.textOffset, OG_VBACode);
                            commonStorage.GetStorage("VBA").GetStream(vbaModule.moduleName).SetData(streamBytes);
                            module_found = true;
                        }
                    }

                    if (module_found == false)
                    {
                        Console.WriteLine("\n[!] Could not find module in document (-m). List all module streams with (-l).\n");
                        cf.Commit();
                        cf.Close();
                        CompoundFile.ShrinkCompoundFile(filename);
                        File.Delete(filename);
                        return;
                    }


                    // Change offset to 0 so that document can find compressed source code.
                    commonStorage.GetStorage("VBA").GetStream("dir").SetData(Utils.Compress(Utils.ChangeOffset(dirStream)));
                    Console.WriteLine("\n[*] Module offset changed to 0.");

                    // Remove performance cache in _VBA_PROJECT stream. Replace the entire stream with _VBA_PROJECT header.
                    byte[] data = Utils.HexToByte("CC-61-FF-FF-00-00-00");
                    commonStorage.GetStorage("VBA").GetStream("_VBA_PROJECT").SetData(data);
                    Console.WriteLine("\n[*] PerformanceCache removed from _VBA_PROJECT stream.");

                    // Check if document contains SRPs. Must be removed for VBA Purging to work.
                    try
                    {
                        commonStorage.GetStorage("VBA").Delete("__SRP_0");
                        commonStorage.GetStorage("VBA").Delete("__SRP_1");
                        commonStorage.GetStorage("VBA").Delete("__SRP_2");
                        commonStorage.GetStorage("VBA").Delete("__SRP_3");
                        Console.WriteLine("\n[*] SRP streams deleted!");
                    }
                    catch (Exception)
                    {
                        Console.WriteLine("\n[*] No SRP streams found.");
                    }

                    // Commit changes and close
                    cf.Commit();
                    cf.Close();
                    CompoundFile.ShrinkCompoundFile(filename);
                    Console.WriteLine("\n[*] VBA Purging completed successfully!\n");
                }

                // Error handle for file not found
                catch (FileNotFoundException ex) when(ex.Message.Contains("Could not find file"))
                {
                    Console.WriteLine("\n[!] Could not find path or file (-f). \n");
                }

                // Error handle when document specified and file chosen don't match
                catch (CFItemNotFound ex) when(ex.Message.Contains("Cannot find item"))
                {
                    Console.WriteLine("\n[!] File (-f) does not match document type selected (-d).\n");
                }

                // Error handle when document is not OLE/CFBF format
                catch (CFFileFormatException)
                {
                    Console.WriteLine("\n[!] Incorrect filetype (-f). Must be an OLE strucutred file. OfficePurge supports .doc, .xls, or .pub documents.\n");
                }
            }
            // Error handle for incorrect use of flags
            catch (IndexOutOfRangeException)
            {
                Console.WriteLine("\n[!] Flags (-d), (-f), (-m) need an argument. Make sure you have provided these flags an argument.\n");
            }
        }