Skip to content

Commit

Permalink
Merge pull request #470 from Washi1337/development
Browse files Browse the repository at this point in the history
5.4.0
  • Loading branch information
Washi1337 authored Jul 16, 2023
2 parents 9d0fe83 + 0c8f8de commit 82989a6
Show file tree
Hide file tree
Showing 111 changed files with 2,244 additions and 442 deletions.
3 changes: 2 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
<RepositoryUrl>https://github.com/Washi1337/AsmResolver</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<LangVersion>10</LangVersion>
<Version>5.3.0</Version>
<Version>5.4.0</Version>
<Deterministic>true</Deterministic>
</PropertyGroup>

</Project>
6 changes: 3 additions & 3 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
- master

image: Visual Studio 2022
version: 5.3.0-master-build.{build}
version: 5.4.0-master-build.{build}
configuration: Release

skip_commits:
Expand All @@ -23,7 +23,7 @@
deploy:
provider: NuGet
api_key:
secure: L3fXsS7umzD8zwAvTsdGxOg/E6tQ4IR4MfwBAcO8elE7ZwjZ8HO8UPwjiWbp4RMw
secure: orcP0C1iuBVKxnv/uAUehgU1KEI/lCpbSxDqbckd3sZ7XxcuENj6PrExs6SdJIf1
skip_symbols: false
artifact: /.*\.nupkg/

Expand All @@ -33,7 +33,7 @@
- development

image: Visual Studio 2022
version: 5.3.0-dev-build.{build}
version: 5.4.0-dev-build.{build}
configuration: Release

skip_commits:
Expand Down
11 changes: 10 additions & 1 deletion docs/guides/dotnet/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,16 @@ references in the `KnownCorLibs` class to target another version of the
library.

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

If you have a .NET runtime identifier as specified in the
`TargetFrameworkAttribute` of an assembly, you can use the `DotNetRuntimeInfo`
structure to get the corresponding default corlib:

``` csharp
var runtime = DotNetRuntimeInfo.Parse(".NETCoreApp,Version=v3.1");
var module = new ModuleDefinition("MyModule.dll", runtime.GetDefaultCorLib());
```

## Opening a .NET module
Expand Down
35 changes: 20 additions & 15 deletions docs/guides/dotnet/bundles.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,11 @@ The major version number refers to the file format that should be used
when saving the manifest. Below an overview of the values that are
recognized by the CLR:

---------------------------------------------------
.NET Version Number Bundle File Format Version
---------------------- ----------------------------
.NET Core 3.1 1

.NET 5.0 2

.NET 6.0 6
---------------------------------------------------
| Minimum .NET Version Number | Bundle File Format Version |
|-----------------------------|-----------------------------|
| .NET Core 3.1 | 1 |
| .NET 5.0 | 2 |
| .NET 6.0 | 6 |

To create a new bundle with a specific bundle identifier, use the
overloaded constructor
Expand Down Expand Up @@ -108,8 +104,12 @@ var manifest = BundleManifest.FromDataSource(contents, bundleAddress);

Constructing new bundled executable files requires a template file that
AsmResolver can base the final output on. This is similar how .NET
compilers themselves do this as well. By default, the .NET SDK installs
template binaries in one of the following directories:
compilers themselves do this as well.

### Using the .NET SDK's template

By default, the .NET SDK installs template apphost binaries in one of the
following directories:

