Parse .NET C # library with dynamic types

I have .NET binaries and I need to restore all sources. I used .NET Reflector and in most cases it works very well. But now I have a problem with dynamic type. I have the following code and I don’t know how to understand it.

dynamic obj2 = component; if (<SetValue>o__SiteContainer0<T>.<>p__Site1 == null) { <SetValue>o__SiteContainer0<T>.<>p__Site1 = CallSite<Func<CallSite, object, bool>>.Create(Binder.UnaryOperation(CSharpBinderFlags.None, ExpressionType.IsTrue, typeof(RecordPropertyDescriptor<T>), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } if (<SetValue>o__SiteContainer0<T>.<>p__Site2 == null) { <SetValue>o__SiteContainer0<T>.<>p__Site2 = CallSite<Func<CallSite, object, object, object>>.Create(Binder.BinaryOperation(CSharpBinderFlags.None, ExpressionType.NotEqual, typeof(RecordPropertyDescriptor<T>), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) })); } if (<SetValue>o__SiteContainer0<T>.<>p__Site1.Target(<SetValue>o__SiteContainer0<T>.<>p__Site1, <SetValue>o__SiteContainer0<T>.<>p__Site2.Target(<SetValue>o__SiteContainer0<T>.<>p__Site2, obj2[this.Name], value))) { // some simple code } 

Any sugestions?

EDIT

I used ilspy.net and for me it is even worse

 Func<CallSite, object, bool> arg_163_0 = RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site1.Target; CallSite arg_163_1 = RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site1; if (RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site2 == null) { RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site2 = CallSite<Func<CallSite, object, object>>.Create(Binder.UnaryOperation(CSharpBinderFlags.None, ExpressionType.Not, typeof(RecordPropertyDescriptor<T>), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } Func<CallSite, object, object> arg_15E_0 = RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site2.Target; CallSite arg_15E_1 = RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site2; if (RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site3 == null) { RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site3 = CallSite<Func<CallSite, Type, object, object, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.None, "Equals", null, typeof(RecordPropertyDescriptor<T>), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) })); } Func<CallSite, Type, object, object, object> arg_159_0 = RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site3.Target; CallSite arg_159_1 = RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site3; Type arg_159_2 = typeof(object); if (RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site4 == null) { RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site4 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.GetIndex(CSharpBinderFlags.None, typeof(RecordPropertyDescriptor<T>), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) })); } if (arg_163_0(arg_163_1, arg_15E_0(arg_15E_1, arg_159_0(arg_159_1, arg_159_2, RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site4.Target(RecordPropertyDescriptor<T>.<SetValue>o__SiteContainer0.<>p__Site4, component, this.Name), value)))) { // some (not so) simple code } 
+4
source share
1 answer

This is not a problem with your disassembler, this is a problem with your expectations. Disassemblers generally tend to crash in any scenario when the C # compiler automatically generates a non-trivial amount of code. This certainly applies to the dynamic keyword; the compiler makes calls to the binder in Microsoft.CSharp.dll. And there, as a rule, a lot , a dynamic keyword is an expensive hobby.

What disassemblers cannot do:

  • restore comments in source code
  • declare const declarations in source code
  • recover the name of local variables in your methods
  • cleanly decompile anonymous delegates
  • purely decompile iterators
  • purely decompile lambda expressions
  • purely decompile understanding of Linq queries
  • purely decompile code that uses dynamic variables.
  • cleanly decompile code that uses async / await

Lambdas and Linq were added in 2008 with C # version 3.0 and were instant hits. Also that year, when Lutz Raeder decided that he no longer wanted to work on Reflector and sold it to Redgate. Time was almost certainly no coincidence.

The list above is a decent guide for programmers who are concerned about decompiling their code. Just add enough of these constructs to your program and you no longer have to worry about obfuscators.

Meanwhile, this will certainly not help you recover the code. You will have to do this manually, relying on your memory of how it might look earlier. Of course, first of all, you need to take care of reliable and restored source control. This is a mistake you make only once.

+13
source

Source: https://habr.com/ru/post/1494665/


All Articles