April 2004 - Posts

In some cases it's needed to authenticate yourself to use an SMTP server to send e-mails. At first sight, the .NET Framework's MailMessage class does not offer support for this. However, there is the magic collection "Fields" of the MailMessage class that can help you to do this. Darren Jefford (MS UK) explains this on his blog: http://blogs.gotdotnet.com/darrenj/permalink.aspx/abb9e979-98dd-4172-b07c-2c4919ed94bfDel.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

For the moment, I'm investigating the possibilities to create 'shell extensions' in Windows Explorer using C#. Since the testing of this requires loading and unloading assemblies quite a lot, it's sometimes necessairy to unload explorer.exe completely before I can start to run another try to get it work. There are actual three ways to do this:

  1. Shut down the machine and reboot :-)
  2. CTRL-ALT-DEL, Task Manager, Processes, explorer.exe, End process
  3. Go to Start, Shut Down and press the Cancel button while holding CTRL, SHIFT, ALT and restart explorer.exe via the Task Manager

The third way seems to be the best way to terminate explorer.exe friendly but you should know about it of course... The same holds for the rather unknown key combination WIN-PAUSE which opens the system properties dialog.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

I'd just like to share some interesting points during my further preparation of the resources I mentioned earlier. For the second part (the last I'll prepare today since I have a rather busy day tomorrow) of the presentation I'm working on the facts about sharing assemblies using the GAC. I hope some of the blog readers already have been doing this, but let's give a quick review on the facts about this.

In .NET assemblies are self-describing and therefore do not need registration in the registry anymore. This is the reason why the xcopy deployment (or zero touch installation) in the .NET Framework works the way it does: just copy the files to a folder and the app will work smoothly. Now, this is great for several reasons: no more DLL hell (finally :-)), support for multiple versions of an assembly living together, simple installation, etc. However, there are situations where you do want to share assemblies across multiple applications running on the machine. For this reason, there is a component of the .NET Framework installation called the Global Assembly Cache or GAC. You can see the GAC as a sort of central 'repository' where the assemblies are stored that should be accessible by any application on the box (e.g. the System.*.dll assemblies live in the GAC). To avoid problems of the DLL hell, the way to put assemblies in the GAC is not analogous to the way of installing COM dll's on the system by using regsvr32.exe. Time to investigate this a little further...

First of all, we can't afford to be tricked by the same mouse trap again as in the COM world, that is the infamous 'version conflict' problem. Thus, it should be possible to install two versions of the same assembly on the system without having a risk on non-backward compatibility problems. This is why the .NET Framework requires that shared assemblies have a strong name, that is a name which consist of

  • the name of the assembly
  • the version
  • a public key (in fact, a hash of the public key in 64 bits, called a 'token')
  • the culture

To create a strong name for an assembly (that is, to generate a key pair), you'll have to use the sn.exe (abbreviation for 'strong name') tool of the .NET Framework. The most used switch is the -k switch that is used to create the pair of keys (private and public) and store it in a specified file (size of 596 bytes). What is of most interest for the 'assembly signing part' is the public key (and the token in particular) of the key pair, which can be extracted from the file using the -p switch (result of 160 bytes). To find out the toke, you can run the sn.exe -tp command which will extract the public key from the given file with the key pair and display the public key token that will be used to sign the assembly.

The next step is to tell the compiler that it should use the key to sign the assembly which can be done in the AssemblyInfo.cs (or .vb) file using the 'AssemblyKeyFile' attribute in the file (although it can be placed in any code file that is part of the compiled unit). My demo file looks as follows:

using System.Reflection;

[assembly:AssemblyKeyFile("test.key")]
class Test
{
 public static void Main()
 {
 }
}

The interesting part happens when the file is compiled and is examined using a hex editor again. During compilation the PE file (I mentioned earlier) is hashed using SHA-1 and signed using the private key (this explains why the specified file needs to have a key pair):

error CS1548: Cryptographic failure while signing assembly 'c:\Documents and
        Settings\Administrator\test.exe' -- 'Key file 'pub.key' is missing the
        private key needed for signing'

This hash results in an RSA signature that is stored inside the file together with the public key as a part of the file's manifest. The hex editor will show you the sign parts in the file (you'll see the string 'RSA' somewhere in the byte stream as well as the original name of the file containing the key). Furthermore, the other metadata can be recognized as well (it's stored in Unicode format), for example the version string. To visualize things somewhat better, you can use the ildasm.exe tool (IL disassembler) using the /BYTES switch to view the public key in hex format as well (take a look in the MANIFEST part).

  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..

  .publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00   // .$..............
                00 24 00 00 52 53 41 31 00 04 00 00 01 00 01 00   // .$..RSA1........
                EB 52 95 2E 19 32 81 86 D8 E9 09 CA 24 30 74 1A   // .R...2......$0t.
                A7 C9 C4 A3 73 50 21 B9 D0 E7 84 9B 5C A5 EA 73   // ....sP!.....\..s
                39 09 09 76 27 0E 27 A4 43 97 42 32 7D E1 99 A8   // 9..v'.'.C.B2}...
                C3 17 29 00 DF 68 FA 4A 99 C6 D8 24 79 02 E3 43   // ..)..h.J...$y..C
                A2 C1 F0 CB B2 A9 78 9E E0 8A 1E D7 C8 63 A6 80   // ......x......c..
                E4 1A 01 EE D1 81 55 39 80 C4 E5 57 A3 B5 8E 15   // ......U9...W....
                C9 B2 51 B9 18 59 EA F7 5F 72 18 F9 65 6C 11 86   // ..Q..Y.._r..el..
                4D 98 F4 8B 3B D0 74 80 22 F9 C4 FF BC 00 99 D9 ) // M...;.t.".......

