Sysinternals Freeware - Mark Russinovich & Bryce Cogswell

Mark's Sysinternals Blog

Buffer Overflows

No, I’m not talking about the kind of buffer overflows that viruses can take advantage of to inject malicious code onto other systems, I’m talking about the kind that, if you use Filemon or Regmon, you’ve probably seen in their traces. If you’ve never noticed one, fire up one of those two tools and after collecting a log of system-wide activity, find an example by searching for “buffer overflow”. Here’s an example of file system buffer overflow errors:



Do these errors indicate a problem? No, they are a standard way for the system to indicate that there’s more information available than can fit into a requester’s output buffer. In other words, the system is telling the caller that if it was to copy all the data requested, it would overflow the buffer. Thus, the error really means that a buffer overflow was avoided, not that one occurred.

Given that a buffer overflow means that a requester didn’t receive all the data that they asked for you’d expect programmers to avoid them, or when they can’t, to follow with another request specifying a buffer large enough for the data. However, in the Filemon trace neither case applies. Instead, there are two different requests in a row, each resulting in buffer overflow errors. In the first request the Csrss.exe process, which is the Windows environment subsystem process, queries information about a file system volume and in the second request it queries information about a particular file. It doesn’t follow up with successful requests, but continues with other activity.

The answer to why Csrss.exe doesn’t care that its requests result in errors lies in the type of requests it’s making. A program that queries volume information using Windows APIs is underneath using the NtQueryVolumeInformationFile API that’s exported by Ntdll.dll, the Native API export DLL (you can read more about the Native API here). There are several different classes of information that a program can query. The one that Csrss is asking for in the trace is FileFsVolumeInformation. The Windows Installable File System (IFS) Kit documents that for that class a caller should expect output data to be formatted as a FILE_FS_VOLUME_INFORMATION structure, which looks like this:

typedef struct _FILE_FS_VOLUME_INFORMATION {
LARGE_INTEGER VolumeCreationTime;
ULONG VolumeSerialNumber;
ULONG VolumeLabelLength;
BOOLEAN SupportsObjects;
WCHAR VolumeLabel[1];
} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION;

Notice that the first four fields in the structure have a fixed length while the last field, VolumeLabel, has a size that depends on the length of the volume’s label string.

When a file system driver gets this type of query it fills in as much information as fits in the caller’s buffer and, if the buffer is too small to hold the entire structure, returns a buffer overflow error and the size of the buffer required to hold all the data. I suspect that Csrss is really only interested in the volume creation time and therefore passing in a buffer only large enough to hold the first part of the structure. The file system driver fills that part in, and because the volume label won’t fit in Csrss’s buffer, returns an error. However, Csrss has gotten the information it wanted and ignores the error.

The second buffer overflow has a similar explaination. Csrss is querying information about a file using the FileAllInformation class of NtQueryInformationFile. The IFS Kit documents the output structure as:

typedef struct _FILE_ALL_INFORMATION {
FILE_BASIC_INFORMATION BasicInformation;
FILE_STANDARD_INFORMATION StandardInformation;
FILE_INTERNAL_INFORMATION InternalInformation;
FILE_EA_INFORMATION EaInformation;
FILE_ACCESS_INFORMATION AccessInformation;
FILE_POSITION_INFORMATION PositionInformation;
FILE_MODE_INFORMATION ModeInformation;
FILE_ALIGNMENT_INFORMATION AlignmentInformation;
FILE_NAME_INFORMATION NameInformation;
} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;

Again, the only variable length field is the last one, which stores the name of the file being queried. If Csrss doesn’t care about the name, only the information preceding it in the structure, it can pass a buffer only large enough to hold those fields and ignore the buffer overflow error.

Incidentally, a stack trace of the second buffer overflow reveals this:



What is the "sxs" module? A look at the sxs DLL in Process Explorer’s DLL View of the Csrss process shows this:



SxS is the “Fusion” DLL, which a little research will show manages the Side-by-Side Assembly storage that allows multiple versions of the same DLLs to exist in harmony on a system. SxS is calling GetFileInformationByHandle, which is a Windows API documented in the Platform SDK. The API takes a file handle as input and returns a buffer formatted as a BY_HANDLE_FILE_INFORMATION structure:

typedef struct _BY_HANDLE_FILE_INFORMATION {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD dwVolumeSerialNumber;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD nNumberOfLinks;
DWORD nFileIndexHigh;
DWORD nFileIndexLow;
} BY_HANDLE_FILE_INFORMATION;

All of the information returned in this structure, except for the volume serial number, is also returned in the FILE_ALL_INFORMATION structure. You can therefore probably guess where the call to NtQueryVolumeInformationFile that occurs immediately prior to the NtQueryInformationFile call originates: GetFileInformationByHandle first queries the volume in order to get its serial number.

Our investigation shows that the buffer overflow errors seen in the Filemon trace are errors expected by the GetFileInformationByHandle API, which is simply avoiding the need to allocate buffers large enough to hold information it’s not interested in. The bottom line is that buffer overflow errors in a Filemon trace are not an indication that there's a security problem and are usually not due to bad programming.

