Visual Studio 2005 security updates and CRT DLL versions in manifest - security

Recent Visual Studio 2005 security updates may be causing problems for us.
We build and internally distribute SDKs written in C++. These SDKs are a collection of header files and static libraries only. After installing the security updates our SDKs now depend on the newer versions of the MSVC CRT DLLs. These SDKs are used downstream in projects which produce EXE files.
If one of these EXE files is built with a mix of SDKs (some from before the security updates, some from after), then the EXE file produced makes reference to two sets of MSVC runtime DLLs. E.g:
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.4053" processorArchitecture="amd64" publicKeyToken="1fc8b3b9a1e18e3b">
</assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.762" processorArchitecture="amd64" publicKeyToken="1fc8b3b9a1e18e3b">
</assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>
Does this mean that at runtime this EXE will be using both versions of the DLL? Does this mean we must distribute both versions of the MSVC Runtime DLLs with this EXE?
Is there a simple way to avoid this problem without forcing all SDKs to be built with the Visual Studio 2005 security patches in place? (This would be undesirable for some of the older and quite stable SDKs that we don't want to rebuild unnecessarily)
Is is possible to simply rewrite the manifest file on either the SDKs or the final EXE file so that only one version of the MSVC CRT DLLs are mentioned?
My understanding is that the relevant updates are as follows:
Security update for Microsoft Visual Studio 2005 Service Pack 1: KB971090
http://go.microsoft.com/fwlink/?LinkId=155934
Security update for Microsoft Visual Studio 2008 Service Pack 1: KB971092
http://go.microsoft.com/fwlink/?LinkID=155933
I have discovered two other questions which are similar:
VC++: KB971090 and selecting Visual C Runtime DLL dependencies
Does the latest Visual Studio 2005 Security Update cause C runtime library issues when hot fixing customer sites

1) Yes it means the runtime is using both versions - something you never want to happen. It should only ever reference a single version of the DLL(s)
2) There is a method that I've developed to force the version to be the SP1 version (without the security update). I've outlined it here
3) You could disable manifests entirely and do them by hand, but I don't recommend this, as it's a pain to maintain different manifests for your debug and release, and it's an error-prone way of dealing with the problem. It would be better to use the workaround I mentioned in (2) above.

As Ted says, at runtime your executable will be trying to use both versions of the DLL. This is probably because you haven't fully recompiled the entire project (or you are using external libraries that have been compiled to depend upon the .762 runtime).
The good news is that if both these libraries are installed on your client systems then the side-by-side redirection policy will mean that only the latest is loaded. By far the more detrimental side-effect you will notice is when only one is installed (probably .762) that the application will fail to start with the old "application is not configured correctly, reinstalling may fix this problem" error message.
Does this mean we must distribute both versions of the MSVC Runtime DLLs with this EXE?
The easiest solution for you would probably be to just ship the latest version of the visual c++ runtime redistributable which you can get from the following link.
http://download.microsoft.com/download/6/B/B/6BB661D6-A8AE-4819-B79F-236472F6070C/vcredist_x86.exe
It can be a bit of a pain because it asks the user to click "I agree" on a EULA page and requires admin priveledges but by general consensus it is the best option if you can get the user to install it.

Related

Why don't programs simply use the newest version of C++ Redistributable?

I've read articles explaining that programs that use C++ redistributable will install multiple versions, depending on what they need. But none of the articles I've read have explained why it's so important to have different versions. Why can't programs just use the content from the newest version?
The only problem I see is if something gets deprecated. But in that case, I think there should be some handler that can still spit out the desired result. Other than that, the only issue would be that old applications wouldn't follow this "rule" of using newest versions.
So, why isn't it that programs will just use the newest version?
Generally the VS CRT is version specific. VS 2013 Update 5 version of the CRT will work with a program built by any version of VS 2013, but it doesn't work with VS 2012 or VS 2015. This is because the language and Standard Library makes use of elements of the CRT, and as the compiler changes so does the CRT.
That said, exactly how the servicing is handled has changed over time. Back in VS 2005 / VS 2008, a side-by-side technology known as "Fusion" was employed to try to make it seamless, but it proved to be quirky and to scale poorly. Since VS 2010, "Fusion" is no longer used and programs are expected to either (a) run in the REDIST EXE/MSM to deploy the needed CRT to the %WINDIR% or (b) put the DLLs application local with your program's EXE. The first gets serviced by Windows Update, the second does not.
See
How to redistribute the Visual C++ Libraries with your application and
C-Runtime Deployment: Why choose AppLocal?
For VS 2015 the CRT was refactored to try to make the "compiler-specific" parts of the CRT distinct from the "platform-specific" parts distinct from the "standard functionality" parts. See The Great C Runtime (CRT) Refactoring and Introducing the Universal CRT
Note that for Universal Window Platform apps, the Windows Store takes care of deploying the CRT for you.
Due to DLL Hell problems, Side-by-side assemblies (including native DLLs, not just managed assemblies) were introduced. This resolves DLL hell problem - i.e. various installers overwriting DLLs used by other programs. With SxS, there has to be multiple versions of same DLL, so that no program would break. You cannot have both (same DLL, but SxS assemblies).
Various VC++ runtimes are nothing but SxS assemblies having GUID based DLLs placed in C:\Windows\WinSxS - your program is bound to particular version, platform - and it won't break.