A pretty cool trick to view more info on an assembly is the use of ildasm.exe /adv (uncommented AFAIK). When you're using this option, you'll get another series of options in the view menu to:

  • show the COR header (consisting of the PE header - see earlier post - and the CLR header)
  • statistics of the file (how much PE headers etc)
  • meta info (using CTRL-M, an option that is available in any single mode, except that it is not visible in the menu when running without the /adv flag)

Now you can put the assembly in the GAC by using the gacutil.exe tool with the i option (or u to uninstall). Gacutil will definitely be your friend if you're developing and using the GAC quite often. One thing to keep in mind, different version numbers will result in different copies of an assembly in the GAC (so it might be useful to disable versioning inside the AssemblyInfo file by replacing the * symbols in the version string by static numbers). When the assembly is installed in the GAC, it will appear in the 'folder' %windir%\assembly (hidden as a real folder by an explorer shell extension), or you can visualize the files on the DOS prompt in %windir%\assembly\GAC (every assembly 'name' has a dedicated folder that contains subfolders for any version/key token pair of the assembly).

A nice part of the demo is the one that shows that a signed file only can be executed when it is tamper-free, so nobody has changed the contents of the file. When you change one byte (e.g. by changing the load address in the PE header) in the test.exe file that was compiled using the key, you'll end up with an exception being thrown by the CLR when the file is tried to be loaded:

Unhandled Exception: System.IO.FileLoadException: Strong name validation failed
for assembly 'test.exe'.
File name: "test.exe"

The same tampering in a non-signed file does not result in an error. However, when you plan to change the file after compilation before shipping it, you may consider to use delayed signing. Another reason is the availability of the private key to sign the file (a private key should be private and thus should not be shared with tons of developers!) and thus delayed/partial signing can help. When you're doing this, you only need the public key to sign the file but as a side-effect you loose the tamper-protection (which is in fact an advantage during development time). To do the delayed signing, you only have to specify the [assembly:AssemblyDelaySignAttribute(true)] attribute. Okay, so far so good. As you'll see, the file can be compiled using the public key file only (generated and shared through sn.exe -p); this is the source code:

using System.Reflection;
using System.Runtime.CompilerServices;

[assembly:AssemblyKeyFile("pub.key")]
[assembly:AssemblyDelaySignAttribute(true)]
class Test
{
}

However, the assembly can't be installed in the GAC right now. The output of the gacutil.exe tool will look as follows:

C:\Documents and Settings\Administrator>gacutil.exe -i test.dll

Microsoft (R) .NET Global Assembly Cache Utility.  Version 1.1.4322.573
Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

Failure adding assembly to the cache: Strong name signature could not be verifie
d.  Was the assembly built delay-signed?

To avoid this problem, we should tell the system to skip the verification on the assembly prior to the installation in the GAC. This can be done using sn.exe as well, using the -Vr switch (and by specifying the file name). By doing this, a verification entry will be stored on the system for the specified assembly-token pair:

Verification entry added for assembly 'test,0E4FC5331591798C'

When you want to drop the entry for verification skipping you can use the -Vu (drop entry for one assembly) and -Vx (drop all entries) switches of sn.exe.

Although delayed signing is useful when you're developing the product, it should not be used in production since we're skipping the verification of the assembly (therefore loosing advantages of the sign process). To roll the assembly in production, the responsible developer for the development and management of the deployment of the application should re-sign the assembly using the key pair (this developer is one of the people who have access to that key!) and the sn.exe -R switch.

Enough for the blog now I'll just finalize some presentation stuff on how the CLR determines which version of a referenced assembly to load and some configuration hooks to help the CLR to find the right assemblies and to change the default behavior. And last but not least, I have to prepare the al.exe stuff as well. Will be late again :-(.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Preparing a talk for some guys on ".NET Framework Internals" to discover the dark sides of the CLR, IL and the rest of the .NET Framework...

