Esempio n. 1
0
        public void CanLoadPdbGeneratedByBuild()
        {
            var folder = TestData.Get(@"TestData\MultiFileCompressed");

            using (var fs = new DisposableFileSystem())
            {
                var intermediateFolder = fs.GetFolder();

                var result = WixRunner.Execute(new[]
                {
                    "build",
                    Path.Combine(folder, "Package.wxs"),
                    Path.Combine(folder, "PackageComponents.wxs"),
                    "-d", "MediaTemplateCompressionLevel",
                    "-loc", Path.Combine(folder, "Package.en-us.wxl"),
                    "-bindpath", Path.Combine(folder, "data"),
                    "-intermediateFolder", intermediateFolder,
                    "-o", Path.Combine(intermediateFolder, @"bin\test.msi")
                }, out var messages);

                Assert.Equal(0, result);

                Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msi")));
                Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\cab1.cab")));

                var pdbPath = Path.Combine(intermediateFolder, @"bin\test.wixpdb");
                Assert.True(File.Exists(pdbPath));

                var pdb = Pdb.Load(pdbPath, suppressVersionCheck: true);
                Assert.NotNull(pdb);
                Assert.NotNull(pdb.Output);
            }
        }
Esempio n. 2
0
        private Pdb LoadPdb()
        {
            // We should never be required to load a PDB for a managed assembly that does
            // not incorporate native code, as no managed-relevant rule currently crawls
            // PDBs for its analysis.
            Debug.Assert(!this.PE.IsManaged || this.PE.IsMixedMode);

            Pdb pdb = null;

            try
            {
                pdb = new Pdb(
                    this.PE.FileName,
                    this.symbolPath,
                    this.localSymbolDirectories,
                    this.tracePdbLoad);
            }
            catch (PdbException ex)
            {
                this.PdbParseException = ex;
            }

            if (pdb != null && pdb.IsStripped)
            {
                this.StrippedPdb = pdb;
                pdb = null;
                this.PdbParseException = new PdbException(BinaryParsersResources.PdbStripped)
                {
                    LoadTrace = this.StrippedPdb.LoadTrace
                };
            }
            return(pdb);
        }
Esempio n. 3
0
        private Pdb LoadPdb()
        {
            Pdb pdb = null;

            try
            {
                pdb = new Pdb(
                    this.PE.FileName,
                    this.symbolPath,
                    this.localSymbolDirectories,
                    this.tracePdbLoad);
            }
            catch (PdbException ex)
            {
                this.PdbParseException = ex;
            }

            if (pdb != null && pdb.IsStripped)
            {
                this.StrippedPdb = pdb;
                pdb = null;
                this.PdbParseException = new PdbException(BinaryParsersResources.PdbStripped)
                {
                    LoadTrace = this.StrippedPdb.LoadTrace
                };
            }
            return(pdb);
        }
        private void AnalyzeManagedAssemblyAndPdb(BinaryAnalyzerContext context)
        {
            PEBinary target = context.PEBinary();
            Pdb      di     = target.Pdb;

            if (target.PE.ManagedPdbSourceFileChecksumAlgorithm(di.FileType) != ChecksumAlgorithmType.Sha256)
            {
                // '{0}' is a managed binary compiled with an insecure (SHA-1) source code hashing algorithm.
                // SHA-1 is subject to collision attacks and its use can compromise supply chain integrity.
                // Pass '-checksumalgorithm:SHA256' on the csc.exe command-line or populate the project
                // <ChecksumAlgorithm> property with 'SHA256' to enable secure source code hashing.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultKind.Fail, context, null,
                                                             nameof(RuleResources.BA2004_Error_Managed),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            // '{0}' is a {1} binary which was compiled with a secure (SHA-256)
            // source code hashing algorithm.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultKind.Pass, context, null,
                                                         nameof(RuleResources.BA2004_Pass),
                                                         context.TargetUri.GetFileName(),
                                                         "managed"));
        }
