Why do we care about a small utility called CorFlags? Most people probably did not, until the release of Windows 2008 R2. W2K8R2 was the first server OS to be released as 64-bit only. Before W2K8R2, the majority of Windows servers were running some version of a 32-bit OS, with the 64-bit flavors mostly reserved for large databases. So as admins began deploying it, all those 32-bit apps were forklifted into a 64-bit environment. This forced everyone to care about about what processor architecture their applications were compiled for.
Beginning with some versions of Windows XP, Microsoft introduced Windows 32-bit on Windows 64-bit. This was a subsystem on the 64-bit Windows operating system to run 32-bit compiled applications. It includes all the Libraries and Drivers that 32-bit applications expect and also transparently maintains separate Registry hives and System32 directories. All this is done to allow 32-bit applications to run seamlessly on 64-bit processors.
The PE header of every executable and assembly contains flags about what platform the executable is targeting. But if you have an executable compiled targeting a platform that doesn’t match what you’re using, you’ll end up with the following error (or something along this vein).
System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
Defining the PE Header
Before we look at how to use CorFlags to modify already compiled applications, lets look at how Flags get set in the PE Header during the build process in Visual Studio.
When a developer builds an executable or assembly in Visual Studio the Project properties has a setting for Target CPU. As of Visual Studio 2013 there are three options: Any CPU (the default), x86, or x64. The last two options are pretty self explanatory, but Any CPU seems to cause a lot of problems. Any CPU doesn’t specify 32-bit or 64-bit, and the application uses the default platform on the system. So on a 64-bit OS, it will run as 64-bit. Some applications will run fine in this manner, but the problem occurs when the application is using another assembly that is explicitly compiled as 32-bit. Lets look at the headers from of each of these builds using CFF Explorer. You can also use the dumpbin.exe utility that installs with Visual Studio to find the same info.
Compiling with the AnyCPU option doesn’t set the 32-bit required flag.
CorFlags Output Version : v4.0.30319 CLR Header: 2.5 PE : PE32 CorFlags : 1 ILONLY : 1 32BIT : 0 Signed : 0
Compiling with the x86 option sets the 32-bit required flag.
CorFlags Output Version : v4.0.30319 CLR Header: 2.5 PE : PE32 CorFlags : 3 ILONLY : 1 32BIT : 1 Signed : 0
Compiling with the x64 option does notset the 32-bit required flag. Notice the PE flag is set to PE32+
CorFlags Output Version : v4.0.30319 CLR Header: 2.5 PE : PE32+ CorFlags : 1 ILONLY : 1 32BIT : 0 Signed : 0
CorFlags.exe is a utility that is bundled with the Windows SDK. Download and install the SDK to get the latest version. CorFlags.exe itself doesn’t require the SDK to be installed, so you can copy the exe to other machines for usage or run it from a share.
To view the current flags on an executable, run the following command:
C:\Code\bin>C:\CorFlags.exe /nologo Worker.exe Version : v4.0.30319 CLR Header: 2.5 PE : PE32+ CorFlags : 1 ILONLY : 1 32BIT : 0 Signed : 0
The most commonly used option is to set the 32BIT flag on an executable that was compiled as AnyCPU. Do that using the /32BIT+ argument, then recheck the set flags.
C:\Code\bin>C:\CorFlags.exe /nologo Worker.exe /32BIT+ C:\Code\bin>C:\CorFlags.exe /nologo Worker.exe Version : v4.0.30319 CLR Header: 2.5 PE : PE32+ CorFlags : 3 ILONLY : 1 32BIT : 1 Signed : 0
What About IIS?
Since the introduction of Application Pools in Windows 2003/IIS6 the targeted processor for the application pool could be set by the Administrator. So if you had a 32-bit compiled ASP.NET, which most were at the time, you could set IIS to run it as 32-bit. This made life easy when dealing with all the existing 32-bit database drivers. In IIS6 you could configure an application pool to run in WoW64 mode. It wasn’t configurable via the IIS6 GUI, but could be set from the command line as follows:
cscript.exe adsutil.vbs set W3SVC/AppPools/Enable32BitAppOnWin64 “true”
In IIS7 and IIS8 life is a bit easier, and this setting shows up in the Admin GUI and is stored in the applicationhost.config.
64bit PEs are always built for a specific platform, only PE32 assemblies are allowed to run on every framework (x86 systems wouldn’t be able to execute a PE64). Anyway, it’s possible to make PE32 assemblies run just on the x86 framework by just setting one flag in the .NET Directory (
IMAGE_COR20_DIRECTORY). The flag is
COMIMAGE_FLAGS_32BITREQUIRED. By setting this flag you’ll force to execute the given assembly as a 32bit process even on 64bit platforms.