public void DecompressionProducesExpectedOutput()
        {
            var decompressed = VbaCompression.Decompress(_expectedCompressedBytes);

            Assert.Equal(_expectedDecompressedBytes.Length, decompressed.Length);
            Assert.True(_expectedDecompressedBytes.SequenceEqual(decompressed));
        }
Beispiel #2
0
        public void GivenLargeByteSequenceWithLowCompressibilityCompressingAndDecompressionProducesSameInput()
        {
            var data = GetLargeByteSequenceWithLowCompressibility().ToArray();

            var compressedData = VbaCompression.Compress(data);
            var convertedData  = VbaCompression.Decompress(compressedData);

            Assert.True(data != convertedData);
            Assert.True(data.LongLength == convertedData.LongLength);
            Assert.True(data.SequenceEqual(convertedData));
        }
Beispiel #3
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));
        }