Exemple #1
0
 public Tuple <ModuleSearchStrategy, PE> ResolveModule(string ModuleName)
 {
     return(BinaryCache.ResolveModule(
                RootPe,
                ModuleName          /*DllImport.Name*/
                ));
 }
Exemple #2
0
        public void LoadPe()
        {
            Action action = () =>
            {
                if (Filepath != null)
                {
                    PE Module = BinaryCache.LoadPe(Filepath);
                    Imports = Module.GetImports().Select(i => ImportDll.From(i)).ToList();

                    try
                    {
                        var PeAssembly = AssemblyDefinition.ReadAssembly(Filepath);

                        ModuleReferences   = PeAssembly.Modules.SelectMany(m => m.ModuleReferences).Where(mr => mr.Name.Length > 0).Select(m => ImportDll.From(m)).ToList();
                        AssemblyReferences = PeAssembly.Modules.SelectMany(m => m.AssemblyReferences).ToList();
                    } catch (BadImageFormatException)
                    {
                    }
                }
                else
                {
                    //Module = null;
                }
            };

            SafeExecutor(action);
        }
Exemple #3
0
        /// <summary>
        /// Background processing of a single PE file.
        /// It can be lengthy since there are disk access (and misses).
        /// </summary>
        /// <param name="NewTreeContexts"> This variable is passed as reference to be updated since this function is run in a separate thread. </param>
        /// <param name="newPe"> Current PE file analyzed </param>
        private void ProcessPe(List <ImportContext> NewTreeContexts, PE newPe)
        {
            List <PeImportDll> PeImports = newPe.GetImports();

            foreach (PeImportDll DllImport in PeImports)
            {
                ImportContext ImportModule = new ImportContext();
                ImportModule.PeFilePath        = null;
                ImportModule.PeProperties      = null;
                ImportModule.ModuleName        = DllImport.Name;
                ImportModule.ApiSetModuleName  = null;
                ImportModule.IsDelayLoadImport = (DllImport.Flags & 0x01) == 0x01; // TODO : Use proper macros


                // Find Dll in "paths"
                Tuple <ModuleSearchStrategy, PE> ResolvedModule = BinaryCache.ResolveModule(this.Pe, DllImport.Name, this.SxsEntriesCache);
                ImportModule.ModuleLocation = ResolvedModule.Item1;
                if (ImportModule.ModuleLocation != ModuleSearchStrategy.NOT_FOUND)
                {
                    ImportModule.PeProperties = ResolvedModule.Item2;
                    ImportModule.PeFilePath   = ResolvedModule.Item2.Filepath;
                }


                // special case for apiset schema
                ImportModule.IsApiSet = (ImportModule.ModuleLocation == ModuleSearchStrategy.ApiSetSchema);
                if (ImportModule.IsApiSet)
                {
                    ImportModule.ApiSetModuleName = BinaryCache.LookupApiSetLibrary(DllImport.Name);
                }

                NewTreeContexts.Add(ImportModule);
            }
        }
Exemple #4
0
        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);
        }
        private ImportContext ResolveImport(PeImportDll DllImport)
        {
            ImportContext ImportModule = new ImportContext();

            ImportModule.PeFilePath       = null;
            ImportModule.PeProperties     = null;
            ImportModule.ModuleName       = DllImport.Name;
            ImportModule.ApiSetModuleName = null;
            ImportModule.Flags            = 0;
            if (DllImport.IsDelayLoad())
            {
                ImportModule.Flags |= ModuleFlag.DelayLoad;
            }

            Tuple <ModuleSearchStrategy, PE> ResolvedModule = BinaryCache.ResolveModule(
                this.Pe,
                DllImport.Name,
                this.SxsEntriesCache,
                this.CustomSearchFolders,
                this.WorkingDirectory
                );

            ImportModule.ModuleLocation = ResolvedModule.Item1;
            if (ImportModule.ModuleLocation != ModuleSearchStrategy.NOT_FOUND)
            {
                ImportModule.PeProperties = ResolvedModule.Item2;

                if (ResolvedModule.Item2 != null)
                {
                    ImportModule.PeFilePath = ResolvedModule.Item2.Filepath;
                    foreach (var Import in BinaryCache.LookupImports(DllImport, ImportModule.PeFilePath))
                    {
                        if (!Import.Item2)
                        {
                            ImportModule.Flags |= ModuleFlag.MissingImports;
                            break;
                        }
                    }
                }
            }
            else
            {
                ImportModule.Flags |= ModuleFlag.NotFound;
            }

            // special case for apiset schema
            ImportModule.IsApiSet = (ImportModule.ModuleLocation == ModuleSearchStrategy.ApiSetSchema);
            if (ImportModule.IsApiSet)
            {
                ImportModule.Flags           |= ModuleFlag.ApiSet;
                ImportModule.ApiSetModuleName = BinaryCache.LookupApiSetLibrary(DllImport.Name);

                if (DllImport.Name.StartsWith("ext-"))
                {
                    ImportModule.Flags |= ModuleFlag.ApiSetExt;
                }
            }

            return(ImportModule);
        }
        private void ConstructDependencyTree(ModuleTreeViewItem RootNode, string FilePath, int RecursionLevel = 0)
        {
            PE CurrentPE = BinaryCache.LoadPe(FilePath);

            if (null == CurrentPE)
            {
                return;
            }

            ConstructDependencyTree(RootNode, CurrentPE, RecursionLevel);
        }
        public void SetImports(string ModuleFilepath, List <PeExport> Exports, List <PeImportDll> ParentImports, PhSymbolProvider SymPrv, DependencyWindow Dependencies)
        {
            this.Items.Clear();

            foreach (PeImportDll DllImport in ParentImports)
            {
                foreach (var Import in BinaryCache.LookupImports(DllImport, Exports))
                {
                    this.Items.Add(new DisplayPeImport(Import.Item1, SymPrv, ModuleFilepath, Import.Item2));
                }
            }
        }
