该问题([1], [2])其实产生于MFC 4.2当中,由于CFileFind::FindFile没有对传入的pstrName参数进行长度校验,而直接调用lstrcpyA将其拷贝入一固定大小的堆中,导致了堆溢出。网上查了下,这个问题已经在07年的时候被披露(CVE-2007-4916),不过没有找到微软的相关补丁。以下是MFC 4.2(vc++ 6.0)中的相关代码:
BOOL CFileFind::FindFile(LPCTSTR pstrName /* = NULL */,
DWORD dwUnused /* = 0 */)
{
UNUSED_ALWAYS(dwUnused);
Close();
m_pNextInfo = new WIN32_FIND_DATA;
m_bGotLast = FALSE;
if (pstrName == NULL)
pstrName = _T("*.*");
lstrcpy(((WIN32_FIND_DATA*) m_pNextInfo)->cFileName, pstrName);
m_hContext = ::FindFirstFile(pstrName, (WIN32_FIND_DATA*) m_pNextInfo);
……
}
typedef struct _WIN32_FIND_DATAA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
CHAR cFileName[ MAX_PATH ];
CHAR cAlternateFileName[ 14 ];
……
}