0xd4d / dnlib Goto Github PK
View Code? Open in Web Editor NEWReads and writes .NET assemblies and modules
License: MIT License
Reads and writes .NET assemblies and modules
License: MIT License
In class MetaDataHeader, SetOffset() uses actual offset when aligning strings but WriteTo() aligns the strings using the string length instead of the actual offset. This can lead to exception being thrown from VerifyWriteTo() when the MetaDataHeader items change and computing the alignment differs between SetOffset() and WriteTo().
Is there a way to remove an assembly reference?
I want to write an application to embed or merge assemblies using dnlib; however, I'm stuck in an early stage, since I can't remove the referenced assembly.
Hi,
are you interested in publishing dnlib as a NuGet package?
There are ways to trigger automatic build and publishing to NuGet, using appveyor, for example.
I use this a lot for my projects and it just eases the release life cycle.
If you are interested you need to:
appveyor.yml
to your project (I provide a sample content below)# appveyor.yml script
version: '{branch}-{build}'
branches:
only:
- master
os: Visual Studio 2015
install:
- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
before_build:
nuget restore
nuget:
account_feed: true
project_feed: true
disable_publish_on_pr: true
configuration: Release
platform: Any CPU
build:
parallel: true
publish_nuget: true
publish_nuget_symbols: true
verbosity: minimal
deploy:
provider: NuGet
api_key:
secure: !!!place your own API key here!!!
skip_symbols: false
The API key you need to provide is the NuGet key encrypted by appveyor (so appveyor is the only one allowed to decipher it).
I would gladly have submitted a push request, however it would have contained my own NuGet key, and this is your great product, not mine ๐ .
Hi,
I try to save obfuscated assembly (looks like .Net Reactor 4.8) using dnlib, but has an exception. My steps:
In .NET 4, TypeIdentifierAttribute is used to indicate two COM interface should be treated as equivalent by runtime even if they're in different assemblies.
e.g.
static void Main(string[] args) {
var path = @"C:\Program Files\Reference Assemblies\Microsoft\VSTO40\v4.0.Framework\";
var t1 = Assembly.LoadFile(path + "Microsoft.Office.Tools.Common.dll").GetType("Microsoft.Office.Tools.AddIn");
var t2 = Assembly.LoadFile(path + "Microsoft.Office.Tools.Common.v4.0.Utilities.dll").GetType("Microsoft.Office.Tools.AddIn");
Console.WriteLine(t1.IsEquivalentTo(t2));
Console.WriteLine(t1.IsAssignableFrom(t2));
}
When resolving member references, these type equivalence should be taken into account. I have some sample people sent to me that shows the problem with resolving. If you need it please tell me about it.
dnlib uses COM interfaces to read PDB. When it is used in other threads, it will produce an error.
I wanted to use the dnlib instead cecil but due to lack of some important properties in the dnlib I was disappointed.
Important properties for me.
IsSetter
IsGetter
IsOther
IsAddOn
IsRemoveOn
IsFire
IsPrimitive
Hi.
I'm trying to use dnlib to remove everything from an existing C++/CLI assembly.
However, when I try to write, I get a ModuleWriterException, saying a type is still referenced.
It seems to me that if I remove all types, there shouldn't be any references?
ModuleDefMD module = ModuleDefMD.Load(assemblyPath);
foreach (TypeDef typeDefinition in module.Types.ToArray())
{
if (typeDefinition.FullName == "<Module>")
{
typeDefinition.CustomAttributes.Clear();
typeDefinition.Methods.Clear();
typeDefinition.Properties.Clear();
typeDefinition.Fields.Clear();
typeDefinition.Events.Clear();
continue;
}
module.Types.Remove(typeDefinition);
}
module.NativeWrite(stubPath);
An unhandled exception of type 'dnlib.DotNet.Writer.ModuleWriterException' occurred in dnlib.dll
Additional information: TypeDef MyNamespace.GraphicsEventArgs (02000035) is not defined in this module (TopSecret.dll). A type was removed that is still referenced by this module.
dnlib fails to resolve methods that has ExportedType in signature, since their scopes are different. One example is SharpDX.AngleSingle.ToString() in the WinRT version of SharpDX SDK. It reference CultureInfo.get_CurrentCulture(), which is an exported type.
The attributes member of AssemblyDef is always zero for me. The x86 flag is set on the source assembly, but the AssemblyDef Attribute property only returns AssemblyAttribute.None.
Also I cannot set the processor architecture x86 flag to my assembly with dnlib. The flag is unchanged when I check the assembly with ILSpy.
Security Directory (as shown by CFF Explorer) is a file offset to the Authenticode signature, not a RVA. Therefore, its data is not preserved by dnlib normally. Even if it is preserved using KeepExtraPEData, the offset will be changed and make the original offset invalid. I suppose dnlib should either clear the directory or update its offset.
I'm currently trying to edit a module where all method bodies except for one are compressed/junk IL. When trying to save the module in dnSpy, it outputs:
Instruction operand is null
Instruction is null
Operand is not a local/arg
All files written to disk.
Perhaps this could be solved with an additional module writer option (metadata flag) to specify that only modified method bodies should be written/interpreted? Something like MetaDataFlags.KeepUnmodifiedMethodBodies
.
With the same file it throws on Mac OS X with this exception
Unhandled Exception:
System.IO.IOException: Could not get length of Project.dll.bak (lseek failed): 22
at dnlib.IO.MemoryMappedFileStreamCreator+Unix.Mmap (dnlib.IO.MemoryMappedFileStreamCreator creator, Boolean mapAsImage) [0x00000] in <filename unknown>:0
at dnlib.IO.MemoryMappedFileStreamCreator.CreateUnix (System.String fileName, Boolean mapAsImage) [0x00000] in <filename unknown>:0
at dnlib.IO.ImageStreamCreator.CreateMemoryMappedFileStreamCreator (System.String fileName, Boolean mapAsImage) [0x00000] in <filename unknown>:0
at dnlib.IO.ImageStreamCreator.Create (System.String fileName, Boolean mapAsImage) [0x00000] in <filename unknown>:0
at dnlib.PE.PEImage..ctor (System.String fileName, Boolean mapAsImage, Boolean verify) [0x00000] in <filename unknown>:0
at dnlib.PE.PEImage..ctor (System.String fileName, Boolean verify) [0x00000] in <filename unknown>:0
at dnlib.PE.PEImage..ctor (System.String fileName) [0x00000] in <filename unknown>:0
at dnlib.DotNet.MD.MetaDataCreator.Load (System.String fileName) [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.IO.IOException: Could not get length of Project.dll.bak (lseek failed): 22
at dnlib.IO.MemoryMappedFileStreamCreator+Unix.Mmap (dnlib.IO.MemoryMappedFileStreamCreator creator, Boolean mapAsImage) [0x00000] in <filename unknown>:0
at dnlib.IO.MemoryMappedFileStreamCreator.CreateUnix (System.String fileName, Boolean mapAsImage) [0x00000] in <filename unknown>:0
at dnlib.IO.ImageStreamCreator.CreateMemoryMappedFileStreamCreator (System.String fileName, Boolean mapAsImage) [0x00000] in <filename unknown>:0
at dnlib.IO.ImageStreamCreator.Create (System.String fileName, Boolean mapAsImage) [0x00000] in <filename unknown>:0
at dnlib.PE.PEImage..ctor (System.String fileName, Boolean mapAsImage, Boolean verify) [0x00000] in <filename unknown>:0
at dnlib.PE.PEImage..ctor (System.String fileName, Boolean verify) [0x00000] in <filename unknown>:0
at dnlib.PE.PEImage..ctor (System.String fileName) [0x00000] in <filename unknown>:0
at dnlib.DotNet.MD.MetaDataCreator.Load (System.String fileName) [0x00000] in <filename unknown>:0
I have the following class:
public class MyGenericArray<T>
{
private T[] array;
public MyGenericArray(int size)
{
array = new T[size + 1];
}
public T getItem(int index)
{
var in2 = index + 1;
in2 = index - in2;
index = index + 1 - in2 - 1;
return array[index];
}
}
I use dnlib to make some changes at the cil code level.
Inside the getItem() method, I want to get the class type of the this parameter, ldarg.0
I am looking in the param.Type where
var param = ((Parameter)_instruction.Operand);
I have searched through all the available fields but I could not find it.
In fact, what I get is
ConsoleCalculator.BasicTests/MyGenericArray`1
and I expect to find
ConsoleCalculator.BasicTests/MyGenericArray`1<!T>
I don't understand why the <!T>
is missing.
For the field private T[] array;
the class is displayed correctly, with the <!T>
at the end.
It seems that dnlib is not available from NuGet, which makes it harder to use. I think you should consider creating a NuGet package for it.
When creating a new instance method and adding it into a TypeDef, the type of this parameter (method.Parameters[0]) is always null because it is only set once at method creation.
Hello and first of all, thanks for a really cool library which I'm using every day :)
Among others I'm using it to generate a hash over the IL code of an assembly. While doing this a MappedFile handle is created on the file the module was loaded from. This handle is never released which makes it impossible to save the assembly.
I was able to track it down to where I start to iterate over the CustomAttributes collection of a MethodDef but I don't know why this handle is created and how I can avoid or close it.
Do you have any ideas?
Best regards
By default, dnlib loads modules using memory mapped files. This requires the caller to explicitly dispose the module to unlock the file. However, there is no way to retrieve cached assemblies (as well as their modules) in an AssemblyResolver to dispose them.
According to the standard, multiple getters/setters/etc... in a property/event is not forbidden, and is verifiable by peverify. However, PropertyDef.GetMethod returns only one of them, and other methods just have IsGetter set.
ILSpy fails to display the remaining methods because it hides members according to IsGetter flag. It would be more convenient to add a GetMethods/SetMethods property to expose the remaining methods.
Sample code:
class S : Attribute {
public S(Type t) { }
}
[S(null)]
class X {
}
dnlib failed to read that custom attribute.
Hi 0xd4d,
is there a way we can talk in private?
Should I post my email address?
Here's what I did:
static void Main()
{
string fileName = @"D:\Bins\cert\test.exe";
ModuleDefMD md = ModuleDefMD.Load(File.ReadAllBytes(fileName));
EmbeddedResource res = new EmbeddedResource(new UTF8String("test"), new byte[] { 0x00 });
md.Resources.Clear();
md.Resources.Add(res);
md.Write(fileName);
Console.ReadLine();
}
However, after writing it, and trying to sign it with signtool, it fails.
Here's how I signed:
signtool sign /f cert.pfx /p password test.exe
And here's what signtool outputs:
Done Adding Additional Store
SignTool Error: SignedCode::Sign returned error: 0x80070057
The parameter is incorrect.
SignTool Error: An error occurred while attempting to sign: test.exe
Number of errors: 1
In dnlib.DotNet.Resolver.FindExportedType
, IsForwarder flag is checked before determining whether it's the correct exported type. However, the CLI standard does not contains this flag, and the SSCLI source code seems to have no special processing about the flag (except reject it if it is generic type). Moreover, according to the source code of Roslyn, it seems that nested types will have this flag unset even if it is exported. Therefore, I think this check of IsForwarder should be omitted.
Say I have a class called TypeA. It is in the same program that uses dnlib to inject this class, called ProgramA. I am loading an assembly, ProgramB, that uses Mono's mscorlib and cannot use Windows' mscorlib. Is there any way I can inject TypeA in ProgramB, making it use Mono's mscorlib instead of Windows'? TypeA does some very simple operations so everything is covered in Mono.
Thanks!
It seems it is not possible to use dnlib to either only add the public key token to the assembly (delay signing) or to sign the assembly with a test key (signing with a key that is not the same as the public key used during delay signing). This is unfortunate as in our corporation we want to obfuscate assemblies and then only sign them on the build server while developers use test key signing as recommended by Microsoft best practices.
In Importer.CreateScopeReference
, it changes public key to tokens via ToPublicKeyToken
. However, the attribute that has AssemblyAttributes.PublicKey
remains unchanged. Changing the attribute copying to Attributes = defAsm.Attributes & ~AssemblyAttributes.PublicKey
fix it for me.
I tried both methods but always return False.
Hi,
It seems that modifying the Win32 resources of an assembly corrupts the PDB.
I have an utility that updates the version number after build, including in the Win32 resources blocks, and after this, some other tools using Cecil do not want to load the .PDB file anymore. Also, some methods do not show their local variables anymore in the debugger.
Since I have absolutely no knowledge at all of .PDB format, I am not very useful to fix the problem.
The enum is defined as flags so I assumed I can use typeDef.HasFlag(TypeAttributes.Public)
to find public types, but since TypeAttributes.NestedPrivate is 3 and TypeAttributes.Public is 1, a private nested type seems return incorrect result here.
When working with WinRT assemblies, it would be convenient to have WinRT type projection in resolvers, since some WinRT type and CLR type are treated as the same. For example, Windows.Foundation.Collections.IMapView
is same as System.Collections.Generic.IReadOnlyDictionary
.
See https://stackoverflow.com/questions/10679515/winrt-projected-types-documentation for details and https://github.com/dotnet/coreclr/blob/master/src/inc/winrtprojectedtypes.h for the projected type list.
Is there any way to add an assembly reference in dnlib?
This is what i'm doing
MainApp
|_Type
|_MethodDef(*)
DLL
|_Type
|_MethodDef(*)
I'm copying the method from the mainApp into the dll & i'm updating where the method was used.
But when saving i get :
Method System.Void TypeDef::TestMe() (06000000) is not defined in this module
Is there any way to add the Dll as reference?
Thank you.
It would be nice to be able to use plain-text strings with Importer :
Importer importer = new Importer(module);
var test = importer.Import("instance void [mscorlib]System.DateTime::.ctor(int64)");
I have the following class:
public class MyGenericArray<T>
{
private T[] array;
public MyGenericArray(int size)
{
array = new T[size + 1];
}
public T getItem(int index)
{
var in2 = index + 1;
in2 = index - in2;
index = index + 1 - in2 - 1;
return array[index];
}
}
I use dnlib to make some changes at the cil code level.
Inside the getItem() method, I want to get the class type of the this parameter, ldarg.0
I am looking in the param.Type where
var param = ((Parameter)_instruction.Operand);
I have searched through all the available fields but I could not find it.
In fact, what I get is
ConsoleCalculator.BasicTests/MyGenericArray`1
and I expect to find
ConsoleCalculator.BasicTests/MyGenericArray`1<!T>
I don't understand why the <!T>
is missing.
For the field private T[] array;
the class is displayed correctly, with the <!T>
at the end.
I'd like to get IL instructions for dynamically generated method.
Module that contains it represented as a InternalModuleBuilder
at the time of execution.
When I pass System.Reflection.Emit.InternalModuleBuilder
as a parameter to ModuleDefMD.Load(System.Reflection.Module mod)
I got error message from this line:
dnlib/src/DotNet/ModuleDefMD.cs
Line 295 in aab6e29
MemberRef can refer to a method in the base type, but dnlib only searchs the current type when resolving them. For example, SharpDX.Serialization.BinarySerializer.ReaderOnly(object) in the WinRT version of [SharpDX SDK] uses [System.Runtime]System.Type::get_Name()
to reference [mscorlib]System.Reflection.MemberInfo::get_Name()
.
Hey,
I noticed when I import a type and it contains a static array field with a direct assignment of the values like:
private static int[] TestArr = new int[]{1,2,3,4,5};
or
private static byte[] BArr = new byte[]{0x01,0x02,0x03};
their will occur a problem when imported.
The field gets added but the output assembly is not runnable.
byte[] expr_06 = new byte[8];
RuntimeHelpers.InitializeArray(expr_06, ldtoken());
StringDecryption.nigga = expr_06;
This is how the produced MSIL looks like.
I am aware of the fact that its possible to import an array field by using the FieldDef and adding it manually, but it would be much more comfortable to improve the importing class of dnlib so the initialization of array fields will be handled automatically without causing trouble with ldtoken OpCodes.
Whats the right way to create a constructor.
For example there is already a type and a constructor that takes an int.
How do I create a parameter-less constructor the right way?
Somehow it never works. I always get errors like "wrong signature" or stack underflow after a "newobj" instruction.
Is there a checklist to keep in mind when creating new constructors? Normal methods are no problem but with ctors I couldn't get it to work.
I also tried to just change the signature of an existing ctor by removing the parameters.
Modifying parameters is another thing. What's the intended way to add /remove parameters from a function? When do I have to call CreateParamDef? And when should I call UpdateParameterTypes?
Do I always have to setup a new parameter signature when changing the paramerDefs?
For example, suppose I have a library in .NET 3.5. There is a method taking an argument of System.Action in System.Core. Then I created an application in .NET 4 to use that library's method.
In this application, the argument's type is System.Action in mscorlib, since it has moved to mscorlib in .NET 4. The runtime will use .NET 4's System.Core, which has exported System.Action to mscorlib and has no problem. However, dnlib will use .NET 3.5's System.Core and cannot match the reference in the application.
ConfuserEx refers to ImportResolver but I couldn't find it in dnlib? Has this module been deprecated? If so what's the replacement and where can I find the original ImportResolver class?
When I modify method body, I always get an error:
Error calculating max stack value. If the method's obfuscated.....
I know I make a mistake, but I don't know which method.
So, how can I know which method is wrong and correct my mistake.
There is a stsfld and a ldsfld in the same module, and the operand is the same field.
But one is FileDef, another is MemberRef, so when I compare them use "==", it tell me false.
Maybe dnlib should use IMemberDef if one reference is defined in the current module, at least tell me true when I use "==".
Hello, is there any equivalent to Mono.Cecil's way of inserting instructions?
Like so: ILProcessor.InsertAfter(InstructionDef, Instruction.Create(OpCodes.Call, MethodDef));
I'm not sure if thats an issue, but anyway I'd like to raise it here.
I've such a method in some class (as seen in SAE for example):
myMeth1(Double[0...,0...], Double[]&&): Boolean
Now, there is a code in some assembly that calls this method
and the 1st parameter is declared as follows:
now, taking into account how dnlib compares the arraysig, the lookup fails....
module: SigComparer.cs
code:
namespace dnlib.DotNet {
......
public bool Equals(TypeSig a, TypeSig b) {
{
...........
case ElementType.Array:
ArraySig ara = a as ArraySig, arb = b as ArraySig;
result = ara.Rank == arb.Rank &&
Equals(ara.Sizes, arb.Sizes) &&
Equals(ara.LowerBounds, arb.LowerBounds) &&
Equals(a.Next, b.Next);
break;
}
here is an example of the comparing code:
bool flag6 = !default(SigComparer).Equals(methodSig.Params[i], babelMethodRef.Parameters[i].Type);
I've looked around, there is interesting arcticle about this case:
Array lower bounds can be only '0'
https://msdn.microsoft.com/en-us/library/ttw7c10x%28v=vs.90%29.aspx
So the question is: does it make sense to relax the LowerBounds comparing way?
maybe it'll make sense to check if one side has 0 lower bounds and another no, then the result still may be "equal"?
Thanks
Given a MethodDef.
How do I know if this method is an implementation of an interface the declaring type implements.
Do I have to go through the inheritance chain and interfaces and check the names & signatures?
Or is there a shortcut?
If there is no shortcut, what is the fast and correct way to do this?
I wanted to patch a MemberRef GenericArgument but saved file without any changes.
Where is the problem?
foreach (MemberRef memberRef in module.GetMemberRefs())
{
if (memberRef.FullName.Contains("System.Collections.Generic.Dictionary`2<System.Tuple`3<!0,ICSharpCode.ILSpy.AccessOverlayIcon,System.Boolean>"))
{
if (memberRef.MethodSig != null) continue;
FieldSig fieldSig = memberRef.FieldSig;
TypeSig genericArgument = ((GenericInstSig) fieldSig.Type).GenericArguments[0];
((GenericInstSig) genericArgument).GenericArguments[1] = module.Import(typeof (System.Int32)).ToTypeSig();
}
}
Hi!
I'm trying to confuse a mixed-mode assembly with ConfuserEx. When the output assembly gets written I'm getting the error "Invalid section RVA" - also when disabling all protections, so I guess ConfuserEx may not be the source of the problem. What does this error message mean? The assembly is a .NET 3.5 standard C++/CLI mixed mode assembly that is signed with an Authenticode certificate. Are there any known issues or any known conditions when this error is raised?
Thank you in advance!
P
I can check if method has fat header using MethodBody.isTiny but I can't get the fat header size. It is usually 12 bytes but IIRC it is variable. It would be nice if dnlib can compute the size for me.
In instruction operand, a GenericVar's OwnerType returns the method's declaring type instead of the owner type of the GenericVar.
using System;
using System.Diagnostics;
using System.Linq;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
internal class X<T> {
public static T W() {
return default(T);
}
}
internal class Program {
static string Q() {
return X<string>.W();
}
static void Main(string[] args) {
var module = ModuleDefMD.Load(typeof(Program).Assembly.Location);
var type = module.Find("Program", true);
var method = type.FindMethod("Q");
var instr = method.Body.Instructions.First(i => i.OpCode == OpCodes.Call);
var operand = (IMethod)instr.Operand;
var x = module.Find("X`1", true);
var retType = operand.MethodSig.RetType; // <T>
Console.WriteLine("{0} {1}", x, retType);
Debug.Assert(retType is GenericVar);
Debug.Assert(new SigComparer().Equals(((GenericVar)retType).OwnerType, x));
Console.ReadKey();
}
}
It seems it is not possible to write, for example, the NumberOfSymbols in ImageFileHeader. I could write it in the OnWriterEvent listener using DestinationStream.Write() but that feels clumsy.
Are there plans to add more setters to the ImageFileHeader class?
And thank you for dnlib, awesome work!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.