/* * Tool name : IEBrowserHistory * Description : Tool to dump IE browser history file content. * Version : 0.2 * Todo : Implementing Firefox browser history dumps. * * Changes : 2008.04.27 - Renamed functions and output text. * : 2008.04.30 - Minor bug fixes. * */ #include #include #include #include #include #define MAX_BUF_SIZE 1024 #pragma comment(lib, "Shell32.lib") /* * Constants, data types and function forward declarations. * */ const int TYPE_UNDEF = 0x00; const int TYPE_URL = 0x01; const int TYPE_REDR = 0x02; const int TYPE_UNKN = 0x03; const int URL_URL_OFFSET = 104; const int URL_TIME_OFFSET = 16; const int REDR_URL_OFFSET = 16; struct sHistory { int lType; char *lURL; SYSTEMTIME st; }; DWORD searchHistoryFiles(char *pBaseDirectory); void dumpHistoryEntries(char *pFileName); int extractURL(char *pBuf, int pType, struct sHistory *pHistory); /* * Program entry point * */ int main() { int lRetVal = 0; searchHistoryFiles(getenv("HOMEPATH")); printf("\n\nHit enter to stop execution ...\n"); getc(stdin); return(lRetVal); } /* * Find Index.dat files by searching recursively * a base directory. Tested on Windows XP with IE 8. * */ DWORD searchHistoryFiles(char *pBaseDirectory) { WIN32_FIND_DATA lFileData; HANDLE lSearchHandle; char lFilePattern[MAX_BUF_SIZE + 1]; char lSubDirectory[MAX_BUF_SIZE + 1]; char lHistoryFile[MAX_BUF_SIZE + 1]; int lRetVal = 0; char lHomeDirectory[MAX_BUF_SIZE + 1]; if (pBaseDirectory != NULL) { /* * Prepare file pattern. We want to check all the files * to detect directories and search inside them, too. * */ ZeroMemory(lHomeDirectory, sizeof(lHomeDirectory)); strncpy(lHomeDirectory, pBaseDirectory, sizeof(lHomeDirectory)); if (lHomeDirectory[strlen(lHomeDirectory) - 1] != '\\') strcat(lHomeDirectory, "\\"); ZeroMemory(lFilePattern, sizeof(lFilePattern)); _snprintf(lFilePattern, sizeof(lFilePattern) - 1, "%s*", lHomeDirectory); /* * Start the search. * */ if ((lSearchHandle = FindFirstFile(lFilePattern, &lFileData)) != INVALID_HANDLE_VALUE) { do { /* * File is a directory. Do a recursive function call to * find index.dat files in that directory. * */ if(lFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (strcmp(lFileData.cFileName, ".") && strcmp(lFileData.cFileName, "..")) { ZeroMemory(lSubDirectory, sizeof(lSubDirectory)); _snprintf(lSubDirectory, sizeof(lSubDirectory) - 1, "%s\\%s", pBaseDirectory, lFileData.cFileName); searchHistoryFiles(lSubDirectory); } // if (strcmp(lFileDa... } else { /* * File is a Internet Explorer history file. * */ if (strstr(lFileData.cFileName, "ndex.dat") && (strstr(pBaseDirectory, "nternet") || strstr(pBaseDirectory, "istory.IE5"))) { ZeroMemory(lHistoryFile, sizeof(lHistoryFile)); _snprintf(lHistoryFile, sizeof(lHistoryFile) - 1, "%s\\%s", pBaseDirectory, lFileData.cFileName); dumpHistoryEntries(lHistoryFile); } // if (strstr(lFileData... } // if(lFileData.dwFileAt... } while (FindNextFile(lSearchHandle, &lFileData)); } // if ((lSearchHandle = FindFirstFile(l... } // if (pBaseDirectory != NULL) return(lRetVal); } /* * Dump URLs from a cache and history file. * */ void dumpHistoryEntries(char *pFileName) { char *lBufPointer = NULL; char *lTempPointer = NULL; long lFileSize; int lCounter = 0; struct sHistory lHistory; int lType = 0; char lTemp[MAX_BUF_SIZE + 1]; char lTimeStamp[MAX_BUF_SIZE + 1]; HANDLE lFileHandle = INVALID_HANDLE_VALUE; DWORD lBytesRead = 0; if ((lFileHandle = CreateFile(pFileName, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { if ((lFileSize = GetFileSize(lFileHandle, NULL)) > 0 && (lTempPointer = (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lFileSize)) != NULL) { if (ReadFile(lFileHandle, lTempPointer, lFileSize, &lBytesRead, NULL)) { /* * Iterate byte after byte through the .dat file. * */ for (lCounter = 0; lCounter < lFileSize; lCounter++) { lBufPointer = lTempPointer + lCounter; /* * Determine URL type * */ if (strncmp(lBufPointer, "URL ", 4) == 0) lType = TYPE_URL; else if (strncmp(lBufPointer, "REF ", 4) == 0) lType = TYPE_REDR; else lType = TYPE_UNDEF; //printf("%d %s\n", lType, lBufPointer); /* * If a valid data type was found, print it. * */ if (lType != TYPE_UNDEF) { ZeroMemory(&lHistory, sizeof(lHistory)); if (extractURL(lBufPointer, lType, &lHistory) > 0 && lHistory.lURL != NULL) { ZeroMemory(lTimeStamp, sizeof(lTimeStamp)); ZeroMemory(lTemp, sizeof(lTemp)); /* * Regular entry in cache file format. * */ if (strstr(lHistory.lURL, "@http@")) { printf("Cache\t%d/%02d/%02d %02d:%02d\t%s\n", lHistory.st.wYear, lHistory.st.wMonth, lHistory.st.wDay, lHistory.st.wHour, lHistory.st.wMinute, lHistory.lURL); /* * Regular Internet Explorer entry in history file format. * */ } else if (strstr(lHistory.lURL, "@http://")) { printf("Inet\t%d/%02d/%02d %02d:%02d\t%s\n", lHistory.st.wYear, lHistory.st.wMonth, lHistory.st.wDay, lHistory.st.wHour, lHistory.st.wMinute, lHistory.lURL); /* * Regular local file explorer entry in history file format. * */ } else if (strstr(lHistory.lURL, "@file:///")) { printf("Local\t%d/%02d/%02d %02d:%02d\t%s\n", lHistory.st.wYear, lHistory.st.wMonth, lHistory.st.wDay, lHistory.st.wHour, lHistory.st.wMinute, lHistory.lURL); } // if (strstr(lHistory... } // if (extractURL(lBufPoint... if (lHistory.lURL != INVALID_HANDLE_VALUE) HeapFree(GetProcessHeap(), 0, lHistory.lURL); } // if (lType != TYPE_UNDEF) } // for (lCounter = 0; lCoun... } // if (ReadFile(lFileHa... HeapFree(GetProcessHeap(), 0, lTempPointer); } // if ((lTempPointer = (char *) HeapA... CloseHandle(lFileHandle); } // if ((lFileHandle = CreateFile(pFi... } /* * Extract first entry from a buffer and * copy it to the history data structure. * */ int extractURL(char *pBuf, int pType, struct sHistory *pHistory) { int lCounter = 0; int lRetVal = 1; FILETIME lFileTime; ZeroMemory(pHistory, sizeof(struct sHistory)); if (pType == TYPE_URL) { CopyMemory((DWORD *) &lFileTime.dwLowDateTime, pBuf + URL_TIME_OFFSET, sizeof(DWORD)); CopyMemory((DWORD *) &lFileTime.dwHighDateTime, pBuf + URL_TIME_OFFSET + 4, sizeof(DWORD)); FileTimeToSystemTime(&lFileTime, &pHistory->st); pHistory->lType = TYPE_URL; pBuf += URL_URL_OFFSET; } else if (pType == TYPE_REDR) { lFileTime.dwHighDateTime = 0; lFileTime.dwLowDateTime = 0; FileTimeToSystemTime( &lFileTime, &pHistory->st ); pHistory->lType = TYPE_REDR; pBuf += REDR_URL_OFFSET; } else { lRetVal = TYPE_UNDEF; goto END; } // if (pType == TYPE_URL ... while (pBuf[lCounter] != 0 && lCounter < 1026) lCounter++; if (lCounter > 1024) { goto END; } else if ((pHistory->lURL = (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1024)) != NULL) { ZeroMemory(pHistory->lURL, 1024); strncpy(pHistory->lURL, pBuf, lCounter); } // if ((pHistory->lURL = (cha... END: return(lRetVal); }