- `<DOTNET-INSTALLATION-PATH>/sdk/<version>/AppHostTemplate`
- `<DOTNET-INSTALLATION-PATH>/packs/Microsoft.NETCore.App.Host.<runtime-identifier>/<version>/runtimes/<runtime-identifier>/native`
Expand Down Expand Up @@ -150,6 +150,15 @@ manifest.WriteUsingTemplate(
imagePathToCopyHeadersFrom: @"C:\Path\To\Original\HelloWorld.exe"));
```

> [!NOTE]
> `BundleManifest` and `BundlerParameters` also define overloads of the
> `WriteUsingTemplate` and `FromTemplate` / `FromExistingBundle`
> respectively, taking `byte[]`, `IDataSource` or `IPEImage` instances
> instead of file paths.

### Using an input binary as template

If you do not have access to a template file (e.g., if the SDK is not
installed) but have another existing PE file that was packaged in a
similar fashion, it is then possible to use this file as a template
Expand Down Expand Up @@ -179,10 +188,6 @@ manifest.WriteUsingTemplate(
> the input file to determine the parameters for patching the input file.
> As heuristics are not perfect, this is not guaranteed to always work.
`BundleManifest` and `BundlerParameters` also define overloads of the
`WriteUsingTemplate` and `FromTemplate` / `FromExistingBundle`
respectively, taking `byte[]`, `IDataSource` or `IPEImage` instances
instead of file paths.

## Managing Files

Expand Down
58 changes: 47 additions & 11 deletions docs/guides/dotnet/cloning.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,8 @@ cloner.Include(rectangleType);
cloner.Include(vectorType);
```

`Include` returns the same `MemberCloner` instance. It is therefore also
possible to create a long method chain of members to include in the
cloning process.
`Include` returns the same `MemberCloner` instance, allowing for more fluent
syntax:

``` csharp
cloner
Expand Down Expand Up @@ -201,7 +200,7 @@ All references to methods defined in the
`System.Runtime.CompilerServices` namespace will then be mapped to the
appropriate method definitions if they exist in the target module.

See [Common Caveats using the Importer](/guides/dotnet/importing.html#common-caveats-using-the-importer)
See [Common Caveats using the Importer](importing.md#common-caveats-using-the-importer)
for more information on reference importing and its caveats.

## Post-processing of cloned members
Expand Down Expand Up @@ -255,7 +254,24 @@ var cloner = new MemberCloner(destinationModule, (original, cloned) => {
});
```

## Injecting the cloned members
Multiple listeners can also be chained together using the `AddListener` method:

```csharp
var cloner = new MemberCloner(destinationModule);
cloner.AddListener(new MyListener1());
cloner.AddListener(new MyListener2());
```

This can also be used in the fluent syntax form:

```csharp
var cloner = new MemberCloner(destinationModule)
.AddListener(new MyListener1())
.AddListener(new MyListener2());
```


## Injecting cloned members

The `Clone` method returns a `MemberCloneResult`, which contains a
register of all members cloned by the member cloner.
Expand Down Expand Up @@ -288,17 +304,37 @@ foreach (var clonedType in clonedTypes)
destinationModule.TopLevelTypes.Add(clonedType);
```

However, since injecting the cloned top level types is a very common
use-case for the cloner, AsmResolver defines the
`InjectTypeClonerListener` class that implements a cloner listener that
injects all top-level types automatically into the destination module.
In such a case, the code can be reduced to the following:
Injecting the cloned top level types is a very common use-case for the cloner.
AsmResolver defines the `InjectTypeClonerListener` class that implements a
cloner listener that injects all top-level types automatically into
the destination module. In such a case, the code can be reduced to the following:

``` csharp
new MemberCloner(destinationModule, new InjectTypeClonerListener(destinationModule))
new MemberCloner(destinationModule)
.Include(rectangleType)
.Include(vectorType)
.AddListener(new InjectTypeClonerListener(destinationModule))
.Clone();

// `destinationModule` now contains copies of `rectangleType` and `vectorType`.
```

AsmResolver provides another built-in listener `AssignTokensClonerListener` that
also allows for preemptively assigning new metadata tokens automatically, should
this be necessary.

``` csharp
new MemberCloner(destinationModule)
.Include(rectangleType)
.Include(vectorType)
.AddListener(new InjectTypeClonerListener(destinationModule))
.AddListener(new AssignTokensClonerListener(destinationModule))
.Clone();