Esempio n. 5
0
        public void CanBuildInstanceTransform()
        {
            var folder = TestData.Get(@"TestData\InstanceTransform");

            using (var fs = new DisposableFileSystem())
            {
                var intermediateFolder = fs.GetFolder();

                var result = WixRunner.Execute(new[]
                {
                    "build",
                    Path.Combine(folder, "Package.wxs"),
                    Path.Combine(folder, "PackageComponents.wxs"),
                    "-loc", Path.Combine(folder, "Package.en-us.wxl"),
                    "-bindpath", Path.Combine(folder, "data"),
                    "-intermediateFolder", intermediateFolder,
                    "-o", Path.Combine(intermediateFolder, @"bin\test.msi")
                }, out var messages);

                Assert.Equal(0, result);

                var pdb = Pdb.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"), false);
                Assert.NotEmpty(pdb.Output.SubStorages);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Extracts files from an MSI database and rewrites the paths embedded in the source .wixpdb to the output .wixpdb.
        /// </summary>
        private void MeltProduct()
        {
            // print friendly message saying what file is being decompiled
            Console.WriteLine("{0} / {1}", Path.GetFileName(this.inputFile), Path.GetFileName(this.inputPdbFile));

            // extract files from the .msi (unless suppressed) and get the path map of File ids to target paths
            string outputDirectory             = this.exportBasePath ?? Environment.GetEnvironmentVariable("WIX_TEMP");
            IDictionary <string, string> paths = null;

            using (InstallPackage package = new InstallPackage(this.inputFile, DatabaseOpenMode.ReadOnly, null, outputDirectory))
            {
                if (!this.suppressExtraction)
                {
                    package.ExtractFiles();
                }

                paths = package.Files.SourcePaths;
            }

            Pdb   inputPdb     = Pdb.Load(this.inputPdbFile, true, true);
            Table wixFileTable = inputPdb.Output.Tables["WixFile"];

            if (null != wixFileTable)
            {
                foreach (Row row in wixFileTable.Rows)
                {
                    WixFileRow fileRow = row as WixFileRow;
                    if (null != fileRow)
                    {
                        string newPath;
                        if (paths.TryGetValue(fileRow.File, out newPath))
                        {
                            fileRow.Source = Path.Combine(outputDirectory, newPath);
                        }
                    }
                }
            }

            string tempPath = Path.Combine(Environment.GetEnvironmentVariable("WIX_TEMP") ?? Path.GetTempPath(), Path.GetRandomFileName());

            try
            {
                inputPdb.Save(this.outputFile, null, null, tempPath);
            }
            finally
            {
                if (this.tidy)
                {
                    if (!AppCommon.DeleteDirectory(tempPath, this.messageHandler))
                    {
                        Console.WriteLine(MeltStrings.WAR_FailedToDeleteTempDir, tempPath);
                    }
                }
                else
                {
                    Console.WriteLine(MeltStrings.INF_TempDirLocatedAt, tempPath);
                }
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            if (Assembly != null)
            {
                Assembly.Dispose();
            }

            if (Pdb != null)
            {
                Pdb.Dispose();
            }
        }
        public override void AnalyzePortableExecutableAndPdb(BinaryAnalyzerContext context)
        {
            PEBinary target = context.PEBinary();
            Pdb      pdb    = target.Pdb;

            if (PrintHeader)
            {
                Console.WriteLine("Target,Compiler Name,Compiler BackEnd Version,Compiler FrontEnd Version,Language,Module Name,Module Library,Hash,Error");
                PrintHeader = false;
            }

            if (pdb == null)
            {
                Console.Write(context.TargetUri.LocalPath + ",");
                Console.WriteLine($",,,,,,{context?.Hashes?.Sha256},{target.PdbParseException.Message}");
                return;
            }

            var records = new Dictionary <string, ObjectModuleDetails>();

            foreach (DisposableEnumerableView <Symbol> omView in pdb.CreateObjectModuleIterator())
            {
                Symbol om = omView.Value;
                ObjectModuleDetails omDetails = om.GetObjectModuleDetails();

                string record =
                    omDetails.CompilerName?.Replace(",", "_").Trim() + "," +
                    omDetails.CompilerBackEndVersion + "," +
                    omDetails.CompilerFrontEndVersion + "," +
                    omDetails.Language;

                if (!records.TryGetValue(record, out ObjectModuleDetails value))
                {
                    records[record] = omDetails;
                }
            }

            foreach (KeyValuePair <string, ObjectModuleDetails> kv in records)
            {
                string compilerData           = kv.Key;
                ObjectModuleDetails omDetails = kv.Value;

                Console.Write(context.TargetUri.LocalPath + ",");
                Console.Write(compilerData + ",");
                Console.Write(omDetails.Name?.Replace(",", "_") + ",");
                Console.Write(omDetails.Library?.Replace(",", ";") + ",");
                Console.Write($"{context?.Hashes?.Sha256},");
                Console.WriteLine();
            }
        }
Esempio n. 9
0
        public void DisposePortableExecutableData()
        {
            if (_pdb != null)
            {
                _pdb.Dispose();
                _pdb = null;
            }

            if (_pe != null)
            {
                _pe.Dispose();
                _pe = null;
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Extract binary data from tables with a Name and Data column in them.
        /// </summary>
        /// <param name="inputPdb">A reference to a <see cref="Pdb"/> as output.  Paths (Data properties) will be modified in this object.</param>
        /// <param name="package">The installer database to rip from.</param>
        /// <param name="exportPath">The full path where files will be exported to.</param>
        /// <param name="tableName">The name of the table to export.</param>
        private static void MeltBinaryTable(Pdb inputPdb, InstallPackage package, string exportPath, string tableName)
        {
            if (string.IsNullOrEmpty(tableName))
            {
                throw new ArgumentNullException("tableName");
            }
            if (string.IsNullOrEmpty(exportPath))
            {
                throw new ArgumentNullException("exportPath");
            }
            if (null == package)
            {
                throw new ArgumentNullException("package");
            }
            if (null == inputPdb)
            {
                throw new ArgumentNullException("inputPdb");
            }

            Table pdbTable = inputPdb.Output.Tables[tableName];

            if (null == pdbTable)
            {
                Console.WriteLine("Table {0} does not exist.", tableName);
                return;
            }

            try
            {
                Directory.CreateDirectory(exportPath);
                Melt.ExtractFilesInBinaryTable(package, null, tableName, exportPath);
                IDictionary <string, string> paths = package.GetFilePaths(exportPath);

                if (null != paths)
                {
                    foreach (Row row in pdbTable.Rows)
                    {
                        string filename = (string)row.Fields[0].Data;
                        row.Fields[1].Data = paths[filename];
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("An error occured extracting the {0} binary table from the install package.", tableName);
                Console.WriteLine(ex.Message);
            }
        }
        public sealed override void Analyze(BinaryAnalyzerContext context)
        {
            // Uses PDB Parsing.
            BinaryParsers.PlatformSpecificHelpers.ThrowIfNotOnWindows();
            PEBinary target = context.PEBinary();

            if (target.Pdb == null)
            {
                Errors.LogExceptionLoadingPdb(context, target.PdbParseException);
                return;
            }

            Pdb di = target.Pdb;

            AnalyzePortableExecutableAndPdb(context);
        }
Esempio n. 12
0
        /// <summary>
        ///     Returns a hash code for this instance.
        /// </summary>
        /// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
        /// <inheritdoc />
        public override int GetHashCode()
        {
            unchecked
            {
                var hashCode = FileName != null?FileName.GetHashCode() : 0;

                hashCode = (hashCode * 397) ^ (int)FileSize;
                hashCode = (hashCode * 397) ^ ImageBase.GetHashCode();
                hashCode = (hashCode * 397) ^ IsManaged.GetHashCode();
                hashCode = (hashCode * 397) ^ IsRuntime.GetHashCode();
                hashCode = (hashCode * 397) ^ (Pdb != null ? Pdb.GetHashCode() : 0);
                hashCode = (hashCode * 397) ^ (PeFile != null ? PeFile.GetHashCode() : 0);
                hashCode = (hashCode * 397) ^ (int)TimeStamp;
                hashCode = (hashCode * 397) ^ Version.GetHashCode();
                return(hashCode);
            }
        }
Esempio n. 13
0
        public int Run()
        {
            if (_args.Length == 0)
            {
                MainHelp();
                return 0;
            }
            _action = AppActions.LookUp(_args[0]);
            if (_action == null)
            {
                WriteError("unknown action: " + _args[0]);
                return 0;
            }
            if (_args.Length == 1)
            {
                WriteError("need file path");
                return 0;
            }
            try
            {
                _pdb = Pdb.Load(_args[1]);
            }
            catch (PdbNotFoundException)
            {
                WriteError("file not found: " + _args[1]);
                return 1;
            }
            catch (PdbFormatException)
            {
                WriteError("wrong pdb format: " + _args[1]);
                return 2;
            }

            try
            {
                _action.Execute(this);
            }
            catch (NotImplementedException ex)
            {
                WriteError("not impl: " + ex.Message + " @ " + _args[1]);
                return 127;
            }
            return 0;
        }
        /// <summary>
        /// Extracts files from an MSI database and rewrites the paths embedded in the source .wixpdb to the output .wixpdb.
        /// </summary>
        private void MeltProduct()
        {
            // print friendly message saying what file is being decompiled
            Console.WriteLine("{0} / {1}", Path.GetFileName(this.inputFile), Path.GetFileName(this.inputPdbFile));

            Pdb inputPdb = Pdb.Load(this.inputPdbFile, true);

            // extract files from the .msi (unless suppressed) and get the path map of File ids to target paths
            string outputDirectory             = this.exportBasePath ?? Environment.GetEnvironmentVariable("WIX_TEMP");
            IDictionary <string, string> paths = null;

            using (InstallPackage package = new InstallPackage(this.inputFile, DatabaseOpenMode.ReadOnly, null, outputDirectory))
            {
                // ignore failures as this is a new validation in v3.x
                ValidateMsiMatchesPdb(package, inputPdb);

                if (!this.suppressExtraction)
                {
                    package.ExtractFiles();
                }

                paths = package.Files.SourcePaths;
            }

            Table wixFileTable = inputPdb.Output.Tables["WixFile"];

            if (null != wixFileTable)
            {
                foreach (Row row in wixFileTable.Rows)
                {
                    WixFileRow fileRow = row as WixFileRow;
                    if (null != fileRow)
                    {
                        string newPath;
                        if (paths.TryGetValue(fileRow.File, out newPath))
                        {
                            fileRow.Source = Path.Combine(outputDirectory, newPath);
                        }
                    }
                }
            }

            inputPdb.Save(this.outputFile);
        }
Esempio n. 15
0
        static void ExtractTrm(string trmPath, string basePath = null)
        {
            if (basePath == null)
            {
                basePath = Path.ChangeExtension(trmPath, null);
            }
            else
            {
                basePath = Path.Combine(basePath, Path.GetFileNameWithoutExtension(trmPath));
            }

            using DatReader dat = new DatReader(Utils.CheckDecompress(File.OpenRead(trmPath)));
            // First entry is texture DAT
            using DatReader txmDat       = new DatReader(new MemoryStream(dat.GetData(0)));
            using ObjConverter converter = new ObjConverter(txmDat);
            string mtlPath = basePath + ".mtl";
            string mtlName = Path.GetFileName(mtlPath);

            // Subsequent entries are train car DATs
            for (int i = 1; i < dat.EntriesCount; ++i)
            {
                using DatReader innerDat = new DatReader(new MemoryStream(dat.GetData(i)));
                // And within each train car DAT are PDBs
                for (int j = 0; j < innerDat.EntriesCount; ++j)
                {
                    using MemoryStream ms = new MemoryStream(innerDat.GetData(j));
                    BinaryReader br  = new BinaryReader(ms);
                    Pdb          pdb = new Pdb();
                    pdb.Read(br);
                    using StreamWriter sw = File.CreateText($"{basePath}.{i}_{j}.obj");
                    sw.WriteLine($"mtllib {mtlName}");
                    sw.WriteLine();

                    converter.ConvertObj(pdb, sw);
                }
            }

            using (StreamWriter sw = File.CreateText(mtlPath))
            {
                converter.ExportTextures(sw, basePath + ".");
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Checks to make sure that the debug symbols match up with the MSI.
        /// This is to help in ensuring that error 1642 does not inexplicably appear.
        /// </summary>
        /// <remarks>
        /// This is meant to assist with Bug # 4792
        /// http://wixtoolset.org/issues/4792/
        /// </remarks>
        /// <param name="package">
        /// The MSI currently being melted.
        /// </param>
        /// <param name="inputPdb">
        /// The debug symbols package being compared against the <paramref name="package"/>.
        /// </param>
        /// <returns></returns>
        private static bool ValidateMsiMatchesPdb(InstallPackage package, Pdb inputPdb)
        {
            string msiPackageCode = (string)package.Property["PackageCode"];

            foreach (Row pdbPropertyRow in inputPdb.Output.Tables["Property"].Rows)
            {
                if ("PackageCode" == (string)pdbPropertyRow.Fields[0].Data)
                {
                    string pdbPackageCode = (string)pdbPropertyRow.Fields[1].Data;
                    if (msiPackageCode != pdbPackageCode)
                    {
                        Console.WriteLine(MeltStrings.WAR_MismatchedPackageCode, msiPackageCode, pdbPackageCode);
                        return(false);
                    }
                    break;
                }
            }

            return(true);
        }
Esempio n. 17
0
        public void ConvertObj(Pdb pdb, StreamWriter sw)
        {
            int startVert = 1;

            if (pdb.Specular != null)
            {
                sw.WriteLine("o specular");
                startVert = WriteObj(pdb.Specular, sw, startVert);
            }
            if (pdb.Diffuse != null)
            {
                sw.WriteLine("o diffuse");
                startVert = WriteObj(pdb.Diffuse, sw, startVert);
            }
            if (pdb.Metallic != null)
            {
                sw.WriteLine("o metallic");
                startVert = WriteObj(pdb.Metallic, sw, startVert);
            }
        }
Esempio n. 18
0
        static void ExtractMapAnim(string mapAnimPath, string basePath = null)
        {
            if (basePath == null)
            {
                basePath = Path.ChangeExtension(mapAnimPath, null);
            }
            else
            {
                basePath = Path.Combine(basePath, Path.GetFileNameWithoutExtension(mapAnimPath));
            }

            using DatReader dat = new DatReader(Utils.CheckDecompress(File.OpenRead(mapAnimPath)));
            // Second entry is texture DAT
            using DatReader txmDat       = new DatReader(new MemoryStream(dat.GetData(1)));
            using ObjConverter converter = new ObjConverter(txmDat);
            string mtlPath = basePath + ".mtl";
            string mtlName = Path.GetFileName(mtlPath);

            // First entry is a collection of weird PDBs
            using DatReader pdbDat = new DatReader(new MemoryStream(dat.GetData(0)));
            for (int i = 0; i < pdbDat.EntriesCount; ++i)
            {
                using MemoryStream ms = new MemoryStream(pdbDat.GetData(i));
                // This is a DAT, but we're going to pretend it's a normal PDB
                BinaryReader br  = new BinaryReader(ms);
                Pdb          pdb = new Pdb();
                pdb.Read(br);
                using StreamWriter sw = File.CreateText($"{basePath}.{i}.obj");
                sw.WriteLine($"mtllib {mtlName}");
                sw.WriteLine();

                converter.ConvertObj(pdb, sw);
            }

            using (StreamWriter sw = File.CreateText(mtlPath))
            {
                converter.ExportTextures(sw, basePath + ".");
            }
        }
Esempio n. 19
0
        public PEBinary(Uri uri) : base(uri)
        {
            PE = new PE(TargetUri.LocalPath);
            IsManagedAssembly = PE.IsManaged;
            LoadException     = PE.LoadException;
            Valid             = PE.IsPEFile;

            try
            {
                Pdb = new Pdb(PE.FileName, Pdb.SymbolPath);
            }
            catch (PdbParseException ex)
            {
                PdbParseException = ex;
            }

            if (Pdb != null && Pdb.IsStripped)
            {
                StrippedPdb       = Pdb;
                Pdb               = null;
                PdbParseException = new PdbParseException(BinaryParsersResources.PdbStripped);
            }
        }
Esempio n. 20
0
        static void ExtractPdb(string pdbPath, string txmPath, string basePath = null, bool forceDirect = false)
        {
            if (basePath == null)
            {
                basePath = Path.ChangeExtension(pdbPath, null);
            }
            else
            {
                basePath = Path.Combine(basePath, Path.GetFileNameWithoutExtension(pdbPath));
            }

            DatReader dat = new DatReader(Utils.CheckDecompress(File.OpenRead(pdbPath)));

            using DatReader txmDat       = new DatReader(Utils.CheckDecompress(File.OpenRead(txmPath)));
            using ObjConverter converter = new ObjConverter(txmDat);
            string mtlPath = basePath + ".mtl";
            string mtlName = Path.GetFileName(mtlPath);

            for (int i = 0; i < dat.EntriesCount; ++i)
            {
                using MemoryStream ms = new MemoryStream(dat.GetData(i));
                BinaryReader br  = new BinaryReader(ms);
                Pdb          pdb = new Pdb();
                pdb.Read(br);
                using StreamWriter sw = File.CreateText($"{basePath}.{i}.obj");
                sw.WriteLine($"mtllib {mtlName}");
                sw.WriteLine();

                converter.ConvertObj(pdb, sw);
            }

            using (StreamWriter sw = File.CreateText(mtlPath))
            {
                converter.ExportTextures(sw, basePath + ".", forceDirect);
            }
        }
Esempio n. 21
0
        private void DumpFile(string target, bool verbose)
        {
            PE  pe;
            var sb = new StringBuilder();

            try
            {
                pe = new PE(target);
            }
            catch (UnauthorizedAccessException)
            {
                Console.WriteLine(Path.GetFileName(target) + ": Unauthorized access exception");
                return;
            }

            sb.AppendLine(Path.GetFileName(pe.FileName) + ":");

            if (verbose)
            {
                sb.AppendLine(Indent + "Path: " + pe.FileName);
            }

            sb.Append(Indent + "Attr: ");

            if (!pe.IsPEFile)
            {
                sb.AppendLine("Not a portable executable");
                sb.AppendLine();
                return;
            }

            string language = pe.IsManaged ? "Pure Managed" : "Native";

            if (pe.IsManaged && !pe.IsILOnly)
            {
                language = "Mixed Managed";
            }
            ;
            sb.Append(language);

            string machine = pe.Machine.ToString();

            sb.Append(Delimiter + machine);

            string subsystem = pe.Subsystem.ToString();

            sb.Append(Delimiter + subsystem);

            if (pe.IsKernelMode)
            {
                sb.Append(Delimiter + "Kernel Mode");
            }

            if (pe.IsResourceOnly)
            {
                sb.Append(Delimiter + "Resource Only");
            }

            sb.Append(Delimiter + "Link " + pe.LinkerVersion.ToString());

            sb.AppendLine(); // Close comma-separated attributes line

            sb.Append(Indent + "Pdb : ");
            Pdb pdb = null;

            try
            {
                pdb = new Pdb(pe.FileName);
            }
            catch (PdbParseException pdbParseException)
            {
                sb.AppendLine(pdbParseException.ExceptionCode.ToString());
                sb.AppendLine();
                return;
            }

            if (verbose)
            {
                sb.AppendLine(pdb.PdbLocation);
            }
            else
            {
                sb.AppendLine(Path.GetFileName(pdb.PdbLocation));
            }

            sb.AppendLine(Indent + "SHA1: " + pe.SHA1Hash);

            Console.Out.WriteLineAsync(sb.ToString());
        }
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEHeader peHeader = context.PE.PEHeaders.PEHeader;

            if (context.Pdb == null)
            {
                Errors.LogExceptionLoadingPdb(context, context.PdbParseException);
                return;
            }

            Pdb di = context.Pdb;

            TruncatedCompilandRecordList warningTooLowModules      = new TruncatedCompilandRecordList();
            TruncatedCompilandRecordList disabledWarningModules    = new TruncatedCompilandRecordList();
            TruncatedCompilandRecordList unknownLanguageModules    = new TruncatedCompilandRecordList();
            TruncatedCompilandRecordList allWarningLevelLowModules = new TruncatedCompilandRecordList();

            string     exampleTooLowWarningCommandLine   = null;
            int        overallMinimumWarningLevel        = Int32.MaxValue;
            string     exampleDisabledWarningCommandLine = null;
            List <int> overallDisabledWarnings           = new List <int>();

            foreach (DisposableEnumerableView <Symbol> omView in di.CreateObjectModuleIterator())
            {
                Symbol om = omView.Value;
                ObjectModuleDetails omDetails = om.GetObjectModuleDetails();
                if (omDetails.Language == Language.Unknown)
                {
                    // See if this module contributed to an executable section. If not, we can ignore the module.
                    if (di.CompilandWithIdIsInExecutableSectionContrib(om.SymIndexId))
                    {
                        unknownLanguageModules.Add(om.CreateCompilandRecord());
                    }

                    continue;
                }

                if ((omDetails.Language != Language.C) && (omDetails.Language != Language.Cxx))
                {
                    continue;
                }

                if (omDetails.Compiler != "Microsoft (R) Optimizing Compiler")
                {
                    continue;
                }

                if (!om.CreateChildIterator(SymTagEnum.SymTagFunction).Any())
                {
                    // uninteresting...
                    continue;
                }

                int        warningLevel             = omDetails.WarningLevel;
                List <int> requiredDisabledWarnings = omDetails.ExplicitlyDisabledWarnings
                                                      .Where(context.Policy.GetProperty(RequiredCompilerWarnings).Contains).ToList();

                if (warningLevel >= 3 && requiredDisabledWarnings.Count == 0)
                {
                    // We duplicate this condition to bail out early and avoid writing the
                    // module description or newline into sbBadWarningModules if everything
                    // in the module is OK.
                    continue;
                }

                List <string> suffix = new List <string>(2);

                overallMinimumWarningLevel = Math.Min(overallMinimumWarningLevel, warningLevel);
                if (warningLevel < 3)
                {
                    exampleTooLowWarningCommandLine = exampleTooLowWarningCommandLine ?? omDetails.CommandLine;

                    string msg = "[warning level: " + warningLevel.ToString(CultureInfo.InvariantCulture) + "]";
                    warningTooLowModules.Add(om.CreateCompilandRecordWithSuffix(msg));
                    suffix.Add(msg);
                }

                if (requiredDisabledWarnings.Count != 0)
                {
                    MergeInto(overallDisabledWarnings, requiredDisabledWarnings);
                    exampleDisabledWarningCommandLine = exampleDisabledWarningCommandLine ?? omDetails.CommandLine;

                    string msg = "[Explicitly disabled warnings: " + CreateTextWarningList(requiredDisabledWarnings) + "]";
                    disabledWarningModules.Add(om.CreateCompilandRecordWithSuffix(msg));
                    suffix.Add(msg);
                }

                allWarningLevelLowModules.Add(om.CreateCompilandRecordWithSuffix(String.Join(" ", suffix)));
            }

            if (unknownLanguageModules.Empty &&
                exampleTooLowWarningCommandLine == null &&
                exampleDisabledWarningCommandLine == null)
            {
                // '{0}' was compiled at a secure warning level ({1}) and does not
                // include any modules that disable specific warnings which are
                // required by policy. As a result, there is a greater likelihood
                // that memory corruption, information disclosure, double-free and
                // other security-related vulnerabilities do not exist in code.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                             nameof(RuleResources.BA2007_Pass),
                                                             overallMinimumWarningLevel.ToString()));
                return;
            }

            if (!unknownLanguageModules.Empty)
            {
                // '{0}' contains code from an unknown language, preventing a
                // comprehensive analysis of the compiler warning settings.
                // The language could not be identified for the following modules: {1}
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2007_Error_UnknownModuleLanguage),
                                                             unknownLanguageModules.CreateSortedObjectList()));
            }

            if (exampleTooLowWarningCommandLine != null)
            {
                // '{0}' was compiled at too low a warning level. Warning level 3 enables
                // important static analysis in the compiler to flag bugs that can lead
                // to memory corruption, information disclosure, or double-free
                // vulnerabilities.To resolve this issue, compile at warning level 3 or
                // higher by supplying / W3, / W4, or / Wall to the compiler, and resolve
                // the warnings emitted.
                // An example compiler command line triggering this check: {1}
                // Modules triggering this check: {2}
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2007_Error_InsufficientWarningLevel),
                                                             overallMinimumWarningLevel.ToString(),
                                                             exampleTooLowWarningCommandLine,
                                                             warningTooLowModules.CreateTruncatedObjectList()));
            }

            if (exampleDisabledWarningCommandLine != null)
            {
                // '{0}' disables compiler warning(s) which are required by policy. A
                // compiler warning is typically required if it has a high likelihood of
                // flagging memory corruption, information disclosure, or double-free
                // vulnerabilities. To resolve this issue, enable the indicated warning(s)
                // by removing /Wxxxx switches (where xxxx is a warning id indicated here)
                // from your command line, and resolve any warnings subsequently raised
                // during compilation.
                // An example compiler command line triggering this check was: {1}
                // Modules triggering this check were: {2}
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2007_Error_WarningsDisabled),
                                                             exampleDisabledWarningCommandLine,
                                                             disabledWarningModules.CreateTruncatedObjectList()));
            }
        }
        public override void AnalyzePortableExecutableAndPdb(BinaryAnalyzerContext context)
        {
            PEBinary target = context.PEBinary();
            Pdb      pdb    = target.Pdb;

            Dictionary <string, TruncatedCompilandRecordList> vulnerabilityToModules = new Dictionary <string, TruncatedCompilandRecordList>();
            TruncatedCompilandRecordList moduleList;

            foreach (DisposableEnumerableView <Symbol> omView in pdb.CreateObjectModuleIterator())
            {
                Symbol om = omView.Value;
                ObjectModuleDetails details = om.GetObjectModuleDetails();
                if (details.Language != Language.C && details.Language != Language.Cxx)
                {
                    continue;
                }

                if (!details.HasDebugInfo)
                {
                    continue;
                }

                foreach (DisposableEnumerableView <SourceFile> sfView in pdb.CreateSourceFileIterator(om))
                {
                    SourceFile sf       = sfView.Value;
                    string     fileName = Path.GetFileName(sf.FileName);

                    if (!_files.Contains(fileName) || sf.HashType == HashType.None)
                    {
                        continue;
                    }

                    string hash = fileName + "#" + BitConverter.ToString(sf.Hash);
                    VulnerableDependencyDescriptor descriptor;

                    if (_filesToVulnerabilitiesMap.TryGetValue(hash, out descriptor))
                    {
                        if (!vulnerabilityToModules.TryGetValue(descriptor.Id, out moduleList))
                        {
                            moduleList = vulnerabilityToModules[descriptor.Id] = new TruncatedCompilandRecordList();
                        }
                        moduleList.Add(om.CreateCompilandRecordWithSuffix(hash));
                    }
                }
            }

            if (vulnerabilityToModules.Count != 0)
            {
                foreach (string id in vulnerabilityToModules.Keys)
                {
                    moduleList = vulnerabilityToModules[id];
                    VulnerableDependencyDescriptor descriptor = (VulnerableDependencyDescriptor)context.Policy.GetProperty(VulnerableDependencies)[id];

                    // '{0}' was built with a version of {1} which is subject to the following issues: {2}.
                    // To resolve this, {3}. The source files that triggered this were: {4}
                    context.Logger.Log(this,
                                       RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                                 nameof(RuleResources.BA2002_Error),
                                                                 context.TargetUri.GetFileName(),
                                                                 descriptor.Name,
                                                                 descriptor.VulnerabilityDescription,
                                                                 descriptor.Resolution,
                                                                 moduleList.CreateSortedObjectList()));
                }
                return;
            }

            // '{0}' does not incorporate any known vulnerable dependencies, as configured by current policy.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2002_Pass),
                                                         context.TargetUri.GetFileName()));
        }
Esempio n. 24
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEHeader peHeader = context.PE.PEHeaders.PEHeader;
            Pdb      pdb      = context.Pdb;

            if (pdb == null)
            {
                Errors.LogExceptionLoadingPdb(context, context.PdbParseException);
                return;
            }

            TruncatedCompilandRecordList noGsModules            = new TruncatedCompilandRecordList();
            TruncatedCompilandRecordList unknownLanguageModules = new TruncatedCompilandRecordList();

            foreach (DisposableEnumerableView <Symbol> omView in pdb.CreateObjectModuleIterator())
            {
                Symbol om = omView.Value;
                ObjectModuleDetails details = om.GetObjectModuleDetails();

                if (details.Language == Language.Unknown)
                {
                    // See if this module contributed to an executable section.
                    // If not, we can ignore the module.
                    if (pdb.CompilandWithIdIsInExecutableSectionContrib(om.SymIndexId))
                    {
                        unknownLanguageModules.Add(om.CreateCompilandRecord());
                    }
                    continue;
                }

                // Detection applies to C/C++ produced by MS compiler only
                if ((details.Language != Language.C) && (details.Language != Language.Cxx) ||
                    details.Compiler != "Microsoft (R) Optimizing Compiler")
                {
                    continue;
                }

                if (!details.HasSecurityChecks && om.CreateChildIterator(SymTagEnum.SymTagFunction).Any())
                {
                    noGsModules.Add(om.CreateCompilandRecord());
                }
            }

            if (unknownLanguageModules.Empty && noGsModules.Empty)
            {
                // '{0}' is a C or C++ binary built with the stack protector buffer security
                // feature enabled for all modules, making it more difficult for an attacker to
                // exploit stack buffer overflow memory corruption vulnerabilities.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                             nameof(RuleResources.BA2011_Pass)));
                return;
            }

            if (!unknownLanguageModules.Empty)
            {
                // '{0}' contains code from unknown language, preventing a comprehensive analysis of the
                // stack protector buffer security features. The language could not be identified for
                // the following modules: {1}.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2011_Error_UnknownModuleLanguage),
                                                             unknownLanguageModules.CreateSortedObjectList()));
            }

            if (!noGsModules.Empty)
            {
                // '{0}' is a C or C++ binary built with the stack protector buffer security feature
                // disabled in one or more modules. The stack protector (/GS) is a security feature
                // of the compiler which makes it more difficult to exploit stack buffer overflow
                // memory corruption vulnerabilities. To resolve this issue, ensure that your code
                // is compiled with the stack protector enabled by supplying /GS on the Visual C++
                // compiler command line. The affected modules were: {1}
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2011_Error),
                                                             noGsModules.ToString()));
            }
        }
Esempio n. 25
0
        public void DisposePortableExecutableData()
        {
            if (_pdb != null)
            {
                _pdb.Dispose();
                _pdb = null;
            }

            if (_pe != null)
            {
                _pe.Dispose();
                _pe = null;
            }
        }
Esempio n. 26
0
 /// <summary>
 /// Inspect the final output after binding.
 /// </summary>
 /// <param name="filePath">The file path to the final bound output.</param>
 /// <param name="pdb">The <see cref="Pdb"/> that contains source line numbers
 /// for the database and all rows.</param>
 public virtual void InspectDatabase(string filePath, Pdb pdb)
 {
 }
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEHeader peHeader = context.PE.PEHeaders.PEHeader;

            if (context.Pdb == null)
            {
                Errors.LogExceptionLoadingPdb(context, context.PdbParseException);
                return;
            }

            Pdb di = context.Pdb;

            bool noCode = !di.CreateGlobalFunctionIterator().Any() && !di.ContainsExecutableSectionContribs();

            if (noCode)
            {
                // '{0}' is a C or C++ binary that is not required to initialize the stack protection, as it does not contain executable code.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                             nameof(RuleResources.BA2013_Pass_NoCode),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            bool bHasGSCheck = di.CreateGlobalFunctionIterator(
                StackProtectionUtilities.GSCheckFunctionName, NameSearchOptions.nsfCaseSensitive).Any();

            bool bHasGSInit = StackProtectionUtilities.GSInitializationFunctionNames.Any(
                functionName => di.CreateGlobalFunctionIterator(functionName,
                                                                NameSearchOptions.nsfCaseSensitive).Any());

            if (!bHasGSCheck && !bHasGSInit)
            {
                // '{0}' is a C or C++ binary that does enable the stack protection buffer
                // security feature. It is therefore not required to initialize the stack protector.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.NotApplicable, context, null,
                                                             nameof(RuleResources.BA2013_NotApplicable_FeatureNotEnabled),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            if (!bHasGSInit)
            {
                // '{0}' is a C or C++ binary that does not initialize the stack protector.
                // The stack protector(/ GS) is a security feature of the compiler which
                // makes it more difficult to exploit stack buffer overflow memory
                // corruption vulnerabilities. The stack protector requires access to
                // entropy in order to be effective, which means a binary must initialize
                // a random number generator at startup, by calling __security_init_cookie()
                // as close to the binary's entry point as possible. Failing to do so will
                // result in spurious buffer overflow detections on the part of the stack
                // protector. To resolve this issue, use the default entry point provided
                // by the C runtime, which will make this call for you, or call
                // __security_init_cookie() manually in your custom entry point.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2013_Error),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            // '{0}' is a C or C++ binary built with the buffer security feature
            // that properly initializes the stack protecter. This has the
            //effect of increasing the effectiveness of the feature and reducing
            // spurious detections.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2013_Pass),
                                                         context.TargetUri.GetFileName()));
        }
