Flipping bits on managed images to make them load with the right bitness...

In a number of blog entries I have discussed how on 64-bit machines .Net applications can run as either 32-bit or 64-bit processes depending on how the exe is produced. Generally it is highly recommended that developers use the compiler options provided by Whidbey compilers to specify the platform on which to run.

However, some people want to change the loading characteristics of an application after it has been compiled, or maybe you don’t have access to the code, etc… For that case we have an SDK tool called corflags.exe. Corflags allows you to modify some of the loading characteristics of a managed app.

Here’s is the command line help for Corflags.exe

Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 2.0.50405.00
Copyright (C) Microsoft Corporation. All rights reserved.

Usage: Corflags.exe Assembly [options]

If no options are specified, the flags for the given image are displayed.

Options:
/ILONLY+ /ILONLY- Sets/clears the ILONLY flag
/32BIT+ /32BIT- Sets/clears the 32BIT flag
/UpgradeCLRHeader Upgrade the CLR Header to version 2.5
/RevertCLRHeader Revert the CLR Header to version 2.0
/Force Force an assembly update even if the image is
strong name signed.
WARNING: Updating a strong name signed assembly
will require the assembly to be resigned before
it will execute properly.
/nologo Prevents corflags from displaying logo
/? or /help Display this usage message

WARNING: Corflags is a powerful tool, and you can break code in weird ways by using it incorrectly. As mentioned previously, it is highly recommended that you control the loading characteristics of your application through compiler switches.

Here are a couple of examples of Corflags.exe usage:

Scenario: you have an application foo.exe which was compiled “any cpu” with a Whidbey compiler, but you want to force it to run as a 32-bit application even on 64-bit machines.

Run: corflags.exe /32BIT+ foo.exe

Result: foo.exe is now marked as if it was compiled /platform:x86

Scenario: you have an Everett (.Net 1.1) application bar.exe which you would like to enable to run on 64-bit.

Run: corflags /UpgradeCLRHeader bar.exe

Result: bar.exe now looks like a Whidbey (.Net 2.0) “any cpu” application and will load under the 64-bit 2.0 runtime on a 64-bit OS. It is still Everett compatible however and will run as a 32-bit 1.1 application on a 32-bit OS.

See this blog entry for more info on what /UpgradeCLRHeader does: https://blogs.msdn.com/joshwil/archive/2004/10/15/243019.aspx

 

It is notable that Corflags.exe doesn’t have the ability to force an application to only run on a 64-bit machine, that is something that needs to be done at the compiler level (Corflags.exe operates on PE32 images, whereas 64-bit only applications need to be PE32+ images).

Corflags wears another hat as a diagnosis tools for figuring out what the loading characteristics of your application will be:

E:\temp>corflags chartest.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 2.0.50405.00
Copyright (C) Microsoft Corporation. All rights reserved.

Version : v2.0.41026
CLR Header: 2.5
PE : PE32
CorFlags : 1
ILONLY : 1
32BIT : 0
Signed : 0

If you run Corflags.exe and pass a managed application name without any switches it will tell you what the state of the interesting flags in the image are. It is educational to play with compiling some test code using the different /platform:X switches and then running Corflags on the exe to see what the state of the executable is. Briefly:

ILONLY: Managed images are allowed to contain native code, however C# and VB images don’t. To be “any cpu” an image may only contain IL.

32BIT: Even if you have an image that only contains IL it still might have platform dependencies, the 32BIT flag is used to distinguish “x86” images from “any cpu” images. 64-bit images are distinguished by the fact that they have a PE type of PE32+.

CLR Header: 2.0 indicates a .Net 1.0 or .Net 1.1 (Everett) image, 2.5 indicates a .Net 2.0 (Whidbey) image. Very confusing, unfortunate but true.

Here’s some other interesting reading on the subject of where managed applications run on 64-bit machines:
https://blogs.msdn.com/joshwil/archive/2005/04/08/406567.aspx
https://blogs.msdn.com/joshwil/archive/2004/03/13/89163.aspx
https://blogs.msdn.com/joshwil/archive/2004/03/11/88280.aspx