[KSECDD] Fix RtlEncryptMemory and improve test

This commit is contained in:
Timo Kreuzer 2020-09-13 19:58:06 +02:00
parent ed02f41af5
commit ab43f86980
2 changed files with 123 additions and 11 deletions

View File

@ -27,6 +27,18 @@ typedef struct _KSEC_LOGON_DATA
LUID LogonId;
} KSEC_LOGON_DATA, *PKSEC_LOGON_DATA;
#if 0
void PrintKeyData(PUCHAR KeyData)
{
ULONG i;
for (i = 0; i < 32; i++)
{
DbgPrint("%02X", KeyData[i]);
}
DbgPrint("\n");
}
#endif
VOID
NTAPI
KsecInitializeEncryptionSupport (
@ -80,6 +92,8 @@ KsecGetKeyData (
if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS)
{
/* Hash some process specific data to generate the key */
RtlZeroMemory(&ProcessData, sizeof(ProcessData));
ProcessData.Process = CurrentProcess;
ProcessData.ProcessId = CurrentProcess->UniqueProcessId;
ProcessData.CreateTime = PsGetProcessCreateTimeQuadPart(CurrentProcess);
@ -87,14 +101,26 @@ KsecGetKeyData (
MD5Update(&Md5Contexts[0], (PVOID)&ProcessData, sizeof(ProcessData));
MD5Update(&Md5Contexts[1], (PVOID)&ProcessData, sizeof(ProcessData));
}
else // if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON)
else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON)
{
/* Hash the logon id to generate the key */
RtlZeroMemory(&LogonData, sizeof(LogonData));
Token = PsReferencePrimaryToken(CurrentProcess);
SeQueryAuthenticationIdToken(Token, &LogonData.LogonId);
PsDereferencePrimaryToken(Token);
MD5Update(&Md5Contexts[0], (PVOID)&LogonData, sizeof(LogonData));
MD5Update(&Md5Contexts[1], (PVOID)&LogonData, sizeof(LogonData));
}
else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS)
{
/* Use the original MD5s to generate the global key */
NOTHING;
}
else
{
/* Must not pass anything else */
ASSERT(FALSE);
}
/* Finalize the MD5s */
MD5Final(&Md5Contexts[0]);

View File

