用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

780 lines
16 KiB

#include "stdafx.h"
#include "ZipArchive.h"
#include <assert.h>
#ifndef __cplusplus
#error ZipArchive requires C++ compilation (use a .cpp suffix)
#endif
#ifdef ZIP_WILDCARD
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
#endif
// Include ZLIB stuff. ZLIB is maintained by Jean-loup Gailly and Mark Adler.
// It is a general GZIP and PKZIP compatible compression library.
#include <zconf.h>
#include <zlib.h>
#include <crtdbg.h>
#include <tchar.h>
#include <malloc.h>
CZipFile::CZipFile(DWORD dwSize/*=0*/)
: m_pData(NULL),
m_dwSize(0),
m_dwPos(0)
{
#ifdef ZLIB_DECRYPTION
m_pCrcTable = NULL;
#endif
if(dwSize!=0)
{
m_pData=new BYTE[dwSize];
m_dwSize=dwSize;
}
}
CZipFile::~CZipFile()
{
Close();
}
BOOL CZipFile::Read(void* pBuffer, DWORD dwSize, LPDWORD pdwRead/* = NULL*/)
{
_ASSERTE(IsOpen());
if (pdwRead != NULL)
*pdwRead = 0;
if (m_pData == NULL)
return FALSE;
if (dwSize == 0 || m_dwPos >= m_dwSize)
return FALSE;
if (m_dwPos + dwSize > m_dwSize)
dwSize = m_dwSize - m_dwPos;
::CopyMemory(pBuffer, m_pData + m_dwPos, dwSize);
m_dwPos += dwSize;
if (pdwRead != NULL)
*pdwRead = dwSize;
return TRUE;
}
BOOL CZipFile::Close()
{
if (m_pData == NULL)
return TRUE;
delete[] m_pData;
m_pData = NULL;
m_dwSize = 0;
m_dwPos = 0;
return TRUE;
}
BOOL CZipFile::IsOpen() const
{
return m_pData != NULL;
}
BYTE* CZipFile::GetData() const
{
_ASSERTE(IsOpen());
return m_pData;
}
DWORD CZipFile::GetSize() const
{
_ASSERTE(IsOpen());
return m_dwSize;
}
DWORD CZipFile::GetPosition() const
{
_ASSERTE(IsOpen());
return m_dwPos;
}
DWORD CZipFile::Seek(DWORD dwOffset, UINT nFrom) // return old pos
{
_ASSERTE(IsOpen());
DWORD dwPos = m_dwPos;
switch (nFrom)
{
case FILE_BEGIN:
m_dwPos = dwOffset;
break;
case FILE_END:
m_dwPos = m_dwSize + dwOffset;
break;
case FILE_CURRENT:
m_dwPos += dwOffset;
break;
}
if (m_dwPos < 0)
m_dwPos = 0;
if (m_dwPos >= m_dwSize)
m_dwPos = m_dwSize;
return dwPos;
}
#ifdef ZLIB_DECRYPTION
BOOL CZipFile::_DecryptFile(LPCSTR pstrPassword, LPBYTE& pData, DWORD& dwSize, DWORD crc32)
{
_ASSERTE(pData);
_ASSERTE(!::IsBadStringPtrA(pstrPassword, -1));
if (!_InitKeys(pstrPassword))
return FALSE;
if (!_DecryptHeader(pData, dwSize, crc32))
return FALSE;
if (!_DecryptData(pData, dwSize))
return FALSE;
return TRUE;
}
BOOL CZipFile::_InitKeys(LPCSTR pstrPassword)
{
m_pCrcTable = get_crc_table();
m_dwKey[0] = 305419896;
m_dwKey[1] = 591751049;
m_dwKey[2] = 878082192;
int nLen = ::lstrlenA(pstrPassword);
if (nLen == 0)
return FALSE;
for(int i = 0; i < nLen; i++)
_UpdateKeys(pstrPassword[i]);
return TRUE;
}
void CZipFile::_UpdateKeys(BYTE c)
{
m_dwKey[0] = _crc32(m_dwKey[0], c);
m_dwKey[1] = m_dwKey[1] + (m_dwKey[0] & 0x000000FF);
m_dwKey[1] = m_dwKey[1] * 134775813 + 1;
BYTE b = (BYTE) (m_dwKey[1] >> 24);
m_dwKey[2] = _crc32(m_dwKey[2], b);
}
DWORD CZipFile::_crc32( DWORD c, BYTE b )
{
assert(m_pCrcTable);
return m_pCrcTable[((DWORD) (c) ^ (b)) & 0xFF] ^ ((c) >> 8);
}
BOOL CZipFile::_DecryptHeader(LPBYTE pData, DWORD dwSize, DWORD crc32)
{
if (dwSize < 12)
return FALSE;
BYTE header[12];
::CopyMemory(&header, pData, 12);
for(int i = 0; i < 12; i++)
{
BYTE c = (BYTE)(header[i] ^ _DecryptByte());
_UpdateKeys(c);
header[i] = c;
}
// Password check
return header[11] == (BYTE)(crc32 >> 24);
}
BYTE CZipFile::_DecryptByte() const
{
DWORD temp = (WORD) (m_dwKey[2] | 2);
return (BYTE)((temp * (temp ^ 1)) >> 8);
}
BOOL CZipFile::_DecryptData(LPBYTE& pData, DWORD& dwSize)
{
LPBYTE pRawData;
pRawData = new BYTE[dwSize - 12];
_ASSERTE(pRawData);
if (pRawData == NULL)
return FALSE;
LPBYTE p = pRawData;
for(DWORD i = 12; i < dwSize; i++)
{
BYTE c = (BYTE) (pData[i] ^ _DecryptByte());
_UpdateKeys(c);
*p++ = c;
}
delete[] pData;
pData = pRawData;
dwSize -= 12;
return TRUE;
}
#endif // ZLIB_DECRYPTION
BOOL CZipFile::Attach(LPBYTE pData, DWORD dwSize)
{
if(m_pData) return FALSE;
_ASSERTE(pData);
_ASSERTE(!::IsBadReadPtr(pData,dwSize));
m_pData = pData;
m_dwSize = dwSize;
return TRUE;
}
void CZipFile::Detach()
{
m_pData = NULL;
m_dwSize = 0;
m_dwPos = 0;
}
//////////////////////////////////////////////////////////////////////////
//CZipArchive
//////////////////////////////////////////////////////////////////////////
CZipArchive::CZipArchive()
: m_hFile(INVALID_HANDLE_VALUE),
m_Files(NULL),
m_DirData(NULL)
{
memset(&m_Header, 0, sizeof(m_Header));
}
CZipArchive::~CZipArchive()
{
Close();
}
BOOL CZipArchive::OpenZip()
{
_ASSERTE(m_hFile);
SeekFile(-(LONG)sizeof(m_Header), FILE_END);
DWORD dwRead = ReadFile(&m_Header, sizeof(m_Header));
_ASSERTE(dwRead == sizeof(m_Header));
if (dwRead != sizeof(m_Header) || m_Header.sig != DIR_SIGNATURE)
{
Close();
return FALSE;
}
_ASSERTE(m_Header.nDirEntries < 1000); // Sanity check
m_DirData = (LPBYTE)malloc(m_Header.dirSize);
_ASSERTE(m_DirData);
m_Files = new ZipDirFileHeader*[m_Header.nDirEntries];
_ASSERTE(m_Files);
if (m_Files == NULL || m_DirData == NULL)
{
Close();
return FALSE;
}
SeekFile(-(LONG)(sizeof(m_Header) + m_Header.dirSize), FILE_END);
dwRead = ReadFile(m_DirData, m_Header.dirSize);
_ASSERTE(dwRead == m_Header.dirSize);
if (dwRead != m_Header.dirSize)
{
Close();
return FALSE;
}
LPBYTE pData = m_DirData;
for (int i = 0; i < m_Header.nDirEntries; i++)
{
// Set the header pointer in the m_Files array
ZipDirFileHeader* fh = (ZipDirFileHeader*) pData;
m_Files[i] = fh;
if (fh->sig != FILE_SIGNATURE)
{
Close();
return FALSE;
}
// Convert UNIX slash to Windows backslash in ANSI string
LPSTR pszName = fh->GetName();
for(int j = 0; j < fh->fnameLen; j++, pszName++)
if (*pszName == '/')
*pszName='\\';
// Get next header
pData += sizeof(ZipDirFileHeader) + fh->fnameLen + fh->xtraLen + fh->cmntLen;
}
m_szPassword[0] = '\0';
return TRUE;
}
void CZipArchive::Close()
{
CloseFile();
if (m_Files != NULL)
{
delete[] m_Files;
m_Files = NULL;
}
if (m_DirData != NULL)
{
free(m_DirData);
m_DirData = NULL;
}
memset(&m_Header, 0, sizeof(m_Header));
}
BOOL CZipArchive::IsOpen() const
{
return m_hFile != INVALID_HANDLE_VALUE;
}
int CZipArchive::GetEntries() const
{
return m_Header.nDirEntries;
}
BOOL CZipArchive::SetPassword(LPCSTR pstrPassword)
{
if(!pstrPassword) return FALSE;
if (::lstrlenA(pstrPassword) >= sizeof(m_szPassword)-1)
return FALSE;
::lstrcpyA(m_szPassword, pstrPassword);
return TRUE;
}
// ZIP File API
BOOL CZipArchive::GetFile(LPCTSTR pszFileName, CZipFile& file)
{
return GetFile(GetFileIndex(pszFileName),file);
}
BOOL CZipArchive::GetFile2(int iIndex, CZipFile& file)
{
_ASSERTE(IsOpen());
if (m_hFile == INVALID_HANDLE_VALUE)
return FALSE;
if (iIndex < 0 || iIndex >= m_Header.nDirEntries)
return FALSE;
ZipLocalHeader hdr;
SeekFile(m_Files[iIndex]->hdrOffset, FILE_BEGIN);
DWORD dwRead = ReadFile(&hdr, sizeof(hdr));
if (dwRead != sizeof(hdr))
return FALSE;
if (hdr.sig != LOCAL_SIGNATURE)
return FALSE;
SeekFile(hdr.fnameLen + hdr.xtraLen, FILE_CURRENT);
DWORD dwSize = hdr.cSize;
if (hdr.flag & 1)
{//这个接口不支持加密
return FALSE;
}
switch (hdr.compression)
{
case LOCAL_COMP_STORE:
_ASSERTE(hdr.cSize == hdr.ucSize);
dwRead = ReadFile(file.GetData(), hdr.cSize);
return dwRead==hdr.cSize;
case LOCAL_COMP_DEFLAT:
{
if(file.GetSize()<hdr.ucSize) return FALSE;
// Read Source Data.
LPBYTE pData=new BYTE[hdr.cSize];
if (pData == NULL)
return FALSE;
dwRead = ReadFile(pData, hdr.cSize);
if (dwRead != hdr.cSize)
{
delete[] pData;
return FALSE;
}
LPBYTE pTarget=file.GetData();
z_stream stream = { 0 };
stream.next_in = (Bytef*) pData;
stream.avail_in = (uInt) hdr.cSize;
stream.next_out = (Bytef*) pTarget;
stream.avail_out = hdr.ucSize;
stream.zalloc = (alloc_func) NULL;
stream.zfree = (free_func) NULL;
// Perform inflation; wbits < 0 indicates no zlib header inside the data.
int err = inflateInit2(&stream, -MAX_WBITS);
if (err == Z_OK)
{
err = inflate(&stream, Z_OK);
if (err != Z_OK && err != Z_STREAM_END)
_ASSERTE(err == Z_OK);
inflateEnd(&stream);
if (err == Z_STREAM_END)
err = Z_OK;
inflateEnd(&stream);
}
delete[] pData;
return err == Z_OK;
}
default:
_ASSERTE(FALSE); // unsupported compression scheme
return FALSE;
}
}
BOOL CZipArchive::GetFile(int iIndex, CZipFile& file)
{
_ASSERTE(IsOpen());
if (m_hFile == INVALID_HANDLE_VALUE)
return FALSE;
if (iIndex < 0 || iIndex >= m_Header.nDirEntries)
return FALSE;
ZipLocalHeader hdr;
SeekFile(m_Files[iIndex]->hdrOffset, FILE_BEGIN);
DWORD dwRead = ReadFile(&hdr, sizeof(hdr));
if (dwRead != sizeof(hdr))
return FALSE;
if (hdr.sig != LOCAL_SIGNATURE)
return FALSE;
SeekFile(hdr.fnameLen + hdr.xtraLen, FILE_CURRENT);
// // Decompress file if needed.
LPBYTE pData;
pData = new BYTE[hdr.cSize];
if (pData == NULL)
return FALSE;
dwRead = ReadFile(pData, hdr.cSize);
if (dwRead != hdr.cSize)
{
delete[] pData;
return FALSE;
}
DWORD dwSize = hdr.cSize;
if (hdr.flag & 1)
{
#ifdef ZLIB_DECRYPTION
if (::lstrlenA(m_szPassword) == 0)
{
delete[] pData;
return FALSE;
}
if (!file._DecryptFile(m_szPassword, pData, dwSize, hdr.crc32))
{
delete[] pData;
return FALSE;
}
#else
delete[] pData;
return FALSE;
#endif
}
switch (hdr.compression)
{
case LOCAL_COMP_STORE:
//_ASSERTE(hdr.cSize == hdr.ucSize);//加密的时这两个值不一定相等
break;
case LOCAL_COMP_DEFLAT:
{
LPBYTE pTarget;
pTarget = new BYTE[hdr.ucSize];
_ASSERTE(pTarget);
if (pTarget == NULL)
return FALSE;
z_stream stream = { 0 };
stream.next_in = (Bytef*) pData;
stream.avail_in = (uInt) hdr.cSize;
stream.next_out = (Bytef*) pTarget;
stream.avail_out = hdr.ucSize;
stream.zalloc = (alloc_func) NULL;
stream.zfree = (free_func) NULL;
// Perform inflation; wbits < 0 indicates no zlib header inside the data.
int err = inflateInit2(&stream, -MAX_WBITS);
if (err == Z_OK)
{
err = inflate(&stream, Z_OK);
if (err != Z_OK && err != Z_STREAM_END)
_ASSERTE(err == Z_OK);
inflateEnd(&stream);
if (err == Z_STREAM_END)
err = Z_OK;
inflateEnd(&stream);
}
delete[] pData;
if (err != Z_OK)
{
delete[] pTarget;
return FALSE;
}
pData = pTarget;
}
break;
default:
_ASSERTE(FALSE); // unsupported compression scheme
return FALSE;
}
// The memory we allocated is passed to the file, which
// takes ownership of it.
file.Attach(pData, hdr.ucSize);
return TRUE;
}
// FindFile API
HANDLE CZipArchive::FindFirstFile(LPCTSTR pszFileName, LPZIP_FIND_DATA lpFindFileData) const
{
_ASSERTE(IsOpen());
_ASSERTE(!::IsBadWritePtr(lpFindFileData, sizeof(ZIP_FIND_DATA)));
::ZeroMemory(lpFindFileData, sizeof(ZIP_FIND_DATA));
_ASSERTE(pszFileName != NULL);
if (pszFileName == NULL || pszFileName[0] == '\0')
return INVALID_HANDLE_VALUE;
FindFileHandle* pFF;
pFF = new FindFileHandle;
if (pFF == NULL)
return INVALID_HANDLE_VALUE;
::lstrcpy(pFF->szSearch, pszFileName);
pFF->nPos = 0;
BOOL bRet = FindNextFile((HANDLE)pFF, lpFindFileData);
if (!bRet)
{
delete pFF;
return INVALID_HANDLE_VALUE;
}
return (HANDLE)pFF;
}
BOOL CZipArchive::FindNextFile(HANDLE hFindFile, LPZIP_FIND_DATA lpFindFileData) const
{
_ASSERTE(IsOpen());
if (!IsOpen())
return FALSE;
if (hFindFile == INVALID_HANDLE_VALUE || hFindFile == NULL)
return FALSE;
FindFileHandle* pFF = reinterpret_cast<FindFileHandle*>(hFindFile);
while (TRUE)
{
if (pFF->nPos >= m_Header.nDirEntries)
return FALSE;
// Extract filename and match with pattern
ZipDirFileHeader* fh = m_Files[pFF->nPos];
TCHAR szFile[MAX_PATH] = { 0 };
::OemToCharBuff(fh->GetName(), szFile, fh->fnameLen);
#ifdef ZIP_WILDCARD
if (::PathMatchSpec(szFile, pFF->szSearch) != NULL)
#else
if (_tcsicmp(szFile, pFF->szSearch) == 0)
#endif
{
// Copy data to the ZIP_FIND_DATA structure
::lstrcpy(lpFindFileData->szFileName, szFile);
lpFindFileData->szComment[0] = _T('\0'); // unsupported right now
lpFindFileData->nFileSizeCompressed = fh->cSize;
lpFindFileData->nFileSizeUncompressed = fh->ucSize;
::DosDateTimeToFileTime(fh->modDate, fh->modTime, &lpFindFileData->ftCreationDate);
lpFindFileData->nIndex = pFF->nPos;
// Figure out the file attributes
DWORD& dwFlags = lpFindFileData->dwFileAttributes = 0;
if (fh->flag & 1)
dwFlags |= FILE_ATTRIBUTE_ENCRYPTED;
if (fh->flag & (2|4))
dwFlags |= FILE_ATTRIBUTE_COMPRESSED;
if (fh->flag & (16|32|64))
dwFlags |= FILE_ATTRIBUTE_OFFLINE; // unsupported compression used
if (dwFlags == 0)
dwFlags = (fh->compression == LOCAL_COMP_STORE) ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
// Ready for next entry...
pFF->nPos++;
return TRUE;
}
pFF->nPos++;
}
return FALSE;
}
BOOL CZipArchive::FindClose(HANDLE hFindFile) const
{
if (hFindFile == INVALID_HANDLE_VALUE || hFindFile == NULL)
return FALSE;
FindFileHandle* pFF = reinterpret_cast<FindFileHandle*>(hFindFile);
delete pFF;
return TRUE;
}
BOOL CZipArchive::Open(LPCTSTR pszFileName)
{
_ASSERTE(!::IsBadStringPtr(pszFileName, MAX_PATH));
HANDLE hFile = ::CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE==hFile) return FALSE;
Close();
m_hFile=hFile;
BOOL bOK=OpenZip();
if(!bOK)
{
CloseHandle(m_hFile);
m_hFile=INVALID_HANDLE_VALUE;
}
return bOK;
}
BOOL CZipArchive::Open(LPBYTE pBytes, DWORD dwByteCount)
{
Close();
m_fileRes.Attach(pBytes, dwByteCount);
// ?
m_hFile = (HANDLE)pBytes;
BOOL bOK=OpenZip();
if(!bOK)
{
m_fileRes.Detach();
m_hFile=INVALID_HANDLE_VALUE;
}
return bOK;
}
BOOL CZipArchive::Open( HMODULE hModule,LPCTSTR pszName,LPCTSTR pszType )
{
HRSRC hResInfo = ::FindResource(hModule, pszName, pszType);
if (hResInfo == NULL)
return FALSE;
DWORD dwLength = ::SizeofResource(hModule, hResInfo);
if (dwLength == 0)
return FALSE;
HGLOBAL hResData = ::LoadResource(hModule, hResInfo);
if (hResData == NULL)
return FALSE;
BYTE* pData = (BYTE*)::LockResource(hResData);
if (pData == NULL)
return FALSE;
Close();
m_fileRes.Attach(pData, dwLength);
m_hFile = (HANDLE)hResInfo;
BOOL bOK=OpenZip();
if(!bOK)
{
m_fileRes.Detach();
m_hFile=INVALID_HANDLE_VALUE;
}
return bOK;
}
void CZipArchive::CloseFile()
{
if (m_hFile != INVALID_HANDLE_VALUE)
{
if (m_fileRes.IsOpen())
m_fileRes.Detach();
else
::CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
}
DWORD CZipArchive::ReadFile(void* pBuffer, DWORD dwBytes)
{
_ASSERTE(m_hFile != INVALID_HANDLE_VALUE);
DWORD dwRead = 0;
if (m_fileRes.IsOpen())
m_fileRes.Read(pBuffer, dwBytes, &dwRead);
else
::ReadFile(m_hFile, pBuffer, dwBytes, &dwRead, NULL);
return dwRead;
}
DWORD CZipArchive::SeekFile(LONG lOffset, UINT nFrom)
{
_ASSERTE(m_hFile != INVALID_HANDLE_VALUE);
if (m_fileRes.IsOpen())
{
m_fileRes.Seek(lOffset, nFrom);
return m_fileRes.GetPosition();
}
return ::SetFilePointer(m_hFile, lOffset, NULL, nFrom);
}
DWORD CZipArchive::GetFileSize( LPCTSTR pszFileName )
{
return GetFileSize(GetFileIndex(pszFileName));
}
DWORD CZipArchive::GetFileSize( int iIndex )
{
if(iIndex==-1) return 0;
if (m_hFile == INVALID_HANDLE_VALUE)
return 0;
if (iIndex < 0 || iIndex >= m_Header.nDirEntries)
return 0;
ZipLocalHeader hdr;
SeekFile(m_Files[iIndex]->hdrOffset, FILE_BEGIN);
DWORD dwRead = ReadFile(&hdr, sizeof(hdr));
if (dwRead != sizeof(hdr))
return 0;
return hdr.ucSize;
}
int CZipArchive::GetFileIndex( LPCTSTR pszFileName )
{
_ASSERTE(IsOpen());
_ASSERTE(!::IsBadStringPtr(pszFileName, MAX_PATH));
ZIP_FIND_DATA fd;
HANDLE hFindFile = FindFirstFile(pszFileName, &fd);
if (hFindFile == INVALID_HANDLE_VALUE)
return -1;
FindClose(hFindFile);
return fd.nIndex;
}