Skip to content

Extension Encryption #791

Open
xHector1337 wants to merge 30 commits into
rapid7:masterfrom
xHector1337:add-extension-encryption-manager
Open

Extension Encryption #791
xHector1337 wants to merge 30 commits into
rapid7:masterfrom
xHector1337:add-extension-encryption-manager

Conversation

@xHector1337

@xHector1337 xHector1337 commented Feb 2, 2026

Copy link
Copy Markdown
Contributor

Extension Encryption: Encryption Manager

This PR creates the basic encryption manager, and start wiring decryption logic inside metsrv.

Coverage:

  • Initialization of Extension Encryption Manager inside the server setup
  • Insertion of an extension if flagged as ENCRYPTABLE and if it was load by ReflectiveLoader
  • Decryption of extension if command handler is within extension mem space
  • Decryption of scheduler event handler if handler is within extension mem space

At the moment the default CryptographicManager is the a "debug" manager that will just force metsrv to rewrite the same bytes to the extension memory space, this chained with a testing extension loaded with the ENCRYPTABLE flag set to true will be used as first PoC to ensure writing the memory will not cause any issue for extension loaded with ReflectiveLoader.

@xHector1337 xHector1337 force-pushed the add-extension-encryption-manager branch from b7248da to df37b63 Compare February 4, 2026 14:39
Comment thread c/meterpreter/source/metsrv/scheduler.c Outdated
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;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we need to think what to do here, make sense to break i guess

Comment on lines +36 to +43
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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sense here to keep track of what type of Cryptographic Manager we have created, holding the ENUM should be enough

Comment on lines +423 to +440
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;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am really curious about running this on a real extension, wondering if ReadProcessMemory and WriteProcessMemory works as expected. With the DEBUG Cryptographic Manager we should just write the same bytes, this seems like a good testing example

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will test it as soon as I can and let you know. Thanks for your reviews!

@dledda-r7

Copy link
Copy Markdown
Contributor

Side note for future me: BEFORE LANDING

  • Pass every function to use the win api

…tion/manager-2

Fix base address, refactor add function
@xHector1337

Copy link
Copy Markdown
Contributor Author
[2500] [LOAD EXTENSION] Adding command ID to response: 1072
[2500] [LOAD EXTENSION] Adding command ID to response: 1071
[2500] [LOAD EXTENSION] Adding command ID to response: 1077
[2500] [LOAD EXTENSION] Adding command ID to response: 1069
[2500] [LOAD EXTENSION] Adding command ID to response: 1068
[2500] [LOAD EXTENSION] Adding command ID to response: 1067
[2500] [LOAD EXTENSION] Adding command ID to response: 1012
[2500] [LOAD EXTENSION] Adding command ID to response: 1013
[2500] [LOAD EXTENSION] Adding command ID to response: 1015
[2500] [LOAD EXTENSION] Adding command ID to response: 1010
[2500] [LOAD EXTENSION] Adding command ID to response: 1005
[2500] [LOAD EXTENSION] Adding command ID to response: 1007
[2500] [LOAD EXTENSION] Adding command ID to response: 1006
[2500] [LOAD EXTENSION] Adding command ID to response: 1016
[2500] [LOAD EXTENSION] Adding command ID to response: 1014
[2500] [LOAD EXTENSION] Adding command ID to response: 1004
[2500] [LOAD EXTENSION] Adding command ID to response: 1003
[2500] [LOAD EXTENSION] Adding command ID to response: 1011
[2500] [LOAD EXTENSION] Adding command ID to response: 1001
[2500] [LOAD EXTENSION] Adding command ID to response: 1008
[2500] [LOAD EXTENSION] Adding command ID to response: 1009
[2500] [LOAD EXTENSION] Adding command ID to response: 1031
[2500] [LOAD EXTENSION] Adding command ID to response: 1030
[2500] [LOAD EXTENSION] Adding command ID to response: 1029
[2500] [LOAD EXTENSION] Adding command ID to response: 1028
[2500] [LOAD EXTENSION] Adding command ID to response: 4
[2500] [extension_encryption][extension_encryption_add] Adding extension
[2500] [extension_encryption][extension_encryption_add] .text section of the extension is found!
[2500] [extension_encryption][extension_encryption_add] lpExtensionStatus->bEncryptable: 1
[2500] [extension_encryption][extension_encryption_add] lpExtensionStatus->bEncrypted: 0
[2500] [extension_encryption][extension_encryption_add] lpExtensionStatus->lpLoc: 00000000008D1000
[2500] [extension_encryption][extension_encryption_add] lpExtensionStatus->dwSize: 323376
[2500] [extension_encryption][extension_encryption_add] lpExtensionStatus->dwLastUsedTime: 326078
[2500] [extension_encryption][extension_encryption_add] Added extension text section at 00000000008D1000 of size 323376
[2500] [extension_encryption][extension_encryption_add] Function exiting

