Taming Chameleon Applications

Another super in-depth write up by Jacques Bensimon.  Thanks JB!

As the great migration to 64-bit Windows continues, most of us have by now had ample opportunity to confirm the statement made in a previous post to the effect that, with few exceptions, a run-of-the-mill 32-bit program that neither knows about nor cares about 64-bit environments is automatically presented a “32-bit view” of a 64-bit environment and should install and operate without issues.  But there are those pesky exceptions, and one particularly strange category of potential exceptions I ran across I initially dubbed “Chameleon Applications” before figuring out what they were, why some of them had issues, and how to get around the issues.
I’ll first describe the observed behavior of just two such problematic applications before explaining the reason for the “chameleon” moniker – in both cases, these were neither particularly new nor particularly old 32-bit applications that had installed without issues or complaints on a 64-bit platform (Windows Server 2008 R2):

· App A:  This app had, during its setup, also successfully installed a 32-bit Crystal Reports runtime component but, when launched, inexplicably complained that it needed the 64-bit Crystal Reports runtime and would refuse to continue without it.

· App B:  This app consists of (1) a system service that occasionally updates a machine Registry key with a list of web addresses downloaded from a backend system (yes, even 32-bit services can run on 64-bit Windows) and of (2) an Internet Explorer plug-in which accesses that list of web addresses from the Registry as part of its job (don’t ask).  This cooperation wasn’t working as expected because, as it turned out, the system service was writing the web addresses to a key somewhere under HKLM\Software\CompanyName… (i.e. unexpected 64-bit behavior) whereas the plug-in  was trying to read them from HKLM\Software\Wow64\32\NodeCompanyName… (i.e. normal 32-bit behavior).

In both cases, since 64-bit behavior was observed, my first thought was that the setup of these applications unexpectedly contained and had installed some 64-bit executables.  Yet, upon verification, both the main executable of App A and the system service executable of App B were confirmed to be 32-bit executables (here’s a new IPM  utility called TSFlag that, besides displaying and optionally changing any executable’s “Terminal Server Aware Flag”, also displays whether the executable is 32-bit, AMD 64-bit or IA64 – see sample screenshots below.   The archive contains both 32-bit and 64-bit versions of the utility).  However, and this is where the “chameleon” behavior comes in, when viewed in Task Manager while running, both the executables in questions were displayed as 64-bit processes!  Understand, we’re not talking here about programs like SysInternals’ “Process Explorer” and “Process Monitor” for example which consist of 32-bit executables that contain and extract a separate 64-bit version when launched on a 64-bit platform – these were 32-bit executables that somehow became 64-bit once loaded into memory and executed, an impossibility as far as I was aware.
The answer:  Upon further examination (looking at the executables’ loaded modules in “Process Explorer”), it became clear that these magic executables were in fact .NET assemblies and that, against the implicit intent of their authors (who clearly had not considered or been aware of the possibility that they might someday be run on a 64-bit platform), they were executing under a 64-bit .NET Framework. This is apparently the default behavior on a 64-bit platform when an assembly isn’t explicitly coded or registered for execution under a 32-bit Framework, and  I neither know how to change this default behavior (if it can be changed) nor do I think it would be a good idea to do so – the ramifications could be very ugly.  There is however a Microsoft tool called CorFlags (found in the Windows SDK) that can modify a specific .NET assembly in such a way that it is compelled to run under a 32-bit Framework (the modification consists of flipping a single bit in the executable, as will be seen in a screenshot below).  The syntax for performing this modification with CorFlags is as follows:
CorFlags.exe assembly /32BIT+ /Force
Since this command actually modifies the target executable, it would be well to create a backup copy of the original executable before applying it.  Also, be aware that if the executable is strong-name signed, which is not frequently the case because strong-signing is not recommended for EXE assemblies, CorFlags warns that it needs to be resigned – I have not found this to be necessary in practice.  Both App A and App B, along with other misbehaving “chameleons” I’ve come across, have been functioning just fine since getting the CorFlags treatment.
NOTE:  There is no statement being made here that a 32-bit .NET assembly that winds up executing under a 64-bit Framework (i.e. a chameleon) will necessarily misbehave.  I’m sure if we look around our systems we’ll all find any number of 32-bit .NET apps and utilities that have been working just fine despite running under a 64-bit Framework, whether or not that was their authors’ intention.  The above workaround should therefore be reserved for those that do misbehave and for which their authors have not (yet) provided 64-bit-compliant versions.
For the purpose of illustrating the above concepts with a real example, I looked for a chameleon executable to which we all have relatively easy access, and came upon the executable vmconnect.exe installed as part of the Hyper-V Tools component of RSAT (Remote Server Administration Tools) on Windows 7 64-bit.  Without further comments, the following screenshots demonstrate that vmconnect.exe is a 32-bit executable that Task Manager lists as a 64-bit process whereas a copy of the executable (vmconnect2.exe) to which CorFlags has been applied as explained above is listed as a 32-bit process.  (Note that this was done only for illustration purposes as vmconnect.exe is not a misbehaving chameleon).
clip_image002
clip_image004
clip_image006

TAGS