Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save managed .NET assembly from memory as EXE/DLL file

I would like to know if it is at all possible, and if so - how, to save a dynamically loaded .net assembly (it was loaded from a byte array, not a file) to a file on disk (exe/dll depending on assembly) and be able to use it directly (i.e. if it is exe, it will contain all exe headers and be runnable or at least "reflectable").

Also do the loaded assemblies actually get stored in memory exactly as they appear in files, i.e. all the PE EXE headers, resources, etc, i.e. essentially exe/dll file in memory, or do they get stored in memory differently and so it will not be possible to save some region of memory as dll/exe .net assembly? That is, if I can use analogy from images: you may load jpeg file into memory as a bitmap, where the actual bytes representing the image in memory will be quite different from the actual bytes representing the jpeg file. So is it the same with loading assemblies?

And finally how do I get the memory addresses (pointers) to where the assembly is actually located in process's memory?

Just to clarify: I do not have any access to the initial byte array from which assembly was loaded via Assembly.Load().

Here's a related question, but it's not clear from the answer if there may be a way to dump assembly loaded via byte array from memory to a file on disk.

Thank you.

like image 337
Fit Dev Avatar asked Nov 14 '22 05:11

Fit Dev


1 Answers

First of all in .NET, an assembly can consist of multiple modules that physical located in different locations. So it is only possible to save a module in the assembly. Most of time you will only need the main module so you can use Assembly.ManifestModule to get it.

Marshal.GetHINSTANCE will return the HINSTANCE of the module, which is the base address of the module according to this article. Although the remarks in MSDN states in-memory modules do not have an HINSTANCE, it seems the method does returns the base address for in-memory modules.

So now we have the base address of the module. The next thing to do is to determining the size of the module. The simplest way to do this is to parse the Section Headers of the PE file. For example:

Name   | Raw Size | Raw Address
.text  | 0x2000   | 0x400
.rsrc  | 0x400    | 0x2400
.reloc | 0x200    | 0x2800

In this case, the size of the module is the maximum Raw Address plus the corresponding Raw Size, that is 0x2A00.

like image 197
Kii Avatar answered Jan 05 '23 23:01

Kii