DebugString: "[27e8] [DISPATCH] Packet type for 1072 is 0"
DebugString: "[27e8] [DISPATCH] executing request handler 1072"
DebugString: "[27e8] [DISPATCH] Calling extensionFindDecrypt for command 1072"
DebugString: "[27e8] [extension_encryption][extension_encryption_get] Getting extension."
DebugString: "[27e8] [extension_encryption][extension_encryption_get] Function exiting."
DebugString: "[27e8] [COMMAND] Decryption successful for command 1072"

@xHector1337 xHector1337 marked this pull request as ready for review March 22, 2026 06:46
@dledda-r7 dledda-r7 requested a review from Copilot April 16, 2026 15:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an “Extension Encryption Manager” to metsrv and wires it into extension load and dispatch paths so extensions flagged as encryptable can be tracked and (de)crypted around handler execution.

Changes:

  • Add extension_encryption.{c,h} implementing a global extension encryption manager (debug + RC4 managers) and routines to add/find/(de)crypt extensions.
  • Initialize the manager during server setup; register encryptable, reflectively-loaded extensions during core_loadlib.
  • Attempt decryption before running extension handlers in the command dispatcher and scheduler; periodically encrypt unused extensions.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
c/meterpreter/workspace/metsrv/metsrv.vcxproj Adds new extension encryption source/header to the build.
c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters Adds new files to Visual Studio filters.
c/meterpreter/source/metsrv/server_setup.c Initializes the Extension Encryption Manager during server setup.
c/meterpreter/source/metsrv/remote_dispatch.c Registers encryptable, reflectively-loaded extensions with the manager.
c/meterpreter/source/metsrv/base.c Attempts extension decryption before handler execution; triggers “encrypt unused” after command handling.
c/meterpreter/source/metsrv/scheduler.c Attempts extension decryption before scheduled routine execution.
c/meterpreter/source/metsrv/extension_encryption.h Declares manager/status structs and public APIs.
c/meterpreter/source/metsrv/extension_encryption.c Implements manager initialization, extension tracking, and (de)cryption routines.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +326 to 348
if (!extensionFindDecryptVal || extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE) {
dprintf("[COMMAND] Decryption successful for command %u", commandId);
}
else {
dprintf("[COMMAND] Decryption failed for command %u", commandId);
//break;
}
serverContinue = command->request.inline_handler(remote, packet, &result) && serverContinue;
dprintf("[DISPATCH] executed %u, continue %s", commandId, serverContinue ? "yes" : "no");
}
else
{
dprintf("[DISPATCH] executing request handler %u", commandId);
dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId);
extensionFindDecryptVal = extensionFindDecrypt(command->request.handler);
if (!extensionFindDecryptVal || extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE) {
dprintf("[COMMAND] Decryption successful for command %u", commandId);
}
else {
dprintf("[COMMAND] Decryption failed for command %u", commandId);
//break;
}
result = command->request.handler(remote, packet);

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If extensionFindDecrypt() reports a decryption failure, the handler is still invoked. For handlers located inside an encrypted extension, this risks executing encrypted bytes (crash/undefined behavior). Consider short-circuiting the dispatch when decryption fails (except for "not encryptable" / "not found" cases), and avoid logging "Decryption successful" unless the return code indicates success.

Suggested change
if (!extensionFindDecryptVal || extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE) {
dprintf("[COMMAND] Decryption successful for command %u", commandId);
}
else {
dprintf("[COMMAND] Decryption failed for command %u", commandId);
//break;
}
serverContinue = command->request.inline_handler(remote, packet, &result) && serverContinue;
dprintf("[DISPATCH] executed %u, continue %s", commandId, serverContinue ? "yes" : "no");
}
else
{
dprintf("[DISPATCH] executing request handler %u", commandId);
dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId);
extensionFindDecryptVal = extensionFindDecrypt(command->request.handler);
if (!extensionFindDecryptVal || extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE) {
dprintf("[COMMAND] Decryption successful for command %u", commandId);
}
else {
dprintf("[COMMAND] Decryption failed for command %u", commandId);
//break;
}
result = command->request.handler(remote, packet);
if (!extensionFindDecryptVal) {
dprintf("[COMMAND] Decryption successful for command %u", commandId);
serverContinue = command->request.inline_handler(remote, packet, &result) && serverContinue;
dprintf("[DISPATCH] executed %u, continue %s", commandId, serverContinue ? "yes" : "no");
}
else if (extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE
|| extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_FOUND) {
dprintf("[COMMAND] Decryption not required 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("[COMMAND] Decryption failed for command %u with error %u", commandId, extensionFindDecryptVal);
result = extensionFindDecryptVal;
}
}
else
{
dprintf("[DISPATCH] executing request handler %u", commandId);
dprintf("[DISPATCH] Calling extensionFindDecrypt for command %u", commandId);
extensionFindDecryptVal = extensionFindDecrypt(command->request.handler);
if (!extensionFindDecryptVal) {
dprintf("[COMMAND] Decryption successful for command %u", commandId);
result = command->request.handler(remote, packet);
}
else if (extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE
|| extensionFindDecryptVal == EXTENSION_ENCRYPTION_EXTENSION_NOT_FOUND) {
dprintf("[COMMAND] Decryption not required for command %u", commandId);
result = command->request.handler(remote, packet);
}
else {
dprintf("[COMMAND] Decryption failed for command %u with error %u", commandId, extensionFindDecryptVal);
result = extensionFindDecryptVal;
}

Copilot uses AI. Check for mistakes.
Comment on lines +107 to +115
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);
}

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RC4 key generation falls back to srand(GetTickCount()) + rand(), which is predictable and not suitable for generating cryptographic keys. If RC4 mode is intended to provide real confidentiality (not just a debug PoC), use a CSPRNG (e.g., BCryptGenRandom / RtlGenRandom) to fill lpCryptoParams.

