View Single Post
  #8  
Old 10-11-2016, 01:10
bongos_man bongos_man is offline
Friend
 
Join Date: Aug 2016
Posts: 25
Rept. Given: 0
Rept. Rcvd 4 Times in 3 Posts
Thanks Given: 4
Thanks Rcvd at 25 Times in 14 Posts
bongos_man Reputation: 4
there has been a lack of technical specifics so far in this thread, but as LaDidi implied above, i'm afraid if you were hoping things would get better with regard to protecting your code, you were waiting in vain. sorry. there is no one-button solution to protecting .NET software.

to address your question about .NET Standard, the short version is that .NET Standard is irrelevant to your concerns and will not help you to protect your code. the long version: .NET Standard is simply an attempt to harmonize the fragmentation that presently exists with regard to standard library support across .NET implementations. .NET Standard is a mandatory base set of APIs that must be supported by all .NET runtimes, including the full Microsoft .NET Framework, Mono, .NET Core, and other frameworks which subsume .NET implementations, such as the Universal Windows Platform. .NET Standard is effectively an upgrade to the .NET PCL. it has nothing to do with how your code will be compiled, therefore it is irrelevant; constraining your program to only use .NET Standard APIs will not make it harder to reverse engineer. you can read more about .NET library compatibility here.

there are more serious fundamental issues as well.

first, MSIL assemblies are rich in metadata. this is required in order to support the CLR's reflection facilities. even if you aren't using reflection, this data will be included in assemblies, and "obfuscation" tools will not remove them. metadata is also required for generics to work: the compilers for most .NET languages do not statically monomorphize generic code, relying on the JIT to generate code at runtime.

second, MSIL is trivially decompilable. it is easy to reconstruct both data provenance (such as for local variables) and higher-level flow control from instructions for a stack-based architecture--flow analysis is far simpler than on a register-based machine. there is also no need for any sort of complicated analysis to reconstruct function boundaries in the assembly, nor calls to library functions. obfuscation tools again do not help here--even if there were advanced packers that converted MSIL into instructions for a proprietary virtual machine (as exist for native code), they too would be mechanically reversible once understood.

.NET Native improves things for you, but with caveats: reflection will fail unless you explicitly include metadata on your assembly, and since there is no JIT, Reflection.Emit does not work at all. even though .NET Native tries to remove metadata, this is basically impossible to do in full, and the reasons go all the way to fundamentals of programming languages and type theory. if we were to formally model the CLR, its static semantics would have no notion of reflection--it is not part of the CLR's type system; it is a purely dynamic phenomenon. reflection is a feature to enable working with value-level representations of types, but without the concept of dependent types, it is impossible for a type system to express "facts" that depend on value-level terms--this is why neither obfuscators nor .NET Native can completely remove metadata. (in case you're not familiar, languages with dependent types are effectively similar to proof assistants, as in order for type-level assertions about values to be safe, machine-verifiable proofs are often required).

by the way, most of what is true of .NET is also true of the JVM and any other system with reflection or dynamic types. TL;DR: if you're paranoid about people reverse engineering your code, you might sleep better at night by using something else, but the reality is that anyone determined enough and smart enough can eventually figure it out. ;]
Reply With Quote