Esempio n. 28
0
        /// <summary>
        /// Main running method for the application.
        /// </summary>
        /// <param name="args">Commandline arguments to the application.</param>
        /// <returns>Returns the application error code.</returns>
        private int Run(string[] args)
        {
            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // exit if there was an error parsing the command line (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                if (0 == this.inputFiles.Count)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    AppCommon.DisplayToolHeader();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(SmokeStrings.HelpMessage);
                    AppCommon.DisplayToolFooter();
                    return(this.messageHandler.LastErrorNumber);
                }

                foreach (string parameter in this.invalidArgs)
                {
                    this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter));
                }
                this.invalidArgs = null;

                validator.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");

                // load any extensions
                bool validatorExtensionLoaded = false;
                foreach (string extension in this.extensionList)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);

                    ValidatorExtension validatorExtension = wixExtension.ValidatorExtension;
                    if (null != validatorExtension)
                    {
                        if (validatorExtensionLoaded)
                        {
                            throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, SmokeStrings.EXP_CannotLoadLinkerExtension, validatorExtension.GetType().ToString(), validator.Extension.ToString()), "ext");
                        }

                        validator.Extension      = validatorExtension;
                        validatorExtensionLoaded = true;
                    }
                }

                // set the message handlers
                validator.Extension.Message += new MessageEventHandler(this.messageHandler.Display);

                // disable ICE33 and ICE66 by default
                this.suppressICEs.Add("ICE33");
                this.suppressICEs.Add("ICE66");

                // set the ICEs
                string[] iceArray = new string[this.ices.Count];
                this.ices.CopyTo(iceArray, 0);
                validator.ICEs = iceArray;

                // set the suppressed ICEs
                string[] suppressICEArray = new string[this.suppressICEs.Count];
                this.suppressICEs.CopyTo(suppressICEArray, 0);
                validator.SuppressedICEs = suppressICEArray;

                // Load the pdb and assign the Output to the validator
                if (null != pdbPath)
                {
                    string pdbFullPath = Path.GetFullPath(pdbPath);
                    Pdb    pdb         = Pdb.Load(pdbFullPath, false, false);
                    this.validator.Output = pdb.Output;
                }

                foreach (string inputFile in this.inputFiles)
                {
                    // set the default cube file
                    Assembly assembly     = Assembly.GetExecutingAssembly();
                    string   appDirectory = Path.GetDirectoryName(assembly.Location);

                    if (this.addDefault)
                    {
                        switch (Path.GetExtension(inputFile).ToLower(CultureInfo.InvariantCulture))
                        {
                        case msm:
                            validator.AddCubeFile(Path.Combine(appDirectory, "mergemod.cub"));
                            break;

                        case msi:
                            validator.AddCubeFile(Path.Combine(appDirectory, "darice.cub"));
                            break;

                        default:
                            throw new WixException(WixErrors.UnexpectedFileExtension(inputFile, ".msi, .msm"));
                        }
                    }

                    // print friendly message saying what file is being validated
                    Console.WriteLine(Path.GetFileName(inputFile));
                    Stopwatch stopwatch = Stopwatch.StartNew();

                    try
                    {
                        validator.Validate(Path.GetFullPath(inputFile));
                    }
                    catch (UnauthorizedAccessException)
                    {
                        this.messageHandler.Display(this, WixErrors.UnauthorizedAccess(Path.GetFullPath(inputFile)));
                    }
                    finally
                    {
                        stopwatch.Stop();
                        this.messageHandler.Display(this, WixVerboses.ValidatedDatabase(stopwatch.ElapsedMilliseconds));

                        if (this.tidy)
                        {
                            if (!validator.DeleteTempFiles())
                            {
                                Console.WriteLine(SmokeStrings.WAR_FailedToDeleteTempDir, validator.TempFilesLocation);
                            }
                        }
                        else
                        {
                            Console.WriteLine(SmokeStrings.INF_TempDirLocatedAt, validator.TempFilesLocation);
                        }
                    }
                }
            }
            catch (WixException we)
            {
                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }
Esempio n. 29
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEHeader peHeader = context.PE.PEHeaders.PEHeader;
            Pdb      pdb      = context.Pdb;

            if (pdb == null)
            {
                Errors.LogExceptionLoadingPdb(context, context.PdbParseException);
                return;
            }

            List <string> names = new List <string>();

            foreach (DisposableEnumerableView <Symbol> functionView in pdb.CreateGlobalFunctionIterator())
            {
                Symbol function = functionView.Value;
                if (function.IsManaged)
                {
                    continue;
                }
                if (!function.IsSafeBuffers)
                {
                    continue;
                }

                string functionName = function.GetUndecoratedName();

                if (functionName == "__security_init_cookie" ||
                    context.Policy.GetProperty(ApprovedFunctionsThatDisableStackProtection).Contains(functionName))
                {
                    continue;
                }
                names.Add(functionName);
            }

            if (names.Count != 0)
            {
                string functionNames = string.Join(";", names);

                // '{0}' is a C or C++ binary built with function(s) ({1}) that disable the stack
                // protector. The stack protector (/GS) is a security feature of the compiler
                // which makes it more difficult to exploit stack buffer overflow memory
                // corruption vulnerabilities. Disabling the stack protector, even on a
                // function -by-function basis, is disallowed by SDL policy. To resolve this
                // issue, remove occurrences of __declspec(safebuffers) from your code. If the
                // additional code inserted by the stack protector has been shown in profiling
                // to cause a significant performance problem for your application, attempt to
                // move stack buffer modifications out of the hot path of execution to allow the
                // compiler to avoid inserting stack protector checks in these locations rather
                // than disabling the stack protector altogether.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2014_Error),
                                                             context.TargetUri.GetFileName(),
                                                             functionNames));
                return;
            }

            // '{0}' is a C or C++ binary built with the stack protector buffer
            // security feature enabled which does not disable protection for
            // any individual functions (via __declspec(safebuffers), making it
            // more difficult for an attacker to exploit stack buffer overflow
            // memory corruption vulnerabilities.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2014_Pass),
                                                         context.TargetUri.GetFileName()));
        }
Esempio n. 30
0
File: melt.cs Progetto: zooba/wix3
        /// <summary>
        /// Checks to make sure that the debug symbols match up with the MSI.
        /// This is to help in ensuring that error 1642 does not inexplicably appear.
        /// </summary>
        /// <remarks>
        /// This is meant to assist with Bug # 4792
        /// http://wixtoolset.org/issues/4792/
        /// </remarks>
        /// <param name="package">
        /// The MSI currently being melted.
        /// </param>
        /// <param name="inputPdb">
        /// The debug symbols package being compared against the <paramref name="package"/>.
        /// </param>
        /// <returns></returns>
        private static bool ValidateMsiMatchesPdb(InstallPackage package, Pdb inputPdb)
        {
            string msiPackageCode = (string)package.Property["PackageCode"];

            foreach (Row pdbPropertyRow in inputPdb.Output.Tables["Property"].Rows)
            {
                if ("PackageCode" == (string)pdbPropertyRow.Fields[0].Data)
                {
                    string pdbPackageCode = (string)pdbPropertyRow.Fields[1].Data;
                    if (msiPackageCode != pdbPackageCode)
                    {
                        Console.WriteLine(MeltStrings.WAR_MismatchedPackageCode, msiPackageCode, pdbPackageCode);
                        return false;
                    }
                    break;
                }
            }

            return true;
        }
