0

Is it possible to have read-access to assemblies modules raw files loaded in memory by the CLR?

I don't ask for Reflection here, I ask for read-access to raw modules files (.dll and .exe) loaded in memory by the CLR. If it is possible I guess I'd need somehow some unmanaged code (and this would be ok to use unmanaged code for that).

I guess this can be done through CLR hosting, but I'd prefer a solution without CLR hosting if possible, a solution where my .NET code would invoke some unmanaged code (with an input such as Assembly.GetExecutingAssembly().GetModules().First().ModuleHandle) and get back a pointer to the file location in memory (assuming the CLR doesn't move such loaded file).

Community
  • 1
  • 1
Patrick from NDepend team
  • 13,237
  • 6
  • 61
  • 92

2 Answers2

0

Nothing special is required to open a file to read the assembly. The CLR doesn't do anything complicated with the assembly, it simply creates a memory-mapped file to map it into virtual memory. Very efficient, you never pay for metadata or MSIL that you don't use, it will simply never be loaded into RAM. As long as you don't try to write to the file then you'll have no problems at all:

using System;
using System.IO;

class Program {
    static void Main(string[] args) {
        using (var fs = new FileStream(System.Reflection.Assembly.GetExecutingAssembly().Location,
            FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
            // No problems...
        }
    }
}

Whether it is actually useful to do this is rather doubtful. You'll want to use Reflection or the low-level .NET metadata services (IMetadataAssemblyImport2 et al) to avoid having to interpret the non-trivial structure of an assembly.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Hans sure I can do this, my question is about accessing the memory used by the CLR to load the assembly file, not load the module file from its location. Why do I want to do that? For some security reasons, I don't want to access the file itself but I am interested by its content. – Patrick from NDepend team Aug 21 '14 at 10:44
  • Why do you think there is a difference? It is a memory mapped file, there is no distinction whatsoever between the file and the memory to which it is mapped. You *can* get a pointer to the virtual memory address where it is mapped, IMetaDataInfo::GetFileMapping() provides it. Which requires IMetaDataDispenser::OpenScope(). No idea what the big secret might be, you are not telling me enough to give you helpful advice. – Hans Passant Aug 21 '14 at 10:56
  • Hans see my answer above. – Patrick from NDepend team Dec 03 '15 at 07:19
0

I found out this is possible to obtain a pointer to a .NET module raw bytes loaded in memory this way, so this exactly answers my question:

System.Reflection.Assembly assembly = ...
IntPtr modulePtr = Marshal.GetHINSTANCE(assembly.ManifestModule);
Patrick from NDepend team
  • 13,237
  • 6
  • 61
  • 92
  • 1
    Hi Patrick , I'm trying to do the same thing but it doesn't work , your method returns 0x05300000 but it's 0x02EBB3C8 checked by memory scanner , i even tried to add it to .net main module base address but it did not work , how you made it work ? –  Mar 11 '19 at 03:06
  • Mike, on my side it just works, both with .NET Fx and .NET Core, I just used Assembly assembly = Assembly.GetExecutingAssembly(); – Patrick from NDepend team Oct 14 '19 at 11:00