1

I need to get memory address of loaded assemblies in my appdomain. When Assemblies are loaded in to a .Net app , they will be fully loaded in main application memory.

If we search a memory for this byte pattern :

byte[] pe_pattern = {
    0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
    0xFF, 0xFF
};

We find where and which address they laid in memory. But I need to do this without a memory scan because of performance .

I tried to get loaded assemblies by AppDomain.CurrentDomain.GetAssemblies() and get their address as objects by Garbage Collector and some other methods can be found here : Memory address of an object in C#

But the address I get is not the correct address , I have no error.

In c++ there's a method to do this to get loaded dlls by loadlibrary but in C# I couldn't find anything.

How can I get memory addresses of loaded assemblies in my C# App ?

2 Answers2

1

I'm not sure if you're looking for (1) the virtual address of the mapped assembly file, or (2) the virtual address where the JITed code gets placed once an assembly is loaded.

Next I'll consider the simple case of a host process loading a few assemblies. The code can be found here. Let's focus on what happens when the x64_Assembly.dll gets loaded.

If what we're looking for is (1) defined above (the virtual address of the mapped file within the process' address space), then this means the highlighted line below, shown in the output of VMMap. It's where the OS loads the file containing the assembly. I'm not aware how you could get this one programmatically from within your own app.

enter image description here

For (2), that is the virtual address where the JITed code of the assembly is found, you can actually see the respective address if you step into your code with the debugger:

enter image description here

As this thread points out, the JITed assembly gets placed in a heap, which you can verify easily by using VMMap again. In my case, the address shown in the debugger can be seen located inside a heap block with VMMap:

enter image description here

So which address are you actually targeting ?

Later Update: You could use CLR MD to get very interesting data. Take a look at the simple code below (taken from Ben Watson's "Writing High-Performance .NET Code") which gets (1) and possibly (2). You can see the image address of the loaded assembly in VMMap matches the value of module.ImageBase, so you'll definitely get (1). For (2) however, the value of module.Address is NOT the same as the m_assembly variable seen in the debugger in my original answer - so one of them is showing something else. However, if you think about it, not all the code is JITed at the same time - instead the CLR will JIT compile methods as (and if) they are called. Therefore I believe the virtual addresses contained by the 2 variables point to some generic structure representing the assembly.

enter image description here

Since you mentioned you do have access to check the memory contents, you can find out pretty quickly which of the 2 variables is of interest for (2).

How could you do this in practice ? I'm thinking build the CLR MD project that simply outputs the info you're after ((1) and (2) in a simple file)), then have this EXE invoked by your main code, so that it analyses your process and the assembly it loads and writes the data. When the CLR MD process terminates, your actual code can retrieve the info written in the file and operate on those virtual addresses that it retrieved. In my sample above the PID was simply hardcoded (I was using Process Explorer to see the assigned PID), but you could probably pass it as an argument to your CLR MD project.

You can use Manage NuGet Packages for Solution option within Visual Studio to install the CLR MD, and have it configured for your specific project, then simply add a using Microsoft.Diagnostics.Runtime.

2 things that need to be kept in mind:

  • the "bitness" of the CLR MD code you're using must match the process you're analyzing (eg don't build one for x86 and the other for x64; the full details about assemblies and cross-bitness loading are in the article I've previously referenced)
  • you'll have to use AttachFlag.Passive in the AttachToProcess method, otherwise your original code gets paused indefinitely. I did test with this option as well after I've taken the above screenshot and got both the module.ImageBase and module.Address values successfully, plus the initial code continued to run just fine.
Mihai Albert
  • 1,288
  • 1
  • 12
  • 27
  • First , Thank you for great answer ! Yes , I need to get both addresses. do you have any suggestion to make it happen ? –  Apr 30 '19 at 15:28
  • It's so interesting , but what If I load assemblies from byte array? or using Fody.Costura to embed dlls ? –  May 01 '19 at 21:40
  • You could use the Assembly.Load version that takes as input a byte array, indeed. Assuming you'd hardcode the assembly as a byte array (or embed it in your code somehow) then the variable that would contain it would end up somewhere on the heap. CLR MD could be used again to walk the heap, and identify its virtual address, somewhat similar to the example above. Note that the byte pattern you're searching for (posted in your question) is actually the beginning of the MS-DOS header, present in every .exe or .dll. When the JIT compiler will actually convert the IL code to native code... – Mihai Albert May 02 '19 at 16:36
  • ...for each method encountered, I *belive* (assumption on my side here) that it will not go to the trouble of storing the MS-DOS header anywhere this time, but simply place the respective method's native code somewhere in memory. So the method of pattern searching wouldn't work for (2), however you could use CLR MD to get the virtual address of each method by enumerating them, yet I don't think that's what you're after. – Mihai Albert May 02 '19 at 16:36
  • let's say , I'm using fody Costura to load assemblies from memory. Dumpers scan the memory and find them by "MZ .... " byte I put top in question and then dump them on disk , some dumpers get them by using something like vmmap and find them in memory without pattern scan , my goal is to find them from my C# app and patch their headers to make dumpers unable to find and dump them , now any idea to do it ? we can work on it if you're interested . –  May 03 '19 at 17:21
  • the concept works well , I created a anti-dumper that works with pattern scanning and patching , but it takes 3 sec to get the job done ! I need to find them by C# app itself and I know it's possible because c# app knows where they are and placed because it's using them . –  May 03 '19 at 17:23
0

For Each assem In AppDomain.CurrentDomain.GetAssemblies() 'The hModule equals the base address - cast to a Long Dim hModule = System.Runtime.InteropServices.Marshal.GetHINSTANCE(assem.ManifestModule) Next

Jens
  • 77
  • 2