Next time I’ll explore buffer overflows in Regmon traces.

posted by Mark Russinovich @ 5:18 PM 8 comments

Running Everyday on 64-bit Windows

Last week I got an HP xw9300 workstation equipped with two 2GHz Opteron processors, the same type of system most of the Windows kernel team uses. The system came with 32-bit Windows XP preinstalled, but I decided to buy into all the 64-bit hype coming out of Microsoft’s Winhec conference and so I scratched the HP image, reformatted the disk, and installed Windows XP 64-bit Edition. Is Windows ready for 64-bit full-time? After a week of development, writing, and experimenting I’m ready for a preliminary report.

The first issue I ran into was lack of built-in driver support for the network adapter and video card. This was easily remedied, though, with a quick trip to Nvidia's web site to download their 64-bit motherboard and video drivers.

After getting Windows running I spent the first few hours with the system installing applications and tools. The installations went smoothly for just about everything except for one application that I’ve come to rely on: MSN Desktop Search (MDS). It’s especially ironic that MDS won’t run on 64-bit Windows given that it’s a high-profile application from the company that’s trumpeting the official arrival of 64-bit computing and telling device manufacturers that if they don’t have 64-bit drivers they’re already behind the times. What’s even more ironic about MDS’ lack of 64-bit support is the way that its installation fails:



The installer doesn’t even know its running on 64-bit Windows. The operating system version number reported on 32-bit Windows XP is 5.1, but since 64-bit Windows XP shares the same kernel as 64-bit Windows Server 2003 SP1 it reports a version number of 5.2 as this Msinfo32 screenshot shows:



I suspect that the MDS installer believes itself to be running on Windows Server 2003 and therefore refuses to install.

I used the application compatibility tab on the installer’s properties to trick the installer into thinking it was running on 32-bit Windows XP, which resulted in the installation getting further, but it failed with the same error a little later. The second time the error message comes from the Windows Installer Service while it’s processing the MDS MSI (Microsoft System Installer) file that the first installer extracts. The installer service is likely checking the operating system version again because of instructions in the MDS MSI.

Even if I had tricked MDS into installing I would have gotten only partial functionality. On 64-bit Windows there’s no cross-interoperability between 64-bit processes like Windows Explorer and 32-bit COM DLLs like those that make up MDS desktop extensions. The taskbar search window wouldn’t have worked, for instance.

The next issue I ran into was with the Emacs editor I’ve been using for at least five years. It requires no installation, but when I ran it on 64-bit windows nothing happened – no application startup cursor, no error dialog, and no Emacs. I ran it inside Windbg to see what was going on, but it provided little help. Here’s the stack trace at process termination:



The only thing I can get from this is that for some reason the Wow64 image loader, which is responsible for kicking off 32-bit application launches, is unhappy with the image. I’d at least expect an error dialog so this looks to me like a bug in the loader. I went to the web and downloaded a more recent version of Emacs for Windows that runs without problem.

Since I came originally from the UNIX world I’m used to keyboards that have a control key in place of the caps-lock key on PC keyboards. The very first tool I wrote for Windows NT back in mid-1996 addresses this problem. Ctrl2cap is a simple keyboard filter driver that converts the caps lock key into a left control. Since 64-bit Windows doesn’t run 32-bit drivers my typing was initially crippled, making a port of Ctrl2cap to 64-bits a top priority. The driver port only took a couple of minutes because there was just one variable cast that the 64-bit compiler didn’t like. Porting the Ctrl2cap installer utility that configures Ctrl2cap’s driver for activation was a different story.

My original goal was to have one installer that would work on both 32-bit and 64-bit versions of Windows. The executable would therefore have to be 32-bit and so I thought I might get away with no work at all. However, I ran into a mechanism called folder redirection: when a 32-bit image accesses the \Windows\System32 directory the Wow64 subsystem redirects it to \Windows\Syswow64 (think about that for a second: 64-bit binaries are in System32 while 32-bit binaries are in Syswow64). Here’s a Filemon trace of the 32-bit command-prompt performing a directory list of “\Windows\System32”:



This prevents 32-bit applications from overwriting the 64-bit system files and configuration stored in \Windows\System32. I wrote the Ctrl2cap installer to copy the Ctrl2cap driver to \Windows\System32\Drivers, which meant that when I ran it on 64-bit Windows the driver was copied to the wrong place (this resulted in a system with a dead keyboard, which I resolved by using the Last Known Good boot option).

I really wanted to avoid having separate 32-bit and 64-bit installers, so I spent time digging through my April 2005 copy of MSDN Library in search of an API that would let the installer override the redirection. I also spent some time investigating the behavior of the folder redirector and discovered what I believe is a bug. If you launch the 32-bit Command Prompt (both 32-bit and 64-bit versions ship with 64-bit Windows) and “cd” into \Windows\System32 you are really in \Windows\Syswow64. Now if you execute “start cmd.exe” you launch another copy of the 32-bit Command Prompt. The system information APIs, which Process Explorer makes use of, report the new cmd.exe’s image as being \Windows\Syswow64\Cmd.exe, but if you execute “start c:\windows\system32\cmd.exe” you get a new 32-bit Command Prompt with the system information APIs reporting the image path as \Windows\System32\Cmd.exe! Now you can’t trust the system information APIs. In the end I gave up and posted the 64-bit Ctrl2cap update with both 32-bit and 64-bit installers.

