|
Few days ago, I even forgot the password for my mailbox, and in order to find it back, I have been searched a lot of tools on Internet, but finally I found it useless for IE7. So I’d have to count on myself. By Google and OllyDbg, I used a whole day to figure out the method to finish password capture automatically for IE7. And I want to share with everyone, so I post it here.
Since IE7, Microsoft completely changed the way of password preservation: save websites’ URL to history files, and preserve passwords auto finished to the location below in registry table:
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\IntelliForms\Storage2.
To get IE7 password auto completion, you need to get the URL records of history folder in IE7 and the password information of registry item HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\IntelliForms\Storage2.
Next are the steps to get the path of History folder automatically in IE7:
-
Get the path of the folder History with ShGetSpecialFolder.
-
Enumerate the file index.dat under the folder History, and abstract visited webistes’ URLs from the file index.dat.
Here’s the structure of the file index.dat:
Head file: 32 bytes.
Start from the address 0x5000 of the file stores visited websites information. And they are arranged in order, each site’s data structure is:
struct Web{
const char Tag[4]; //symbol of 4 bytes,content is "URL ", could be the judgment if data is correct or not.
int LenNumber; //length index of the data block,with the length of LenNumber*128
char unknown[44]; //unknown data of 44 bytes
int DataPos; //Visited: the field is relative to the excursion value of the structure head,namely, &Web+DataPos pointing to the Visited
char unknown[]; //unknown data with variable length,however, as observed evidence, seems the DataPos above are all the same,so this one should be of fixed length, forget it, leave it alone, but for safety, we consider it as variable.
const char Tag1[8]; //"Visited:"
char Data[]; //structure XXX@????, XXX is user name,??? is URL, could be located by searching @ from the Visited sites
char Unknown[]; //variable length
};
Notice: the URL in the structure above is of ANSI format.
-
Open the registry and locate to HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\IntelliForms\Storage2,, enumerate its values. And the position in registry here saves user name and password for IE7 auto completion or that kind of things.
-
Hash the URL captured in the step 2 in turn, and then compare the Hash value to the ValueName captured in step 3, and the accordant is the information of this URL. If they’re accordant, decrypt the ValueName.
The structure of the ValueData after decryption.
struct ValueData{
int HeadLen;//4 bytes,representing the length of the head of the data structure
int DataPos;//excursion for the real data to the structure head,namely: &ValueData+HeadLen+DataPos points to valid data.
int DataLen;//the length of valid data
char unknown[];
wchar UserName[];
wchar Password[];
};
HeadLen+HeadLen+DataPos=sizeof(ValueData);
Note:
(1) Hash calculation:
//Algorithm=0x8004
//0x8004=ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1=CALG_SHA1, originally it adopted CALG_SHA1 caculation
//attention: here the DataLen ends with 0 of Unicode
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)) //both of them are ok, have no idea what is the last parameter for
{
// 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
{
// Error during CryptCreateHash!
bResult = FALSE;
}
CryptReleaseContext(hProv, 0);
}
return bResult;
}
(2) Decryption calculation:
unsigned char pcryptdata[]={ // the ValueData extracted from registry,that is the information encrypted like user password.
0x01,0x00,0x00,0x00,0xD0,0x8C,0x9D,0xDF,0x01,0x15, 0xD1,0x11,0x8C,0x7A,0x00,0xC0,0x4F,0xC2,0x97,0xEB, 0x01,0x00,0x00,0x00,0x58,0x26,0xE4,0x1A,0x81,0x86, 0x2F,0x4D,
0xA9,0x19,0x95,0xED,0x94,0x6F,0xC5,0x2A,0x00,0x00, 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x03,0x66, 0x00,0x00,0xA8,0x00,0x00,0x00,0x10,0x00,0x00,0x00, 0xB5,0x67,
0x51,0xE5,0x1A,0x73,0x67,0x75,0x0F,0x84,0xF2,0x97, 0xCE,0x07,0x21,0x31,0x00,0x00,0x00,0x00,0x04,0x80, 0x00,0x00,0xA0,0x00,0x00,0x00,0x10,0x00,0x00,0x00, 0x75,0xFB,
0x3F,0xC8,0x4C,0x7F,0xDB,0xBA,0xC8,0x27,0xD9,0xC0, 0x64,0xD8,0x05,0xEF,0x68,0x00,0x00,0x00,0x50,0x63, 0x0F,0x8B,0x7B,0xBC,0xDF,0x96,0xFD,0xE4,0x11,0xEB, 0x97,0x43,
0xD8,0x4E,0x7C,0xB6,0x96,0x55,0xA6,0xB5,0x50,0x41, 0x5D,0xD5,0xA7,0x4B,0xFA,0x16,0x4E,0x65,0xF5,0xB6, 0x0D,0xC5,0xC1,0xCE,0xEB,0x3D,0x28,0x79,0xA2,0xBD, 0xAA,0x97,
0x9D,0x31,0xE8,0x84,0xBD,0xC5,0x49,0x74,0x64,0x40, 0xFA,0x09,0xE5,0x2C,0x0F,0x27,0xD7,0x65,0x9D,0xAF, 0x39,0x80,0x89,0x70,0x4C,0x43,0x65,0x5F,0xDC,0x0A, 0xF1,0x7E,
0x8E,0x35,0x61,0x4F,0xDB,0x84,0xFC,0x50,0xE7,0x96, 0x1A,0xAE,0x12,0x82,0x2D,0xE6,0x3A,0x0A,0x86,0xA7, 0xA7,0x60,0x30,0x99,0x54,0xA7,0x14,0x00,0x00,0x00, 0x5B,0xA4,
0x89,0xFF,0xE6,0x48,0x4B,0x05,0x28,0xCF,0xFF,0x28, 0xDC,0x11,0x46,0xCB,0x26,0x5D,0x9A,0x0F
};
WCHAR Test[]=L"http://www.ershou.net/userlogin.aspx\0"; // URL address captured by hashing to the URL and comparing with ValueName
DATA_BLOB DataOut;
if(Decrypt(Test,74,pcryptdata,0xf2,&DataOut))
{
for(int i=0;i
{
printf("%c",DataOut.pbData[i]);
}
printf("\r\nOver \r\n");
}
bool Decrypt(WCHAR *pURL,int URLLen,unsigned char * pCryptedData,int CryptedLen,DATA_BLOB *pDataOut)// for decryption
{
DATA_BLOB DataIn;
//DATA_BLOB DataOut;
DATA_BLOB DescrOut;
DataIn.pbData=pCryptedData;
DataIn.cbData=CryptedLen;
DescrOut.cbData=URLLen;
DescrOut.pbData=(unsigned char *)pURL;
if(CryptUnprotectData(&DataIn,NULL,&DescrOut,NULL,NULL,0,pDataOut))
{
//pBuffer=DataOut.pbData;
return true;
}
else
return false;
}
|