28

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.

Brian Leahy
  • 34,677
  • 12
  • 45
  • 60
Calmarius
  • 18,570
  • 18
  • 110
  • 157
  • See MSDN for `CorBindToRuntimeEx` function in particular and CLR Unmanaged API in general. – Mehrdad Afshari Feb 25 '10 at 23:08
  • Just curious: have you considered using an obfuscator to dissuade reverse-engineering? It's not perfect... but it's close to out-of-the-box to utilize – STW Feb 25 '10 at 23:09
  • Wouldn't it be easier to just use a non-interpereted language? I mean I love .NET, but there's always the concept of ROI. – David Feb 25 '10 at 23:13
  • 11
    @David: .NET is not interpreted. Where did you get _that_ idea? The IL code is just-in-time compiled to machine language, optimized for the machine it's running on. It's quite the opposite of interpreted! – John Saunders Feb 25 '10 at 23:18
  • @David : You are right. IL is sort of like the assembly code ages ago. No matter which .NET language you are using, they all can be translated into IL and it is the .NET CLR that does the execution. You should not touch anything beyong IL so as not to interfere with the .NET Frakework. – Michael Mao Feb 25 '10 at 23:25
  • 20
    I really would like to see some of this phenomenal super-secret code that so many people consider so important to hide from prying eyes. Even the .NET Framework itself is basically wide open. There must be some mind-blowing stuff in here. – Aaronaught Feb 25 '10 at 23:26
  • Using the dotNet Reflector is a great way to see the entire framework until it calls Windows API . At that point it is all hidden like half of System.Window.Forms.Control. So no matter how much of the framework you copy, you are still stuck having everything reference the API. When you build a .NET app with no underlying unmanaged dlls, then the entire source base is open to be copied without the theather that keeps them coming back to you as the developer. If your project has enough important logic you wish to protect, then you want to do everything possible prevent others from taking it. – JDMX Feb 25 '10 at 23:44
  • 2
    @JDMX: Sure, they get the entire source code... without documentation, variable names, or anything else that would help actually *understand* the translated IL. If that's all it takes for someone to rip you off, I'd have to believe that it would be almost as easy to just reverse-engineer. – Aaronaught Feb 25 '10 at 23:51
  • @Aaronaught.. Have you used a Reflector? Yes you do not get the documentation, variable names or comments but there is alot in there you can understand. If you have any knowledge of how the end process works and what to look for top level ( forms, buttons, etc ), you can easily drill down to find what you need to know. I have used the Reflector numerous times to see what actually happens in System.Windows.Forms.Control and the classes that inherit it so I can better develop custom controls like when are events called, do I have to override WndProc, etc. – JDMX Feb 26 '10 at 00:01
  • @JDMX: I use Reflector just about every day. I maintain that for a deployed application it's not going to be very useful; it's useful for the .NET Framework and certain other libraries because *we already have a documented public interface*, and also because the framework is extremely well-designed - the private implementation is just filling in the blanks. Very few shrinkwrap or business apps are going to be so easy to follow. Even if they are, the question still remains, just what is in there that can't be reverse-engineered? – Aaronaught Feb 26 '10 at 00:11
  • @Aaronaught. True.. a multi-tier platform is very hard to follow without docs.. but then all the information is not in the same exe either. But what if it was a game, picture manager, or some other program that is not as complex but still very useful. As far as reverse-engineering, it can be with on anything with enough time and money. But you want more protection than someone who uses the Reflector to open the exe and copy each class. – JDMX Feb 26 '10 at 00:22
  • @Aaronaught - as an aside (and also to support your point that the framework is wide open): Visual Studio has an option to enable .NET source stepping, which means you can step into .NET Framework source code with your debugger! Not exactly air-tight, but extremely useful in some cases. – Mark Carpenter Feb 26 '10 at 05:26

7 Answers7

37

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
  • 2,755
  • 18
  • 20
  • #2 - for sure. Could you use a digital certificate for decryption maybe as an alternative to embedding an encryption key? – Russell Feb 26 '10 at 02:13
  • 3
    @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 Feb 26 '10 at 02:59
  • 13
    Instead of encrypting assemblies - You can just code in Perl. – Arnis Lapsa Feb 26 '10 at 14:39
  • 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. – Roman Starkov May 16 '10 at 09:09
  • "Noone cares about your code" - worst comment award. It's business, it's monetization, intellectual property. – Epirocks Jun 13 '17 at 12:19
27

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
  • 647,829
  • 179
  • 1,238
  • 2,067
20

the generated exe file just a launcher that starts the runtime and passes the IL code to it.

Not exactly. There are different ways you can set up your program, but normally the IL code is compiled to native machine code that runs in process with the runtime.

As for the kiddies — you're deluding yourself if you think you can sell to them or anyone who uses what they redistribute. If they can't unlock your app they'll move on and find one they can or do without. They represent exactly $0 in potential sales; it makes little sense to spend too much effort attempting to thwart them because there'd be no return on your investment. A basic obfuscator might be fine, but don't go much beyond that.

Realistically, most developers face a much bigger challenge from obscurity than from piracy. Anything you do that prevents you from getting the word out about your product hurts you more than the pirates do. This includes making people pay money to get it. Most of the time a better approach is to have a free version of your app that the kiddies don't even need to unlock; something that already works for them well enough that cracking your app would just be a waste of their time, and not just a time or feature-limited trial. Let them and as many others as possible spread it far and wide.

Now I know that you do eventually need some paying customers. The key is to now use all the attention you get from the free product to upsell or promote something else that's more profitable. One option here is to also have a premium version with additional features targeted largely at a business audience; things like making it easy to deploy to an entire network and manage that way. Businesses have deeper pockets and are more likely to pay your license fees. Your free version then serves to promote your product and give it legitimacy for your business customers.

Of course, there are other models as well, but no matter what you do it's worth remembering that obscurity is the bigger challenge and that pirated copies of your software will never translate into sales. Ultimately (and of course this depends on your execution) you'll be able to make more money with a business model that takes advantage of those points than you will trying to fight them.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
6

"...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
  • 33,626
  • 4
  • 73
  • 96
6

"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
  • 61
  • 1
3

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
  • 37,399
  • 24
  • 94
  • 109
2

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)

Community
  • 1
  • 1
Michael Stum
  • 177,530
  • 117
  • 400
  • 535