AsmResolver Versions Save

A library for creating, reading and editing PE files and .NET modules.

v5.5.1

2 months ago

This is an incremental maintenance release that adds .NET 8.0 as an official target and fixes issues related to type signatures, CIL optimizations, as well as some rare edge cases in .NET metadata directory parsing.

New Features

  • Add support for importing function pointer type signatures via reflection (#523, thanks @Windows10CE).
  • Add BinaryStreamWriter::AlignRelative (af2e49d434a6e6071a3f03f6930858207b992c08)
  • Add .NET 8.0 target.

Bug Fixes

  • Fix a couple issues regarding hash computation of generic instance and custom modifier type signatures in SignatureComparer (#512, thanks @rstarkov)
  • Fix an issue where optimizing ldloca and ldarga opcodes would not shorten to their shorter variants (9ab4e94d5e18e6c5fe373a22fcb31d9f2add3554)
  • Fix an issue where the same metadata members could be added twice to the exact same collection, resulting in ownership problems (#513)
  • Fix an issue where .NET modules containing a metadata directory at an unaligned offset would read stream headers incorrectly (af2e49d434a6e6071a3f03f6930858207b992c08).

v5.5.0

5 months ago

This version brings rudimentary low-level .NET ReadyToRun (R2R) parsing and writing to AsmResolver, allowing you to locate and read native code of precompiled managed method bodies (see documentation). Additionally, basic Span<T> support was added to primitives like IDataSource and Utf8String for newer .NET runtime targets (netstandard 2.1 and above), and some new convenience APIs were added. Finally, some bugfixes were implemented, increasing general stability of the library.

New Features

  • Add support for low level .NET ReadyToRun assembly parsing (#294, #495). See documentation.
  • Add basic Span<T> support for IDataSources and Utf8String (#483, thanks @DaZombieKiller).
  • Add option to suppress .NET resource data deduplication (#492).
  • Add TypeDefinition::GetConstructor, MethodDefinition::CreateConstructor and similar (#480).
  • Add ReferenceTable primitive segment class, representing structures like VTables that can be directly used as a writable ISegment.
  • Add BinaryStreamReader::RemainingLength.
  • Reduce allocations of null SegmentReferences.
  • Add netstandard2.1 target.

Bug Fixes

  • TypeReference::IsImportedInModule now correctly takes its resolution scope into account (#497).
  • Type resolution now correctly first checks whether the resolution scope refers to the current assembly (740369250ba86ab675dbfc7aba06fcf7d39b3959).
  • TypeNameParser now correctly does not return fully imported types, but they can still be resolved using .Resolve() (#497).
  • MemberCloner now correctly fixes cross-references to included System.Type arguments in Custom Attributes (#482, #493).
  • Fixed an issue where .NET resource data with a malformed header would crash the parser (#492).
  • Fixed an issue where ZeroesDataSource would clear out too much data in the buffer provided to ReadBytes (thanks @DaZombieKiller)
  • Fixed an issue where BitList would incorrectly accept negative indices (#478).
  • Fixed an issue where duplicated members would not be added even when preserving metadata tokens (#478).
  • Fixed an issue where members with manually assigned tokens would not be saved correctly when assembly had no backing .NET directory (#478)
  • Fixed a race condition in the caching mechanism of assembly resolution (61b6ddf38701ac1ff92d1b142cec5c897b60d0aa)
  • Fixed a race condition in the caching mechanism of input file services (61b6ddf38701ac1ff92d1b142cec5c897b60d0aa)
  • Fixed an issue where string operands in IL pretty printed instructions were not escaped properly (6e039b98944e654ab774091cc72b0dbf29a29e0b)

Minor Breaking Changes

  • Remove TlsCallbackCollection, replaced with ReferenceTable.
  • TlsDirectory::CallbackFunctions is now of type ReferenceTable.
  • IDotNetDirectory::ManagedNativeHeader is now of the more specific segment type IManagedNativeHeader.

v5.4.0

9 months ago

This release includes support for PE certificate tables, PE forwarder exports, as well as various quality of life improvements and bug fixes. Check out the documentation and the full change-log below:

New Features

  • Add read/write support for PE certificate tables (#451).
  • Add support for arbitrary symbols to be references in NativeMethodBody (#444, #449).
  • Let assembly resolution mechanism respect ModuleReaderParameters::WorkingDirectory (#438, #441).
  • Add read/write support for ExportedSymbol::IsForwarder (#437, #440).
  • Add ManagedPEFileBuilder::ErrorListener (#468).
  • Allow for ITypeDescriptor::Scope to be null and of type ModuleDefinition. (#466)
  • Add language identifiers for Version Info win32 resources (#457)
  • Add support for attaching multiple listeners to the MemberCloner (#461)
  • Add DotNetRuntimeInfo::GetDefaultCorLib and KnownCorlibs::FromRuntimeInfo (#462)
  • PEFile::CreateReaderAtFileOffset now supports reading from EOF data (582142876aad038721a3f6f6969f0195f99f332a).
  • Add Source Link (#469, thanks @ds5678)

Bug fixes

  • Fix an issue when resolution scope of a type reference set to 0 when the coded index to the current module was meant instead (#459, #466).
  • Fix an issue where field RVA rows were not always correctly updated when writing unchanged serialized PEs (#468).
  • Fix an issue where win32 resource VersionInfo tables were not correctly aligned to the next 4-byte boundary, resulting in some of the resource to be trimmed away when rebuilding (#456).
  • Fix an issue where the Culture= part of AssemblyDescriptor.FullName was not included in the output (#458).
  • Fix an issue where PE section names would result in spurious "name too long" exceptions when containing unconventional UTF-8 code points (#453, #455).
  • Fix an issue where GetImpliedMemoryLayout would stack-overflow with unresolved generic parameter type signatures (#447, #448).
  • Fix an issue where ModuleReaderParameters were not passed along correctly in ModuleDefinition::FromBytes (bbf57811bdcfdf22a77365a8aef28795d7d7a517)

v5.3.0

1 year ago

This version is mostly a maintenance version with performance improvements and bug fixes. Developers of .NET obfsucators and deobfuscators will also be happy to know that ManagedPEImageBuilder now accepts any IErrorListener. This should make it easier to ignore any invalid metadata that is introduced to the assembly model (e.g., by passing in an EmptyErrorListener). Finally, a migration from readthedocs to DocFX was made, giving a new home and look to the documentation. Let us know what you think of it!

New Features

  • Add support for arbitrary IErrorListener objects as opposed to just DiagnosticBags in ManagedPEImageBuilder (#367, thanks @ds5678 for the help!).
  • Add LazyVariable<TOwner, TValue>, reducing the number of allocations made by AsmResolver's internals significantly for larger binaries (#428)
  • Add Platform::Is32Bit, Platform::Is64Bit and Platform::PointerSize (#430)
  • Add ZeroesSegment and ZeroesDataSource for creating, reading and writing memory-efficient segments containing only zero bytes (#430).
  • Migrate documentation to DocFX with full API reference (2545e1a4374fd070e2b1f3667d7aa053c7caf3be).

Bug Fixes

  • Fixed an issue where SignatureComparer::GetHashCode for assembly descriptors did not respect the configuration flags passed into the constructor (#427, #429).
  • Field RVA reader now correctly supports reading the data for IntPtr and UIntPtr typed fields (#430).
  • Fixed an issue where reading from a section that is empty on the disk would throw even if the section has a non-zero virtual size (#430).
  • Fixed an issue where entries in an import descriptor were not read correctly if OriginalFirstThunk = 0. This is the case for many packed executables such as UPX packed binaries (#431, #432)

Deprecations

  • PEImageBuildContext::DiagnosticBag is superseded by PEImageBuildContext::IErrorListener.
  • The constructor PEImageBuildResult taking a DiagnosticBag is superseded by the one taking an IErrorListener.

Minor Breaking Changes

  • The signature for IFieldRvaDataReader::ResolveFieldData has changed slightly. See the documentation for how to use the new interface (#430).

v5.2.0

1 year ago

New Features

  • Add TypeSignature::IsCompatibleWith and TypeSignature::IsAssignableTo methods (#421)
  • Add support for patching AppHost / SingleFileHost files without requiring the original SDK template file (#420, #424)
  • Add support for metadata tokens and unmanaged entry points in DotNetDirectory (#422)
  • Add Parameter::GetOrCreateDefinition() (#418, thanks @ElektroKill)
  • Add read support for PDB modules (#412)
  • Add read support for many more PDB symbol and leaf record types (#412)
  • Add basic metadata properties to PdbImage (e28df25ba827d4112e3edfebdfca980814c6a2e1)
  • Add OptionalHeader::SetDataDirectory helper method (8357a77dd4873facb5af59473e12a279dede12f7)
  • Add CallingConventionSignature::CallingConvention convenience property that masks out the used convention from Attributes (#414)
  • Add undocumented CallingConvention::NativeVarArg (#414)

Bug Fixes

  • Fix an issue related to metadata token preservation of MemberRefParents (caeef35393655f18b30d3e79526a6bb5cf7ae99b)
  • Fix an issue with MethodSignature's sentinel parameter type preservation (#413, #414).
  • Fix ParameterCollection::ThisParameter's parameter type for generic instance types (e27b6e8c2d70fb189fb409a81b676925856763bb, thanks @ElektroKill)
  • Fix MethodSignatureBase::GetTotalParameterCount() for ExplicitThis signatures (dae99095fd2df0831fae87f95722243d25a436a7, thanks @ElektroKill)

Deprecations

  • All constructors of BundlerParameters are superseded by BundlerParameters::FromTemplate and BundlerParameters::FromExistingFile.
  • Assignments of DotNetDirectory::EntryPoint using an uint are obsoleted and should be replaced with a construction of a DotNetEntryPoint structure.

Minor Breaking ABI Changes

  • Remove spurious CallingConventionSignature::IsSentinel (#414)
  • Change property type of DotNetDirectory::EntryPoint from uint to DotNetEntryPoint DU struct.

v5.1.0

1 year ago

New Features

  • Add fluent patching API, allowing for easy and quick binary patches on PE files as well as individual segments (#403, #405). Check out the documentation.
  • Add option to preserve spurious metadata streams and their order (#394, #406)
  • Add generic ModuleDefinition::LookupMember<T> and ModuleDefinition::TryLookupMember<T> methods (#392, #402)
  • Add TypeDefinition::IsModuleType (#391, thanks @sunnamed434)
  • Add rudimentary custom attribute validation, avoiding the accidental construction of incorrect attribute signatures (#389, #407)

Bug Fixes

  • Fix generic custom attributes reader errors (#397, #401)
  • Fix GetModuleType() behavior for .NET Core / .NET 5+ modules (#395, #396)
  • Fix .NET runtime detection when multiple corlibs references are present in the binary (a0bb1dfe282def3e6ec394fdae8170ad8ad599e4)

Deprecations

  • CodeSegment is now deprecated. Use the DataSegment combined with the new patching API for address fixups.

Other

  • Fixed some spelling mistakes in the documentation (#398, #400, thanks @svenskithesource)

v5.0.0

1 year ago

This marks the first major version bump since the rewrite of AsmResolver. A huge thanks to all the contributors and testers. Without them this release would not have been possible!

Summary

  • Significant performance boost and memory consumption reductions across the board.
  • Rudimentary read support for PDB files (both Windows PDB and Portable PDB).
  • Various Quality-of-Life improvements of the API.
  • Overall robustness improvements against malformed input binaries and/or edge-cases.

Full change log

New Features

  • Add read / write support for PortablePDB metadata streams and tables (#348)
  • Add a new WIP package called AsmResolver.Symbols.Pdb for reading and writing Windows PDB files using only managed code (#324, #326, #342, #368 (thanks @ds5678))
  • Add the notion of IMemberClonerListeners, allowing for automatically post-processing cloned metadata (e.g., automatically injecting it into the target module) as the cloner is cloning metadata (#333, #337, #354, thanks @CursedLand)
  • Add DotNetRuntimeInfo::IsNetCoreApp, IsNetFramework and IsNetStandard properties for easily identifying whether a module targets .NET Core, .NET Framework or .NET Standard (505da7a9255a96bb649023f7a36b9d628a41ad63).
  • Add SignatureComparer::Default (#366, thanks @ds5678)
  • Add TypeDefinition::IsByRefLike (#358, #362)
  • Make AsmResolver.DotNet trimmable (#304, thanks @ds5678)
  • Add MetadataTable::IsSorted property (#348)
  • DynamicMethodDefinition now has better support for dynamic methods that are initialized via DynamicILInfo (b0b13c8be4a81ed56d983b57589fc00a3913288e)
  • Add convenience constructors for BinaryStreamReader that take a byte[] or a IDataSource alone (54c65ee64277b42326aec54f499efc7407a4e556).
  • Add OriginalMetadataTokenProvider (#361)
  • Add type.IsTypeOfUtf8 to avoid conversions from Utf8String to string (baf25ac0e3881e31698f0367a8ea03ce4fc0e652)

Breaking Changes

  • Make SignatureComparer immutable (#366, thanks @ds5678)
  • Refactor class BlobReadContext to a mutable struct BlobReaderContext (#356, c0283c721957ddbb149a1edbfa77b16b1555ae2d).
  • Change ISegment::UpdateOffsets's method signature (#236, #346)
  • Remove ITlsDirectory::ImageBase and CodeSegment::ImageBase (#346)
  • Remove SegmentReference::CanUpdateOffsets and SegmentReference::UpdateOffsets (#346)
  • Add setter to TypeDefOrRefSignature::Type and GenericInstanceTypeSignature::Type (#338, thanks @JPaja)
  • Move AsmResolver.DotNet.Dynamic into a separate nuget package (#304).
  • Rename Entrypoint to EntryPoint (b6fa3edd613a0521c2fc9dbecb554605ac25706e).
  • Rename OptionalHeaderMagic::Pe32 and Pe32Plus to PE32 and PE32Plus (d954be07d8dabcbcd2e97e521342d9f6213dca2e).
  • Let LazyVariable lock on itself (16367c198a9a50470a9cb780e83038c102ebe0f7)
  • Consolidate ContinuousMetadataRange and RedirectedMetadataRange to a single struct MetadataRange (3bb6b6ad33cf41b86411142a50332c0423020126)
  • Let OneToManyRelation return a ValueSet with a struct enumerator instead of a generic ICollection (07b09c33cbc7a98d616e64c7baed834a767e20df)
  • Change type of MemberClonerContext::Importer to CloneContextAwareReferenceImporter.
  • Many constructors of metadata members taking a name parameter are now of type Utf8String instead of string (baf25ac0e3881e31698f0367a8ea03ce4fc0e652, 5d8cb885873d58c9af1a9f62a42e45068e4ce704).
  • Rename FullNameGenerator to MemberNameGenerator. This class has a new layout and is not API compatible with the old version (#386).

Performance Improvements

  • Precomputing capacity properties for lists containing read metadata reduced memory consumption by roughly 5%-10% (#316)
  • Many small buffers and temporary memory streams are being reused during the writing process where possible. This reduces the number of allocations by up to 20% (#317).
  • Various reader context types are now stack allocated (#356, c0283c721957ddbb149a1edbfa77b16b1555ae2d).
  • Custom attribute signatures are now only read when absolutely necessary, preventing many unnecessary expensive type resolutions and thus many allocations (#336, #351).
  • MethodImplementation now implements IEquatable<MethodImplementation>, drastically reducing allocations and increasing performance for large binaries with lots of interface implementations (d10cf47c1eef0a7974f162285310b38df4621f3f).
  • Replace PE section lookup LINQ code with expanded for loop, drastically reducing allocations in general (1ff0a0ffaf70cd8f72e80650de184276add24148)
  • OneToManyRelation now returns a ValueSet with a struct enumerator instead of an interface (07b09c33cbc7a98d616e64c7baed834a767e20df)
  • Avoid many string allocations from Utf8String instances when resolving types and members (baf25ac0e3881e31698f0367a8ea03ce4fc0e652)
  • Avoid many allocations of traversed tokens during type signature parsing where possible, reducing memory consumption of the reader in general (c0283c721957ddbb149a1edbfa77b16b1555ae2d)
  • Avoid duplication of Utf8String objects in StringStreamBuffer (533a9117b99e53ca521e30289e798ad2d67adff1)
  • Avoid allocation of many empty metadata value sets (especially for custom attributes), significantly reducing memory consumption (ce0a94f8ee9d7762433412e2bd5c10caeaa38828)
  • Significantly improve performance of member.FullName and reduced memory consumption by up to 70% (#386)

Bug Fixes

  • Modifications to a LazyList<T> (and all its derivatives) are now guarded with locks to prevent concurrency issues (#364).
  • Importing a nested type via System.Reflection now correctly imports the declaring type. This was especially a problem when converting DynamicMethods to a DynamicMethodDefinition. (#365)
  • Local variables are now properly resolved from DynamicMethods initialized with DynamicILInfo.
  • Reading and importing complex COR_ELEMENT_TYPE_INTERNAL types should be fixed.
  • Various CIL body parsing improvements, allowing for better recovery of invalid method body code / data (#361)
  • Metadata stream selection is now properly reflecting the behavior of the runtime for both compressed and EnC metadata (#352)
  • ExpandMacros correctly expands ldarga.s and bge.un.s to their correct expanded forms (#322, thanks @N78750469)
  • Importing via Reflection of MethodBases that use generic parameters of its declaring type in its signature should now be fixed.
  • LPArrayMarshalDesriptor now correctly respects signatures with a null ArrayElementType (d9ef330187efdb1d645beb7b6193ddcd9983f9a0).
  • Fix stack overflow when trying to compute a token of a full sized public key of an assembly reference (#381, #382)
  • The endfinally opcode correctly clears the stack during stack analysis (eb41d58f81a77f94a7cf8a8c2e49863ba64ae9c4)
  • Sorted metadata tables are now stable sorts, ensuring order for metadata members such as custom attributes (#387)

v5.0.0-beta.2

1 year ago

This quick hotfix addresses a few problems in 5.0.0-beta.1 with DynamicILInfo initialized DynamicMethods. In particular:

  • Local variables are now properly resolved from DynamicMethods.
  • Reading and importing complex COR_ELEMENT_TYPE_INTERNAL types should be fixed
  • Importing via Reflection of MethodBases that use generic parameters of its declaring type in its signature should now be fixed.

Note this is still a prerelease. Breaking changes can still happen until the final release. See the remainder of changelog of 5.0.0-beta.1

v5.0.0-beta.1

1 year ago

This marks the first major version bump since the rewrite of AsmResolver. Note that, this is still a pre-release. last-minute breaking API changes may still happen before the full release.

New Features

  • Read / Write support for PortablePDB metadata streams and tables (#348)
  • A new WIP package called AsmResolver.Symbols.Pdb for reading and writing Windows PDB files using only managed code (#324, #326, #342)
  • Add SignatureComparer::Default (#366, thanks @ds5678)
  • Add TypeDefinition::IsByRefLike (#358, #362)
  • Add the notion of IMemberClonerListeners, allowing for automatically post-processing cloned metadata (e.g., automatically injecting it into the target module) as the cloner is cloning metadata (#333, #337, #354, thanks @CursedLand)
  • AsmResolver.DotNet is now trimmable (#304, thanks @ds5678)
  • Add DotNetRuntimeInfo::IsNetCoreApp, IsNetFramework and IsNetStandard properties for easily identifying whether a module targets .NET Core, .NET Framework or .NET Standard (505da7a9255a96bb649023f7a36b9d628a41ad63).
  • Add MetadataTable::IsSorted property (#348)
  • DynamicMethodDefinition now supports dynamic methods that are initialized via DynamicILInfo (b0b13c8be4a81ed56d983b57589fc00a3913288e)
  • Add convenience constructors for BinaryStreamReader that take a byte[] or a IDataSource alone (54c65ee64277b42326aec54f499efc7407a4e556).
  • Add OriginalMetadataTokenProvider (#361)

Breaking Changes

  • Make SignatureComparer immutable (#366, thanks @ds5678)
  • Make BlobReadContext a struct (#356).
  • Change ISegment::UpdateOffsets's method signature (#236, #346)
  • Remove ITlsDirectory::ImageBase and CodeSegment::ImageBase (#346)
  • Remove SegmentReference::CanUpdateOffsets and SegmentReference::UpdateOffsets (#346)
  • Add setter for TypeDefOrRefSignature::Type and GenericInstanceTypeSignature::Type (#338, thanks @JPaja)
  • Move AsmResolver.DotNet.Dynamic into a separate nuget package (#304).
  • Rename Entrypoint to EntryPoint (b6fa3edd613a0521c2fc9dbecb554605ac25706e).
  • Rename OptionalHeaderMagic::Pe32 and Pe32Plus to PE32 and PE32Plus (d954be07d8dabcbcd2e97e521342d9f6213dca2e).
  • Let LazyVariable lock on itself (16367c198a9a50470a9cb780e83038c102ebe0f7)
  • Consolidate ContinuousMetadataRange and RedirectedMetadataRange to a single struct MetadataRange (3bb6b6ad33cf41b86411142a50332c0423020126)
  • Let OneToManyRelation return a ValueSet with a struct enumerator instead of a generic ICollection (07b09c33cbc7a98d616e64c7baed834a767e20df)
  • Change type of MemberClonerContext::Importer to CloneContextAwareReferenceImporter.

Performance Improvements

  • Precomputing capacity properties for lists containing read metadata reduced memory consumption by roughly 5%-10% (#316)
  • Many small buffers and temporary memory streams are being reused during the writing process where possible. This reduces the number of allocations by up to 20% (#317).
  • Various reader context types are now stack allocated (#356).
  • Custom attribute signatures are now only read when absolutely necessary, preventing many unnecessary expensive type resolutions and thus many allocations (#336, #351).
  • MethodImplementation now implements IEquatable<MethodImplementation>, drastically reducing allocations and increasing performance for large binaries with lots of interface implementations (d10cf47c1eef0a7974f162285310b38df4621f3f).
  • Replace PE section lookup LINQ code with expanded for loop, drastically reducing allocations in general (1ff0a0ffaf70cd8f72e80650de184276add24148)
  • OneToManyRelation now returns a ValueSet with a struct enumerator instead of an interface (07b09c33cbc7a98d616e64c7baed834a767e20df)

Bug Fixes

  • Modifications to a LazyList<T> (and all its derivatives) are now guarded with locks to prevent concurrency issues (#364).
  • Importing a nested type via System.Reflection now correctly imports the declaring type. This was especially a problem when converting DynamicMethods to a DynamicMethodDefinition. (#365)
  • Various CIL body parsing improvements, allowing for better recovery of invalid method body code / data (#361)
  • Metadata stream selection is now properly reflecting the behavior of the runtime for both compressed and EnC metadata (#352)
  • ExpandMacros correctly expands ldarga.s and bge.un.s to their correct expanded forms (#322, thanks @N78750469)

v4.11.2

1 year ago

Note: v4.11.x is very likely the last minor version bump for version 4 of AsmResolver. We are working on version 5.0, which will include some breaking changes. There might be a few more hotfixes before 5.0 will be merged into master, but no more new features will be introduced until the next major version bump.

Bug Fixes

  • Fixed an issue where preserving type reference tokens would cause nested type references to get the wrong RIDs assigned occasionally and cause a "Token is already in use" error (#329, #330).
  • Fixed an issue where metadata resolution would fail if the target assembly used an older .NET version (#321, #331)

See also change logs of 4.11.1 and 4.11.0