Beispiel #1
0
        // find dll with same name as sxs assembly in target directory
        public static SxsEntries SxsFindTargetDll(string AssemblyName, string Folder)
        {
            SxsEntries EntriesFromElement = new SxsEntries();

            string TargetFilePath = Path.Combine(Folder, AssemblyName);

            if (File.Exists(TargetFilePath))
            {
                var Name = System.IO.Path.GetFileName(TargetFilePath);
                var Path = TargetFilePath;

                EntriesFromElement.Add(new SxsEntry(Name, Path));
                return(EntriesFromElement);
            }

            string TargetDllPath = Path.Combine(Folder, String.Format("{0:s}.dll", AssemblyName));

            if (File.Exists(TargetDllPath))
            {
                var Name = System.IO.Path.GetFileName(TargetDllPath);
                var Path = TargetDllPath;

                EntriesFromElement.Add(new SxsEntry(Name, Path));
                return(EntriesFromElement);
            }

            return(EntriesFromElement);
        }
Beispiel #2
0
        public static SxsEntries FromSxsAssembly(XElement SxsAssembly, XNamespace Namespace, string Folder)
        {
            SxsEntries Entries = new SxsEntries();

            XElement SxsAssemblyIdentity = SxsAssembly.Element(Namespace + "assemblyIdentity");

            foreach (XElement SxsFile in SxsAssembly.Elements(Namespace + "file"))
            {
                Entries.Add(new SxsEntry(SxsAssemblyIdentity, SxsFile, Folder));
            }

            return(Entries);
        }
Beispiel #3
0
        public static void DumpSxsEntries(PE Application)
        {
            SxsEntries SxsDependencies = SxsManifest.GetSxsEntries(Application);

            VerboseWriteLine("[-] sxs dependencies for executable : {0}", Application.Filepath);
            foreach (var entry in SxsDependencies)
            {
                if (entry.Path.Contains("???"))
                {
                    Console.WriteLine("  [x] {0:s} : {1:s}", entry.Name, entry.Path);
                }
                else
                {
                    Console.WriteLine("  [+] {0:s} : {1:s}", entry.Name, Path.GetFullPath(entry.Path));
                }
            }
        }
Beispiel #4
0
        public static SxsEntries ExtractDependenciesFromSxsManifest(System.IO.Stream ManifestStream, string Folder, string ExecutableName = "", bool Wow64Pe = false)
        {
            SxsEntries AdditionnalDependencies = new SxsEntries();

            XDocument  XmlManifest = ParseSxsManifest(ManifestStream);
            XNamespace Namespace   = XmlManifest.Root.GetDefaultNamespace();

            // Find any declared dll
            //< assembly xmlns = 'urn:schemas-microsoft-com:asm.v1' manifestVersion = '1.0' >
            //    < assemblyIdentity name = 'additional_dll' version = 'XXX.YY.ZZ' type = 'win32' />
            //    < file name = 'additional_dll.dll' />
            //</ assembly >
            foreach (XElement SxsAssembly in XmlManifest.Descendants(Namespace + "assembly"))
            {
                AdditionnalDependencies.AddRange(SxsEntries.FromSxsAssembly(SxsAssembly, Namespace, Folder));
            }



            // Find any dependencies :
            // <dependency>
            //     <dependentAssembly>
            //         <assemblyIdentity
            //             type="win32"
            //             name="Microsoft.Windows.Common-Controls"
            //             version="6.0.0.0"
            //             processorArchitecture="amd64"
            //             publicKeyToken="6595b64144ccf1df"
            //             language="*"
            //         />
            //     </dependentAssembly>
            // </dependency>
            foreach (XElement SxsAssembly in XmlManifest.Descendants(Namespace + "dependency")
                     .Elements(Namespace + "dependentAssembly")
                     .Elements(Namespace + "assemblyIdentity")
                     )
            {
                // find target PE
                AdditionnalDependencies.AddRange(ExtractDependenciesFromSxsElement(SxsAssembly, Folder, ExecutableName, Wow64Pe));
            }

            return(AdditionnalDependencies);
        }