Esempio n. 31
0
        public override void AnalyzePortableExecutableAndPdb(BinaryAnalyzerContext context)
        {
            PEBinary target = context.PEBinary();

            Machine reflectionMachineType = target.PE.Machine;

            // The current Machine enum does not have support for Arm64, so translate to our Machine enum
            ExtendedMachine machineType = (ExtendedMachine)reflectionMachineType;

            if (!machineType.CanBeMitigated())
            {
                // QUESTION:
                // Machine HW is unsupported for mitigations...
                // should this be in the CanAnalyze() method or here and issue a warning?
                return;
            }

            Pdb pdb = target.Pdb;

            TruncatedCompilandRecordList masmModules = new TruncatedCompilandRecordList();
            TruncatedCompilandRecordList mitigationNotEnabledModules         = new TruncatedCompilandRecordList();
            TruncatedCompilandRecordList mitigationDisabledInDebugBuild      = new TruncatedCompilandRecordList();
            TruncatedCompilandRecordList mitigationExplicitlyDisabledModules = new TruncatedCompilandRecordList();

            StringToVersionMap allowedLibraries = context.Policy.GetProperty(AllowedLibraries);

            foreach (DisposableEnumerableView <Symbol> omView in pdb.CreateObjectModuleIterator())
            {
                Symbol om = omView.Value;
                ObjectModuleDetails omDetails = om.GetObjectModuleDetails();

                // See if the item is in our skip list.
                if (!string.IsNullOrEmpty(om.Lib))
                {
                    string  libFileName = string.Concat(System.IO.Path.GetFileName(om.Lib), ",", omDetails.Language.ToString()).ToLowerInvariant();
                    Version minAllowedVersion;

                    if (allowedLibraries.TryGetValue(libFileName, out minAllowedVersion) &&
                        omDetails.CompilerVersion >= minAllowedVersion)
                    {
                        continue;
                    }
                }

                Version  actualVersion;
                Language omLanguage = omDetails.Language;

                // We already opted-out of IL Only binaries, so only check for native languages
                // or those that can appear in mixed binaries.
                switch (omLanguage)
                {
                case Language.C:
                case Language.Cxx:
                {
                    if (omDetails.WellKnownCompiler != WellKnownCompilers.MicrosoftNativeCompiler)
                    {
                        // TODO: https://github.com/Microsoft/binskim/issues/114
                        continue;
                    }
                    else
                    {
                        actualVersion = omDetails.CompilerVersion;
                    }
                    break;
                }

                case Language.MASM:
                {
                    masmModules.Add(om.CreateCompilandRecord());
                    continue;
                }

                case Language.LINK:
                {
                    // Linker is not involved in the mitigations, so no need to check version or switches at this time.
                    continue;
                }

                case Language.CVTRES:
                {
                    // Resource compiler is not involved in the mitigations, so no need to check version or switches at this time.
                    continue;
                }

                case Language.HLSL:
                {
                    // HLSL compiler is not involved in the mitigations, so no need to check version or switches at this time.
                    continue;
                }

                // Mixed binaries (/clr) can contain non C++ compilands if they are linked in via netmodules
                // .NET IL should be mitigated by the runtime if any mitigations are necessary
                // At this point simply accept them as safe until this is disproven.
                case Language.CSharp:
                case Language.MSIL:
                case Language.ILASM:
                {
                    continue;
                }

                case Language.Unknown:
                {
                    // The linker may emit debug information for modules from static libraries that do not contribute to actual code.
                    // do not contribute to actual code. Currently these come back as Language.Unknown :(
                    // TODO: https://github.com/Microsoft/binskim/issues/116
                    continue;
                }

                default:
                {
                    // TODO: https://github.com/Microsoft/binskim/issues/117
                    // Review unknown languages for this and all checks
                }
                    continue;
                }

                // Get the appropriate compiler version against which to check this compiland.
                // check that we are greater than or equal to the first fully supported release: 15.6 first
                Version omVersion = omDetails.CompilerVersion;

                CompilerMitigations availableMitigations = GetAvailableMitigations(context, machineType, omVersion);

                if (availableMitigations == CompilerMitigations.None)
                {
                    // Built with a compiler version {0} that does not support any Spectre
                    // mitigations. We do not report here. BA2006 will fire instead.
                    continue;
                }
                string[] mitigationSwitches = new string[] { "/Qspectre", "/guardspecload" };

                SwitchState effectiveState;

                // Go process the command line to check for switches
                effectiveState = omDetails.GetSwitchState(mitigationSwitches, null, SwitchState.SwitchDisabled, OrderOfPrecedence.LastWins);

                if (effectiveState == SwitchState.SwitchDisabled)
                {
                    SwitchState QSpectreState        = SwitchState.SwitchNotFound;
                    SwitchState d2guardspecloadState = SwitchState.SwitchNotFound;

                    if (availableMitigations.HasFlag(CompilerMitigations.QSpectreAvailable))
                    {
                        QSpectreState = omDetails.GetSwitchState(mitigationSwitches[0] /*"/Qspectre"*/, OrderOfPrecedence.LastWins);
                    }

                    if (availableMitigations.HasFlag(CompilerMitigations.D2GuardSpecLoadAvailable))
                    {
                        // /d2xxxx options show up in the PDB without the d2 string
                        // So search for just /guardspecload
                        d2guardspecloadState = omDetails.GetSwitchState(mitigationSwitches[1] /*"/guardspecload"*/, OrderOfPrecedence.LastWins);
                    }

                    // TODO: https://github.com/Microsoft/binskim/issues/119
                    // We should flag cases where /d2guardspecload is enabled but the
                    // toolset supports /qSpectre (which should be preferred).

                    if (QSpectreState == SwitchState.SwitchNotFound && d2guardspecloadState == SwitchState.SwitchNotFound)
                    {
                        // Built with tools that support the Spectre mitigations but these have not been enabled.
                        mitigationNotEnabledModules.Add(om.CreateCompilandRecord());
                    }
                    else
                    {
                        // Built with the Spectre mitigations explicitly disabled.
                        mitigationExplicitlyDisabledModules.Add(om.CreateCompilandRecord());
                    }

                    continue;
                }

                if (!availableMitigations.HasFlag(CompilerMitigations.NonoptimizedCodeMitigated))
                {
                    string[] OdSwitches = { "/Od" };
                    // These switches override /Od - there is no one place to find this information on msdn at this time.
                    string[] OptimizeSwitches = { "/O1", "/O2", "/Ox", "/Og" };

                    bool debugEnabled = false;

                    if (omDetails.GetSwitchState(OdSwitches, OptimizeSwitches, SwitchState.SwitchEnabled, OrderOfPrecedence.LastWins) == SwitchState.SwitchEnabled)
                    {
                        debugEnabled = true;
                    }

                    if (debugEnabled)
                    {
                        // Built with /Od which disables Spectre mitigations.
                        mitigationDisabledInDebugBuild.Add(om.CreateCompilandRecord());
                        continue;
                    }
                }
            }

            string line;
            var    sb = new StringBuilder();

            if (!mitigationExplicitlyDisabledModules.Empty)
            {
                // The following modules were compiled with Spectre
                // mitigations explicitly disabled: {0}
                line = string.Format(
                    RuleResources.BA2024_Error_SpectreMitigationExplicitlyDisabled,
                    mitigationExplicitlyDisabledModules.CreateSortedObjectList());
                sb.AppendLine(line);
            }

            if (!mitigationNotEnabledModules.Empty)
            {
                // The following modules were compiled with a toolset that supports
                // /Qspectre but the switch was not enabled on the command-line: {0}
                line = string.Format(
                    RuleResources.BA2024_Error_SpectreMitigationNotEnabled,
                    mitigationNotEnabledModules.CreateSortedObjectList());
                sb.AppendLine(line);
            }

            if (!mitigationDisabledInDebugBuild.Empty)
            {
                // The following modules were compiled with optimizations disabled(/ Od),
                // a condition that disables Spectre mitigations: {0}
                line = string.Format(
                    RuleResources.BA2024_Error_OptimizationsDisabled,
                    mitigationDisabledInDebugBuild.CreateSortedObjectList());
                sb.AppendLine(line);
            }

            if ((context.Policy.GetProperty(Reporting) & ReportingOptions.WarnIfMasmModulesPresent) == ReportingOptions.WarnIfMasmModulesPresent &&
                !masmModules.Empty)
            {
                line = string.Format(
                    RuleResources.BA2024_Error_MasmModulesDetected,
                    masmModules.CreateSortedObjectList());
                sb.AppendLine(line);
            }

            if (sb.Length > 0)
            {
                // '{0}' was compiled with one or more modules that do not properly enable code
                // generation mitigations for speculative execution side-channel attack (Spectre)
                // vulnerabilities. Spectre attacks can compromise hardware-based isolation,
                // allowing non-privileged users to retrieve potentially sensitive data from the
                // CPU cache. To resolve the issue, provide the /Qspectre switch on the compiler
                // command-line (or /d2guardspecload in cases where your compiler supports this
                // switch and it is not possible to update to a toolset that supports /Qspectre).
                // The following modules are out of policy: {1}
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2024_Error),
                                                             context.TargetUri.GetFileName(),
                                                             sb.ToString()));
                return;
            }

            // All linked modules ‘{0}’ were compiled with mitigations enabled that help prevent Spectre (speculative execution side-channel attack) vulnerabilities.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2024_Pass),
                                                         context.TargetUri.GetFileName()));
        }
        public override void AnalyzePortableExecutableAndPdb(BinaryAnalyzerContext context)
        {
            PEBinary target = context.PEBinary();
            Pdb      pdb    = target.Pdb;

            Version minCompilerVersion;

            minCompilerVersion = (target.PE.IsXBox)
                ?  context.Policy.GetProperty(MinimumToolVersions)[MIN_XBOX_COMPILER_VER]
                : context.Policy.GetProperty(MinimumToolVersions)[MIN_COMPILER_VER];

            TruncatedCompilandRecordList badModuleList    = new TruncatedCompilandRecordList();
            StringToVersionMap           allowedLibraries = context.Policy.GetProperty(AllowedLibraries);

            foreach (DisposableEnumerableView <Symbol> omView in pdb.CreateObjectModuleIterator())
            {
                Symbol om = omView.Value;
                ObjectModuleDetails omDetails = om.GetObjectModuleDetails();

                if (omDetails.WellKnownCompiler != WellKnownCompilers.MicrosoftNativeCompiler)
                {
                    continue;
                }

                // See if the item is in our skip list
                if (!string.IsNullOrEmpty(om.Lib))
                {
                    string  libFileName = string.Concat(System.IO.Path.GetFileName(om.Lib), ",", omDetails.Language.ToString()).ToLowerInvariant();
                    Version minAllowedVersion;

                    if (allowedLibraries.TryGetValue(libFileName, out minAllowedVersion) &&
                        omDetails.CompilerVersion >= minAllowedVersion)
                    {
                        continue;
                    }
                }

                Version  actualVersion;
                Version  minimumVersion;
                Language omLanguage = omDetails.Language;
                switch (omLanguage)
                {
                case Language.C:
                case Language.Cxx:
                    actualVersion  = Minimum(omDetails.CompilerVersion, omDetails.CompilerFrontEndVersion);
                    minimumVersion = minCompilerVersion;
                    break;

                default:
                    continue;
                }

                bool foundIssue = actualVersion < minimumVersion;

                AdvancedMitigations advancedMitigations = context.Policy.GetProperty(AdvancedMitigationsEnforced);
                if (!foundIssue &&
                    (advancedMitigations & AdvancedMitigations.Spectre) == AdvancedMitigations.Spectre)
                {
                    ExtendedMachine machineType = (ExtendedMachine)target.PE.Machine;

                    // Current toolchain is within the version range to validate.
                    // Now we'll retrieve relevant compiler mitigation details to
                    // ensure this object module's build and revision meet
                    // expectations.
                    CompilerMitigations newMitigationData =
                        EnableSpectreMitigations.GetAvailableMitigations(context, machineType, actualVersion);

                    // Current compiler version does not support Spectre mitigations.
                    foundIssue = !newMitigationData.HasFlag(CompilerMitigations.D2GuardSpecLoadAvailable) &&
                                 !newMitigationData.HasFlag(CompilerMitigations.QSpectreAvailable);

                    if (foundIssue)
                    {
                        // Get the closest compiler version that has mitigations--i.e. if the user is using a 19.0 (VS2015) compiler, we should be recommending an upgrade to the
                        // 19.0 version that has the mitigations, not an upgrade to a 19.10+ (VS2017) compiler.
                        // Limitation--if there are multiple 'upgrade to' versions to recommend, this just going to give users the last one we see in the error.
                        minCompilerVersion = EnableSpectreMitigations.GetClosestCompilerVersionWithSpectreMitigations(context, machineType, actualVersion);

                        // Indicates Spectre mitigations are not supported on this platform.  We won't flag this case.
                        if (minCompilerVersion == null)
                        {
                            foundIssue = false;
                        }
                    }
                }

                if (foundIssue)
                {
                    // built with {0} compiler version {1} (Front end version: {2})
                    badModuleList.Add(
                        om.CreateCompilandRecordWithSuffix(
                            String.Format(CultureInfo.InvariantCulture,
                                          RuleResources.BA2006_Error_BadModule,
                                          omLanguage, omDetails.CompilerVersion, omDetails.CompilerFrontEndVersion)));
                }
            }

            if (!badModuleList.Empty)
            {
                // '{0}' was compiled with one or more modules which were not built using
                // minimum required tool versions (compiler version {1}). More recent toolchains
                // contain mitigations that make it more difficult for an attacker to exploit
                // vulnerabilities in programs they produce. To resolve this issue, compile
                // and /or link your binary with more recent tools. If you are servicing a
                // product where the tool chain cannot be modified (e.g. producing a hotfix
                // for an already shipped version) ignore this warning. Modules built outside
                // of policy: {2}
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2006_Error),
                                                             context.TargetUri.GetFileName(),
                                                             minCompilerVersion.ToString(),
                                                             badModuleList.CreateSortedObjectList()));
                return;
            }

            // All linked modules of '{0}' generated by the Microsoft front-end
            // satisfy configured policy (compiler minimum version {1}).
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2006_Pass),
                                                         context.TargetUri.GetFileName(),
                                                         minCompilerVersion.ToString()));
        }
