IE7自动完成口令获取

IE7自动完成口令获取
作者:grassgrass (kityest_at_163.com)
前一阵子自己邮箱的口令忘记了 , 为了找回邮箱口令到网上找了好多密码找回的工具 , 发现在IE7下都不好使 , 迫于无奈 , 只好自己研究了 , 通过Google和 OllyDbg , 用了1整天时间终于弄清楚了IE7下的自动完成口令获取方法 , 不敢独享 , 特公布如下 , 希望能对大家有帮助 。
自Internet Explorer 7.0开始,微软完全改变了密码保存的方式 , 将网站的URL保存于历史文件中 , 将自动完成的密码保存于注册表中的以下位置: HKEY_CURRENT_USERSoftwareMicrosoftInternet ExplorerIntelliFormsStorage2 。
【IE7自动完成口令获取】
要获取IE7的自动完成口令就需要同时获取IE7环境下历史文件夹中的URL记录和注册表HKEY_CURRENT_USERSoftwareMicrosoftInternet ExplorerIntelliFormsStorage2下的密码信息 。
以下是IE7自动完成口令获取的步骤:
1、用ShGetSpecialFolder获取History文件夹路径
2、枚举History文件夹下的index.dat文件 , 并从index.dat文件中提取访问过的网站URL 。
index.dat文件结构:
文件头32字节
从文件的第0x5000地址处开始存放的是访问过的网站信息 , 网站信息顺序存放 , 每个网站数据块结构为:
struct Web{
const char Tag[4]; //4个字节的标志 , 内容为"URL ",可作为数据是否正确的判断 。
int LenNumber//该数据块的长度指数 , 数据块的长度为LenNumber*128
char unknown[44]; //44字节的未知数据
int DataPos//Visited:字段相对于该结构块头的偏移值 , 即&Web DataPos就指向Visited了
char unknown[]//不定长度未知数据 , 不过据观察似乎上述DataPos都是一样的 , 那这个也应该定长了 , 算了 , 不管他 , 安全起见 , 就当不定长了
const char Tag1[8];;;//"Visited:"
char Data[]//结构 XXX@????,其中XXX是用户名 , ???就是URL,可以从Visited处搜索@来定位
char Unknown[]//长度不定
};
注意 , 上述结构中的URL是ANSI形式的
3、打开注册表HKEY_CURRENT_USERSoftwareMicrosoftInternet ExplorerIntelliFormsStorage2 , 枚举其Values
注册表该位置保存的是IE7自动完成的用户名密码之类 , 其中ValueName就是经过Hash的网站的URL,ValueData就是加密的用户名密码之类了 。
4、对第2步获取的URL依次进行Hash , 然后用其Hash值依次与第三步中获取的ValueName进行比较 , 一致的就是该URL的信息
如果一致 , 就对ValueData进行解密 。
ValueData解密后数据结构
struct ValueData{
int HeadLen;//4字节 , 用来表示该数据结构的头部长度 。
int DataPos;//真正的数据相对于数据结构头部的偏移 , 即:&ValueData HeadLen DataPos就指向有效数据了
int DataLen;//有效数据的长度
char unknown[];
wchar UserName[];
wchar Password[];
};
HeadLen HeadLen DataPos=sizeof(ValueData);
注:
1、Hash算法:
//Algorithm=0x8004
//0x8004=ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1=CALG_SHA1,原来采用的是CALG_SHA1算法
//注意:此处这个DataLen是带Unicode的结尾的0的
BOOL HashData(WCHAR *pData,int DataLen, char *pHashData,int *pHashLen,int Algorithm)
{
BOOL bResult = TRUE;
HCRYPTPROV hProv = NULL;
HCRYPTHASH hHash = NULL;
DWORD dwLength;
// Get handle to user default provider.
if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0))//0xF0000000)) //两个都行,不知道最后一个参数是干什么的
{
// Create hash object.
if (CryptCreateHash(hProv, Algorithm, 0, 0, &hHash))
{
// Hash password string.
if (CryptHashData(hHash, (BYTE *)pData, DataLen, 0))
{
CryptGetHashParam(hHash,2,(BYTE*)pHashData,(DWORD*)pHashLen,0);
}
else
{
// Error during CryptHashData!
bResult = FALSE;
}
CryptDestroyHash(hHash); // Destroy session key.
}
else
{

推荐阅读