Microsoft vcredist uses later version at runtime than specified in the manifest

How does the Microsoft C++ redistributable package work?
I have a binary which is built in visual studio 2008. It uses the RunTime Library as "Multi-threaded DLL (/MD)". The version in the manifest is Microsoft.VC90.CRT" version="9.0.21022.8". I have chosen the option to embed the manifest to the binary.
When this binary is deployed in the target machine, it gives a runtime error stating that
The procedure entry point could not be located in the dynamic link library MSVCP90.dll
I understand that the version of msvcp90.dll which the machine contains by default, doesn't have a function that my binary is referring to.
Now I install the vc++ redistributable (vcredist_x86_9.0.30729.17) and run the binary again.
This time it works fine and I see that the loaded msvcp90.dll is of version 9.0.30729 instead of 9.0.21022.8.
How does this happen? How does my exe choose the latest version of msvcp90.dll even though the embedded manifest has the version as 9.0.21022.8?
I believe these variances are specific to the VS 2008 RTM vs the SP1.
The manifest will specify the code's intent, necessary privileges, etc. However, the system will detect the dependencies even if a manifest doesn't exist. Your program depends on VC90 ver 9.0.21022.8 or greater. That is the only concern. The app.config however can assist in the specific version that is bound, similar to the following:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<configuration>
<windows>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
<bindingRedirect oldVersion="9.0.30729.1" newVersion="9.0.21022.8"/>
</dependentAssembly>
</assemblyBinding>
</windows>
</configuration>
In the app.manifest, you can set _BIND_TO_CURRENT_VCLIBS_VERSION to control this.
The .h and .lib files determine the dependency.
--> EDIT:
Regarding your comment about the name mangled entry point _Xbad#tr1#std##YAXW4error_type#regex_constants#12##Z:
(undecorated is void std::tr1::_Xbad(enum std::tr1::regex_constants::error_type))
It is in fact found in the later SP1 MSVCP90.DLL (9.0.30729.17)
Ordinal: 1513 (0x05E9)
However it is not located in the older RTM version (9.0.21022.8)
(Use dependency walker to view the entry points)
You must have compiled your code with the latest .h and .lib for the linker to resolve the function, so it is curious why your dependency version would not be updated since your code requires a function which does not exist in the older version. I would ensure that your dependencies target the newer version. I hope this helps.

How to allow DLLs compiled against different versions of Visual Studio in the same process to use Threading Building Blocks

In my DirectShow application I have a third party DLL (a 32bit DirectShow filter) that I don't have source for that links against the 32bit Windows version of Intel Threading Building Blocks (tbb.dll).
If I want to use Threading Building Blocks in my own DLL in the same process (e.g. another 32bit DirectShow filter) does this force me to use the same version of Visual Studio that the author of this third party DLL used?
EDIT - I've realised that the version independent _mt library is probably the best one to use in this scenario. What happens if third party vendors haven't built for this _mt dll?
In my own Threading Building blocks installation I notice that there are different versions of tbb.dll for different versions of Visual Studio - 2005, 2008, 2010 and 'MT' (not sure what that is yet). One obvious reason for this is that the different versions of tbb.dll link against different versions of the Visual Studio runtime library DLLs. Is it possible to tell which version of tbb.dll is required by inspection or do I have to grub around looking for strings in the binary indicating the compiler version used (the third party DLL appears to be linking the visual studio runtimes statically)?
As far as I can tell tbb.dll doesn't use manifests and side by side versioning and is given the same name for different compiler versions. A last resort would be to rename the different tbb.dlls and hack the import library or imports to reference the renamed dlls but I'd really rather avoid this. Is there a clean way to redirect the imports with linker options?
As these DLLs are well behaved DirectShow filters they won't be passing Visual Studio runtime or TBB objects between them which would clearly be dangerous. Their interaction will be limited to calling each other via standard COM DirectShow calls.
If you are not using TBB, the question is only about Visual Studio versions, then you don't have to worry: Visual C++ Runtime DLLs have different names across versions, e.g. MSVCR70.DLL, MSVCR90.DLL etc. And, as you already discovered, /MT switch will compile/link a static version of runtime and will embed the stuff into your DLL without having to worry about sharing right DLL with a peer DLL.

