背景:
博主去年在国内某知名互联网公司做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"------------------------------------------ "); 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] ",strRefUrl.c_str()); lpDownloadUrl = (LPWSTR)((LPBYTE)lpRefUrl+((wcslen(lpRefUrl)+1)*2)); strDownloadUrl = lpDownloadUrl; if (!strDownloadUrl.empty()) { wprintf(L"DownloadUrl[%s] ",strDownloadUrl.c_str()); lpDestFile= (LPWSTR)((LPBYTE)lpDownloadUrl+((wcslen(lpDownloadUrl)+1)*2)); strDestFile = lpDestFile; wprintf(L"DestFile[%s] ",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] ",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] ",strMIMEType.c_str()); lpSrcFile = (LPWSTR)((LPBYTE)lpMIMEType+((wcslen(lpMIMEType)+1)*2)); } strSrcFile = lpSrcFile; if (!strSrcFile.empty()) { wprintf(L"SrcFile[%s] ",strSrcFile.c_str()); lpDownloadUrl= (LPWSTR)((LPBYTE)lpSrcFile+((wcslen(lpSrcFile)+1)*2)); } strDownloadUrl = lpDownloadUrl; if (!strDownloadUrl.empty()) { wprintf(L"DownloadUrl[%s] ",strDownloadUrl.c_str()); lpDestFile= (LPWSTR)((LPBYTE)lpDownloadUrl+((wcslen(lpDownloadUrl)+1)*2)); wprintf(L"DestFile[%s] ",lpDestFile); strDestFile = lpDestFile; } } //兼容从IE9升级到IE10以上版本 else { lpDownloadUrl = (LPWSTR)((LPBYTE)lpRefUrl+((wcslen(lpRefUrl)+1)*2)); strDownloadUrl = lpDownloadUrl; if (!strDownloadUrl.empty()) { wprintf(L"DownloadUrl[%s] ",strDownloadUrl.c_str()); lpDestFile= (LPWSTR)((LPBYTE)lpDownloadUrl+((wcslen(lpDownloadUrl)+1)*2)); strDestFile = lpDestFile; wprintf(L"DestFile[%s] ",strDestFile.c_str()); } } } wprintf(L"------------------------------------------ "); } } 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"------------------------------------------ "); wprintf(L"lpszSourceUrl[%s] ",strDownloadUrl.c_str()); wprintf(L"lpszLocalFile[%s] ",strDestFile.c_str()); wprintf(L"------------------------------------------ "); } } //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------------------------ ")); 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(("------------------------------------------ ")); 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] ",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] ",strMIMEType.c_str())); lpSrcFile = (LPWSTR)((LPBYTE)lpMIMEType+((wcslen(lpMIMEType)+1)*2)); } strSrcFile = lpSrcFile; if (!strSrcFile.empty()) { DEBUG_PUT(("SrcFile[%s] ",strSrcFile.c_str())); lpDownloadUrl= (LPWSTR)((LPBYTE)lpSrcFile+((wcslen(lpSrcFile)+1)*2)); } strDownloadUrl = lpDownloadUrl; if (!strDownloadUrl.empty()) { DEBUG_PUT(("DownloadUrl[%s] ",strDownloadUrl.c_str())); lpDestFile= (LPWSTR)((LPBYTE)lpDownloadUrl+((wcslen(lpDownloadUrl)+1)*2)); DEBUG_PUT(("DestFile[%s] ",lpDestFile)); strDestFile = lpDestFile; } } //兼容IE9 else { lpDownloadUrl = (LPWSTR)((LPBYTE)lpRefUrl+((wcslen(lpRefUrl)+1)*2)); strDownloadUrl = lpDownloadUrl; if (!strDownloadUrl.empty()) { DEBUG_PUT(("DownloadUrl[%s] ",strDownloadUrl.c_str())); lpDestFile= (LPWSTR)((LPBYTE)lpDownloadUrl+((wcslen(lpDownloadUrl)+1)*2)); strDestFile = lpDestFile; DEBUG_PUT(("DestFile[%s] ",strDestFile.c_str())); } } DEBUG_PUT(("------------------------------------------ ")); } } 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; }