@ -9,26 +9,112 @@
#include <ntsecapi.h>
START_TEST(RtlEncryptMemory)
static const CHAR TestData[32] = "This is some test Message!!!";
void TestEncrypt(ULONG OptionFlags)
{
static const CHAR TestData[32] = "This is some test Message!!!";
CHAR Buffer[32];
CHAR DECLSPEC_ALIGN(8) Buffer[32];
NTSTATUS Status;
/* Size must be aligned to 8 bytes */
Status = RtlEncryptMemory(Buffer, 7, RTL_ENCRYPT_OPTION_SAME_PROCESS);
/* Size must be aligned to 8 bytes (aka RTL_ENCRYPT_MEMORY_SIZE) */
RtlCopyMemory(Buffer, TestData, sizeof(Buffer));
Status = RtlEncryptMemory(Buffer, 7, OptionFlags);
ok_ntstatus(Status, STATUS_INVALID_PARAMETER);
/* Buffer must not be aligned to 8 bytes */
Status = RtlEncryptMemory(&Buffer[1], 8, RTL_ENCRYPT_OPTION_SAME_PROCESS);
/* Buffer can be unaligned */
RtlCopyMemory(Buffer, TestData, sizeof(Buffer));
Status = RtlEncryptMemory(&Buffer[1], 8, OptionFlags);
ok_ntstatus(Status, STATUS_SUCCESS);
Status = RtlDecryptMemory(&Buffer[1], 8, OptionFlags);
ok_ntstatus(Status, STATUS_SUCCESS);
ok(RtlEqualMemory(Buffer, TestData, sizeof(Buffer)) == 1,
"OptionFlags=%lu, Buffer='%s', TestData='%s'\n",
OptionFlags, Buffer, TestData);
RtlCopyMemory(Buffer, TestData, sizeof(Buffer));
Status = RtlEncryptMemory(Buffer, sizeof(Buffer), RTL_ENCRYPT_OPTION_SAME_PROCESS);
Status = RtlEncryptMemory(Buffer, sizeof(Buffer), OptionFlags);
ok_ntstatus(Status, STATUS_SUCCESS);
ok_int(RtlEqualMemory(Buffer, TestData, sizeof(Buffer)), 0);
Status = RtlDecryptMemory(Buffer, sizeof(Buffer), RTL_ENCRYPT_OPTION_SAME_PROCESS);
Status = RtlDecryptMemory(Buffer, sizeof(Buffer), OptionFlags);
ok_ntstatus(Status, STATUS_SUCCESS);
ok_int(RtlEqualMemory(Buffer, TestData, sizeof(Buffer)), 1);
}
void TestCrossProcessDecrypt(PSTR Param)
{
UCHAR Buffer[32] = { 0 };
ULONG OptionFlags;
PSTR StrData;
ULONG i;
NTSTATUS Status;
OptionFlags = Param[3] == '1' ? RTL_ENCRYPT_OPTION_CROSS_PROCESS : RTL_ENCRYPT_OPTION_SAME_LOGON;
/* Convert the HEX string to binary ('-cp<1|2>:<data>') */
StrData = Param + 5;
for (i = 0; i < sizeof(Buffer); i++)
{
UINT x;
sscanf(&StrData[2 * i], "%02X", &x);
Buffer[i] = (UCHAR)x;
}
/* Decrypt the data */
Status = RtlDecryptMemory(Buffer, sizeof(Buffer), OptionFlags);
ok_ntstatus(Status, STATUS_SUCCESS);
ok_int(RtlEqualMemory(Buffer, TestData, sizeof(Buffer)), 1);
}
void TestCrossProcessEncrypt(ULONG OptionFlags)
{
UCHAR Buffer[32];
CHAR CmdLine[MAX_PATH];
PSTR StrBuffer;
NTSTATUS Status;
ULONG i;
INT result;
/* Encrypt the test string */
RtlCopyMemory(Buffer, TestData, sizeof(Buffer));
Status = RtlEncryptMemory(Buffer, sizeof(Buffer), OptionFlags);
ok_ntstatus(Status, STATUS_SUCCESS);
/* Start building a command line */
sprintf(CmdLine, "advapi32_apitest.exe RtlEncryptMemory -cp%lu:", OptionFlags);
StrBuffer = CmdLine + strlen(CmdLine);
/* Convert encrypted data into a hex string */
for (i = 0; i < sizeof(Buffer); i++)
{
sprintf(&StrBuffer[2 * i], "%02X", Buffer[i]);
}
result = system(CmdLine);
ok_int(result, 0);
}
START_TEST(RtlEncryptMemory)
{
CHAR Buffer[8] = { 0 };
PSTR CommandLine, Param;
NTSTATUS Status;
/* Check recursive call */
CommandLine = GetCommandLineA();
Param = strstr(CommandLine, "-cp");
if (Param != NULL)
{
TestCrossProcessDecrypt(Param);
return;
}
TestEncrypt(RTL_ENCRYPT_OPTION_SAME_PROCESS);
TestEncrypt(RTL_ENCRYPT_OPTION_CROSS_PROCESS);
TestEncrypt(RTL_ENCRYPT_OPTION_SAME_LOGON);
Status = RtlEncryptMemory(Buffer, sizeof(Buffer), 4);
ok_ntstatus(Status, STATUS_INVALID_PARAMETER);
TestCrossProcessEncrypt(RTL_ENCRYPT_OPTION_CROSS_PROCESS);
TestCrossProcessEncrypt(RTL_ENCRYPT_OPTION_SAME_LOGON);
}