Exemple #8
0
 public void LoadPe()
 {
     if (Filepath != null)
     {
         PE Module = BinaryCache.LoadPe(Filepath);
         Imports = Module.GetImports();
     }
     else
     {
         //Module = null;
     }
 }
        /// <summary>
        /// Background processing of a single PE file.
        /// It can be lengthy since there are disk access (and misses).
        /// </summary>
        /// <param name="NewTreeContexts"> This variable is passed as reference to be updated since this function is run in a separate thread. </param>
        /// <param name="newPe"> Current PE file analyzed </param>
        private void ProcessPe(List <ImportContext> NewTreeContexts, PE newPe)
        {
            List <PeImportDll> PeImports = newPe.GetImports();

            foreach (PeImportDll DllImport in PeImports)
            {
                bool   FoundApiSet   = false;
                string ImportDllName = DllImport.Name;


                // Look for api set target
                if (ImportDllName.StartsWith("api-") || ImportDllName.StartsWith("ext-"))
                {
                    // Strip the .dll extension and the last number (which is probably a build counter)
                    string ImportDllNameWithoutExtension = Path.GetFileNameWithoutExtension(ImportDllName);
                    string ImportDllHashKey = ImportDllNameWithoutExtension.Substring(0, ImportDllNameWithoutExtension.LastIndexOf("-"));

                    if (this.ApiSetmapCache.ContainsKey(ImportDllHashKey))
                    {
                        ApiSetTarget Targets = this.ApiSetmapCache[ImportDllHashKey];
                        if (Targets.Count > 0)
                        {
                            FoundApiSet   = true;
                            ImportDllName = Targets[0];
                        }
                    }
                }



                ImportContext ImportModule = new ImportContext();
                ImportModule.PeFilePath        = null;
                ImportModule.PeProperties      = null;
                ImportModule.ModuleName        = DllImport.Name;
                ImportModule.IsApiSet          = FoundApiSet;
                ImportModule.ApiSetModuleName  = ImportDllName;
                ImportModule.IsDelayLoadImport = (DllImport.Flags & 0x01) == 0x01; // TODO : Use proper macros


                // Find Dll in "paths"
                Tuple <ModuleSearchStrategy, String> FoundPe = FindPe.FindPeFromDefault(this.Pe, ImportDllName, this.SxsEntriesCache);
                ImportModule.ModuleLocation = FoundPe.Item1;
                if (ImportModule.ModuleLocation != ModuleSearchStrategy.NOT_FOUND)
                {
                    ImportModule.PeFilePath   = FoundPe.Item2;
                    ImportModule.PeProperties = BinaryCache.LoadPe(ImportModule.PeFilePath);
                }

                NewTreeContexts.Add(ImportModule);
            }
        }
Exemple #10
0
        public PE LoadImport(string ModuleName, DisplayModuleInfo CurrentModule = null, bool DelayLoad = false)
        {
            if (CurrentModule == null)
            {
                CurrentModule = this._SelectedModule;
            }

            Tuple <ModuleSearchStrategy, PE> ResolvedModule = BinaryCache.ResolveModule(
                this.Pe,
                ModuleName,
                this.SxsEntriesCache,
                this.CustomSearchFolders,
                this.WorkingDirectory
                );
            string ModuleFilepath = (ResolvedModule.Item2 != null) ? ResolvedModule.Item2.Filepath : null;

            ModuleCacheKey ModuleKey = new ModuleCacheKey(ModuleName, ModuleFilepath);

            if ((ModuleFilepath != null) && !this.ProcessedModulesCache.ContainsKey(ModuleKey))
            {
                ModuleFlag DelayLoadFlag = (DelayLoad) ? ModuleFlag.DelayLoad : 0;

                if (ResolvedModule.Item1 == ModuleSearchStrategy.ApiSetSchema)
                {
                    var ApiSetContractModule = new DisplayModuleInfo(
                        BinaryCache.LookupApiSetLibrary(ModuleName),
                        ResolvedModule.Item2,
                        ResolvedModule.Item1,
                        DelayLoadFlag & ModuleFlag.ApiSet
                        );
                    var NewModule = new ApiSetModuleInfo(ModuleName, ref ApiSetContractModule);
                    this.ProcessedModulesCache[ModuleKey] = NewModule;
                }
                else
                {
                    var NewModule = new DisplayModuleInfo(
                        ModuleName,
                        ResolvedModule.Item2,
                        ResolvedModule.Item1,
                        DelayLoadFlag
                        );
                    this.ProcessedModulesCache[ModuleKey] = NewModule;
                }

                // add it to the module list
                this.ModulesList.AddModule(this.ProcessedModulesCache[ModuleKey]);
            }

            return(ResolvedModule.Item2);
        }
        public DependencyWindow(String FileName)
        {
            InitializeComponent();

            this.Filename = FileName;
            this.Pe       = BinaryCache.LoadPe(FileName);

            if (!this.Pe.LoadSuccessful)
            {
                MessageBox.Show(
                    String.Format("{0:s} is not a valid PE-COFF file", this.Filename),
                    "Invalid PE",
                    MessageBoxButton.OK
                    );
                return;
            }

            this.SymPrv                = new PhSymbolProvider();
            this.RootFolder            = Path.GetDirectoryName(FileName);
            this.SxsEntriesCache       = SxsManifest.GetSxsEntries(this.Pe);
            this.ProcessedModulesCache = new ModulesCache();
            this.ApiSetmapCache        = Phlib.GetApiSetSchema();
            this._SelectedModule       = null;
            this._DisplayWarning       = false;

            // TODO : Find a way to properly bind commands instead of using this hack
            this.ModulesList.DoFindModuleInTreeCommand   = DoFindModuleInTree;
            this.ModulesList.ConfigureSearchOrderCommand = ConfigureSearchOrderCommand;

            var RootFilename = Path.GetFileName(FileName);
            var RootModule   = new DisplayModuleInfo(RootFilename, this.Pe, ModuleSearchStrategy.ROOT);

            this.ProcessedModulesCache.Add(new ModuleCacheKey(RootFilename, FileName), RootModule);

            ModuleTreeViewItem    treeNode             = new ModuleTreeViewItem();
            DependencyNodeContext childTreeInfoContext = new DependencyNodeContext()
            {
                ModuleInfo = new WeakReference(RootModule),
                IsDummy    = false
            };

            treeNode.DataContext = childTreeInfoContext;
            treeNode.Header      = treeNode.GetTreeNodeHeaderName(Dependencies.Properties.Settings.Default.FullPath);
            treeNode.IsExpanded  = true;

            this.DllTreeView.Items.Add(treeNode);

            // Recursively construct tree of dll imports
            ConstructDependencyTree(treeNode, this.Pe);
        }
        public void SetImports(List <PeImportDll> Imports, PhSymbolProvider SymPrv, DependencyWindow Dependencies)
        {
            this.Items.Clear();

            foreach (PeImportDll DllImport in Imports)
            {
                PE     ModuleImport   = Dependencies.LoadImport(DllImport.Name, null, DllImport.IsDelayLoad());
                string ModuleFilepath = (ModuleImport != null) ? ModuleImport.Filepath : null;

                foreach (var Import in BinaryCache.LookupImports(DllImport, ModuleFilepath))
                {
                    this.Items.Add(new DisplayPeImport(Import.Item1, SymPrv, ModuleFilepath, Import.Item2));
                }
            }
        }
Exemple #13
0
        public PE LoadBinary(string path)
        {
            StatusBarMessage = String.Format("Loading module {0:s} ...", path);
            PE pe = BinaryCache.LoadPe(path);

            if (!pe.LoadSuccessful)
            {
                StatusBarMessage = String.Format("Loading module {0:s} failed.", path);
            }
            else
            {
                StatusBarMessage = String.Format("Loading PE file \"{0:s}\" successful.", pe.Filepath);
            }

            return(pe);
        }
Exemple #14
0
        static string FindPeFromPath(string ModuleName, List <string> CandidateFolders, bool Wow64Dll = false)
        {
            string PeFilePath = null;

            foreach (String CandidatePath in CandidateFolders)
            {
                PeFilePath = Path.Combine(CandidatePath, ModuleName);
                PE TestPe = BinaryCache.LoadPe(PeFilePath);

                if ((TestPe != null) && (TestPe.LoadSuccessful) && (TestPe.IsWow64Dll() == Wow64Dll))
                {
                    return(PeFilePath);
                }
            }

            return(null);
        }
Exemple #15
0
        public void LoadPe()
        {
            Action action = () =>
            {
                if (Filepath != null)
                {
                    PE Module = BinaryCache.LoadPe(Filepath);
                    Imports = Module.GetImports();
                }
                else
                {
                    //Module = null;
                }
            };

            SafeExecutor(action);
        }
Exemple #16
0
        public static void InitializeBinaryCache(bool UseCache)
        {
            if (UseCache)
            {
                string ApplicationLocalAppDataPath = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                    "Dependencies"
                    );
                Instance = new BinaryCacheImpl(ApplicationLocalAppDataPath, 200);
            }
            else
            {
                Instance = new BinaryNoCacheImpl();
            }

            Instance.Load();
        }
        private bool VerifyModuleImports()
        {
            // current module has issues
            if ((Flags & (ModuleFlag.NotFound | ModuleFlag.MissingImports | ModuleFlag.ChildrenError)) != 0)
            {
                return(true);
            }

            // no parent : it's probably the root item
            ModuleTreeViewItem ParentModule = this.ParentModule;

            if (ParentModule == null)
            {
                return(false);
            }

            // Check we have any imports issues
            foreach (PeImportDll DllImport in ParentModule.ModuleInfo.Imports)
            {
                if (DllImport.Name != ModuleInfo._Name)
                {
                    continue;
                }



                List <Tuple <PeImport, bool> > resolvedImports = BinaryCache.LookupImports(DllImport, ModuleInfo.Filepath);
                if (resolvedImports.Count == 0)
                {
                    return(true);
                }

                foreach (var Import in resolvedImports)
                {
                    if (!Import.Item2)
                    {
                        return(true);
                    }
                }
            }



            return(false);
        }
Exemple #18
0
        void App_Startup(object sender, StartupEventArgs e)
        {
            (Application.Current as App).PropertyChanged += App_PropertyChanged;

            Phlib.InitializePhLib();

            // Load singleton for binary caching
            BinaryCache.InitializeBinaryCache(Dependencies.BinaryCacheOption.GetGlobalBehaviour() == Dependencies.BinaryCacheOption.BinaryCacheOptionValue.Yes);


            // https://www.red-gate.com/simple-talk/blogs/wpf-menu-displays-to-the-left-of-the-window/
            SetDropDownMenuToBeRightAligned();

            mainWindow          = new MainWindow();
            mainWindow.IsMaster = true;

            switch (Phlib.GetClrPhArch())
            {
            case CLRPH_ARCH.x86:
                mainWindow.Title = "Dependencies (x86)";
                break;

            case CLRPH_ARCH.x64:
                mainWindow.Title = "Dependencies (x64)";
                break;

            case CLRPH_ARCH.WOW64:
                mainWindow.Title = "Dependencies (WoW64)";
                break;
            }

            mainWindow.Show();



            // Process command line args
            if (e.Args.Length > 0)
            {
                mainWindow.OpenNewDependencyWindow(e.Args[0]);
            }
        }
Exemple #19
0
        private void VerifyModuleImports()
        {
            // no parent : it's probably the root item
            ModuleTreeViewItem ParentModule = this.ParentModule;

            if (ParentModule == null)
            {
                ModuleInfo.HasErrors = false;
                return;
            }


            foreach (PeImportDll DllImport in ParentModule.ModuleInfo.Imports)
            {
                if (DllImport.Name != ModuleInfo._Name)
                {
                    continue;
                }



                List <Tuple <PeImport, bool> > resolvedImports = BinaryCache.LookupImports(DllImport, ModuleInfo.Filepath);
                if (resolvedImports.Count == 0)
                {
                    ModuleInfo.HasErrors = true;
                    return;
                }

                foreach (var Import in resolvedImports)
                {
                    if (!Import.Item2)
                    {
                        ModuleInfo.HasErrors = true;
                        return;
                    }
                }
            }

            ModuleInfo.HasErrors = false;
        }
Exemple #20
0
        public PeDependencyItem(PeDependencies _Root, string _ModuleName, string ModuleFilepath, ModuleSearchStrategy Strategy, int Level)
        {
            Root       = _Root;
            ModuleName = _ModuleName;

            if (ModuleFilepath != null)
            {
                PE Module = BinaryCache.LoadPe(ModuleFilepath);
                Imports = Module.GetImports();
            }
            else
            {
                //Module = null;
                Imports = new List <PeImportDll>();
            }

            Filepath       = ModuleFilepath;
            SearchStrategy = Strategy;
            RecursionLevel = Level;

            DependenciesResolved = false;
        }
Exemple #21
0
        public PE LoadBinary(string path)
        {
            StatusBarMessage = String.Format("Loading module {0:s} ...", path);

            if (!NativeFile.Exists(path))
            {
                StatusBarMessage = String.Format("Loading PE file \"{0:s}\" failed : file not present on disk.", path);
                return(null);
            }

            PE pe = BinaryCache.LoadPe(path);

            if (pe == null || !pe.LoadSuccessful)
            {
                StatusBarMessage = String.Format("Loading module {0:s} failed.", path);
            }
            else
            {
                StatusBarMessage = String.Format("Loading PE file \"{0:s}\" successful.", pe.Filepath);
            }

            return(pe);
        }
Exemple #22
0
        static string FindPeFromPath(string ModuleName, List <string> CandidateFolders, bool Wow64Dll = false)
        {
            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) && (TestPe.IsWow64Dll() == Wow64Dll))
                {
                    return(PeFilePath);
                }
            }

            return(null);
        }
        private void ProcessAppInitDlls(Dictionary <string, ImportContext> NewTreeContexts, PE AnalyzedPe, ImportContext ImportModule)
        {
            List <PeImportDll> PeImports = AnalyzedPe.GetImports();

            // only user32 triggers appinit dlls
            string User32Filepath = Path.Combine(FindPe.GetSystemPath(this.Pe), "user32.dll");

            if (ImportModule.PeFilePath != User32Filepath)
            {
                return;
            }

            string AppInitRegistryKey =
                (this.Pe.IsArm32Dll()) ?
                "SOFTWARE\\WowAA32Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows" :
                (this.Pe.IsWow64Dll()) ?
                "SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows" :
                "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows";

            // Opening registry values
            RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);

            localKey = localKey.OpenSubKey(AppInitRegistryKey);
            int    LoadAppInitDlls = (int)localKey.GetValue("LoadAppInit_DLLs", 0);
            string AppInitDlls     = (string)localKey.GetValue("AppInit_DLLs", "");

            if (LoadAppInitDlls == 0 || String.IsNullOrEmpty(AppInitDlls))
            {
                return;
            }

            // Extremely crude parser. TODO : Add support for quotes wrapped paths with spaces
            foreach (var AppInitDll in AppInitDlls.Split(' '))
            {
                Debug.WriteLine("AppInit loading " + AppInitDll);

                // Do not process twice the same imported module
                if (null != PeImports.Find(module => module.Name == AppInitDll))
                {
                    continue;
                }

                if (NewTreeContexts.ContainsKey(AppInitDll))
                {
                    continue;
                }

                ImportContext AppInitImportModule = new ImportContext();
                AppInitImportModule.PeFilePath       = null;
                AppInitImportModule.PeProperties     = null;
                AppInitImportModule.ModuleName       = AppInitDll;
                AppInitImportModule.ApiSetModuleName = null;
                AppInitImportModule.Flags            = 0;
                AppInitImportModule.ModuleLocation   = ModuleSearchStrategy.AppInitDLL;



                Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule(
                    this.Pe,
                    AppInitDll,
                    this.SxsEntriesCache,
                    this.CustomSearchFolders,
                    this.WorkingDirectory
                    );
                if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND)
                {
                    AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2;
                    AppInitImportModule.PeFilePath   = ResolvedAppInitModule.Item2.Filepath;
                }
                else
                {
                    AppInitImportModule.Flags |= ModuleFlag.NotFound;
                }

                NewTreeContexts.Add(AppInitDll, AppInitImportModule);
            }
        }
