views:

859

answers:

7

What happens exactly when I launch a .NET exe? I know that C# is compiled to IL code and I think the generated exe file just a launcher that starts the runtime and passes the IL code to it. But how? And how complex process is it?

IL code is embedded in the exe. I think it can be executed from the memory without writing it to the disk while ordinary exe's are not (ok, yes but it is very complicated).

My final aim is extracting the IL code and write my own encrypted launcher to prevent scriptkiddies to open my code in Reflector and just steal all my classes easily. Well I can't prevent reverse engineering completely. If they are able to inspect the memory and catch the moment when I'm passing the pure IL to the runtime then it won't matter if it is a .net exe or not, is it? I know there are several obfuscator tools but I don't want to mess up the IL code itself.

EDIT: so it seems it isn't worth trying what I wanted. They will crack it anyway... So I will look for an obfuscation tool. And yes my friends said too that it is enough to rename all symbols to a meaningless name. And reverse engineering won't be so easy after all.

+3  A: 

Personally I think that obfuscation is the way to go. It is simple and can be effective, especially if all your code is within an exe (I'm not sure what the concern is with "messing up the IL").

However, if you feel like that won't work for you, perhaps you can encrypt your exe and embed it as a resoource within your launcher. The simplest way to handle it would be to decrypt the exe resource and write it out too file and execute it. Once the exe has completed executing, delete the file. You might also be able to run it through the Emit functions. I have no idea how this would work, but here is an article to get you started - Using Reflection Emit to Cache .NET Assemblies.

Of course your decryption key would probably have to be embedded in the exe as well so somebody really determined will be able to decrypt your assembly anyway. This is why obfuscation is probably the best approach.

Brian
+5  A: 

"...prevent scriptkiddies to open my code in Reflector and just steal all my classes easily."

Unfortunately, regardless of how you obscure launching, it's a matter of half a dozen commands in a debugger to dump a currently-running assembly to a file of the user's choice. So, even if you can launch your application as Brian suggested, it's not hard to get that application's components into Reflector once it's running (I can post a sample from WinDbg if someone would find it interesting).

Obfuscation tools are created from huge amounts of technical experience, and are often designed to make it difficult for debuggers to reliably attach to a process, or to extract information from it. As Brian said: I'm not sure why you're determined to preserve the IL and, if you want any meaningful protection from script kiddies, that's something you may have to change your mind on.

Dan Puzey
+16  A: 
Joel Coehoorn
+25  A: 

If you absolutely insist on encrypting your assembly, probably the best way to do it is to put your program code into class library assemblies and encrypt them. You would then write a small stub executable which decrypts the assemblies into memory and executes them.

This is an extremely bad idea for two reasons:

  1. You're going to have to include the encryption key in your stub. If a 1337 hacker can meaningfully use your reflected assemblies, he can just as easily steal your encryption key and decrypt them himself. (This is basically the Analog Hole)
  2. Nobody cares about your 1337 code. I'm sorry, but that's tough love. Nobody else ever thinks anyone's code is nearly as interesting as the author does.
Kennet Belenky
+1 for #2. So true.
Erik Forbes
the classic a. hole problem...
Michael La Voie
#2 - for sure. Could you use a digital certificate for decryption maybe as an alternative to embedding an encryption key?
Russell
@Russell I'm not sure how a digital certificate would help. If the code is going to be executed then you can't hide it from the CPU forever. Sooner or later you have to give the CPU the code, and when you do, a determined attacker with access to the machine will be there to swipe it. My real point is, nobody determined enough to bother even ROT-13 decoding something unless it poops gold nuggets.
Kennet Belenky
Instead of encrypting assemblies - You can just code in Perl.
Arnis L.
I disagree with "extremely bad idea". I don't care if someone looks at my code. I just want to make it a little bit harder for the registration code check to be ripped out. If this is as simple as running my binary through a tool, then it's _totally_ worth it.
romkyns
+16  A: 

A "secret" that you share with thousands of people is not a secret. Remember, your attackers only have to break your trivial-to-break-because-the-key-is-right-there "encryption" scheme exactly once.

If your code is so valuable that it must be kept secret then keep it secret. Leave the code only on your own servers; write your software as a web service. Then secure the server.

Eric Lippert
+1 for web service. That was my first thought after reading the question.
statenjason
It would be nice if the team responsible for Windows activation and WGA could figure this out... :)
jasonh
+2  A: 

Copying my answer from this question (which is not exactly duplicate but can be answered with the same answer, hence CW):

A Windows EXE contains multiple "parts". Simplified, the .net Code (=MSIL) is only a Part of the EXE, and there is also a "real" native Windows Part inside the EXE that serves as some sort of launcher for the .net Framework which then executes the MSIL.

Mono will just take the MSIL and execute it, ignoring the native Windows Launcher stuff.

Again, this is a simplified overview.

Edit: I fear my understanding of the deep depp details is not good enough for really much detail (I know roughly what a PE Header is, but not really the details), but i found these links helpful:

NET Assembly Structure – Part II

.NET Foundations - .NET assembly structure

Appendix: If you really want to go deeper, pick up a copy on Advanced .net Debugging. The very first chapter explains exactly how the .net Assembly is loaded prior and after Windows XP (since XP, the Windows Loader is .net aware which radically changes how .net Applications are started)

Michael Stum
A: 

"They copied all they could follow, but they couldn't copy my mind, so I left them sweating and stealing a year and a half behind." -- R. Kipling

r. kipling