how to get the loaded assemblies of a process programatically

Philip Stuyck 0 Reputation points
2024-06-03T07:53:23.16+00:00

Reference to this old question : https://stackoverflow.com/questions/36431220/getting-a-list-of-dlls-currently-loaded-in-a-process-c-sharp

I am writing a security application where we are monitoring our in house developed software (EPD) which is composed of many assemblies which are not all loaded, it just depends on what functionality is used by an arbitrary physician (user). The reason behind doing this is that our application is a client server application and we don't want a hacker to get access to the sql server database to obtain sensitive patient data.

For .NET8 the proposed solutions as per the reference work and i can get the list i am looking for. But we have a version currently installed that is based on .NetFramework 4.8. and then even though sysinternals gives all the assemblies that are loaded, I cannot seem to find any code examples where I can get this list programatically.

Would it be possible to starting from a process id, or the process object share the appropriate code where I can get this list of assemblies preferably with their paths.

So my problem is not related to the use of sysinternals itself, it works excellent, but i need to incorporate part of its functionality in my own application written in C# using netframework4.8 so since sysinternals is not a .net application and likely written in c++ or c, it will involve doing native calls to the OS. Is it possible to share this code with me ?

Sysinternals
Sysinternals
Advanced system utilities to manage, troubleshoot, and diagnose Windows and Linux systems and applications.
1,170 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Castorix31 85,956 Reputation points
    2024-06-05T00:35:38.2533333+00:00

    A way in .NET Framework 4.8 with System.Reflection.Metadata Nuget Package (must be compiled in x64 to read both 32 and 64-bit processes):

    (could be improved because EnumProcessModulesEx does not display a Shell Extension DLL that Process Explorer displays...) :

    //string sProcessName = "CSharp_Test5";
    string sProcessName = "Explorer";
    Process[] procs = Process.GetProcessesByName(sProcessName);
    if (procs.Count() > 0)
    {
        Console.WriteLine("Process : " + procs[0].ProcessName);
        int nPID = procs[0].Id;
        IntPtr hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, nPID);
        if (hProcess != IntPtr.Zero)
        {
            IntPtr[] modulesHandles = new IntPtr[1024];
            int nSize = 0;
            bool bRet = EnumProcessModulesEx(hProcess, modulesHandles, Marshal.SizeOf(typeof(IntPtr)) * modulesHandles.Length,
                out nSize, MODULEFILTERFLAGS.LIST_MODULES_ALL);
            int nErr = Marshal.GetLastWin32Error();
            if (bRet)
            {
                for (int i = 0; i < nSize / Marshal.SizeOf(typeof(IntPtr)); i++)
                {
                    StringBuilder sbModuleName = new StringBuilder(1024);
                    uint nLength = GetModuleFileNameEx(hProcess, modulesHandles[i], sbModuleName,(uint)sbModuleName.Capacity);
                    try
                    {
                        using (FileStream fs = new FileStream(sbModuleName.ToString(), FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        {
                            using (PEReader peReader = new PEReader(fs))
                            {
                                if (peReader.HasMetadata)
                                {
                                    MetadataReader mr = peReader.GetMetadataReader();
                                    if (mr.IsAssembly)
                                        Console.WriteLine("\tAssembly : " + sbModuleName.ToString());
                                }
                            }
                        }
                    }
                    catch (System.Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            }
            CloseHandle(hProcess);
        }
    }
    
    

    with :

            [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
    
            public const int PROCESS_VM_READ = (0x0010);
            public const int PROCESS_QUERY_INFORMATION = (0x0400);
            public const int PROCESS_QUERY_LIMITED_INFORMATION = (0x1000);       
    
            [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern bool QueryFullProcessImageName(IntPtr hProcess, int dwFlags, StringBuilder lpExeName, ref uint lpdwSize);
    
            [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern bool CloseHandle(IntPtr hObject);
    
            [DllImport("psapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool EnumProcessModulesEx([In] IntPtr hProcess,[Out] IntPtr[] lphModule, [In] int cb,
                [Out] out int lpcbNeeded,[In] MODULEFILTERFLAGS dwFilterFlag);
    
            [Flags]
            public enum MODULEFILTERFLAGS
            {
                LIST_MODULES_DEFAULT = 0x0,
                LIST_MODULES_32BIT = 0x01,
                LIST_MODULES_64BIT = 0x02,
                LIST_MODULES_ALL = 0x03,            
            }
    
            [DllImport("psapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern uint GetModuleFileNameEx([In] IntPtr hProcess, [In] IntPtr hModule,
               [Out][MarshalAs(UnmanagedType.LPTStr)] System.Text.StringBuilder lpFilename, uint nSize);
    
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.