Copilot uses AI. Check for mistakes.
Comment thread c/meterpreter/source/metsrv/scheduler.c Outdated
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;

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When extensionFindDecrypt() indicates a decryption failure, the code still calls entry->routine(...). If the routine lives in an encrypted .text section, this can lead to executing encrypted bytes (crash/undefined behavior). Only invoke the routine when decryption succeeded (or the handler isn't within an encryptable extension), and avoid logging "decrypted successfully" on failure.

Suggested change
//break;
break;

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, this'll be uncommented in following PRs.

Comment on lines +198 to +207
EnterCriticalSection(&g_ExtensionEncryptionManager->cs);
do {
dprintf("[extension_encryption][extension_encryption_add] Adding extension");
if (g_ExtensionEncryptionManager->dwExtensionsCount >= MAX_EXTENSIONS) {
BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] Maximum number of extensions reached.", ERROR_NOT_ENOUGH_MEMORY);
}

if (hLib == NULL || hLib == INVALID_HANDLE_VALUE) {
BREAK_WITH_ERROR("[extension_encryption][extension_encryption_add] Invalid parameters.", ERROR_INVALID_PARAMETER);
}

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extension_encryption_add() enters the manager critical section but only calls LeaveCriticalSection on the success path. Any BREAK_WITH_ERROR(...) will break out of the loop and return while still holding the lock, causing deadlocks in all future extension-encryption operations. Restructure so the critical section is always released (e.g., a single LeaveCriticalSection after the do { ... } while (0) block).

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a good catch!

Comment on lines +376 to +400
if (!bError) {
for (DWORD i = 0; i != ExtensionSize; i += diff) {
if ((ExtensionSize - i) < BUFFER_SIZE) {
diff = ExtensionSize - i;
}
ret = ReadProcessMemory(GetCurrentProcess(), (unsigned char*)ExtensionLoc + i, lpTempBufferRead, diff, &ByteCounter);
if (!ret || ByteCounter != diff) {
dprintf("[extension_encryption][extension_encryption_encrypt] ReadProcessMemory failed with error 0x%x", GetLastError());
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;
}

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extension_encryption_encrypt() sets lpExtensionStatus->bEncrypted = TRUE even if the loop breaks early due to Read/Write/Crypto failure (those paths don't set bError). This can mark a partially-encrypted extension as "encrypted" and break subsequent decrypt/execute logic. Only flip bEncrypted (and update dwLastUsedTime) after a verified full success, and treat partial failures as errors.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a good catch as well!

return EXTENSION_ENCRYPTION_EXTENSION_NOT_ENCRYPTABLE;
}

if (!extensionStatus->bEncrypted || !encryptionManager->decrypt(extensionStatus)) {

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extensionFindDecrypt() currently returns EXTENSION_ENCRYPTION_DECRYPTION_ERROR when the extension is not encrypted because of if (!extensionStatus->bEncrypted || !decrypt(...)). This should be the opposite: if it's already decrypted, return success; only call decrypt() (and fail) when bEncrypted is true and decryption fails.

Suggested change
if (!extensionStatus->bEncrypted || !encryptionManager->decrypt(extensionStatus)) {
if (!extensionStatus->bEncrypted) {
return ERROR_SUCCESS;
}
if (!encryptionManager->decrypt(extensionStatus)) {

Copilot uses AI. Check for mistakes.
} while (0);

} while (0);
extension_encryption_encrypt_unused();

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

command_handle calls extension_encryption_encrypt_unused() unconditionally. If InitExtensionEncryptionManager() failed (or was never called), extension_encryption_encrypt_unused() dereferences g_ExtensionEncryptionManager and will crash. Guard this call (or make extension_encryption_encrypt_unused() a no-op when the manager is NULL).

Suggested change
extension_encryption_encrypt_unused();
if (g_ExtensionEncryptionManager != NULL)
{
extension_encryption_encrypt_unused();
}

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah good catch, we might not need the below suggestion if we do this. I'm not sure, I will take a look at it on VS.

Comment on lines +403 to +404
if(encryptionManager == NULL) {
dprintf("[SERVER] Extension Encryption Manager Initialization failed! proceeding without extension encryption.");

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InitExtensionEncryptionManager() failure is logged as "proceeding without extension encryption", but other paths (e.g., command_handle -> extension_encryption_encrypt_unused) assume the manager exists and will dereference a NULL global. Either ensure init cannot fail here, or fully gate all extension-encryption calls on successful initialization.

Suggested change
if(encryptionManager == NULL) {
dprintf("[SERVER] Extension Encryption Manager Initialization failed! proceeding without extension encryption.");
if (encryptionManager == NULL)
{
dprintf("[SERVER] Extension Encryption Manager initialization failed, aborting server setup.");
break;

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, this is the tricky part. For now, we dont need it since every extension is not encryptable. But in the future, a similar mechanism can be implemented. What do you think @dledda-r7 ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should probably cover this edge case now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok I will fix these on this weekend.

Comment on lines +55 to +70
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;

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RC4 encryption/decryption uses a single RC4_CTX that is mutated by RC4Cipher. Because cryptographic_manager_rc4_encrypt() doesn't refresh/reset the context before each encryption, the keystream position depends on previous operations, making later decryptions (which do refresh in extension_encryption_decrypt) incorrect. Refresh/reset the RC4 context before both encrypt and decrypt operations (or use a per-operation/per-extension context) so encrypt/decrypt are reversible.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's right, but I'm not sure about this. Imho we were calling the Initialiser before every cipher call, but I'm not sure.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that was a good catch

Comment on lines +532 to +544

EnterCriticalSection(&g_ExtensionEncryptionManager->cs);
ExtensionEncryptionStatus** extension_statuses = g_ExtensionEncryptionManager->extensionStatuses;
DWORD current_time = GetTickCount();
for (DWORD i = 0; i < g_ExtensionEncryptionManager->dwExtensionsCount; i++) {
ExtensionEncryptionStatus* status = extension_statuses[i];
if (status != NULL && status->bEncryptable && !status->bEncrypted) {
if (current_time - status->dwLastUsedTime > ENCRYPTION_UNUSED_COOLDOWN_MS) {
g_ExtensionEncryptionManager->encrypt(status);
}
}
}
LeaveCriticalSection(&g_ExtensionEncryptionManager->cs);

Copilot AI Apr 16, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extension_encryption_encrypt_unused() assumes g_ExtensionEncryptionManager is non-NULL and immediately enters its critical section. If the manager wasn't initialized (or init failed), this will crash. Add a NULL check at the start and return early when the manager is unavailable.

Suggested change
EnterCriticalSection(&g_ExtensionEncryptionManager->cs);
ExtensionEncryptionStatus** extension_statuses = g_ExtensionEncryptionManager->extensionStatuses;
DWORD current_time = GetTickCount();
for (DWORD i = 0; i < g_ExtensionEncryptionManager->dwExtensionsCount; i++) {
ExtensionEncryptionStatus* status = extension_statuses[i];
if (status != NULL && status->bEncryptable && !status->bEncrypted) {
if (current_time - status->dwLastUsedTime > ENCRYPTION_UNUSED_COOLDOWN_MS) {
g_ExtensionEncryptionManager->encrypt(status);
}
}
}
LeaveCriticalSection(&g_ExtensionEncryptionManager->cs);
ExtensionEncryptionManager* encryptionManager = g_ExtensionEncryptionManager;
if (encryptionManager == NULL) {
return;
}
EnterCriticalSection(&encryptionManager->cs);
ExtensionEncryptionStatus** extension_statuses = encryptionManager->extensionStatuses;
DWORD current_time = GetTickCount();
for (DWORD i = 0; i < encryptionManager->dwExtensionsCount; i++) {
ExtensionEncryptionStatus* status = extension_statuses[i];
if (status != NULL && status->bEncryptable && !status->bEncrypted) {
if (current_time - status->dwLastUsedTime > ENCRYPTION_UNUSED_COOLDOWN_MS) {
encryptionManager->encrypt(status);
}
}
}
LeaveCriticalSection(&encryptionManager->cs);

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice. Gonna check the remaining ones later. @dledda-r7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants