static string FindPeFromPath(string ModuleName, List <string> CandidateFolders, string ProcessorArch) { string PeFilePath = null; // Filter out "problematic" search paths before it triggers an exception from Path.Combine // see https://github.com/lucasg/Dependencies/issues/49 var CuratedCandidateFolders = CandidateFolders.Where( path => !IsFilepathInvalid(path) ); foreach (String CandidatePath in CuratedCandidateFolders) { PeFilePath = Path.Combine(CandidatePath, ModuleName); PE TestPe = BinaryCache.LoadPe(PeFilePath); if (TestPe != null && TestPe.LoadSuccessful) { Debug.WriteLine("Attempt to load {0:s} {1:s} {2:s}", PeFilePath, TestPe.GetProcessor(), ProcessorArch); if (TestPe.GetProcessor() == ProcessorArch) { return(PeFilePath); } } } return(null); }
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.GetProcessor() )); } // 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.GetProcessor() ); return(Entries); }
// default search order : // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx // // if (SafeDllSearchMode) { // -1. Sxs manifests // 0. KnownDlls list // 1. Loaded PE folder // 2. C:\Windows\(System32 | SysWow64 ) // 3. 16-bit system directory <-- ignored // 4. C:\Windows // 5. %pwd% // 6. AppDatas // } public static Tuple <ModuleSearchStrategy, string> FindPeFromDefault(PE RootPe, string ModuleName, SxsEntries SxsCache, List <string> CustomSearchFolders, string WorkingDirectory) { bool Wow64Dll = RootPe.IsWow64Dll(); string ProcessorArch = RootPe.GetProcessor(); string RootPeFolder = Path.GetDirectoryName(RootPe.Filepath); string FoundPePath = null; Environment.SpecialFolder WindowsSystemFolder = (Wow64Dll) ? Environment.SpecialFolder.SystemX86 : Environment.SpecialFolder.System; String WindowsSystemFolderPath = (RootPe.IsArm32Dll()) ? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "SysArm32") : Environment.GetFolderPath(WindowsSystemFolder); // -1. Look in Sxs manifest (copious reversing needed) // TODO : find dll search order if (SxsCache.Count != 0) { SxsEntry Entry = SxsCache.Find(SxsItem => string.Equals(SxsItem.Name, ModuleName, StringComparison.OrdinalIgnoreCase) ); if (Entry != null) { return(new Tuple <ModuleSearchStrategy, string>(ModuleSearchStrategy.SxS, Entry.Path)); } } // 0. Look in well-known dlls list // HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\KnownDLLs // https://blogs.msdn.microsoft.com/larryosterman/2004/07/19/what-are-known-dlls-anyway/ String KnownDll = Phlib.GetKnownDlls(Wow64Dll).Find(x => string.Equals(x, ModuleName, StringComparison.OrdinalIgnoreCase)); if (KnownDll != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.WellKnownDlls, Path.Combine(WindowsSystemFolderPath, KnownDll) )); } // 1. Look in application folder FoundPePath = FindPeFromPath(ModuleName, new List <string>(new string[] { RootPeFolder }), ProcessorArch); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.ApplicationDirectory, FoundPePath )); } // {2-3-4}. Look in system folders List <String> SystemFolders = new List <string>(new string[] { WindowsSystemFolderPath, Environment.GetFolderPath(Environment.SpecialFolder.Windows) } ); FoundPePath = FindPeFromPath(ModuleName, SystemFolders, ProcessorArch); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.WindowsFolder, FoundPePath )); } // 5. Look in current directory // Ignored for the time being since we can't know from // where the exe is run // TODO : Add a user supplied path emulating %cwd% FoundPePath = FindPeFromPath(ModuleName, new List <string>(new string[] { WorkingDirectory }), ProcessorArch); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.WorkingDirectory, FoundPePath )); } // 6. Look in local app data (check for python for exemple) // 7. Find in PATH string PATH = Environment.GetEnvironmentVariable("PATH"); List <String> PATHFolders = new List <string>(PATH.Split(';')); // Filter out empty paths, since it resolve to the current working directory // fix https://github.com/lucasg/Dependencies/issues/51 PATHFolders = PATHFolders.Where(path => path.Length != 0).ToList(); FoundPePath = FindPeFromPath(ModuleName, PATHFolders, ProcessorArch); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.Environment, FoundPePath )); } // 8. Check if it's an absolute import if (ModuleName != "" && (Path.GetFullPath(ModuleName) == ModuleName) && File.Exists(ModuleName)) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.Fullpath, ModuleName )); } // 0xff. Allow the user to supply custom search folders, to take into account // specific cases. FoundPePath = FindPeFromPath(ModuleName, CustomSearchFolders, ProcessorArch); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.UserDefined, FoundPePath )); } return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.NOT_FOUND, null )); }