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. 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值