Is it safe to rewrite an EXE or DLL manifest to force a particular version of the MSVC CRT DLLs?

Is it supported by Microsoft to simply rewrite the manifest of an EXE or DLL to force the use of a specific version of the MSVC CRT?
I am interested in doing this because of recent problems with Visual Studio 2005/2008 security updates (KB971090 and KB971092). I would like to simply rewrite the manifest as a post build step in order to stop the problem of multiple versions of the CRT DLLs appearing there.
The two versions of the MSVC CRT DLL in question are v8.0.50727.4053 and v8.0.50727.762, so only minor version number changes.
This question has branched out from: Visual Studio 2005 security updates and CRT DLL versions in manifest
this is a safe way and is automated so does not require any manual maintenance of manifest files

RunDll32 Problem on Win2k with Visual C++ 2008 Express Compiled DLL

First off, I'm not a C++ programmer (but I am learning). I have finally managed to modify and compile some C++ source code using Visual C++ 2008 Express Edition. I've tried to get the same code compiled in the full version of Visual C++ 2003 without success (I get a wide variety of errors, but no luck).
The problem is that everything is working fine using RunDll32 to call the DLL on Windows Vista, but when I try the same rundll32 call on Windows 2000, I get the following error:
"Error loading mysampledll.dll"
"The specified module could not be found."
Of course, I've tried setting the full path, moving the file around, etc...but no luck. I guarantee that the file exists and has the correct permissions.
I thought perhaps that there is something wrong with the manifest that is getting compiled along with the DLL in Vista. So I removed it using a resource editor, but then I get the same error in Vista and Win2k. Here's the manifest:
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.DebugCRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>
Now, I assume that the problem is with Win2k not having the Microsoft.VC90.CRT installed, but why does my DLL have this dependency? I've set the "Common Language Runtime Support" to "No Common Language Runtime Support" in the project properties, so why does it still require the CLR? Is there a way to change the manifest to use an older Visual C++ runtime that is available by default in Win2k? Sorry for my ignorance in these matters, and thanks in advance for any help.
Try installing the Visual Studio 2008 Redistributable package.
It contains the C++ runtime DLL that your program needs.
Don't get confused. That is not the CLR. The CLR is for managed code, not native Intel executables. Even native executables need the Microsoft runtime library dll if you dynamically link them to the runtime. This is the default in project properties, C++, Code Generation, Runtime Library = Multi-Threaded DLL. You can avoid this by choosing Multi-threaded, which would statically link in the library code.
I would say that on the Windows 2000 box your DLL won't load because it is missing a dependency.
You find out what is missing by downloading the Depends utility found here: http://www.dependencywalker.com/
If it is a MSCRT DLL that is mising then you will need to reditribute these DLL's with your DLL.
The problem is that you are trying to run a DLL compiled with the debug C-Runtime (CRT) library linked in.
To fix the problem, link in the non debug CRT with your DLL:
Option 1: Build and distribute the release version. (This is what you should be doing anyway when it's time to release.)
To do this:
List item
Build.Configuration Manager... and change your target flavor from Debug to Release; or
Build.Batch Build... and check of both Debug and Release; and
Use the binaries that come out of the Release directory.
Option 2: Build your debug binaries with the non-debug CRT.
To do this:
List item
Project.Properties...
Navigate to C/C++, Code Generation
For Runtime Library, select Multithreaded DLL or Multithreaded.
I tend to go with option 2 for quick and dirty projects, where I want the speed of the retail CLR, but want all the debug info for my code.
(By the way, CLR != CRT, but that's a different discussion.)
Note that you can also redistribute the CRT DLLs with your application, if you'd rather not require your users to run the CRT installer. You'll find them in your VC installation directory under redist\x86 (C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT is the full path on my machine). Note that you must copy all four files in that directory (three DLLs and a manifest) and place them next to your EXE for this to work properly.
If you're doing anything more complicated, like building a DLL that other applications will load this is insufficient, but this suffices for most cases.

Resources