The fact that I had to post two different executables, as I’ve had to do for the other Sysinternals tools that have required 64-bit ports and that I’ve ported to 64-bit, like Filemon, Regmon and Process Explorer, highlights what I believe is a deficiency in the 64-bit loader. It should be possible to simply concatenate 32-bit and a 64-bit images together in the same file. These multi-platform images would run without change on 32-bit Windows, which would simply view them as 32-bit executables with some stuff added on the end. The 64-bit loader would require a very minor change to support them where it could quickly determine that such an image has several executables within it and launch the 64-bit version. Microsoft implemented a similar approach during the transition from the DOS image format to the Windows image format (Portable Executable) where a DOS stub built into every 32-bit image reports “This program cannot be run in DOS mode.” when executed by the DOS image loader. No change was made to the DOS loader to support that. Other operating systems that support 32-bit and 64-bit hardware support multi-image files and there are many cases, like for my tools, where it would make life easier in Windows.

A few days after I posted the new 64-bit Ctrl2cap, David Solomon, who heard my Ctrl2cap installer griping, wrote to tell me that in the Windows Server 2003 SP1 Platform Software Development Kit (SDK) “what’s new” section he came across an API named Wow64DisableWow64FsRedirection. The API does what its name implies and I promptly posted (source code included) a new Ctrl2cap with a single 32-bit installer. However, this brought to my attention the way that Microsoft is handling the Platform SDK.

First, I’m an MSDN Universal subscriber, yet I never received a copy of the Windows Server 2003 SP1 Platform SDK. When I went on-line to look for it in MSDN subscriber downloads I first went to Tools, SDKs and DDKs->Platform Tools, SDKs, DDKs->Platform SDK. There are two “latest” versions posted there: the November 2002 Edition and the Windows XP SP2 Platform SDK. There’s no sign of the Windows Server 2003 SP1 Platform SDK, which is over in Tools, SDKs and DDKs->Platform Tools, SDKs, DDKs->Windows Server 2003.

So the first problem is that instead of one Platform SDK, there are now three different versions. Second, there’s no single place to go find them, and third, the April release of the MSDN Library, which is the one shipped to MSDN subscribers, doesn’t include the latest SDK documentation (the on-line version of the library does include it). Microsoft should have a single Platform SDK and keep the MSDN Library that’s shipped to subscribers in sync with the Web version. But I digress.

Another Microsoft application I installed is Microsoft Antispyware (MSAS). The install went without problems, though MSAS is not really 64-bit ready. It’s a 32-bit application and is therefore subject to Wow64 Registry redirection on parts of the Registry, including HKLM\Software, which redirects to HKLM\Software\Wow6432Node. While MSAS will detect 32-bit spyware and adware configured to autostart, it won’t detect 64-bit malware. Sysinternals Autoruns also currently suffers this limitation.

Throughout the week I ran into a small number of other issues. For example, if you launch a process under the Visual Studio 6 debugger and then stop debugging the process is left as a zombie. The Borland Delphi 2005 debugger has a more serious issue: when you launch a process under the debugger it believes that the process exits immediately when the process actually starts properly. A workaround is to attach the debugger to the process after its launched. Finally, there are no 64-bit drivers for the iPod and no 64-bit CD burning software that I know of. For synching my iPod and burning CDs I use my previous desktop, a 32-bit system.

All in all, the 64-bit everyday OS experience has been pretty painless, and with a few exceptions, totally seamless.

posted by Mark Russinovich @ 1:05 PM 28 comments

This page is powered by Blogger. Isn't yours?

RSS Feed

RSS
    2.0

Index

Full Blog Index

Recent Posts

On My Way to Microsoft!
The Power in Power Users
Why Winternals Sued Best Buy
The Case of the Mysterious Driver
Running as Limited User - the Easy Way
Using Rootkits to Defeat Digital Rights Management
Inside the WMF Backdoor
Rootkits in Commercial Software
The Antispyware Conspiracy
Sony Settles

Archives

03/01/2005 - 03/31/2005
04/01/2005 - 04/30/2005
05/01/2005 - 05/31/2005
06/01/2005 - 06/30/2005
07/01/2005 - 07/31/2005
08/01/2005 - 08/31/2005
09/01/2005 - 09/30/2005
10/01/2005 - 10/31/2005
11/01/2005 - 11/30/2005
12/01/2005 - 12/31/2005
01/01/2006 - 01/31/2006
02/01/2006 - 02/28/2006
03/01/2006 - 03/31/2006
04/01/2006 - 04/30/2006
05/01/2006 - 05/31/2006
07/01/2006 - 07/31/2006

Other Blogs

Raymond Chen
Dana Epp
Aaron Margosis
Wes Miller
Larry Osterman
Bruce Schneier
Larry Seltzer