首页 > 技术文章 > 获取IE下载历史的具体实现

cpuimage 2015-10-21 10:31 原文

背景:

博主去年在国内某知名互联网公司做URL安全检测时写的一份草稿。

最后却没用到项目上。

当时主要想用于URL网址安全的入库以及更新,需要建立下载文件以及URL的安全属性关联。

逻辑大致是这样的:

若下载的文件报毒则拉黑该URL,认定URL为危险,若不报毒了,则恢复该URL为安全。

当时找了不少资料都不理想,特别是针对不同版本的IE浏览器,网上前人的思路几乎已经都失效了。

最后无奈操刀,逆向了IE浏览器的这部分函数,才算是达到目标,具体实现代码如下:

#include <WinInet.h>
#pragma comment(lib,"wininet.lib")
HRESULT getIeDownloadCache(HANDLE &hEnumHandle, LPINTERNET_CACHE_ENTRY_INFOA &lpCache, DWORD &nEntrySize)
{
 HRESULT hr;
 DWORD nError;
 DWORD dwSize;
 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntry;
 HANDLE hHandle;
 DWORD dwEntrySize;
 dwEntrySize = 0;
 hr = E_INVALIDARG;
 if ( !FindFirstUrlCacheEntryExA("iedownload:", 0, 0xFFFFFFFF, 0, NULL, &dwEntrySize, NULL, NULL, NULL) )
 {
  if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
   goto FailExit;
  dwSize = dwEntrySize;
  lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFOA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
  if ( !lpCacheEntry )
   return E_OUTOFMEMORY;
  hHandle = FindFirstUrlCacheEntryExA("iedownload:",0,0xFFFFFFFF,0,lpCacheEntry,&dwEntrySize,NULL,NULL,NULL);
  if ( hHandle )
  {
   hr = 0;
   lpCache = lpCacheEntry;
   nEntrySize = dwEntrySize;
   hEnumHandle = hHandle;
  }
  else
  {
FailExit:
   nError = GetLastError();
   hr = nError;
   if ( (signed int)nError > 0 )
    hr = (unsigned __int16)nError | 0x80070000;
  }
 }
 return hr;
}
HRESULT FindNextCache(HANDLE &hEnumHandle, LPINTERNET_CACHE_ENTRY_INFOA &lpCache, DWORD &dwEntrySize)
{
 HRESULT hr;
 DWORD nSize;
 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntry;
 DWORD nError;
 DWORD cbCacheEntryInfo;
 cbCacheEntryInfo = 0;
 hr = E_INVALIDARG;
 if ( !FindNextUrlCacheEntryA(hEnumHandle, NULL, &cbCacheEntryInfo) )
 {
  if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
   goto FailExit;
  nSize = cbCacheEntryInfo;
  lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFOA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSize);
  if ( !lpCacheEntry )
   return E_OUTOFMEMORY;
  if ( FindNextUrlCacheEntryA(hEnumHandle, lpCacheEntry, &cbCacheEntryInfo) )
  {
   hr = 0;
   lpCache = lpCacheEntry;
     dwEntrySize = cbCacheEntryInfo;
  }
  else
  {
FailExit:
   nError = GetLastError();
   hr = nError;
   if ( (signed int)nError > 0 )
    hr = (unsigned __int16)nError | 0x80070000;
  }
 }
 return hr;
}
void __cdecl myHeapFree(LPVOID lpMem)
{
 HANDLE hHeap;
 if ( lpMem )
 {
  hHeap = GetProcessHeap();
  HeapFree(hHeap, 0, lpMem);
 }
}
 
