Basic I/O

Note

The documentation has a new home: Check it out!

Every .NET image interaction is done through classes defined by the AsmResolver.DotNet namespace:

using AsmResolver.DotNet;

Creating a new .NET module

Creating a new image can be done by instantiating a ModuleDefinition class:

var module = new ModuleDefinition("MyModule.exe");

The above will create a module that references mscorlib.dll 4.0.0.0 (.NET Framework 4.0). If another version of the Common Object Runtime Library is desired, we can use one of the overloads of the constructor, and use a custom AssemblyReference, or one of the pre-defined assembly references in the KnownCorLibs class to target another version of the library.

var module = new ModuleDefinition("MyModule.exe", KnownCorLibs.SystemRuntime_v4_2_2_0);

Opening a .NET module

Opening a .NET module can be done through one of the FromXXX methods from the ModuleDefinition class:

byte[] raw = ...
var module = ModuleDefinition.FromBytes(raw);
var module = ModuleDefinition.FromFile(@"C:\myfile.exe");
PEFile peFile = ...
var module = ModuleDefinition.FromFile(peFile);
BinaryStreamReader reader = ...
var module = ModuleDefinition.FromReader(reader);
IPEImage peImage = ...
var module = ModuleDefinition.FromImage(peImage);

If you want to read large files (+100MB), consider using memory mapped I/O instead:

using var service = new MemoryMappedFileService();
var module = ModuleDefinition.FromFile(service.OpenFile(@"C:\myfile.exe"));

On Windows, if a module is loaded and mapped in memory (e.g. as a dependency defined in Metadata or by the means of System.Reflection), it is possible to load the module from memory by using FromModule, or by transforming the module into a HINSTANCE and then providing it to the FromModuleBaseAddress method:

Module module = ...;
var module = ModuleDefinition.FromModule(module);
Module module = ...;
IntPtr hInstance = Marshal.GetHINSTANCE(module);
var module = ModuleDefinition.FromModuleBaseAddress(hInstance);

Writing a .NET module

Writing a .NET module can be done through one of the Write method overloads.

module.Write(@"C:\myfile.patched.exe");
Stream stream = ...;
module.Write(stream);

For more advanced options to write .NET modules, see Advanced PE Image Building.

Creating a new .NET assembly

AsmResolver also supports creating entire (multi-module) .NET assemblies instead.

var assembly = new AssemblyDefinition("MyAssembly", new Version(1, 0, 0, 0));

Opening a .NET assembly

Opening (multi-module) .NET assemblies can be done in a very similar fashion as reading a single module:

byte[] raw = ...
var assembly = AssemblyDefinition.FromBytes(raw);
var assembly = AssemblyDefinition.FromFile(@"C:\myfile.exe");
IPEFile peFile = ...
var assembly = AssemblyDefinition.FromFile(peFile);
BinaryStreamReader reader = ...
var assembly = AssemblyDefinition.FromReader(reader);
IPEImage peImage = ...
var assembly = AssemblyDefinition.FromImage(peImage);

Similar to reading module definitions, if you want to read large files (+100MB), consider using memory mapped I/O instead:

using var service = new MemoryMappedFileService();
var assembly = AssemblyDefinition.FromFile(service.OpenFile(@"C:\myfile.exe"));

Writing a .NET assembly

Writing a .NET assembly can be done through one of the Write method overloads.

assembly.Write(@"C:\myfile.patched.exe");

For more advanced options to write .NET assemblies, see Advanced PE Image Building.