// `destinationModule` now contains copies of `rectangleType` and `vectorType`
// and all its members have been assigned a metadata token preemptively.
```

The `AssignTokensClonerListener` uses the target module's `TokenAllocator`. See
[Metadata Token Allocation](token-allocation.md) for more information on how this
class operates.
2 changes: 1 addition & 1 deletion docs/guides/dotnet/dynamic-methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,6 @@ contextModule.GetOrCreateModuleType().Methods.Add(definition);
contextModule.Write("Program.patched.dll");
```

See [Obtaining methods and fields](/guides/dotnet/member-tree.html#obtaining-methods-and-fields)
See [Obtaining methods and fields](member-tree.md#obtaining-methods-and-fields)
and [CIL Method Bodies](managed-method-bodies.md) for more
information on how to use `MethodDefinition` objects.
2 changes: 1 addition & 1 deletion docs/guides/dotnet/managed-method-bodies.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ body.Instructions[i].ReplaceWith(CilOpCodes.Ldc_I4, 1234);
```

Since it is very common to replace instructions with a
[nop]{.title-ref}, AsmResolver also defines a special `ReplaceWithNop`
`nop`, AsmResolver also defines a special `ReplaceWithNop`
helper function:

``` csharp
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/dotnet/unmanaged-method-bodies.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ module.IsBit32Required = true;
As per ECMA-335 specification, a method definition can only represent a
native function via Platform Invoke (P/Invoke). While P/Invoke is
usually used for importing functions from external libraries (such as
[kernel32.dll]{.title-ref}), it is also needed for implementing native
`kernel32.dll`), it is also needed for implementing native
methods that are defined within the current .NET module itself.
Therefore, to be able to assign a valid native body to a method, the
right flags need to be set in both the `Attributes` and `ImplAttributes`
Expand Down
6 changes: 3 additions & 3 deletions docs/guides/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ writing).