Beispiel #5
0
        public static SxsEntries GetSxsEntries(PE Pe)
        {
            SxsEntries Entries = new SxsEntries();

            string RootPeFolder   = Path.GetDirectoryName(Pe.Filepath);
            string RootPeFilename = Path.GetFileName(Pe.Filepath);

            // Look for overriding manifest file (named "{$name}.manifest)
            string OverridingManifest = String.Format("{0:s}.manifest", Pe.Filepath);

            if (File.Exists(OverridingManifest))
            {
                return(ExtractDependenciesFromSxsManifestFile(
                           OverridingManifest,
                           RootPeFolder,
                           RootPeFilename,
                           Pe.IsWow64Dll()
                           ));
            }

            // Retrieve embedded manifest
            string PeManifest = Pe.GetManifest();

            if (PeManifest.Length == 0)
            {
                return(Entries);
            }


            byte[]           RawManifest    = System.Text.Encoding.UTF8.GetBytes(PeManifest);
            System.IO.Stream ManifestStream = new System.IO.MemoryStream(RawManifest);

            Entries = ExtractDependenciesFromSxsManifest(
                ManifestStream,
                RootPeFolder,
                RootPeFilename,
                Pe.IsWow64Dll()
                );
            return(Entries);
        }
Beispiel #6
0
        public static SxsEntries ExtractDependenciesFromSxsElement(XElement SxsAssembly, string Folder, string ExecutableName = "", bool Wow64Pe = false)
        {
            // Private assembly search sequence : https://msdn.microsoft.com/en-us/library/windows/desktop/aa374224(v=vs.85).aspx
            //
            // * In the application's folder. Typically, this is the folder containing the application's executable file.
            // * In a subfolder in the application's folder. The subfolder must have the same name as the assembly.
            // * In a language-specific subfolder in the application's folder.
            //      -> The name of the subfolder is a string of DHTML language codes indicating a language-culture or language.
            // * In a subfolder of a language-specific subfolder in the application's folder.
            //      -> The name of the higher subfolder is a string of DHTML language codes indicating a language-culture or language. The deeper subfolder has the same name as the assembly.
            //
            //
            // 0.   Side-by-side searches the WinSxS folder.
            // 1.   \\<appdir>\<assemblyname>.DLL
            // 2.   \\<appdir>\<assemblyname>.manifest
            // 3.   \\<appdir>\<assemblyname>\<assemblyname>.DLL
            // 4.   \\<appdir>\<assemblyname>\<assemblyname>.manifest

            string TargetSxsManifestPath;
            string SxsManifestName = SxsAssembly.Attribute("name").Value.ToString();
            string SxsManifestDir  = Path.Combine(Folder, SxsManifestName);


            // 0. find publisher manifest in %WINDIR%/WinSxs/Manifest
            if (SxsAssembly.Attribute("publicKeyToken") != null)
            {
                string WinSxsDir = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.Windows),
                    "WinSxs"
                    );

                string WinSxsManifestDir   = Path.Combine(WinSxsDir, "Manifests");
                var    RegisteredManifests = Directory.EnumerateFiles(
                    WinSxsManifestDir,
                    "*.manifest"
                    );

                string PublicKeyToken = SxsAssembly.Attribute("publicKeyToken").Value;
                string Name           = SxsAssembly.Attribute("name").Value.ToLower();
                string ProcessArch    = SxsAssembly.Attribute("processorArchitecture") != null?SxsAssembly.Attribute("processorArchitecture").Value : "*";

                string Version = SxsAssembly.Attribute("version").Value;
                string Langage = SxsAssembly.Attribute("langage") != null?SxsAssembly.Attribute("langage").Value : "none";   // TODO : support localized sxs redirection


                switch (ProcessArch.ToLower())
                {
                case "$(build.arch)":
                case "*":
                    ProcessArch = (Wow64Pe) ? "x86" : "amd64";
                    break;

                case "amd64":
                case "x86":
                case "wow64":
                case "msil":
                    break;     // nothing to do

                default:
                    ProcessArch = ".*";
                    break;
                }

                Regex  MajorVersionRegex = new Regex(@"([0-9]+)\.(.*)", RegexOptions.IgnoreCase);
                Match  MajorVersionMatch = MajorVersionRegex.Match(Version);
                string MajorVersion      = (MajorVersionMatch.Success) ? MajorVersionMatch.Groups[1].Value.ToString() : ".*";

                // Manifest filename : {ProcArch}_{Name}_{PublicKeyToken}_{FuzzyVersion}_{Langage}_{some_hash}.manifest
                Regex ManifestFileNameRegex = new Regex(
                    String.Format(@"({0:s}_{1:s}_{2:s}_({3:s}\.[\.0-9]*)_none_([a-fA-F0-9]+))\.manifest",
                                  ProcessArch,
                                  Name,
                                  PublicKeyToken,
                                  MajorVersion
                                  //Langage,
                                  // some hash
                                  ),
                    RegexOptions.IgnoreCase
                    );

                foreach (var FileName in RegisteredManifests)
                {
                    Match MatchingSxsFile = ManifestFileNameRegex.Match(FileName);
                    if (MatchingSxsFile.Success)
                    {
                        TargetSxsManifestPath = Path.Combine(WinSxsManifestDir, FileName);
                        SxsManifestDir        = Path.Combine(WinSxsDir, MatchingSxsFile.Groups[1].Value);

                        // "{name}.local" local sxs directory hijack ( really used for UAC bypasses )
                        if (ExecutableName != "")
                        {
                            string LocalSxsDir         = Path.Combine(Folder, String.Format("{0:s}.local", ExecutableName));
                            string MatchingLocalSxsDir = Path.Combine(LocalSxsDir, MatchingSxsFile.Groups[1].Value);

                            if (Directory.Exists(LocalSxsDir) && Directory.Exists(MatchingLocalSxsDir))
                            {
                                SxsManifestDir = MatchingLocalSxsDir;
                            }
                        }

                        return(ExtractDependenciesFromSxsManifestFile(TargetSxsManifestPath, SxsManifestDir, ExecutableName, Wow64Pe));
                    }
                }
            }

            // 1. \\<appdir>\<assemblyname>.DLL
            // find dll with same assembly name in same directory
            SxsEntries EntriesFromMatchingDll = SxsFindTargetDll(SxsManifestName, Folder);

            if (EntriesFromMatchingDll.Count > 0)
            {
                return(EntriesFromMatchingDll);
            }


            // 2. \\<appdir>\<assemblyname>.manifest
            // find manifest with same assembly name in same directory
            TargetSxsManifestPath = Path.Combine(Folder, String.Format("{0:s}.manifest", SxsManifestName));
            if (File.Exists(TargetSxsManifestPath))
            {
                return(ExtractDependenciesFromSxsManifestFile(TargetSxsManifestPath, Folder, ExecutableName, Wow64Pe));
            }


            // 3. \\<appdir>\<assemblyname>\<assemblyname>.DLL
            // find matching dll in sub directory
            SxsEntries EntriesFromMatchingDllSub = SxsFindTargetDll(SxsManifestName, SxsManifestDir);

            if (EntriesFromMatchingDllSub.Count > 0)
            {
                return(EntriesFromMatchingDllSub);
            }

            // 4. \<appdir>\<assemblyname>\<assemblyname>.manifest
            // find manifest in sub directory
            TargetSxsManifestPath = Path.Combine(SxsManifestDir, String.Format("{0:s}.manifest", SxsManifestName));
            if (Directory.Exists(SxsManifestDir) && File.Exists(TargetSxsManifestPath))
            {
                return(ExtractDependenciesFromSxsManifestFile(TargetSxsManifestPath, SxsManifestDir, ExecutableName, Wow64Pe));
            }

            // TODO : do the same thing for localization
            //
            // 0. Side-by-side searches the WinSxS folder.
            // 1. \\<appdir>\<language-culture>\<assemblyname>.DLL
            // 2. \\<appdir>\<language-culture>\<assemblyname>.manifest
            // 3. \\<appdir>\<language-culture>\<assemblyname>\<assemblyname>.DLL
            // 4. \\<appdir>\<language-culture>\<assemblyname>\<assemblyname>.manifest

            // TODO : also take into account Multilanguage User Interface (MUI) when
            // scanning manifests and WinSxs dll. God this is horrendously complicated.

            // Could not find the dependency
            {
                SxsEntries EntriesFromElement = new SxsEntries();
                EntriesFromElement.Add(new SxsEntry(SxsManifestName, "file ???"));
                return(EntriesFromElement);
            }
        }