int GetIEVersion()
{
 HKEY hKey = NULL;
 DWORD dwType = 0;
 CHAR szData[16] = {0};
 DWORD dwDataSize = 15;
 int nVersion = 0;
 if(RegOpenKeyExA(HKEY_LOCAL_MACHINE,
  "SOFTWARE\\Microsoft\\Internet Explorer",
  0,
  KEY_READ,
  &hKey) != ERROR_SUCCESS)
 {
  goto Exit0;
 }
 CHAR szVersion[MAX_PATH] = {0};
 DWORD dwVersionSize = MAX_PATH-1;
 LONG lRet = RegQueryValueExA(hKey, "svcVersion", NULL, &dwType, (BYTE*)szVersion, &dwVersionSize);
 if (ERROR_SUCCESS == lRet && REG_SZ == dwType)
 {
  PCHAR pFind = strstr(szVersion, ".");
  if (pFind != NULL)
  {
   *pFind = 0;
   int nVer = atoi(szVersion);
   if (9 == nVer ||
    10 == nVer ||
    11 == nVer)
   {
    nVersion = nVer;
    goto Exit0;
   }
  }
 }
 if (ERROR_SUCCESS != RegQueryValueExA(hKey, "Build", NULL, &dwType, (BYTE*)szData, &dwDataSize))
 {
  goto Exit0;
 }
 nVersion = atoi(szData);
 while (nVersion >= 15)
 {
  nVersion = nVersion / 10;
 }
 if (nVersion < 6)
 {
  nVersion = 0;
  goto Exit0;
 }
Exit0:
 if (hKey != NULL)
 {
  RegCloseKey(hKey);
 }
 return nVersion;
}
BOOL GetIeDownloadHistoryFormCache(wstring & DestFile,wstring & refUrl, wstring &downloadUrl)
{
 unsigned int i;
 LPINTERNET_CACHE_ENTRY_INFOA lpCache;
 BOOL bRet = FALSE;
 HANDLE hEnumHandle;
 DWORD dwSize;
 DWORD IEURL_BUFFER_OFFSET = 0;
 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntry;
 DWORD IEVer=GetIEVersion();
 wstring strRefUrl,strMIMEType,strSrcFile,strDownloadUrl,strDestFile;
 hEnumHandle = NULL;
 lpCacheEntry = NULL;
 dwSize = 0;
 for ( i = getIeDownloadCache( hEnumHandle, lpCacheEntry, dwSize);
  (i & 0x80000000u) == 0;
  i = FindNextCache(hEnumHandle, lpCacheEntry, dwSize) )
 {
  lpCache = lpCacheEntry;
  if ( strnicmp(lpCache->lpszSourceUrlName, "iedownload:", 11) == 0 )
  {
   if (lpCache->lpHeaderInfo)
   {
    bRet = TRUE;
    DWORD dwLimitSize = 0x200;
    for ( DWORD n = 0; n < dwLimitSize; n++)
    {
     BYTE http[] =
     {
      0x68, 0x00, 0x74, 0x00, 0x74, 0x00 ,0x70, 0x00, 0x3a, 0x00 ,0x2f ,0x00 ,0x2f
     };
     BYTE https[] =
     {
      0x68, 0x00, 0x74, 0x00, 0x74, 0x00 ,0x70, 0x00, 0x73, 0x00, 0x3a, 0x00 ,0x2f ,0x00 ,0x2f
     };
     BYTE ftp[] =
     {
      0x66, 0x00, 0x74, 0x00 ,0x70, 0x00, 0x3a, 0x00 ,0x2f ,0x00 ,0x2f
     };
     if( (memcmp(lpCache->lpHeaderInfo+n, (PBYTE)http,sizeof(http) ) == 0)
      || (memcmp(lpCache->lpHeaderInfo+n, (PBYTE)ftp,sizeof(ftp) ) == 0)
      || (memcmp(lpCache->lpHeaderInfo+n, (PBYTE)https,sizeof(https) ) == 0))
     {
      IEURL_BUFFER_OFFSET = n;
      break;
     }
    }
    wprintf(L"------------------------------------------\n");
    LPWSTR lpRefUrl;
    LPWSTR lpMIMEType;
    LPWSTR lpSrcFile;
    LPWSTR lpDownloadUrl;
    LPWSTR lpDestFile;
   
    if (IEVer == 9)
    {
     lpRefUrl = (LPWSTR)((LPBYTE)lpCache->lpHeaderInfo+IEURL_BUFFER_OFFSET);
     strRefUrl = lpRefUrl;
     if (!strRefUrl.empty())
     {
      wprintf(L"RefUrl[%s]\n",strRefUrl.c_str());
      lpDownloadUrl = (LPWSTR)((LPBYTE)lpRefUrl+((wcslen(lpRefUrl)+1)*2));
      strDownloadUrl = lpDownloadUrl;
      if (!strDownloadUrl.empty())
      {
       wprintf(L"DownloadUrl[%s]\n",strDownloadUrl.c_str());
       lpDestFile= (LPWSTR)((LPBYTE)lpDownloadUrl+((wcslen(lpDownloadUrl)+1)*2));
       strDestFile = lpDestFile;
       wprintf(L"DestFile[%s]\n",strDestFile.c_str());
      }
     }
    }
    else if (IEVer == 11||IEVer == 10)
    {
     lpRefUrl = (LPWSTR)((LPBYTE)lpCache->lpHeaderInfo+IEURL_BUFFER_OFFSET);
      strRefUrl = lpRefUrl;
     if (!strRefUrl.empty())
     {
      wprintf(L"RefUrl[%s]\n",strRefUrl.c_str());
      lpMIMEType = (LPWSTR)((LPBYTE)lpRefUrl+((wcslen(lpRefUrl)+1)*2));
     }
     strMIMEType = lpMIMEType;
     if ( strMIMEType.find(L"tp:/")== wstring::npos )
     {
      if (!strMIMEType.empty())
      {
       wprintf(L"MIMEType[%s]\n",strMIMEType.c_str());
       lpSrcFile = (LPWSTR)((LPBYTE)lpMIMEType+((wcslen(lpMIMEType)+1)*2));
       }
      strSrcFile = lpSrcFile;
      if (!strSrcFile.empty())
      {
       wprintf(L"SrcFile[%s]\n",strSrcFile.c_str());
       lpDownloadUrl= (LPWSTR)((LPBYTE)lpSrcFile+((wcslen(lpSrcFile)+1)*2));
       }
      strDownloadUrl = lpDownloadUrl;
      if (!strDownloadUrl.empty())
      {
       wprintf(L"DownloadUrl[%s]\n",strDownloadUrl.c_str());
       lpDestFile= (LPWSTR)((LPBYTE)lpDownloadUrl+((wcslen(lpDownloadUrl)+1)*2));
       wprintf(L"DestFile[%s]\n",lpDestFile);
    strDestFile = lpDestFile;
      }
     }
     //兼容从IE9升级到IE10以上版本
     else
     {
      lpDownloadUrl = (LPWSTR)((LPBYTE)lpRefUrl+((wcslen(lpRefUrl)+1)*2));
      strDownloadUrl = lpDownloadUrl;
      if (!strDownloadUrl.empty())
      {
       wprintf(L"DownloadUrl[%s]\n",strDownloadUrl.c_str());
       lpDestFile= (LPWSTR)((LPBYTE)lpDownloadUrl+((wcslen(lpDownloadUrl)+1)*2));
       strDestFile = lpDestFile;
       wprintf(L"DestFile[%s]\n",strDestFile.c_str());
      }
     }
     
    }
    wprintf(L"------------------------------------------\n");
   }
  }
  else
   //ie9以下版本
  {
   strDownloadUrl=CA2W(lpCache->lpszSourceUrlName);
   strDestFile=CA2W(lpCache->lpszLocalFileName);
   transform(strDestFile.begin(), strDestFile.end(), strDestFile.begin(), towlower);
   //过滤目标文件目录是临时目录
   if (strDestFile.find(L"content.ie5")==std::string::npos)
   {
    wprintf(L"------------------------------------------\n");
    wprintf(L"lpszSourceUrl[%s]\n",strDownloadUrl.c_str());
    wprintf(L"lpszLocalFile[%s]\n",strDestFile.c_str());
    wprintf(L"------------------------------------------\n");
   }
  }
  //DeleteUrlCacheEntryA(lpCache->lpszSourceUrlName);
  myHeapFree(lpCache);
  transform(strDestFile.begin(), strDestFile.end(), strDestFile.begin(), towlower);
  transform(DestFile.begin(), DestFile.end(), DestFile.begin(), towlower);
  if (strDestFile.find(DestFile.c_str())!=wstring::npos)
  {
   refUrl=strRefUrl;
   downloadUrl = strDownloadUrl;
   return bRet;
  }
 }
 return bRet;
}
-------------------------------------------------------------------------------------------------
BOOL GetIEDownloadFileUrl(wstring& strCacheFilePath, wstring& RefUrl,wstring& FileUrl)
{
 unsigned int i;
 LPINTERNET_CACHE_ENTRY_INFOA lpCache;
 BOOL bRet = FALSE;
 HANDLE hEnumHandle;
 DWORD dwSize;
 DWORD IEURL_BUFFER_OFFSET = 0;
 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntry;
 wstring strRefUrl,strMIMEType,strSrcFile,strDownloadUrl,strDestFile;
 hEnumHandle = NULL;
 lpCacheEntry = NULL;
 dwSize = 0;
 DEBUG_PUT(("------------------GetIeDownloadHistoryFormCache------------------------\n"));
 for ( i = getIeDownloadCache( hEnumHandle, lpCacheEntry, dwSize);
  (i & 0x80000000) == 0;
  i = FindNextCache(hEnumHandle, lpCacheEntry, dwSize) )
 {
  lpCache = lpCacheEntry;
  if ( strnicmp(lpCache->lpszSourceUrlName, "iedownload:", 11) == 0 )
  {
   if (lpCache->lpHeaderInfo)
   {
    bRet = TRUE;
    DWORD dwLimitSize = 0x200;
    for ( DWORD n = 0; n < dwLimitSize; n++)
    {
     BYTE http[] =
     {
      0x68, 0x00, 0x74, 0x00, 0x74, 0x00 ,0x70, 0x00, 0x3a, 0x00 ,0x2f ,0x00 ,0x2f
     };
     BYTE https[] =
     {
      0x68, 0x00, 0x74, 0x00, 0x74, 0x00 ,0x70, 0x00, 0x73, 0x00, 0x3a, 0x00 ,0x2f ,0x00 ,0x2f
     };
     BYTE ftp[] =
     {
      0x66, 0x00, 0x74, 0x00 ,0x70, 0x00, 0x3a, 0x00 ,0x2f ,0x00 ,0x2f
     };
     if( (memcmp(lpCache->lpHeaderInfo+n, (PBYTE)http,sizeof(http) ) == 0)
      || (memcmp(lpCache->lpHeaderInfo+n, (PBYTE)ftp,sizeof(ftp) ) == 0)
      || (memcmp(lpCache->lpHeaderInfo+n, (PBYTE)https,sizeof(https) ) == 0))
     {
      IEURL_BUFFER_OFFSET = n;
      break;
     }
    }
    DEBUG_PUT(("------------------------------------------\n"));
    LPWSTR lpRefUrl;
    LPWSTR lpMIMEType;
    LPWSTR lpSrcFile;
    LPWSTR lpDownloadUrl;
    LPWSTR lpDestFile;
    lpRefUrl = (LPWSTR)((LPBYTE)lpCache->lpHeaderInfo+IEURL_BUFFER_OFFSET);
    strRefUrl = lpRefUrl;
    if (!strRefUrl.empty())
    {
     DEBUG_PUT(("RefUrl[%s]\n",strRefUrl.c_str()));
     lpMIMEType = (LPWSTR)((LPBYTE)lpRefUrl+((wcslen(lpRefUrl)+1)*2));
     strMIMEType = lpMIMEType;
    }
    if ( strMIMEType.find(L"tp:/")== wstring::npos )
    {
     if (!strMIMEType.empty())
     {
      DEBUG_PUT(("MIMEType[%s]\n",strMIMEType.c_str()));
      lpSrcFile = (LPWSTR)((LPBYTE)lpMIMEType+((wcslen(lpMIMEType)+1)*2));
     }
     strSrcFile = lpSrcFile;
     if (!strSrcFile.empty())
     {
      DEBUG_PUT(("SrcFile[%s]\n",strSrcFile.c_str()));
      lpDownloadUrl= (LPWSTR)((LPBYTE)lpSrcFile+((wcslen(lpSrcFile)+1)*2));
     }
     strDownloadUrl = lpDownloadUrl;
     if (!strDownloadUrl.empty())
     {
      DEBUG_PUT(("DownloadUrl[%s]\n",strDownloadUrl.c_str()));
      lpDestFile= (LPWSTR)((LPBYTE)lpDownloadUrl+((wcslen(lpDownloadUrl)+1)*2));
      DEBUG_PUT(("DestFile[%s]\n",lpDestFile));
      strDestFile = lpDestFile;
     }
    }
    //兼容IE9
    else
    {
     lpDownloadUrl = (LPWSTR)((LPBYTE)lpRefUrl+((wcslen(lpRefUrl)+1)*2));
     strDownloadUrl = lpDownloadUrl;
     if (!strDownloadUrl.empty())
     {
      DEBUG_PUT(("DownloadUrl[%s]\n",strDownloadUrl.c_str()));
      lpDestFile= (LPWSTR)((LPBYTE)lpDownloadUrl+((wcslen(lpDownloadUrl)+1)*2));
      strDestFile = lpDestFile;
      DEBUG_PUT(("DestFile[%s]\n",strDestFile.c_str()));
     }
    }
    DEBUG_PUT(("------------------------------------------\n"));
   }
  }
  else
  {
   //兼容IE9以下版本
   strDownloadUrl=CA2W(lpCache->lpszSourceUrlName);
   strDestFile=CA2W(lpCache->lpszLocalFileName);
   transform(strDestFile.begin(), strDestFile.end(), strDestFile.begin(), towlower);
  }
  //清除记录
  //DeleteUrlCacheEntryA(lpCache->lpszSourceUrlName);
  myHeapFree(lpCache);
  transform(strDestFile.begin(), strDestFile.end(), strDestFile.begin(), towlower);
  transform(strCacheFilePath.begin(), strCacheFilePath.end(), strCacheFilePath.begin(), towlower);
  if (strDestFile.find(strCacheFilePath)!=wstring::npos)
  {
   RefUrl=strRefUrl;
   FileUrl = strDownloadUrl;
   return TRUE;
  }
 }
 return bRet;
}
  

  

推荐阅读