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.