Esempio n. 33
0
File: melt.cs Progetto: zooba/wix3
        /// <summary>
        /// Extract binary data from tables with a Name and Data column in them.
        /// </summary>
        /// <param name="inputPdb">A reference to a <see cref="Pdb"/> as output.  Paths (Data properties) will be modified in this object.</param>
        /// <param name="package">The installer database to rip from.</param>
        /// <param name="exportPath">The full path where files will be exported to.</param>
        /// <param name="tableName">The name of the table to export.</param>
        private static void MeltBinaryTable(Pdb inputPdb, InstallPackage package, string exportPath, string tableName)
        {
            if (string.IsNullOrEmpty(tableName))
            {
                throw new ArgumentNullException("tableName");
            }
            if (string.IsNullOrEmpty(exportPath))
            {
                throw new ArgumentNullException("exportPath");
            }
            if (null == package)
            {
                throw new ArgumentNullException("package");
            }
            if (null == inputPdb)
            {
                throw new ArgumentNullException("inputPdb");
            }

            Table pdbTable = inputPdb.Output.Tables[tableName];
            if (null == pdbTable)
            {
                Console.WriteLine("Table {0} does not exist.", tableName);
                return;
            }

            try
            {
                Directory.CreateDirectory(exportPath);
                Melt.ExtractFilesInBinaryTable(package, null, tableName, exportPath);
                IDictionary<string, string> paths = package.GetFilePaths(exportPath);

                if (null != paths)
                {
                    foreach (Row row in pdbTable.Rows)
                    {
                        string filename = (string)row.Fields[0].Data;
                        row.Fields[1].Data = paths[filename];
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("An error occured extracting the {0} binary table from the install package.", tableName);
                Console.WriteLine(ex.Message);
            }
        }
Esempio n. 34
0
        /// <summary>
        /// Main running method for the application.
        /// </summary>
        /// <param name="args">Commandline arguments to the application.</param>
        /// <returns>Returns the application error code.</returns>
        private int Run(string[] args)
        {
            Microsoft.Tools.WindowsInstallerXml.Binder binder = null;
            Differ   differ   = null;
            Unbinder unbinder = null;

            TempFileCollection tempFileCollection = null;

            try
            {
                // parse the command line
                this.ParseCommandLine(args);

                // validate the inputs
                if (this.xmlInputs && this.adminImage)
                {
                    this.messageHandler.Display(this, WixErrors.IllegalCommandlineArgumentCombination("a", "xi"));
                    this.showHelp = true;
                }

                string[] allValidExtensions               = new string[] { wixMstExtension, wixOutExtension, wixPdbExtension, msiExtension };
                string[] expectedSingleInputExtensions    = new string[] { wixMstExtension, wixOutExtension };
                string[] expectedDoubleInputXmlExtensions = new string[] { wixOutExtension, wixPdbExtension };
                string[] expectedDoubleInputMsiExtensions = new string[] { msiExtension };

                // Validate that all inputs have the correct extension and we dont have too many inputs.
                if (1 == this.inputFiles.Count)
                {
                    string inputFile = this.inputFiles[0];

                    bool hasValidExtension = false;
                    foreach (string extension in expectedSingleInputExtensions)
                    {
                        if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                        {
                            hasValidExtension = true;
                            break;
                        }
                    }

                    if (!hasValidExtension)
                    {
                        bool missingInput = false;

                        // Check if its using an extension that could be valid in other scenarios.
                        foreach (string validExtension in allValidExtensions)
                        {
                            if (String.Equals(Path.GetExtension(inputFile), validExtension, StringComparison.OrdinalIgnoreCase))
                            {
                                this.messageHandler.Display(this, WixErrors.WrongFileExtensionForNumberOfInputs(Path.GetExtension(inputFile), inputFile));
                                missingInput = true;
                                break;
                            }
                        }

                        if (!missingInput)
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(inputFile, String.Join(", ", expectedSingleInputExtensions)));
                        }
                    }
                }
                else if (2 == this.inputFiles.Count)
                {
                    foreach (string inputFile in inputFiles)
                    {
                        bool     hasValidExtension  = false;
                        string[] expectedExtensions = allValidExtensions;
                        if (this.xmlInputs)
                        {
                            foreach (string extension in expectedDoubleInputXmlExtensions)
                            {
                                if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                                {
                                    hasValidExtension  = true;
                                    expectedExtensions = expectedDoubleInputXmlExtensions;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            foreach (string extension in expectedDoubleInputMsiExtensions)
                            {
                                if (String.Equals(Path.GetExtension(inputFile), extension, StringComparison.OrdinalIgnoreCase))
                                {
                                    hasValidExtension  = true;
                                    expectedExtensions = expectedDoubleInputMsiExtensions;
                                    break;
                                }
                            }
                        }

                        if (!hasValidExtension)
                        {
                            this.messageHandler.Display(this, WixErrors.UnexpectedFileExtension(inputFile, String.Join(", ", expectedExtensions)));
                        }
                    }
                }
                else
                {
                    this.showHelp = true;
                }

                // exit if there was an error parsing the command line or with a file extension (otherwise the logo appears after error messages)
                if (this.messageHandler.EncounteredError)
                {
                    return(this.messageHandler.LastErrorNumber);
                }

                if (null == this.outputFile)
                {
                    this.showHelp = true;
                }

                if (this.showLogo)
                {
                    AppCommon.DisplayToolHeader();
                }

                if (this.showHelp)
                {
                    Console.WriteLine(TorchStrings.HelpMessage);
                    AppCommon.DisplayToolFooter();
                    return(this.messageHandler.LastErrorNumber);
                }

                foreach (string parameter in this.invalidArgs)
                {
                    this.messageHandler.Display(this, WixWarnings.UnsupportedCommandLineArgument(parameter));
                }
                this.invalidArgs = null;

                binder   = new Microsoft.Tools.WindowsInstallerXml.Binder();
                differ   = new Differ();
                unbinder = new Unbinder();

                // load any extensions
                foreach (string extension in this.extensionList)
                {
                    WixExtension wixExtension = WixExtension.Load(extension);
                    unbinder.AddExtension(wixExtension);
                    binder.AddExtension(wixExtension);
                    differ.AddExtension(wixExtension);
                }

                binder.Message   += new MessageEventHandler(this.messageHandler.Display);
                differ.Message   += new MessageEventHandler(this.messageHandler.Display);
                unbinder.Message += new MessageEventHandler(this.messageHandler.Display);

                binder.TempFilesLocation   = Environment.GetEnvironmentVariable("WIX_TEMP");
                unbinder.TempFilesLocation = Environment.GetEnvironmentVariable("WIX_TEMP");
                tempFileCollection         = new TempFileCollection(Environment.GetEnvironmentVariable("WIX_TEMP"));

                binder.WixVariableResolver       = new WixVariableResolver();
                differ.PreserveUnchangedRows     = this.preserveUnchangedRows;
                differ.ShowPedanticMessages      = this.showPedanticMessages;
                unbinder.SuppressExtractCabinets = true;
                unbinder.IsAdminImage            = this.adminImage;

                if (null == this.exportBasePath)
                {
                    this.exportBasePath = tempFileCollection.BasePath;
                }

                // load and process the inputs
                Output transform;
                if (1 == this.inputFiles.Count)
                {
                    transform = Output.Load(this.inputFiles[0], false, false);
                    if (OutputType.Transform != transform.Type)
                    {
                        this.messageHandler.Display(this, WixErrors.InvalidWixTransform(this.inputFiles[0]));
                        return(this.messageHandler.LastErrorNumber);
                    }
                }
                else // 2 inputs
                {
                    Output targetOutput;
                    Output updatedOutput;

                    if (this.xmlInputs)
                    {
                        // load the target database
                        if (String.Equals(Path.GetExtension(inputFiles[0]), wixPdbExtension, StringComparison.OrdinalIgnoreCase))
                        {
                            Pdb targetPdb = Pdb.Load(this.inputFiles[0], false, false);
                            targetOutput = targetPdb.Output;
                        }
                        else
                        {
                            targetOutput = Output.Load(this.inputFiles[0], false, false);
                        }

                        // load the updated database
                        if (String.Equals(Path.GetExtension(inputFiles[1]), wixPdbExtension, StringComparison.OrdinalIgnoreCase))
                        {
                            Pdb updatedPdb = Pdb.Load(this.inputFiles[1], false, false);
                            updatedOutput = updatedPdb.Output;
                        }
                        else
                        {
                            updatedOutput = Output.Load(this.inputFiles[1], false, false);
                        }

                        this.xmlOutput = true;
                    }
                    else
                    {
                        // load the target database
                        targetOutput = unbinder.Unbind(this.inputFiles[0], OutputType.Product, Path.Combine(this.exportBasePath, "targetBinaries"));

                        // load the updated database
                        updatedOutput = unbinder.Unbind(this.inputFiles[1], OutputType.Product, Path.Combine(this.exportBasePath, "updatedBinaries"));
                    }

                    // diff the target and updated databases
                    transform = differ.Diff(targetOutput, updatedOutput, this.validationFlags);

                    if (null == transform.Tables || 0 >= transform.Tables.Count)
                    {
                        throw new WixException(WixErrors.NoDifferencesInTransform(transform.SourceLineNumbers));
                    }
                }

                // output the transform
                if (null != transform)
                {
                    // If either the user selected xml output or gave xml input, save as xml output.
                    // With xml inputs, many funtions of the binder have not been performed on the inputs (ie. file sequencing). This results in bad IDT files which cannot be put in a transform.
                    if (this.xmlOutput)
                    {
                        transform.Save(this.outputFile, null, null, tempFileCollection.BasePath);
                    }
                    else
                    {
                        binder.Bind(transform, this.outputFile);
                    }
                }
            }
            catch (WixException we)
            {
                if (we is WixInvalidIdtException)
                {
                    // make sure the IDT files stay around
                    this.tidy = false;
                }

                this.messageHandler.Display(this, we.Error);
            }
            catch (Exception e)
            {
                // make sure the files stay around for debugging
                this.tidy = false;

                this.messageHandler.Display(this, WixErrors.UnexpectedException(e.Message, e.GetType().ToString(), e.StackTrace));
                if (e is NullReferenceException || e is SEHException)
                {
                    throw;
                }
            }
            finally
            {
                if (null != binder)
                {
                    if (this.tidy)
                    {
                        if (!binder.DeleteTempFiles())
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_BinderTempDirLocatedAt, binder.TempFilesLocation);
                    }
                }

                if (null != unbinder)
                {
                    if (this.tidy)
                    {
                        if (!unbinder.DeleteTempFiles())
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, binder.TempFilesLocation);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_UnbinderTempDirLocatedAt, binder.TempFilesLocation);
                    }
                }

                if (null != tempFileCollection)
                {
                    if (this.tidy)
                    {
                        try
                        {
                            Directory.Delete(tempFileCollection.BasePath, true);
                        }
                        catch (DirectoryNotFoundException)
                        {
                            // if the path doesn't exist, then there is nothing for us to worry about
                        }
                        catch
                        {
                            Console.WriteLine(TorchStrings.WAR_FailedToDeleteTempDir, tempFileCollection.BasePath);
                        }
                    }
                    else
                    {
                        Console.WriteLine(TorchStrings.INF_TorchTempDirLocatedAt, tempFileCollection.BasePath);
                    }
                }
            }

            return(this.messageHandler.LastErrorNumber);
        }
Esempio n. 35
0
        /// <summary>
        /// The library "hash". This is an XOR of the 1st 16 bytes of all source file hashes.
        /// </summary>
        public byte[] GetObjectFileHash(Pdb session)
        {
            bool hashPresent = false;
            byte[] res = new byte[16];

            // go through all source files in the lib and XOR their hashes (if present)
            // NB: there are a couple of interesting cases worth considering:
            //      1. .h files may be used to build more than one object files in the lib
            //          and when XOR'ed they cancel each other out;
            //      2. Some source files may not have hashes, in which case our results won't be totally reliable.
            foreach (DisposableEnumerableView<SourceFile> sfView in session.CreateSourceFileIterator(this))
            {
                SourceFile sf = sfView.Value;
                if (sf.HashType != HashType.None)
                {
                    byte[] hash = sf.Hash;

                    if ((hash == null) || (hash.Length < 16))
                    {
                        throw new PdbParseException("Unexpected hash length for file " + sf);
                    }

                    for (int j = 0; j < 16; j++)
                    {
                        res[j] ^= hash[j];
                    }

                    hashPresent = true;
                }
            }

            if (!hashPresent)
            {
                return null;
            }

            return res;
        }