AsmResolver often can ignore and recover from kinds of errors, but this
is not enabled by default. To enable these, please refer to
[Advanced PE Image Reading](/guides/peimage/advanced-pe-reading.html#custom-error-handling) (PE)
or [Advanced Module Reading](/guides/dotnet/advanced-module-reading.html#pe-image-reading-parameters) (.NET),
and [Image Builder Diagnostics](/guides/dotnet/advanced-pe-image-building.html#image-builder-diagnostics) (.NET).
[Advanced PE Image Reading](peimage/advanced-pe-reading.md#custom-error-handling) (PE)
or [Advanced Module Reading](dotnet/advanced-module-reading.md#pe-image-reading-parameters) (.NET),
and [Image Builder Diagnostics](dotnet/advanced-pe-image-building.md#image-builder-diagnostics) (.NET).
Be careful with ignoring errors though. Especially for disabling writer
verification can cause the output to not work anymore unless you know
what you are doing.
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/pefile/sections.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Some sections (such as `.data` or `.bss`) contain uninitialized data,
and might be resized in virtual memory at runtime. As such, the virtual
size of the contents might be different than its physical size. To make
dynamically sized sections, it is possible to use the `VirtualSegment`
to decorate a normal [ISegment]{.title-ref} with a different virtual
to decorate a normal `ISegment` with a different virtual
size.

``` csharp
Expand All @@ -76,7 +76,7 @@ file.Sections.Add(section);
```

For more advanced section building, see
[Building Sections](/guides/peimage/pe-building.html#building-sections)
[Building Sections](../peimage/pe-building.md#building-sections)
[Reading and Writing File Segments](../core/segments.md).

## Updating Section Offsets
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/peimage/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ var peImage = new PEImage();

## Opening a PE image

Opening an image can be done through one of the [FromXXX]{.title-ref}
methods from the `PEImage` class:
Opening an image can be done through one of the `FromXXX` methods from the
`PEImage` class:

``` csharp
byte[] raw = ...
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/peimage/dotnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ var fieldRva = new FieldRvaRow(myData.ToReference(), 0);

## TypeReference Hash (TRH)

Similar to the :ref:`pe-import-hash`, the TypeReference Hash (TRH) can be used
Similar to the [Import Hash](imports.md#import-hash), the TypeReference Hash (TRH) can be used
to help identify malware families written in a .NET language. However, unlike
the Import Hash, the TRH is based on the names of all imported type references
instead of the symbols specified in the imports directory of the PE. This is a
Expand Down
3 changes: 1 addition & 2 deletions docs/guides/peimage/exports.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ Dynamically linked libraries (DLLs) often expose symbols through
defining exports in the exports directory.

The `IPEImage` interface exposes the `Exports` property, exposing a
mutable instance of [ExportDirectory]{.title-ref}, which defines the
following properties:
mutable instance of `ExportDirectory`, which defines the following properties:

- `Name`: The name of the dynamically linked library.
- `BaseOrdinal`: The base ordinal of all exported symbols.
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/peimage/imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,4 @@ While the Import Hash can be a good identifier for native PE images, for
.NET images this is not the case. .NET images usually only import a
single external symbol (either `mscoree.dll!_CorExeMain` or
`mscoree.dll!_CorDllMain`), and as such they will almost always have the
exact same Import Hash. See [TypeReference Hash (TRH)](/guides/peimage/dotnet.html#typereference-hash-trh) for an alternative for .NET images.
exact same Import Hash. See [TypeReference Hash (TRH)](dotnet.md#typereference-hash-trh) for an alternative for .NET images.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Nullable" Version="1.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
6 changes: 5 additions & 1 deletion src/AsmResolver.DotNet/AsmResolver.DotNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Nullable" Version="1.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Text.Json" Version="6.0.7" />
<PackageReference Include="System.Text.Json" Version="6.0.8" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion src/AsmResolver.DotNet/AssemblyDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public virtual bool TryGetTargetFramework(out DotNetRuntimeInfo info)

if (ctor?.DeclaringType is not null
&& ctor.DeclaringType.IsTypeOf("System.Runtime.Versioning", nameof(TargetFrameworkAttribute))
&& CustomAttributes[i].Signature?.FixedArguments[0].Element is string name
&& CustomAttributes[i].Signature?.FixedArguments[0].Element?.ToString() is { } name
&& DotNetRuntimeInfo.TryParse(name, out info))
{
return true;
Expand Down
8 changes: 6 additions & 2 deletions src/AsmResolver.DotNet/AssemblyDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,16 @@ public string FullName
{
get
{
var publicKeyToken = GetPublicKeyToken();
string cultureString = !Utf8String.IsNullOrEmpty(Culture)
? Culture
: "neutral";

byte[]? publicKeyToken = GetPublicKeyToken();
string publicKeyTokenString = publicKeyToken is not null
? string.Join(string.Empty, publicKeyToken.Select(x => x.ToString("x2")))
: "null";

return $"{Name}, Version={Version}, PublicKeyToken={publicKeyTokenString}";
return $"{Name}, Version={Version}, Culture={cultureString}, PublicKeyToken={publicKeyTokenString}";
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private uint AddResolutionScope(IResolutionScope? scope, bool allowDuplicates, b
TableIndex.AssemblyRef => AddAssemblyReference(scope as AssemblyReference, allowDuplicates, preserveRid),
TableIndex.TypeRef => AddTypeReference(scope as TypeReference, allowDuplicates, preserveRid),
TableIndex.ModuleRef => AddModuleReference(scope as ModuleReference, allowDuplicates, preserveRid),
TableIndex.Module => 0,
TableIndex.Module => new MetadataToken(TableIndex.Module, 1),
_ => throw new ArgumentOutOfRangeException(nameof(scope))
};

Expand Down
Loading

0 comments on commit 82989a6

Please sign in to comment.