/****************************************************************************************************
都是网上的代码,自己组合起来的,刚开始报很多错误,花了很多时间终于搞定了
环境:VC6.0+SDK(SDK必须)
简单说明:IE7 IE8 IE9将网站的URL保存于历史文件中,将自动完成的密码保存于注册表中的以下位置:
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\IntelliForms\Storage2。
很简单,有我的部分注释,哈哈。
****************************************************************************************************/
#include "stdio.h"
#include <windows.h>
#define _WIN32_WINNT 0x0500 //必须,否则wincrypt.h用不了,报很多错误,郁闷
#include <Wincrypt.h>
#include "COMDEF.H"
#include "URLHIST.H" // Needed for IUrlHistoryStg2 and IID_IUrlHistoryStg2
#include <shlguid.h> // Needed for CLSID_CUrlHistory
#define URL_HISTORY_MAX 5000
#pragma comment(lib, "Crypt32.lib")
int GetUrlHistory(wchar_t *UrlHistory[URL_HISTORY_MAX])
{
int max = 0;
CoInitialize(NULL);
IUrlHistoryStg2* pUrlHistoryStg2=NULL;
HRESULT hr = CoCreateInstance(CLSID_CUrlHistory, NULL, CLSCTX_INPROC_SERVER,IID_IUrlHistoryStg2,(void**)(&pUrlHistoryStg2));
if(SUCCEEDED(hr))
{
IEnumSTATURL* pEnumUrls;
hr = pUrlHistoryStg2->EnumUrls(&pEnumUrls);
if (SUCCEEDED(hr))
{
STATURL StatUrl[1];
ULONG ulFetched;
while (max<URL_HISTORY_MAX && (hr = pEnumUrls->Next(1, StatUrl, &ulFetched)) == S_OK){
if (StatUrl->pwcsUrl != NULL)
{
wchar_t *p;
if(NULL!=(p = wcschr(StatUrl->pwcsUrl,'?')))
*p='\0';
UrlHistory[max] = new wchar_t[wcslen(StatUrl->pwcsUrl)+1];
wcscpy(UrlHistory[max],StatUrl->pwcsUrl);
max++;
}
}
pEnumUrls->Release();
}
pUrlHistoryStg2->Release();
}
CoUninitialize();
return max;
}
//计算hash
void GetHashStr(wchar_t *Password,char *HashStr)
{
HashStr[0]='\0';
HCRYPTPROV hProv = NULL;
HCRYPTHASH hHash = NULL;
CryptAcquireContext(&hProv, 0,0,PROV_RSA_FULL,0);
if(CryptCreateHash(hProv,CALG_SHA1, 0, 0,&hHash))
{
if(CryptHashData(hHash,(unsigned char *)Password,(wcslen(Password)+1)*2,0))
{
DWORD dwHashLen=20;
BYTE Buffer[20];
if(CryptGetHashParam(hHash,HP_HASHVAL,Buffer,&dwHashLen,0))
{
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
char TmpBuf[128];
unsigned char tail=0;
for(int i=0;i<20;i++){
unsigned char c = Buffer[i];
tail+=c;
wsprintf(TmpBuf,"%s%2.2X",HashStr,c);
strcpy(HashStr,TmpBuf);
}
wsprintf(TmpBuf,"%s%2.2X",HashStr,tail);
strcpy(HashStr,TmpBuf);
}
}
}
}
//数据输出
void PrintData(char *Data)
{
unsigned int HeaderSize;
unsigned int DataSize;
unsigned int DataMax;
memcpy(&HeaderSize,&Data[4],4); //the 4th byte from the beginning is Header size
memcpy(&DataSize,&Data[8],4); //the 8th byte from the beginning is Data size
memcpy(&DataMax,&Data[20],4); //the 20th byte from the beginning is Data number
printf("HeaderSize=%d DataSize=%d DataMax=%d\n",HeaderSize,DataSize,DataMax);
char *pInfo = &Data[36];
char *pData = &Data[HeaderSize];
// afterwards, the same number of information data (16 bytes) as the data number comes
for(int n=0;n<DataMax;n++)
{
FILETIME ft,ftLocal;
SYSTEMTIME st;
unsigned int offset;
memcpy(&offset,pInfo,4); // the null byte from the beginning of information data is the offset of the data
memcpy(&ft,pInfo+4,8); // the 4th byte from the beginning of information data is the date
// the 12th byte from the beginning of information data is the data length
FileTimeToLocalFileTime(&ft,&ftLocal);
FileTimeToSystemTime(&ftLocal, &st);
char TmpBuf[1024];
int l = ::WideCharToMultiByte(CP_THREAD_ACP, 0,(wchar_t*)
&Data[HeaderSize+12+offset], -1, NULL, 0, NULL, NULL );
if(-1!=l)
{
::WideCharToMultiByte(CP_THREAD_ACP, 0, (wchar_t*)&Data[HeaderSize+12+offset],
wcslen((wchar_t*)&Data[HeaderSize+12+offset])+1, TmpBuf, l, NULL, NULL );
printf("[%d][%4.4d/%2.2d/%2.2d %2.2d:%2.2d]%s\n",n,st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,TmpBuf);
}
pInfo+=16;
}
}
int main()
{
// TODO: Place code here.
wchar_t *UrlHistory[URL_HISTORY_MAX];
int UrlListoryMax = GetUrlHistory(UrlHistory);
char *KeyStr = {"Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage2"};
HKEY hKey;
if(ERROR_SUCCESS==RegOpenKeyEx(HKEY_CURRENT_USER,KeyStr,0,KEY_QUERY_VALUE,&hKey)){
for(int i=0;;i++)
{
char Val[1024];
DWORD Size = 1024;
if(ERROR_NO_MORE_ITEMS==RegEnumValue(hKey,i,Val, &Size, NULL,NULL, NULL, NULL))//i Storage2下第i个键值,返回键的名称
break;
for(int n=0;n<UrlListoryMax;n++)
{
char HashStr[1024];
GetHashStr(UrlHistory[n],HashStr);
if(strcmp(Val,HashStr)==0)
{
printf("ur : %ls\n",UrlHistory[n]);
printf("hash : %s\n",HashStr);
DWORD BufferLen;
DWORD dwType;
RegQueryValueEx(hKey,Val,0,&dwType,NULL,&BufferLen);
BYTE *Buffer = new BYTE[BufferLen];
if(RegQueryValueEx(hKey,Val,0,&dwType,Buffer,&BufferLen)==ERROR_SUCCESS)
{
DATA_BLOB DataIn;
DATA_BLOB DataOut;
DATA_BLOB OptionalEntropy;
DataIn.pbData = Buffer;
DataIn.cbData = BufferLen;
OptionalEntropy.pbData = (unsigned char *)UrlHistory[n];
OptionalEntropy.cbData = (wcslen(UrlHistory[n])+1)*2;
//CryptUnprotectData 确实在Wincrypt.h中,但是是定义在 Platform SDK中
if(CryptUnprotectData(&DataIn,0,&OptionalEntropy,NULL,NULL,1,&DataOut)){
PrintData((char *)DataOut.pbData); //纯粹的数据输出
//printf("%s\n",(char *)DataOut.pbData);
LocalFree(DataOut.pbData);
}
delete Buffer;
}
break;
}
}
}
RegCloseKey(hKey);
}
return 0;
}