Exemple #24
0
        /// <summary>
        /// Background processing of a single PE file.
        /// It can be lengthy since there are disk access (and misses).
        /// </summary>
        /// <param name="NewTreeContexts"> This variable is passed as reference to be updated since this function is run in a separate thread. </param>
        /// <param name="newPe"> Current PE file analyzed </param>
        private void ProcessPe(Dictionary <string, ImportContext> NewTreeContexts, PE newPe)
        {
            List <PeImportDll> PeImports = newPe.GetImports();

            Environment.SpecialFolder WindowsSystemFolder = (this.Pe.IsWow64Dll()) ?
                                                            Environment.SpecialFolder.SystemX86 :
                                                            Environment.SpecialFolder.System;
            string User32Filepath  = Path.Combine(Environment.GetFolderPath(WindowsSystemFolder), "user32.dll");
            string MsCoreeFilepath = Path.Combine(Environment.GetFolderPath(WindowsSystemFolder), "mscoree.dll");

            foreach (PeImportDll DllImport in PeImports)
            {
                ImportContext ImportModule = new ImportContext();
                ImportModule.PeFilePath       = null;
                ImportModule.PeProperties     = null;
                ImportModule.ModuleName       = DllImport.Name;
                ImportModule.ApiSetModuleName = null;
                ImportModule.Flags            = 0;
                if (DllImport.IsDelayLoad())
                {
                    ImportModule.Flags |= ModuleFlag.DelayLoad;
                }

                if (NewTreeContexts.ContainsKey(DllImport.Name))
                {
                    continue;
                }

                // Find Dll in "paths"
                Tuple <ModuleSearchStrategy, PE> ResolvedModule = BinaryCache.ResolveModule(this.Pe, DllImport.Name, this.SxsEntriesCache);
                ImportModule.ModuleLocation = ResolvedModule.Item1;
                if (ImportModule.ModuleLocation != ModuleSearchStrategy.NOT_FOUND)
                {
                    ImportModule.PeProperties = ResolvedModule.Item2;
                    ImportModule.PeFilePath   = ResolvedModule.Item2.Filepath;
                }

                // special case for apiset schema
                ImportModule.IsApiSet = (ImportModule.ModuleLocation == ModuleSearchStrategy.ApiSetSchema);
                if (ImportModule.IsApiSet)
                {
                    ImportModule.ApiSetModuleName = BinaryCache.LookupApiSetLibrary(DllImport.Name);
                }

                // add warning for appv isv applications
                if (String.Compare(DllImport.Name, "AppvIsvSubsystems32.dll", StringComparison.OrdinalIgnoreCase) == 0 ||
                    String.Compare(DllImport.Name, "AppvIsvSubsystems64.dll", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (!this._DisplayWarning)
                    {
                        MessageBoxResult result = MessageBox.Show(
                            "This binary use the App-V containerization technology which fiddle with search directories and PATH env in ways Dependencies can't handle.\n\nFollowing results are probably not quite exact.",
                            "App-V ISV disclaimer"
                            );

                        this._DisplayWarning = true; // prevent the same warning window to popup several times
                    }
                }

                NewTreeContexts.Add(DllImport.Name, ImportModule);


                // AppInitDlls are triggered by user32.dll, so if the binary does not import user32.dll they are not loaded.
                if (ImportModule.PeFilePath == User32Filepath)
                {
                    string AppInitRegistryKey = (this.Pe.IsWow64Dll()) ?
                                                "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows" :
                                                "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows";

                    int    LoadAppInitDlls = (int)Registry.GetValue(AppInitRegistryKey, "LoadAppInit_DLLs", 0);
                    string AppInitDlls     = (string)Registry.GetValue(AppInitRegistryKey, "AppInit_DLLs", "");

                    if ((LoadAppInitDlls != 0) && (AppInitDlls != ""))
                    {
                        // Extremely crude parser. TODO : Add support for quotes wrapped paths with spaces
                        foreach (var AppInitDll in AppInitDlls.Split(' '))
                        {
                            Debug.WriteLine("AppInit loading " + AppInitDll);

                            // Do not process twice the same imported module
                            if (null != PeImports.Find(module => module.Name == AppInitDll))
                            {
                                continue;
                            }

                            if (NewTreeContexts.ContainsKey(AppInitDll))
                            {
                                continue;
                            }

                            ImportContext AppInitImportModule = new ImportContext();
                            AppInitImportModule.PeFilePath       = null;
                            AppInitImportModule.PeProperties     = null;
                            AppInitImportModule.ModuleName       = AppInitDll;
                            AppInitImportModule.ApiSetModuleName = null;
                            AppInitImportModule.Flags            = 0;
                            AppInitImportModule.ModuleLocation   = ModuleSearchStrategy.AppInitDLL;



                            Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule(this.Pe, AppInitDll, this.SxsEntriesCache);
                            if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND)
                            {
                                AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2;
                                AppInitImportModule.PeFilePath   = ResolvedAppInitModule.Item2.Filepath;
                            }

                            NewTreeContexts.Add(AppInitDll, AppInitImportModule);
                        }
                    }
                }


                // if mscoree.dll is imported, it means the module is a C# assembly, and we can use Mono.Cecil to enumerate its references
                if (ImportModule.PeFilePath == MsCoreeFilepath)
                {
                    var resolver = new DefaultAssemblyResolver();
                    resolver.AddSearchDirectory(RootFolder);

                    AssemblyDefinition PeAssembly = AssemblyDefinition.ReadAssembly(newPe.Filepath);

                    foreach (var module in PeAssembly.Modules)
                    {
                        // Process CLR referenced assemblies
                        foreach (var assembly in module.AssemblyReferences)
                        {
                            AssemblyDefinition definition = resolver.Resolve(assembly);

                            foreach (var AssemblyModule in definition.Modules)
                            {
                                Debug.WriteLine("Referenced Assembling loading " + AssemblyModule.Name + " : " + AssemblyModule.FileName);

                                // Do not process twice the same imported module
                                if (null != PeImports.Find(mod => mod.Name == Path.GetFileName(AssemblyModule.FileName)))
                                {
                                    continue;
                                }

                                ImportContext AppInitImportModule = new ImportContext();
                                AppInitImportModule.PeFilePath       = null;
                                AppInitImportModule.PeProperties     = null;
                                AppInitImportModule.ModuleName       = Path.GetFileName(AssemblyModule.FileName);
                                AppInitImportModule.ApiSetModuleName = null;
                                AppInitImportModule.Flags            = ModuleFlag.ClrReference;
                                AppInitImportModule.ModuleLocation   = ModuleSearchStrategy.ClrAssembly;

                                Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule(this.Pe, AssemblyModule.FileName, this.SxsEntriesCache);
                                if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND)
                                {
                                    AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2;
                                    AppInitImportModule.PeFilePath   = ResolvedAppInitModule.Item2.Filepath;
                                }

                                if (!NewTreeContexts.ContainsKey(AppInitImportModule.ModuleName))
                                {
                                    NewTreeContexts.Add(AppInitImportModule.ModuleName, AppInitImportModule);
                                }
                            }
                        }

                        // Process unmanaged dlls for native calls
                        foreach (var UnmanagedModule in module.ModuleReferences)
                        {
                            // some clr dll have a reference to an "empty" dll
                            if (UnmanagedModule.Name.Length == 0)
                            {
                                continue;
                            }

                            Debug.WriteLine("Referenced module loading " + UnmanagedModule.Name);

                            // Do not process twice the same imported module
                            if (null != PeImports.Find(m => m.Name == UnmanagedModule.Name))
                            {
                                continue;
                            }



                            ImportContext AppInitImportModule = new ImportContext();
                            AppInitImportModule.PeFilePath       = null;
                            AppInitImportModule.PeProperties     = null;
                            AppInitImportModule.ModuleName       = UnmanagedModule.Name;
                            AppInitImportModule.ApiSetModuleName = null;
                            AppInitImportModule.Flags            = ModuleFlag.ClrReference;
                            AppInitImportModule.ModuleLocation   = ModuleSearchStrategy.ClrAssembly;

                            Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule(this.Pe, UnmanagedModule.Name, this.SxsEntriesCache);
                            if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND)
                            {
                                AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2;
                                AppInitImportModule.PeFilePath   = ResolvedAppInitModule.Item2.Filepath;
                            }

                            if (!NewTreeContexts.ContainsKey(AppInitImportModule.ModuleName))
                            {
                                NewTreeContexts.Add(AppInitImportModule.ModuleName, AppInitImportModule);
                            }
                        }
                    }
                }
            }
        }
        private void ProcessClrImports(Dictionary <string, ImportContext> NewTreeContexts, PE AnalyzedPe, ImportContext ImportModule)
        {
            List <PeImportDll> PeImports = AnalyzedPe.GetImports();

            // only mscorre triggers clr parsing
            string User32Filepath = Path.Combine(FindPe.GetSystemPath(this.Pe), "mscoree.dll");

            if (ImportModule.PeFilePath != User32Filepath)
            {
                return;
            }

            var resolver = new DefaultAssemblyResolver();

            resolver.AddSearchDirectory(RootFolder);

            // Parse it via cecil
            AssemblyDefinition PeAssembly = null;

            try
            {
                PeAssembly = AssemblyDefinition.ReadAssembly(AnalyzedPe.Filepath);
            }
            catch (BadImageFormatException)
            {
                MessageBoxResult result = MessageBox.Show(
                    String.Format("Cecil could not correctly parse {0:s}, which can happens on .NET Core executables. CLR imports will be not shown", AnalyzedPe.Filepath),
                    "CLR parsing fail"
                    );

                return;
            }

            foreach (var module in PeAssembly.Modules)
            {
                // Process CLR referenced assemblies
                foreach (var assembly in module.AssemblyReferences)
                {
                    AssemblyDefinition definition;
                    try
                    {
                        definition = resolver.Resolve(assembly);
                    }
                    catch (AssemblyResolutionException)
                    {
                        ImportContext AppInitImportModule = new ImportContext();
                        AppInitImportModule.PeFilePath       = null;
                        AppInitImportModule.PeProperties     = null;
                        AppInitImportModule.ModuleName       = Path.GetFileName(assembly.Name);
                        AppInitImportModule.ApiSetModuleName = null;
                        AppInitImportModule.Flags            = ModuleFlag.ClrReference;
                        AppInitImportModule.ModuleLocation   = ModuleSearchStrategy.ClrAssembly;
                        AppInitImportModule.Flags           |= ModuleFlag.NotFound;

                        if (!NewTreeContexts.ContainsKey(AppInitImportModule.ModuleName))
                        {
                            NewTreeContexts.Add(AppInitImportModule.ModuleName, AppInitImportModule);
                        }

                        continue;
                    }

                    foreach (var AssemblyModule in definition.Modules)
                    {
                        Debug.WriteLine("Referenced Assembling loading " + AssemblyModule.Name + " : " + AssemblyModule.FileName);

                        // Do not process twice the same imported module
                        if (null != PeImports.Find(mod => mod.Name == Path.GetFileName(AssemblyModule.FileName)))
                        {
                            continue;
                        }

                        ImportContext AppInitImportModule = new ImportContext();
                        AppInitImportModule.PeFilePath       = null;
                        AppInitImportModule.PeProperties     = null;
                        AppInitImportModule.ModuleName       = Path.GetFileName(AssemblyModule.FileName);
                        AppInitImportModule.ApiSetModuleName = null;
                        AppInitImportModule.Flags            = ModuleFlag.ClrReference;
                        AppInitImportModule.ModuleLocation   = ModuleSearchStrategy.ClrAssembly;

                        Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule(
                            this.Pe,
                            AssemblyModule.FileName,
                            this.SxsEntriesCache,
                            this.CustomSearchFolders,
                            this.WorkingDirectory
                            );
                        if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND)
                        {
                            AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2;
                            AppInitImportModule.PeFilePath   = ResolvedAppInitModule.Item2.Filepath;
                        }
                        else
                        {
                            AppInitImportModule.Flags |= ModuleFlag.NotFound;
                        }

                        if (!NewTreeContexts.ContainsKey(AppInitImportModule.ModuleName))
                        {
                            NewTreeContexts.Add(AppInitImportModule.ModuleName, AppInitImportModule);
                        }
                    }
                }

                // Process unmanaged dlls for native calls
                foreach (var UnmanagedModule in module.ModuleReferences)
                {
                    // some clr dll have a reference to an "empty" dll
                    if (UnmanagedModule.Name.Length == 0)
                    {
                        continue;
                    }

                    Debug.WriteLine("Referenced module loading " + UnmanagedModule.Name);

                    // Do not process twice the same imported module
                    if (null != PeImports.Find(m => m.Name == UnmanagedModule.Name))
                    {
                        continue;
                    }



                    ImportContext AppInitImportModule = new ImportContext();
                    AppInitImportModule.PeFilePath       = null;
                    AppInitImportModule.PeProperties     = null;
                    AppInitImportModule.ModuleName       = UnmanagedModule.Name;
                    AppInitImportModule.ApiSetModuleName = null;
                    AppInitImportModule.Flags            = ModuleFlag.ClrReference;
                    AppInitImportModule.ModuleLocation   = ModuleSearchStrategy.ClrAssembly;

                    Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule(
                        this.Pe,
                        UnmanagedModule.Name,
                        this.SxsEntriesCache,
                        this.CustomSearchFolders,
                        this.WorkingDirectory
                        );
                    if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND)
                    {
                        AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2;
                        AppInitImportModule.PeFilePath   = ResolvedAppInitModule.Item2.Filepath;
                    }

                    if (!NewTreeContexts.ContainsKey(AppInitImportModule.ModuleName))
                    {
                        NewTreeContexts.Add(AppInitImportModule.ModuleName, AppInitImportModule);
                    }
                }
            }
        }
Exemple #26
0
        static void Main(string[] args)
        {
            // always the first call to make
            Phlib.InitializePhLib();

            int         recursion_depth = 0;
            bool        early_exit      = false;
            bool        show_help       = false;
            bool        export_as_json  = false;
            bool        use_bin_cache   = false;
            DumpCommand command         = null;

            OptionSet opts = new OptionSet()
            {
                { "h|help", "show this message and exit", v => show_help = v != null },
                { "json", "Export results in json format", v => export_as_json = v != null },
                { "cache", "load and use binary cache to prevent dll file locking", v => use_bin_cache = v != null },
                { "d|depth=", "limit recursion depth when analysing loaded modules or dependency chain. Default value is infinite", (int v) => recursion_depth = v },
                { "knowndll", "List all known dlls", v => { DumpKnownDlls(GetObjectPrinter(export_as_json));  early_exit = true; } },
                { "apisets", "List apisets redirections", v => { DumpApiSets(GetObjectPrinter(export_as_json));  early_exit = true; } },
                { "apisetsdll", "List apisets redirections from apisetschema <FILE>", v => command = DumpApiSets },
                { "manifest", "show manifest information embedded in <FILE>", v => command = DumpManifest },
                { "sxsentries", "dump all of <FILE>'s sxs dependencies", v => command = DumpSxsEntries },
                { "imports", "dump <FILE> imports", v => command = DumpImports },
                { "exports", "dump <FILE> exports", v => command = DumpExports },
                { "assemblyrefs", "dump <FILE> assemblyrefs", v => command = DumpAssemblyReferences },
                { "modulerefs", "dump <FILE> modulerefs", v => command = DumpModuleReferences },
                { "chain", "dump <FILE> whole dependency chain", v => command = DumpDependencyChain },
                { "modules", "dump <FILE> resolved modules", v => command = DumpModules },
            };

            List <string> eps = opts.Parse(args);

            if (early_exit)
            {
                return;
            }

            if ((show_help) || (args.Length == 0) || (command == null))
            {
                DumpUsage();
                return;
            }

            BinaryCache.InitializeBinaryCache(use_bin_cache);

            if (eps.Count == 0)
            {
                Console.Error.WriteLine("[x] Command {0:s} needs to have a PE <FILE> argument", command.Method.Name);
                Console.Error.WriteLine("");

                DumpUsage();
                return;
            }

            String FileName = eps[0];

            if (!NativeFile.Exists(FileName))
            {
                Console.Error.WriteLine("[x] Could not find file {0:s} on disk", FileName);
                return;
            }

            Debug.WriteLine("[-] Loading file {0:s} ", FileName);
            PE Pe = new PE(FileName);

            if (!Pe.Load())
            {
                Console.Error.WriteLine("[x] Could not load file {0:s} as a PE", FileName);
                return;
            }

            command(Pe, GetObjectPrinter(export_as_json), recursion_depth);
        }
        /// <summary>
        /// Background processing of a single PE file.
        /// It can be lengthy since there are disk access (and misses).
        /// </summary>
        /// <param name="NewTreeContexts"> This variable is passed as reference to be updated since this function is run in a separate thread. </param>
        /// <param name="newPe"> Current PE file analyzed </param>
        private void ProcessPe(List <ImportContext> NewTreeContexts, PE newPe)
        {
            List <PeImportDll> PeImports = newPe.GetImports();

            Environment.SpecialFolder WindowsSystemFolder = (this.Pe.IsWow64Dll()) ?
                                                            Environment.SpecialFolder.SystemX86 :
                                                            Environment.SpecialFolder.System;
            string User32Filepath = Path.Combine(Environment.GetFolderPath(WindowsSystemFolder), "user32.dll");

            foreach (PeImportDll DllImport in PeImports)
            {
                ImportContext ImportModule = new ImportContext();
                ImportModule.PeFilePath        = null;
                ImportModule.PeProperties      = null;
                ImportModule.ModuleName        = DllImport.Name;
                ImportModule.ApiSetModuleName  = null;
                ImportModule.IsDelayLoadImport = DllImport.IsDelayLoad();


                // Find Dll in "paths"
                Tuple <ModuleSearchStrategy, PE> ResolvedModule = BinaryCache.ResolveModule(this.Pe, DllImport.Name, this.SxsEntriesCache);
                ImportModule.ModuleLocation = ResolvedModule.Item1;
                if (ImportModule.ModuleLocation != ModuleSearchStrategy.NOT_FOUND)
                {
                    ImportModule.PeProperties = ResolvedModule.Item2;
                    ImportModule.PeFilePath   = ResolvedModule.Item2.Filepath;
                }

                // special case for apiset schema
                ImportModule.IsApiSet = (ImportModule.ModuleLocation == ModuleSearchStrategy.ApiSetSchema);
                if (ImportModule.IsApiSet)
                {
                    ImportModule.ApiSetModuleName = BinaryCache.LookupApiSetLibrary(DllImport.Name);
                }

                // add warning for appv isv applications
                if (String.Compare(DllImport.Name, "AppvIsvSubsystems32.dll", StringComparison.OrdinalIgnoreCase) == 0 ||
                    String.Compare(DllImport.Name, "AppvIsvSubsystems64.dll", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (!this._DisplayWarning)
                    {
                        MessageBoxResult result = MessageBox.Show(
                            "This binary use the App-V containerization technology which fiddle with search directories and PATH env in ways Dependencies can't handle.\n\nFollowing results are probably not quite exact.",
                            "App-V ISV disclaimer"
                            );

                        this._DisplayWarning = true; // prevent the same warning window to popup several times
                    }
                }

                NewTreeContexts.Add(ImportModule);


                // AppInitDlls are triggered by user32.dll, so if the binary does not import user32.dll they are not loaded.
                if (ImportModule.PeFilePath == User32Filepath)
                {
                    string AppInitRegistryKey = (this.Pe.IsWow64Dll()) ?
                                                "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows" :
                                                "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows";

                    int    LoadAppInitDlls = (int)Registry.GetValue(AppInitRegistryKey, "LoadAppInit_DLLs", 0);
                    string AppInitDlls     = (string)Registry.GetValue(AppInitRegistryKey, "AppInit_DLLs", "");

                    if ((LoadAppInitDlls != 0) && (AppInitDlls != ""))
                    {
                        // Extremely crude parser. TODO : Add support for quotes wrapped paths with spaces
                        foreach (var AppInitDll in AppInitDlls.Split(' '))
                        {
                            Debug.WriteLine("AppInit loading " + AppInitDll);

                            ImportContext AppInitImportModule = new ImportContext();
                            AppInitImportModule.PeFilePath        = null;
                            AppInitImportModule.PeProperties      = null;
                            AppInitImportModule.ModuleName        = AppInitDll;
                            AppInitImportModule.ApiSetModuleName  = null;
                            AppInitImportModule.IsDelayLoadImport = false;
                            AppInitImportModule.ModuleLocation    = ModuleSearchStrategy.AppInitDLL;

                            Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule(this.Pe, AppInitDll, this.SxsEntriesCache);
                            if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND)
                            {
                                AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2;
                                AppInitImportModule.PeFilePath   = ResolvedAppInitModule.Item2.Filepath;
                            }

                            NewTreeContexts.Add(AppInitImportModule);
                        }
                    }
                }
            }
        }
 private void ConstructDependencyTree(ModuleTreeViewItem RootNode, string FilePath, int RecursionLevel = 0)
 {
     ConstructDependencyTree(RootNode, BinaryCache.LoadPe(FilePath), RecursionLevel);
 }