Did you ever wonder how .NET assemblies are executed when you start the .exe file? Let's start with some brief overview of the role of the CLR in this - I hope everybody who has ever worked with .NET knows this already: when you're using one of the .NET compilers (such as csc.exe, vbc.exe) you'll be compiling your code into IL - intermediate language - which is a sort of 'universal machine code' that can be executed by the CLR. The CLR has the role to load the IL and JIT (just-in-time) compile it to native code according to the platform the code is running on. This makes the use of the .NET Framework a real advantage: it's language-independent (in contrast to other middleware systems), it's fast since it's compiled at some point (in contrast ...), it's portable (okay, not in contrast to ... :-)). Now, let's compare this with the way Java works: there's a javac.exe compiler to create bytecode in a .class file and there's the interpreter called java.exe to read the bytecode and execute it. This is fairly simple to understand: you take the message which the computer itself does not understand and give it to some translator to read the code, translate it and execute it on the target platform. The .NET Framework (and the CLR more specifically) works different. Although it's still a language which is not understood by the processor of the machine (it's IL, not native code), it's stored in a .exe file. This is one of the 'dark sides' of the .NET Framework which I'll explain during my talk. I'll try to explain it over here as well.

What the .NET compilers spit out is a file called an assembly which has the extension .dll or .exe. Assemblies are a pure .NET-related word which did not exist in the pre-.NET COM-world (or hell?). Now, what does this file contain? It mainly consists of 4 key parts:

  • The IL-code (Intermediate Language) which is the translation of the original language to the code that can be executed by the CLR.
  • Metadata that makes the assembly self-describing (remember the xcopy deployment of .NET assemblies vs. the regsvr32 deployment in the world of COM)
  • A header for the CLR to find out CLR-version info, tokens, flags, the strong name (for assemblies in the GAC signed using sn.exe), etc
  • The PE header that is found in any executable and contains information on the type of the application etc (note: this has nothing to do with Windows PE ;-))

As you can see, the only common part with classic executable is the PE header (portable executable) in the file that is used by Windows to load the executable and start the execution of it. This is where the tricky part takes places. In fact, a CLR assembly just uses this PE header to start the CLR and give the CLR the instruction to take over the execution of the file (other information in the PE header is ignored, while for classic executables the PE header contains information about the native CPU code as well). To find out how things work, open a .exe assembly using a heximal editor. You'll find a few elements in the file that are of interest:

  • mscoree.dll - this is a reference to the main .dll of the CLR that contains the Component Object Runtime Execution Engine (the import takes places in a special import section marked as .idata)
  • _CorExeMain - the name of the entry point in the CLR's dll file to transfer the execution of the file to (at this point, the CLR takes over the control and determines the entry point of the loaded assembly to start JITting and exeucting the file)

In hexadecimal format, the magic occurs over here:

5F 43 6F 72 45 78 65 4D 61 69 6E 00 6D 73 63 6F 72 65 65 2E 64 6C 6C

So, the power is in the jump-instruction to the imported _CorExeMain function (or _CorDllMain for .dll assemblies). More information (although limited) can be found on MSDN via http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/grfuncorexemain.asp. In order to get this thing to work in all kinds of Windows OSes (starting with Windows 98 and NT 4) the compilers generate a JMP 'stub function' of 6 bytes (x86 format, you know). Since Windows Server 2003 and XP support both 64-bits architectures as well (cf. Itanium), the executable loader in these OSes was changed to support the execution of managed code natively (skipping the .idata mscoree.dll load) by examining the PE file header.

Maybe this looks exciting but in fact it's not that new :-). All flavors of pre-.NET Visual Basic use the same tricks to launch the - in this case - interpreter to execute the VB code. The dll that is responsible for the execution is called MSVBVMxx.dll (stands for Visual Basic Virtual Machine). This time the hex magic looks as follows:

4D 53 56 42 56 4D 36 30 2E 44 4C 4C

PS: Unfortunately, the talk is not a 'public event' but I'll put the resources on-line after the session if I don't forget :-)

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Check out on the Microsoft Belux website for this event for developers, IT Pro's and Technology decision makers on security:
http://www.microsoft.com/belux/nl/securitymobilization/securitysummit/default.mspx

When? May 4th
Where? Kinepolis Brussels
Cost? Free, but limited seating, so register asap

I'll be there. Hope to see you as well :-)

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Please welcome the two first bloggers of Microsoft Belux (AFAIK):

Rudi Larno on http://blogs.msdn.com/rudi_larno
Yves Kerwyn on http://www.kerwyn.be

Welcome guys!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Good news for both parties. By giving more access to each other's technologies, product can be improved and the interoperability claim of .NET (think of XML Web Services etc) will become more and more a reality. As mentioned in the PressPass article: "Microsoft Corporation (NASDAQ: MSFT) and Sun Microsystems, Inc. (NASDAQ: SUNW) today announced that they have entered into a broad technology collaboration arrangement to enable their products to work better together and to settle all pending litigation between the two companies. The companies have also entered into agreements on patents and other issues." More info on http://www.microsoft.com/presspass/press/2004/apr04/04-02SunAgreementPR.asp.

My personal opinion: although I know Java rather well I'm not a real Java-fan as most of you know but this is definitely a great step to make both the .NET technology and the Java technology capable to work together. And for the everyday end-user, the confusion on which Java to use etc (think of Windows XP SP1 with the struggles on MSJVM) will hopefully stop. Because of this, the MSJVM will be supported again by Microsoft.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

More Posts