Wednesday, December 20, 2006

Extracting a .Net assembly from af Netz compressed applicationI recently stumbled upon the Netz tool. The Netz tool can compress a complete .Net application and package it into a single executeable. That makes it great for deployment without an installer.
What struck me was that someone claimed that this tool protects your code from dissassembly through reflection (using a tool, such as Reflector).
Creating such a program is not possible, see my post on Obfuscation for an argument and explanation.

As the assembly is merely inserted into the Netz loader, as an embedded resource, it is very easy to write a small program that reads all such resources from an executeable, and dumps them to disk. In fact the code for this is just these lines:

Assembly asm = Assembly.LoadFile(Path.GetFullPath("NetzLoader.exe"));
ResourceManager rm = new ResourceManager("app", asm);

byte[] t = UnZip((byte[])rm.GetObject("A6C24BF5-3690-4982-887E-11E1B159B24"));
Stream st = File.Create("objdump.exe");
st.Write(t, 0, t.Length);

The GUID in the code, can be obtained by opening a Netz executeable, and view the resources. It seems that the name of the Resource is always app.resource.
The function named UnZip is not included in the code. It is a standard UnZip function, that takes a compressed byte array, and returns an uncompressed stream.

If you try to encrypt this stream, remeber that the decryption will have to run on the client machine, so one may load the assembly, and execute the decryption function (in short: Don't bother).

You can actually dump the resource file from a tool such as Reflector, but there are no functions that create a ResourceManager from a stream or byte array..
This procedure can be repeated for any number of files. I imagine that it is possible to obtain all the different resource names programatically, but I didn't bother trying.

I've also seen claims that the load time will decrease, as the disk image is smaller. I doubt that any disk IO will slow the program more than decompressing a stream. Also, there is a significant memory overhead, as the image will have to be in memory a number of times, during the read/unzip/load procedure.

The only proper use for this tool, is to allow distribution without an installer (msi installers carry compressed files per default).
The compressed format, makes it perfect for easy distribution. However, there are a few caveats that has to be adressed.

  • .Net executeables downloaded from the internet will carry a special attribute, that impairs their functionality. Such an executeable may not read registry keys, P/Invoke, etc.

  • There is no way to uninstall the program.

  • It may be possible to bypass virus scanners, seeing that no virus scanners open .Net executeables and try to decompress their resources.

The first two problems may not be a problem, if your application is a lightweight program, that does not interact with the users systen (such a program could be a calculator program).
The third problem may be adressed later by virus scanner builders, and thus suddenly disabling your program.

Generally you should choose to use the MSI installer format. If you want the easy way, use the tools in Visual Studio, if you like control, use the Nullsoft Install System.
If you truly have a lightweight application, consider the ClickOnce deployment system.

If you still think that having a single executeable is neat, try ILMerge.

No comments: