packet encryption!

This commit is contained in:
donnaskiez 2024-05-11 22:54:58 +10:00
parent d5e3aa3dd4
commit 2ada40ddbd
28 changed files with 1036 additions and 432 deletions

View file

@ -7,7 +7,7 @@ VOID
GetApcContextByIndex(_Out_ PVOID* Context, _In_ INT Index)
{
AcquireDriverConfigLock();
*Context = GetApcContextArray()[Index];
*Context = (PVOID)GetApcContextArray()[Index];
ReleaseDriverConfigLock();
}
@ -39,14 +39,14 @@ unlock:
* we hold the lock during the entire decrement and free process.
*/
BOOLEAN
FreeApcContextStructure(_Out_ PAPC_CONTEXT_HEADER Context)
FreeApcContextStructure(_Inout_ PAPC_CONTEXT_HEADER Context)
{
DEBUG_VERBOSE("All APCs executed, freeing context structure");
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
PUINT64 entry = GetApcContextArray();
if (entry[index] != Context)
if (entry[index] != (UINT64)Context)
continue;
if (Context->count > 0)
@ -121,21 +121,21 @@ FreeApcAndDecrementApcCount(_Inout_ PRKAPC Apc, _In_ LONG ContextId)
NTSTATUS
QueryActiveApcContextsForCompletion()
{
AcquireDriverConfigLock();
AcquireDriverConfigLock();
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
PAPC_CONTEXT_HEADER entry = NULL;
GetApcContextByIndex(&entry, index);
if (!entry)
continue;
continue;
if (entry->count > 0 || entry->allocation_in_progress == TRUE)
continue;
continue;
switch (entry->context_id) {
case APC_CONTEXT_ID_STACKWALK:
FreeApcStackwalkApcContextInformation(entry);
FreeApcStackwalkApcContextInformation((PAPC_STACKWALK_CONTEXT)entry);
FreeApcContextStructure(entry);
break;
}
@ -149,16 +149,15 @@ VOID
InsertApcContext(_In_ PVOID Context)
{
if (IsDriverUnloading())
return STATUS_UNSUCCESSFUL;
return;
AcquireDriverConfigLock();
PAPC_CONTEXT_HEADER header = Context;
for (INT index = 0; index < MAXIMUM_APC_CONTEXTS; index++) {
PUINT64 entry = GetApcContextArray();
if (entry[index] == NULL) {
entry[index] = Context;
entry[index] = (UINT64)Context;
goto end;
}
}
@ -213,7 +212,7 @@ DrvUnloadFreeAllApcContextStructures()
ImpExFreePoolWithTag(context, POOL_TAG_APC);
}
unlock:
ReleaseDriverConfigLock();
return TRUE;
}

View file

@ -15,7 +15,7 @@ VOID
GetApcContext(_Out_ PVOID* Context, _In_ LONG ContextIdentifier);
BOOLEAN
FreeApcContextStructure(_Out_ PAPC_CONTEXT_HEADER Context);
FreeApcContextStructure(_Inout_ PAPC_CONTEXT_HEADER Context);
VOID
IncrementApcCount(_In_ LONG ContextId);

View file

@ -9,6 +9,7 @@
#include "imports.h"
#include "list.h"
#include "session.h"
#include "crypt.h"
STATIC
BOOLEAN
@ -124,7 +125,7 @@ EnumerateThreadListWithCallbackRoutine(
while (entry) {
CallbackRoutine(entry, Context);
entry = entry->list.Next;
entry = (PTHREAD_LIST_ENTRY)entry->list.Next;
}
unlock:
@ -145,7 +146,7 @@ EnumerateProcessListWithCallbackRoutine(
while (entry) {
CallbackRoutine(entry, Context);
entry = entry->list.Next;
entry = (PPROCESS_LIST_ENTRY)entry->list.Next;
}
unlock:
@ -166,7 +167,7 @@ EnumerateDriverListWithCallbackRoutine(
while (entry) {
CallbackRoutine(entry, Context);
entry = entry->list.Next;
entry = (PDRIVER_LIST_ENTRY)entry->list.Next;
}
unlock:
@ -249,7 +250,6 @@ InitialiseDriverList()
list->active = TRUE;
end:
if (modules.address)
ImpExFreePoolWithTag(modules.address, SYSTEM_MODULES_POOL);
@ -288,12 +288,13 @@ ImageLoadNotifyRoutineCallback(_In_opt_ PUNICODE_STRING FullImageName,
_In_ HANDLE ProcessId,
_In_ PIMAGE_INFO ImageInfo)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDRIVER_LIST_ENTRY entry = NULL;
RTL_MODULE_EXTENDED_INFO module = {0};
PDRIVER_LIST_HEAD list = GetDriverList();
ANSI_STRING ansi_path = {0};
UINT32 ansi_string_length = 0;
UNREFERENCED_PARAMETER(ProcessId);
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDRIVER_LIST_ENTRY entry = NULL;
RTL_MODULE_EXTENDED_INFO module = {0};
PDRIVER_LIST_HEAD list = GetDriverList();
ANSI_STRING ansi_path = {0};
if (InterlockedExchange(&list->active, list->active) == FALSE)
return;
@ -486,8 +487,6 @@ ProcessCreateNotifyRoutine(_In_ HANDLE ParentId,
process_name = ImpPsGetProcessImageFileName(process);
DEBUG_INFO("process create notify: %s", process_name);
if (Create) {
entry = ExAllocateFromLookasideListEx(&list->lookaside_list);
@ -585,6 +584,49 @@ ObPostOpCallbackRoutine(_In_ PVOID RegistrationContext,
UNREFERENCED_PARAMETER(OperationInformation);
}
#define MAX_PROCESS_NAME_LENGTH 30
#define PROCESS_HANDLE_OPEN_DOWNGRADE_COUNT 4
CHAR PROCESS_HANDLE_OPEN_DOWNGRADE[PROCESS_HANDLE_OPEN_DOWNGRADE_COUNT]
[MAX_PROCESS_NAME_LENGTH] = {"lsass.exe",
"csrss.exe",
"WerFault.exe",
"MsMpEng.exe"};
#define PROCESS_HANDLE_OPEN_WHITELIST_COUNT 3
CHAR PROCESS_HANDLE_OPEN_WHITELIST[PROCESS_HANDLE_OPEN_WHITELIST_COUNT]
[MAX_PROCESS_NAME_LENGTH] = {"Discord.exe",
"svchost.exe",
"explorer.exe"};
STATIC
BOOLEAN
IsWhitelistedHandleOpenProcess(_In_ LPCSTR ProcessName)
{
for (UINT32 index = 0; index < PROCESS_HANDLE_OPEN_WHITELIST_COUNT;
index++) {
if (!strcmp(ProcessName, PROCESS_HANDLE_OPEN_WHITELIST[index]))
return TRUE;
}
return FALSE;
}
STATIC
BOOLEAN
IsDowngradeHandleOpenProcess(_In_ LPCSTR ProcessName)
{
DEBUG_INFO("proc name: %s", ProcessName);
for (UINT32 index = 0; index < PROCESS_HANDLE_OPEN_DOWNGRADE_COUNT;
index++) {
if (!strcmp(ProcessName, PROCESS_HANDLE_OPEN_DOWNGRADE[index]))
return TRUE;
}
return FALSE;
}
// https://www.sysnative.com/forums/threads/object-headers-handles-and-types.34987/
#define GET_OBJECT_HEADER_FROM_HANDLE(x) ((x << 4) | 0xffff000000000000);
@ -603,6 +645,7 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
* This callback routine is executed in the context of the thread that
* is requesting to open said handle
*/
NTSTATUS status = STATUS_UNSUCCESSFUL;
PEPROCESS process_creator = PsGetCurrentProcess();
PEPROCESS protected_process = NULL;
PEPROCESS target_process = (PEPROCESS)OperationInformation->Object;
@ -612,6 +655,7 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
LPCSTR target_process_name = NULL;
LPCSTR protected_process_name = NULL;
POB_CALLBACKS_CONFIG configuration = NULL;
UINT32 report_size = 0;
/*
* This is to prevent the condition where the thread executing this
@ -648,10 +692,7 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
* todo: perform stricter checks rather then the image name.
* perhapds check some certificate or something.
*/
if (!strcmp(process_creator_name, "lsass.exe") ||
!strcmp(process_creator_name, "csrss.exe") ||
!strcmp(process_creator_name, "WerFault.exe") ||
!strcmp(process_creator_name, "MsMpEng.exe") ||
if (IsDowngradeHandleOpenProcess(process_creator_name) ||
!strcmp(process_creator_name, target_process_name)) {
/* We will downgrade these handles later */
// DEBUG_LOG("Handles created by CSRSS, LSASS and
@ -674,27 +715,19 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
* atleast.
*/
if (!strcmp(process_creator_name, "Discord.exe") ||
!strcmp(process_creator_name, "svchost.exe") ||
!strcmp(process_creator_name, "explorer.exe"))
if (IsWhitelistedHandleOpenProcess(process_creator_name))
goto end;
POPEN_HANDLE_FAILURE_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(OPEN_HANDLE_FAILURE_REPORT),
REPORT_POOL_TAG);
report_size = CryptRequestRequiredBufferLength(
sizeof(OPEN_HANDLE_FAILURE_REPORT));
POPEN_HANDLE_FAILURE_REPORT report = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, report_size, REPORT_POOL_TAG);
if (!report)
goto end;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(
&report->report_header, REPORT_ILLEGAL_HANDLE_OPERATION, 0);
DEBUG_INFO("packet type: %hx", report->header.packet_type);
DEBUG_INFO("report code: %lx", report->report_header.report_code);
DEBUG_INFO("report subcode: %lx",
report->report_header.report_sub_type);
INIT_REPORT_PACKET(report, REPORT_ILLEGAL_HANDLE_OPERATION, 0);
report->is_kernel_handle = OperationInformation->KernelHandle;
report->process_id = process_creator_id;
@ -706,7 +739,15 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
process_creator_name,
HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
IrpQueueCompletePacket(report, sizeof(OPEN_HANDLE_FAILURE_REPORT));
status = CryptEncryptBuffer(report, report_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %x", status);
ExFreePoolWithTag(report, report_size);
goto end;
}
IrpQueueCompletePacket(report, report_size);
}
end:
@ -727,7 +768,18 @@ ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable,
old_value = InterlockedOr((PLONG)&HandleTableEntry->VolatileLowValue, 1);
/* Unblock any waiters */
#pragma warning(push)
#pragma warning(disable : C6387)
ImpExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL);
#pragma warning(pop)
}
FORCEINLINE
STATIC
ACCESS_MASK
GetHandleAccessMask(_In_ PHANDLE_TABLE_ENTRY Entry)
{
return (ACCESS_MASK)Entry->GrantedAccessBits;
}
static UNICODE_STRING OBJECT_TYPE_PROCESS = RTL_CONSTANT_STRING(L"Process");
@ -742,6 +794,9 @@ EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
{
PAGED_CODE();
UNREFERENCED_PARAMETER(Context);
NTSTATUS status = STATUS_UNSUCCESSFUL;
PVOID object = NULL;
PVOID object_header = NULL;
POBJECT_TYPE object_type = NULL;
@ -750,12 +805,12 @@ EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
LPCSTR process_name = NULL;
LPCSTR protected_process_name = NULL;
ACCESS_MASK handle_access_mask = 0;
UINT32 report_size = 0;
object_header = GET_OBJECT_HEADER_FROM_HANDLE(Entry->ObjectPointerBits);
/* Object header is the first 30 bytes of the object */
object = (uintptr_t)object_header + OBJECT_HEADER_SIZE;
object = (uintptr_t)object_header + OBJECT_HEADER_SIZE;
object_type = ImpObGetObjectType(object);
/* TODO: check for threads aswell */
@ -778,7 +833,7 @@ EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
"Handle references our protected process with access mask: %lx",
(ACCESS_MASK)Entry->GrantedAccessBits);
handle_access_mask = (ACCESS_MASK)Entry->GrantedAccessBits;
handle_access_mask = GetHandleAccessMask(Entry);
/* These permissions can be stripped from every process
* including CSRSS and LSASS */
@ -851,10 +906,11 @@ EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
DEBUG_VERBOSE("Stripped PROCESS_VM_WRITE");
}
report_size =
CryptRequestRequiredBufferLength(sizeof(OPEN_HANDLE_FAILURE_REPORT));
POPEN_HANDLE_FAILURE_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(OPEN_HANDLE_FAILURE_REPORT),
REPORT_POOL_TAG);
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, report_size, REPORT_POOL_TAG);
if (!report)
goto end;
@ -867,9 +923,7 @@ EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
* also don't think its worth creating another queue
* specifically for open handle reports since they will be rare.
*/
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(
&report->report_header, REPORT_ILLEGAL_HANDLE_OPERATION, 0);
INIT_REPORT_PACKET(report, REPORT_ILLEGAL_HANDLE_OPERATION, 0);
report->is_kernel_handle = Entry->Attributes & OBJ_KERNEL_HANDLE;
report->process_id = ImpPsGetProcessId(process);
@ -880,12 +934,16 @@ EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
process_name,
HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
if (!NT_SUCCESS(IrpQueueCompletePacket(
report, sizeof(OPEN_HANDLE_FAILURE_REPORT)))) {
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
status = CryptEncryptBuffer(report, report_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, report_size);
goto end;
}
IrpQueueCompletePacket(report, report_size);
end:
ExUnlockHandleTableEntry(HandleTable, Entry);
return FALSE;
@ -919,8 +977,7 @@ EnumerateProcessHandles(_In_ PPROCESS_LIST_ENTRY ProcessListEntry,
#pragma warning(push)
#pragma warning(suppress : 6387)
BOOLEAN result =
ImpExEnumHandleTable(handle_table, EnumHandleCallback, NULL, NULL);
ImpExEnumHandleTable(handle_table, EnumHandleCallback, NULL, NULL);
#pragma warning(pop)
@ -929,8 +986,7 @@ EnumerateProcessHandles(_In_ PPROCESS_LIST_ENTRY ProcessListEntry,
#define REPEAT_TIME_10_SEC 10000
ULONG value = 10;
STATIC
VOID
TimerObjectWorkItemRoutine(_In_ PDEVICE_OBJECT DeviceObject,
_In_opt_ PVOID Context)
@ -939,6 +995,11 @@ TimerObjectWorkItemRoutine(_In_ PDEVICE_OBJECT DeviceObject,
PTIMER_OBJECT timer = (PTIMER_OBJECT)Context;
PDRIVER_LIST_HEAD list = GetDriverList();
UNREFERENCED_PARAMETER(DeviceObject);
if (!ARGUMENT_PRESENT(Context))
return;
if (!list->active)
goto end;
@ -960,17 +1021,22 @@ end:
/*
* This routine is executed every x seconds, and is run at IRQL = DISPATCH_LEVEL
*/
STATIC
VOID
TimerObjectCallbackRoutine(_In_ PKDPC Dpc,
_In_opt_ PVOID DeferredContext,
_In_opt_ PVOID SystemArgument1,
_In_opt_ PVOID SystemArgument2)
{
PTIMER_OBJECT timer = (PTIMER_OBJECT)DeferredContext;
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(SystemArgument1);
UNREFERENCED_PARAMETER(SystemArgument2);
if (!HasDriverLoaded())
if (!HasDriverLoaded() || !ARGUMENT_PRESENT(DeferredContext))
return;
PTIMER_OBJECT timer = (PTIMER_OBJECT)DeferredContext;
/* we dont want to queue our work item if it hasnt executed */
if (timer->state)
return;
@ -987,10 +1053,7 @@ TimerObjectCallbackRoutine(_In_ PKDPC Dpc,
NTSTATUS
InitialiseTimerObject(_Out_ PTIMER_OBJECT Timer)
{
LARGE_INTEGER due_time = {0};
LONG period = 0;
due_time.QuadPart = -ABSOLUTE(SECONDS(5));
LARGE_INTEGER due_time = {.QuadPart = -ABSOLUTE(SECONDS(5))};
Timer->work_item = IoAllocateWorkItem(GetDriverDeviceObject());
@ -1006,7 +1069,7 @@ InitialiseTimerObject(_Out_ PTIMER_OBJECT Timer)
}
VOID
CleanupDriverTimerObjects(_Out_ PTIMER_OBJECT Timer)
CleanupDriverTimerObjects(_Inout_ PTIMER_OBJECT Timer)
{
/* this routine blocks until all queued DPCs on all processors have
* executed. */
@ -1044,16 +1107,14 @@ RegisterProcessObCallbacks()
{
PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL;
PACTIVE_SESSION config = GetActiveSession();
NTSTATUS status = STATUS_UNSUCCESSFUL;
PACTIVE_SESSION config = GetActiveSession();
OB_CALLBACK_REGISTRATION callback_registration = {0};
OB_OPERATION_REGISTRATION operation_registration = {0};
DEBUG_VERBOSE("Enabling ObRegisterCallbacks.");
AcquireDriverConfigLock();
OB_CALLBACK_REGISTRATION callback_registration = {0};
OB_OPERATION_REGISTRATION operation_registration = {0};
PCREATE_PROCESS_NOTIFY_ROUTINE_EX notify_routine = {0};
operation_registration.ObjectType = PsProcessType;
operation_registration.Operations |= OB_OPERATION_HANDLE_CREATE;
operation_registration.Operations |= OB_OPERATION_HANDLE_DUPLICATE;

View file

@ -77,11 +77,11 @@ CleanupThreadListOnDriverUnload();
VOID
FindThreadListEntryByThreadAddress(_In_ PKTHREAD Thread,
_Inout_ PTHREAD_LIST_ENTRY* Entry);
_Out_ PTHREAD_LIST_ENTRY* Entry);
VOID
FindProcessListEntryByProcess(_In_ PKPROCESS Process,
_Inout_ PPROCESS_LIST_ENTRY* Entry);
_Out_ PPROCESS_LIST_ENTRY* Entry);
VOID
EnumerateThreadListWithCallbackRoutine(
@ -110,7 +110,7 @@ NTSTATUS
InitialiseTimerObject(_Out_ PTIMER_OBJECT Timer);
VOID
CleanupDriverTimerObjects(_Out_ PTIMER_OBJECT Timer);
CleanupDriverTimerObjects(_Inout_ PTIMER_OBJECT Timer);
VOID
UnregisterProcessCreateNotifyRoutine();

View file

@ -6,6 +6,7 @@
#include "io.h"
#include "types/types.h"
#include <bcrypt.h>
/*
* For numbers < 32, these are equivalent to 0ul << x.
@ -80,10 +81,10 @@ typedef struct _DRIVER_LIST_HEAD {
KGUARDED_MUTEX lock;
/* modules that need to be hashed later. */
PIO_WORKITEM work_item;
LIST_ENTRY deferred_list;
PIO_WORKITEM work_item;
LIST_ENTRY deferred_list;
volatile BOOLEAN deferred_complete;
volatile LONG can_hash_x86;
volatile LONG can_hash_x86;
} DRIVER_LIST_HEAD, *PDRIVER_LIST_HEAD;
@ -213,7 +214,8 @@ typedef struct _IRP_QUEUE_ENTRY {
* the target process to protect is open / closed / changes etc.
*/
#define AES_128_KEY_SIZE 16
#define AES_256_KEY_SIZE 32
#define AES_256_IV_SIZE 16
typedef struct _HEARTBEAT_CONFIGURATION {
volatile UINT32 counter;
@ -233,6 +235,14 @@ typedef struct _HEARTBEAT_CONFIGURATION {
} HEARTBEAT_CONFIGURATION, *PHEARTBEAT_CONFIGURATION;
typedef struct _SESSION_INITIATION_PACKET {
UINT32 cookie;
PVOID process_id;
UCHAR aes_key[AES_256_KEY_SIZE];
UCHAR aes_iv[AES_256_IV_SIZE];
} SESSION_INITIATION_PACKET, *PSESSION_INITIATION_PACKET;
typedef struct _ACTIVE_SESSION {
BOOLEAN is_session_active;
PVOID um_handle;
@ -240,8 +250,16 @@ typedef struct _ACTIVE_SESSION {
PEPROCESS process;
OB_CALLBACKS_CONFIG callback_configuration;
UINT32 session_cookie;
CHAR session_aes_key[AES_128_KEY_SIZE];
struct {
UINT32 cookie;
UINT32 magic_number;
PUCHAR aes_key[AES_256_KEY_SIZE];
PUCHAR iv[AES_256_IV_SIZE];
BCRYPT_KEY_HANDLE key_handle;
PUCHAR key_object;
UINT32 key_object_length;
};
struct SESSION_STATISTICS {
UINT32 irps_received;
@ -250,7 +268,7 @@ typedef struct _ACTIVE_SESSION {
};
HEARTBEAT_CONFIGURATION heartbeat_config;
KGUARDED_MUTEX lock;
KSPIN_LOCK lock;
} ACTIVE_SESSION, *PACTIVE_SESSION;
@ -259,6 +277,7 @@ typedef struct _ACTIVE_SESSION {
#define INVALID_DRIVER_LIST_HEAD_POOL 'rwar'
#define INVALID_DRIVER_LIST_ENTRY_POOL 'gaah'
#define POOL_TAG_APC 'apcc'
#define POOL_TAG_CRYPT 'tpcr'
#define POOL_TAG_HW 'hwhw'
#define POOL_TAG_DPC 'apcc'
#define POOL_TAG_HEARTBEAT 'teab'

View file

@ -1,8 +1,10 @@
#include "crypt.h"
#include <immintrin.h>
#include "imports.h"
#include "session.h"
#include "driver.h"
#include <immintrin.h>
#include <bcrypt.h>
#define XOR_KEY_1 0x1122334455667788
@ -58,7 +60,7 @@ CryptDecryptImportBlock(_In_ PUINT64 Array, _In_ UINT32 BlockIndex)
return _mm256_xor_si256(load_block, CryptGenerateSseXorKey());
}
STATIC
FORCEINLINE
INLINE
VOID
CryptFindContainingBlockForArrayIndex(_In_ UINT32 EntryIndex,
@ -127,16 +129,188 @@ CryptDecryptImportsArrayEntry(_In_ PUINT64 Array,
return pointer;
}
/*
* simple for now.. just to get it working
*/
VOID
CryptDecryptBufferWithCookie(_In_ PVOID Buffer,
_In_ UINT32 BufferSize,
_In_ UINT32 Cookie)
STATIC
PBCRYPT_KEY_DATA_BLOB_HEADER
CryptBuildBlobForKeyImport(_In_ PACTIVE_SESSION Session)
{
PCHAR buffer = (PCHAR)Buffer;
for (UINT32 index = 0; index < BufferSize; index++) {
buffer[index] ^= Cookie;
}
PBCRYPT_KEY_DATA_BLOB_HEADER blob =
ExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + AES_256_KEY_SIZE,
POOL_TAG_CRYPT);
if (!blob)
return NULL;
blob->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
blob->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
blob->cbKeyData = AES_256_KEY_SIZE;
RtlCopyMemory((UINT64)blob + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER),
Session->aes_key,
AES_256_KEY_SIZE);
return blob;
}
#define AES_256_BLOCK_SIZE 16
UINT32
CryptRequestRequiredBufferLength(_In_ UINT32 BufferLength)
{
// status = BCryptEncrypt(session->key_handle,
// lol,
// BufferLength,
// NULL,
// session->iv,
// sizeof(session->iv),
// NULL,
// 0,
// RequiredLength,
// 0);
// if (!NT_SUCCESS(status))
// DEBUG_ERROR("CryptRequestRequiredBufferLength -> BCryptEncrypt: %x",
// status);
return (BufferLength + AES_256_BLOCK_SIZE - 1) / AES_256_BLOCK_SIZE *
AES_256_BLOCK_SIZE;
}
/* Encrypts in place! */
NTSTATUS
CryptEncryptBuffer(_In_ PVOID Buffer, _In_ UINT32 BufferLength)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 data_copied = 0;
PACTIVE_SESSION session = GetActiveSession();
UCHAR local_iv[sizeof(session->iv)] = {0};
UINT64 buffer = (UINT64)Buffer;
UINT32 length = BufferLength;
/* The IV is consumed during every encrypt / decrypt procedure, so to ensure
* we have access to the iv we need to create a local copy.*/
RtlCopyMemory(local_iv, session->iv, sizeof(session->iv));
/* We arent encrypting the first 16 bytes */
buffer = buffer + AES_256_BLOCK_SIZE;
length = length - AES_256_BLOCK_SIZE;
status = BCryptEncrypt(session->key_handle,
buffer,
length,
NULL,
local_iv,
sizeof(local_iv),
buffer,
length,
&data_copied,
0);
if (!NT_SUCCESS(status))
DEBUG_ERROR("CryptEncryptBuffer -> BCryptEncrypt: %x", status);
return status;
}
/* Lock is held */
VOID
CryptCloseSessionCryptObjects()
{
PACTIVE_SESSION session = GetActiveSession();
if (session->key_handle) {
BCryptDestroyKey(session->key_handle);
session->key_handle = NULL;
}
if (session->key_object) {
ExFreePoolWithTag(session->key_object, POOL_TAG_CRYPT);
session->key_object = NULL;
}
session->key_object_length = 0;
}
NTSTATUS
CryptInitialiseSessionCryptObjects()
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 data_copied = 0;
PACTIVE_SESSION session = GetActiveSession();
PBCRYPT_KEY_DATA_BLOB_HEADER blob = NULL;
BCRYPT_ALG_HANDLE* handle = GetCryptAlgHandle();
blob = CryptBuildBlobForKeyImport(session);
if (!blob)
return STATUS_INSUFFICIENT_RESOURCES;
status = BCryptGetProperty(*handle,
BCRYPT_OBJECT_LENGTH,
&session->key_object_length,
sizeof(UINT32),
&data_copied,
0);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("BCryptGetProperty: %x", status);
goto end;
}
session->key_object = ExAllocatePool2(
POOL_FLAG_NON_PAGED, session->key_object_length, POOL_TAG_CRYPT);
if (!session->key_object) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto end;
}
DEBUG_INFO("key object: %llx, key_object_length: %lx",
session->key_object,
session->key_object_length);
status =
BCryptImportKey(*handle,
NULL,
BCRYPT_KEY_DATA_BLOB,
&session->key_handle,
session->key_object,
session->key_object_length,
blob,
sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + AES_256_KEY_SIZE,
0);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("BCryptImportKey: %x", status);
ExFreePoolWithTag(session->key_object, POOL_TAG_CRYPT);
goto end;
}
end:
if (blob)
ExFreePoolWithTag(blob, POOL_TAG_CRYPT);
return status;
}
NTSTATUS
CryptInitialiseProvider()
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
BCRYPT_ALG_HANDLE* handle = GetCryptAlgHandle();
status = BCryptOpenAlgorithmProvider(
handle, BCRYPT_AES_ALGORITHM, NULL, BCRYPT_PROV_DISPATCH);
if (!NT_SUCCESS(status))
DEBUG_ERROR("BCryptOpenAlgorithmProvider: %x", status);
return status;
}
VOID
CryptCloseProvider()
{
BCRYPT_ALG_HANDLE* handle = GetCryptAlgHandle();
BCryptCloseAlgorithmProvider(*handle, 0);
}

View file

@ -11,9 +11,22 @@ CryptDecryptImportsArrayEntry(_In_ PUINT64 Array,
_In_ UINT32 Entries,
_In_ UINT32 EntryIndex);
NTSTATUS
CryptInitialiseProvider();
UINT32
CryptRequestRequiredBufferLength(_In_ UINT32 BufferLength);
NTSTATUS
CryptEncryptBuffer(_In_ PVOID Buffer, _In_ UINT32 BufferLength);
NTSTATUS
CryptInitialiseSessionCryptObjects();
VOID
CryptDecryptBufferWithCookie(_In_ PVOID Buffer,
_In_ UINT32 BufferSize,
_In_ UINT32 Cookie);
CryptCloseSessionCryptObjects();
VOID
CryptCloseProvider();
#endif

View file

@ -93,14 +93,16 @@ typedef struct _DRIVER_CONFIG {
IRP_QUEUE_HEAD irp_queue;
/* terrible name..lol what is tis timer for ?? */
TIMER_OBJECT timer;
TIMER_OBJECT timer;
ACTIVE_SESSION session_information;
THREAD_LIST_HEAD thread_list;
DRIVER_LIST_HEAD driver_list;
PROCESS_LIST_HEAD process_list;
SHARED_MAPPING mapping;
BOOLEAN has_driver_loaded;
ACTIVE_SESSION session_information;
THREAD_LIST_HEAD thread_list;
DRIVER_LIST_HEAD driver_list;
PROCESS_LIST_HEAD process_list;
SHARED_MAPPING mapping;
BOOLEAN has_driver_loaded;
BCRYPT_ALG_HANDLE alg_handle;
} DRIVER_CONFIG, *PDRIVER_CONFIG;
@ -120,6 +122,12 @@ PDRIVER_CONFIG g_DriverConfig = NULL;
#define POOL_TAG_CONFIG 'conf'
BCRYPT_ALG_HANDLE*
GetCryptAlgHandle()
{
return &g_DriverConfig->alg_handle;
}
BOOLEAN
HasDriverLoaded()
{
@ -382,6 +390,8 @@ DriverUnload(_In_ PDRIVER_OBJECT DriverObject)
DrvUnloadFreeProcessList();
DrvUnloadFreeDriverList();
CryptCloseProvider();
DrvUnloadFreeConfigStrings();
DrvUnloadDeleteSymbolicLink();
ImpIoDeleteDevice(DriverObject->DeviceObject);
@ -863,7 +873,15 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
return status;
}
SessionInitialiseStructure();
status = SessionInitialiseStructure();
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("SessionInitialiseStructure failed with status %x", status);
DrvUnloadFreeConfigStrings();
DrvUnloadFreeTimerObject();
ImpIoDeleteDevice(DriverObject->DeviceObject);
return status;
}
status = IoCreateSymbolicLink(g_DriverConfig->device_symbolic_link,
g_DriverConfig->device_name);

View file

@ -10,6 +10,9 @@
#include "integrity.h"
#include "callbacks.h"
BCRYPT_ALG_HANDLE*
GetCryptAlgHandle();
NTSTATUS
QueryActiveApcContextsForCompletion();

View file

@ -64,7 +64,7 @@ STATIC
NTSTATUS
QueryPciDeviceConfigurationSpace(_In_ PDEVICE_OBJECT DeviceObject,
_In_ UINT32 Offset,
_Out_ PVOID Buffer,
_Out_opt_ PVOID Buffer,
_In_ UINT32 BufferLength)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
@ -100,7 +100,7 @@ QueryPciDeviceConfigurationSpace(_In_ PDEVICE_OBJECT DeviceObject,
status = IoCallDriver(DeviceObject, irp);
if (status = STATUS_PENDING) {
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = io.Status;
}
@ -127,6 +127,7 @@ EnumerateDriverObjectDeviceObjects(_In_ PDRIVER_OBJECT DriverObject,
UINT32 buffer_size = 0;
*DeviceObjectArray = NULL;
*ArrayEntries = 0;
status = IoEnumerateDeviceObjectList(DriverObject, NULL, 0, &object_count);
@ -200,7 +201,6 @@ EnumeratePciDeviceObjects(_In_ PCI_DEVICE_CALLBACK CallbackRoutine,
PDEVICE_OBJECT* pci_device_objects = NULL;
PDEVICE_OBJECT current_device = NULL;
UINT32 pci_device_objects_count = 0;
USHORT vendor_id = 0;
status = GetDriverObjectByDriverName(&pci, &pci_driver_object);
@ -238,7 +238,6 @@ EnumeratePciDeviceObjects(_In_ PCI_DEVICE_CALLBACK CallbackRoutine,
ObDereferenceObject(current_device);
}
end:
if (pci_device_objects)
ExFreePoolWithTag(pci_device_objects, POOL_TAG_HW);
@ -260,6 +259,8 @@ STATIC
NTSTATUS
PciDeviceQueryCallback(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
{
UNREFERENCED_PARAMETER(Context);
NTSTATUS status = STATUS_UNSUCCESSFUL;
PCI_COMMON_HEADER header = {0};

View file

@ -9,6 +9,7 @@
#include "session.h"
#include "util.h"
#include "pe.h"
#include "crypt.h"
#include <bcrypt.h>
#include <initguid.h>
@ -174,6 +175,8 @@ GetModuleInformationByName(_Out_ PRTL_MODULE_EXTENDED_INFO ModuleInfo,
return status;
}
/* TODO: think this remains from testing, we only use this to find our
* driver anyway but should be fixed. */
driver_info = FindSystemModuleByName(driver_name, &modules);
if (!driver_info) {
@ -244,7 +247,6 @@ StoreModuleExecutableRegionsInBuffer(_Out_ PVOID* Buffer,
PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL;
PIMAGE_DOS_HEADER dos_header = NULL;
PNT_HEADER_64 nt_header = NULL;
PIMAGE_SECTION_HEADER section = NULL;
ULONG total_packet_size = 0;
@ -865,24 +867,32 @@ STATIC
VOID
ReportInvalidProcessModule(_In_ PPROCESS_MODULE_INFORMATION Module)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 report_size = CryptRequestRequiredBufferLength(
sizeof(PROCESS_MODULE_VALIDATION_REPORT));
PPROCESS_MODULE_VALIDATION_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(PROCESS_MODULE_VALIDATION_REPORT),
REPORT_POOL_TAG);
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, report_size, REPORT_POOL_TAG);
if (!report)
return;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(
&report->report_header, REPORT_INVALID_PROCESS_MODULE, 0);
INIT_REPORT_PACKET(report, REPORT_INVALID_PROCESS_MODULE, 0);
report->image_base = Module->module_base;
report->image_size = Module->module_size;
RtlCopyMemory(
report->module_path, Module->module_path, sizeof(report->module_path));
IrpQueueCompletePacket(report, sizeof(PROCESS_MODULE_VALIDATION_REPORT));
status = CryptEncryptBuffer(report, report_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, report_size);
return;
}
IrpQueueCompletePacket(report, report_size);
}
/*
@ -961,7 +971,7 @@ ValidateProcessLoadedModule(_Inout_ PIRP Irp)
}
status = MapDiskImageIntoVirtualAddressSpace(
&section_handle, &section, &module_path, &section_size, 0);
&section_handle, &section, &module_path, &section_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("MapDiskImageIntoVirtualAddressSpace failed with status %x",
@ -1450,8 +1460,12 @@ Enablex86Hashing(_In_ PDRIVER_LIST_HEAD Head)
}
VOID
DeferredModuleHashingCallback()
DeferredModuleHashingCallback(_In_ PDEVICE_OBJECT DeviceObject,
_In_opt_ PVOID Context)
{
UNREFERENCED_PARAMETER(Context);
UNREFERENCED_PARAMETER(DeviceObject);
NTSTATUS status = STATUS_UNSUCCESSFUL;
RTL_MODULE_EXTENDED_INFO module = {0};
PDRIVER_LIST_HEAD driver_list = GetDriverList();
@ -1488,6 +1502,7 @@ DeferredModuleHashingCallback()
}
end:
DEBUG_VERBOSE("All deferred modules hashed.");
ImpIoFreeWorkItem(driver_list->work_item);
driver_list->work_item = NULL;
@ -1510,7 +1525,7 @@ HashModule(_In_ PRTL_MODULE_EXTENDED_INFO Module, _Out_ PVOID Hash)
if (!ansi_string.Buffer) {
DEBUG_ERROR("RtlInitAnsiString failed with status %x", status);
return;
return STATUS_UNSUCCESSFUL;
}
status = ImpRtlAnsiStringToUnicodeString(&path, &ansi_string, TRUE);
@ -1518,7 +1533,7 @@ HashModule(_In_ PRTL_MODULE_EXTENDED_INFO Module, _Out_ PVOID Hash)
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("RtlAnsiStringToUnicodeString failed with status %x",
status);
goto end;
return status;
}
/*
@ -1622,6 +1637,7 @@ ValidateSystemModule(_In_ PRTL_MODULE_EXTENDED_INFO Module)
Module->FullPathName);
end:
if (hash)
ExFreePoolWithTag(hash, POOL_TAG_INTEGRITY);
}
@ -1754,6 +1770,8 @@ VOID
SystemModuleVerificationDispatchFunction(_In_ PDEVICE_OBJECT DeviceObject,
_In_ PSYS_MODULE_VAL_CONTEXT Context)
{
UNREFERENCED_PARAMETER(DeviceObject);
IncrementActiveThreadCount(Context);
UINT32 count = GetCurrentVerificationIndex(Context);
@ -2068,7 +2086,7 @@ AllocateHeartbeatObjects(_Inout_ PHEARTBEAT_CONFIGURATION Configuration)
* intervals. */
STATIC
LARGE_INTEGER
GenerateHeartbeatDueTime(_In_ PHEARTBEAT_CONFIGURATION Configuration)
GenerateHeartbeatDueTime()
{
LARGE_INTEGER ticks = {0};
KeQueryTickCount(&ticks);
@ -2089,9 +2107,8 @@ InitialiseHeartbeatObjects(_Inout_ PHEARTBEAT_CONFIGURATION Configuration)
{
KeInitializeDpc(Configuration->dpc, HeartbeatDpcRoutine, Configuration);
KeInitializeTimer(Configuration->timer);
KeSetTimer(Configuration->timer,
GenerateHeartbeatDueTime(Configuration),
Configuration->dpc);
KeSetTimer(
Configuration->timer, GenerateHeartbeatDueTime(), Configuration->dpc);
}
FORCEINLINE
@ -2158,16 +2175,17 @@ IncrementHeartbeatCounter(_In_ PHEARTBEAT_CONFIGURATION Configuration)
FORCEINLINE
STATIC
PHEARTBEAT_PACKET
BuildHeartbeatPacket(_In_ PHEARTBEAT_CONFIGURATION Configuration)
BuildHeartbeatPacket(_In_ UINT32 PacketSize)
{
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
PHEARTBEAT_PACKET packet = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, sizeof(HEARTBEAT_PACKET), POOL_TAG_HEARTBEAT);
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
PHEARTBEAT_PACKET packet =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, PacketSize, POOL_TAG_HEARTBEAT);
if (!packet)
return NULL;
INIT_PACKET_HEADER(&packet->header, PACKET_TYPE_HEARTBEAT);
INIT_HEARTBEAT_PACKET(packet);
/* This routine always runs at DPC level */
KeAcquireSpinLockAtDpcLevel(&queue->lock);
@ -2199,22 +2217,32 @@ HeartbeatDpcRoutine(_In_ PKDPC Dpc,
if (!ARGUMENT_PRESENT(DeferredContext))
return;
NTSTATUS status = STATUS_UNSUCCESSFUL;
PHEARTBEAT_CONFIGURATION config = (PHEARTBEAT_CONFIGURATION)DeferredContext;
PHEARTBEAT_PACKET packet = NULL;
UINT32 packet_size = 0;
DEBUG_VERBOSE("Heartbeat timer alerted. Generating heartbeat packet.");
SetHeartbeatActive(config);
packet = BuildHeartbeatPacket(config);
packet_size = CryptRequestRequiredBufferLength(sizeof(HEARTBEAT_PACKET));
packet = BuildHeartbeatPacket(packet_size);
if (packet) {
IrpQueueCompletePacket(packet, sizeof(HEARTBEAT_PACKET));
status = CryptEncryptBuffer(packet, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(packet, POOL_TAG_HEARTBEAT);
goto end;
}
IrpQueueCompletePacket(packet, packet_size);
IncrementHeartbeatCounter(config);
}
end:
IoQueueWorkItem(
config->work_item, HeartbeatWorkItem, NormalWorkQueue, config);
}

View file

@ -115,7 +115,8 @@ BOOLEAN
ValidateOurDriversDispatchRoutines();
VOID
DeferredModuleHashingCallback();
DeferredModuleHashingCallback(_In_ PDEVICE_OBJECT DeviceObject,
_In_opt_ PVOID Context);
VOID
FindWinLogonProcess(_In_ PPROCESS_LIST_ENTRY Entry, _In_opt_ PVOID Context);

View file

@ -8,6 +8,7 @@
#include "apc.h"
#include "thread.h"
#include "pe.h"
#include "crypt.h"
#define WHITELISTED_MODULE_TAG 'whte'
@ -340,18 +341,17 @@ STATIC
VOID
ReportInvalidDriverObject(_In_ PDRIVER_OBJECT Driver, _In_ UINT32 ReportSubType)
{
PMODULE_VALIDATION_FAILURE report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(MODULE_VALIDATION_FAILURE),
POOL_TAG_INTEGRITY);
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size =
CryptRequestRequiredBufferLength(sizeof(MODULE_VALIDATION_FAILURE));
PMODULE_VALIDATION_FAILURE report = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, packet_size, POOL_TAG_INTEGRITY);
if (!report)
return;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(&report->report_header,
REPORT_MODULE_VALIDATION_FAILURE,
ReportSubType);
INIT_REPORT_PACKET(report, REPORT_MODULE_VALIDATION_FAILURE, ReportSubType);
report->driver_base_address = Driver->DriverStart;
report->driver_size = Driver->DriverSize;
@ -363,7 +363,16 @@ ReportInvalidDriverObject(_In_ PDRIVER_OBJECT Driver, _In_ UINT32 ReportSubType)
/* Continue regardless of result */
ImpRtlUnicodeStringToAnsiString(&string, &Driver->DriverName, FALSE);
IrpQueueCompletePacket(report, sizeof(MODULE_VALIDATION_FAILURE));
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
return;
}
IrpQueueCompletePacket(report, packet_size);
}
FORCEINLINE
@ -562,20 +571,31 @@ STATIC
VOID
ReportNmiBlocking()
{
PNMI_CALLBACK_FAILURE report = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, sizeof(NMI_CALLBACK_FAILURE), REPORT_POOL_TAG);
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size =
CryptRequestRequiredBufferLength(sizeof(NMI_CALLBACK_FAILURE));
PNMI_CALLBACK_FAILURE report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
if (!report)
return STATUS_INSUFFICIENT_RESOURCES;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(&report->report_header, REPORT_NMI_CALLBACK_FAILURE, 0);
INIT_REPORT_PACKET(report, REPORT_NMI_CALLBACK_FAILURE, 0);
report->kthread_address = NULL;
report->invalid_rip = NULL;
report->were_nmis_disabled = TRUE;
IrpQueueCompletePacket(report, sizeof(NMI_CALLBACK_FAILURE));
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
return;
}
IrpQueueCompletePacket(report, packet_size);
}
STATIC
@ -585,16 +605,17 @@ ReportMissingCidTableEntry(_In_ PNMI_CONTEXT Context)
DEBUG_WARNING("Thread: %llx was not found in the pspcid table.",
Context->kthread);
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size =
CryptRequestRequiredBufferLength(sizeof(HIDDEN_SYSTEM_THREAD_REPORT));
PHIDDEN_SYSTEM_THREAD_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(HIDDEN_SYSTEM_THREAD_REPORT),
REPORT_POOL_TAG);
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
if (!report)
return;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(&report->report_header, REPORT_HIDDEN_SYSTEM_THREAD, 0);
INIT_REPORT_PACKET(report, REPORT_HIDDEN_SYSTEM_THREAD, 0);
report->found_in_kthreadlist = FALSE; // wip
report->found_in_pspcidtable = FALSE;
@ -602,29 +623,47 @@ ReportMissingCidTableEntry(_In_ PNMI_CONTEXT Context)
report->thread_address = Context->kthread;
RtlCopyMemory(report->thread, Context->kthread, sizeof(report->thread));
IrpQueueCompletePacket(report, sizeof(HIDDEN_SYSTEM_THREAD_REPORT));
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
return;
}
IrpQueueCompletePacket(report, packet_size);
}
STATIC
VOID
ReportInvalidRipFoundDuringNmi(_In_ PNMI_CONTEXT Context)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size =
CryptRequestRequiredBufferLength(sizeof(HIDDEN_SYSTEM_THREAD_REPORT));
PNMI_CALLBACK_FAILURE report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(HIDDEN_SYSTEM_THREAD_REPORT),
REPORT_POOL_TAG);
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
if (!report)
return;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(&report->report_header, REPORT_NMI_CALLBACK_FAILURE, 0);
INIT_REPORT_PACKET(report, REPORT_NMI_CALLBACK_FAILURE, 0);
report->kthread_address = Context->kthread;
report->invalid_rip = Context->interrupted_rip;
report->were_nmis_disabled = FALSE;
IrpQueueCompletePacket(report, sizeof(HIDDEN_SYSTEM_THREAD_REPORT));
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
return;
}
IrpQueueCompletePacket(report, packet_size);
}
/*
@ -728,6 +767,9 @@ NmiCallback(_Inout_opt_ PVOID Context, _In_ BOOLEAN Handled)
TASK_STATE_SEGMENT_64* tss = NULL;
PMACHINE_FRAME machine_frame = NULL;
if (!ARGUMENT_PRESENT(Context))
return TRUE;
/*
* To find the IRETQ frame (MACHINE_FRAME) we need to find the top of
* the NMI ISR stack. This is stored at TSS->Ist[3]. To find the TSS, we
@ -890,20 +932,31 @@ STATIC
VOID
ReportApcStackwalkViolation(_In_ UINT64 Rip)
{
PAPC_STACKWALK_REPORT report = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, sizeof(APC_STACKWALK_REPORT), REPORT_POOL_TAG);
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size =
CryptRequestRequiredBufferLength(sizeof(APC_STACKWALK_REPORT));
PAPC_STACKWALK_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
if (!report)
return;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(&report->report_header, REPORT_APC_STACKWALK, 0);
INIT_REPORT_PACKET(report, REPORT_APC_STACKWALK, 0);
report->kthread_address = (UINT64)KeGetCurrentThread();
report->invalid_rip = Rip;
// report->driver ?? todo!
IrpQueueCompletePacket(report, sizeof(APC_STACKWALK_REPORT));
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
return;
}
IrpQueueCompletePacket(report, packet_size);
}
/*
@ -1004,6 +1057,9 @@ ValidateThreadViaKernelApcCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry,
LPCSTR process_name = NULL;
PAPC_STACKWALK_CONTEXT context = (PAPC_STACKWALK_CONTEXT)Context;
if (!ARGUMENT_PRESENT(Context))
return;
process_name =
ImpPsGetProcessImageFileName(ThreadListEntry->owning_process);
@ -1165,6 +1221,12 @@ DpcStackwalkCallbackRoutine(_In_ PKDPC Dpc,
_In_opt_ PVOID SystemArgument1,
_In_opt_ PVOID SystemArgument2)
{
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(SystemArgument2);
if (!ARGUMENT_PRESENT(DeferredContext))
return;
PDPC_CONTEXT context =
&((PDPC_CONTEXT)DeferredContext)[KeGetCurrentProcessorNumber()];
@ -1174,7 +1236,11 @@ DpcStackwalkCallbackRoutine(_In_ PKDPC Dpc,
&context->stack_frame,
NULL);
InterlockedExchange(&context->executed, TRUE);
#pragma warning(push)
#pragma warning(disable : C6387)
ImpKeSignalCallDpcDone(SystemArgument1);
#pragma warning(pop)
DEBUG_VERBOSE("Executed DPC on core: %lx, with %lx frames captured.",
KeGetCurrentProcessorNumber(),
@ -1198,14 +1264,17 @@ STATIC
VOID
ReportDpcStackwalkViolation(_In_ PDPC_CONTEXT Context, _In_ UINT64 Frame)
{
PDPC_STACKWALK_REPORT report = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, sizeof(DPC_STACKWALK_REPORT), REPORT_POOL_TAG);
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size =
CryptRequestRequiredBufferLength(sizeof(DPC_STACKWALK_REPORT));
PDPC_STACKWALK_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
if (!report)
return;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(&report->report_header, REPORT_DPC_STACKWALK, 0);
INIT_REPORT_PACKET(report, REPORT_DPC_STACKWALK, 0);
report->kthread_address = PsGetCurrentThread();
report->invalid_rip = Frame;
@ -1215,7 +1284,15 @@ ReportDpcStackwalkViolation(_In_ PDPC_CONTEXT Context, _In_ UINT64 Frame)
// - 0x50,
// APC_STACKWALK_BUFFER_SIZE);
IrpQueueCompletePacket(report, sizeof(DPC_STACKWALK_REPORT));
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
return;
}
IrpQueueCompletePacket(report, packet_size);
}
STATIC
@ -1500,10 +1577,12 @@ STATIC
VOID
ReportDataTableInvalidRoutine(_In_ TABLE_ID TableId, _In_ UINT64 Address)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size =
CryptRequestRequiredBufferLength(sizeof(DATA_TABLE_ROUTINE_REPORT));
PDATA_TABLE_ROUTINE_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(DATA_TABLE_ROUTINE_REPORT),
REPORT_POOL_TAG);
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
if (!report)
return;
@ -1512,17 +1591,22 @@ ReportDataTableInvalidRoutine(_In_ TABLE_ID TableId, _In_ UINT64 Address)
TableId,
Address);
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(&report->report_header, REPORT_DATA_TABLE_ROUTINE, 0);
INIT_REPORT_PACKET(report, REPORT_DATA_TABLE_ROUTINE, 0);
report->address = Address;
report->table_id = TableId;
report->index = 0;
RtlCopyMemory(report->routine, Address, DATA_TABLE_ROUTINE_BUF_SIZE);
if (!NT_SUCCESS(
IrpQueueCompletePacket(report, sizeof(DATA_TABLE_ROUTINE_REPORT))))
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
return;
}
IrpQueueCompletePacket(report, packet_size);
}
NTSTATUS
@ -1835,16 +1919,17 @@ VOID
ReportWin32kBase_DxgInterfaceViolation(_In_ UINT32 TableIndex,
_In_ UINT64 Address)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
UINT32 packet_size =
CryptRequestRequiredBufferLength(sizeof(DATA_TABLE_ROUTINE_REPORT));
PDATA_TABLE_ROUTINE_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(DATA_TABLE_ROUTINE_REPORT),
REPORT_POOL_TAG);
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
if (!report)
return;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(&report->report_header, REPORT_DATA_TABLE_ROUTINE, 0);
INIT_REPORT_PACKET(report, REPORT_DATA_TABLE_ROUTINE, 0);
report->address = Address;
report->table_id = Win32kBase_gDxgInterface;
@ -1852,7 +1937,15 @@ ReportWin32kBase_DxgInterfaceViolation(_In_ UINT32 TableIndex,
// todo! report->routine = ??
// todo: maybe get routine by name from index ?
IrpQueueCompletePacket(report, sizeof(DPC_STACKWALK_REPORT));
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
return;
}
IrpQueueCompletePacket(report, packet_size);
}
STATIC

View file

@ -48,9 +48,6 @@ FindSystemModuleByName(_In_ LPCSTR ModuleName,
NTSTATUS
HandleNmiIOCTL();
BOOLEAN
FreeApcContextStructure(_Inout_ PAPC_CONTEXT_HEADER Context);
NTSTATUS
ValidateThreadsViaKernelApc();

View file

@ -6,6 +6,7 @@
#include "queue.h"
#include "ia32.h"
#include "imports.h"
#include "crypt.h"
#define PAGE_BASE_SIZE 0x1000
#define POOL_TAG_SIZE 0x004
@ -678,9 +679,12 @@ FindUnlinkedProcesses()
{
PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL;
PUINT64 allocation_address = NULL;
PROCESS_SCAN_CONTEXT context = {0};
PINVALID_PROCESS_ALLOCATION_REPORT report = NULL;
UINT32 packet_size = CryptRequestRequiredBufferLength(
sizeof(INVALID_PROCESS_ALLOCATION_REPORT));
EnumerateProcessListWithCallbackRoutine(IncrementProcessCounter, &context);
@ -722,25 +726,26 @@ FindUnlinkedProcesses()
"Potentially found an unlinked process allocation at address: %llx",
allocation);
report = ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
sizeof(INVALID_PROCESS_ALLOCATION_REPORT),
REPORT_POOL_TAG);
report = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
if (!report)
continue;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(
&report->report_header, REPORT_INVALID_PROCESS_ALLOCATION, 0);
INIT_REPORT_PACKET(report, REPORT_INVALID_PROCESS_ALLOCATION, 0);
RtlCopyMemory(
report->process, allocation, REPORT_INVALID_PROCESS_BUFFER_SIZE);
if (!NT_SUCCESS(IrpQueueCompletePacket(
report, sizeof(INVALID_PROCESS_ALLOCATION_REPORT)))) {
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
continue;
}
IrpQueueCompletePacket(report, packet_size);
}
end:

View file

@ -1,64 +1,61 @@
#include "session.h"
#include "imports.h"
#include "crypt.h"
/* for now, lets just xor the aes key with our cookie */
typedef struct _SESSION_INITIATION_PACKET {
UINT32 session_cookie;
CHAR session_aes_key[AES_128_KEY_SIZE];
PVOID protected_process_id;
} SESSION_INITIATION_PACKET, *PSESSION_INITIATION_PACKET;
VOID
NTSTATUS
SessionInitialiseStructure()
{
PAGED_CODE();
ImpKeInitializeGuardedMutex(&GetActiveSession()->lock);
NTSTATUS status = STATUS_UNSUCCESSFUL;
PACTIVE_SESSION session = GetActiveSession();
KeInitializeSpinLock(&session->lock);
status = CryptInitialiseProvider();
if (!NT_SUCCESS(status))
DEBUG_ERROR("CryptInitialiseProvider: %x", status);
return status;
}
VOID
SessionInitialiseCallbackConfiguration()
{
PAGED_CODE();
InitialiseObCallbacksConfiguration(GetActiveSession());
}
VOID
SessionIsActive(_Out_ PBOOLEAN Flag)
{
PAGED_CODE();
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
*Flag = GetActiveSession()->is_session_active;
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
KIRQL irql = KeAcquireSpinLockRaiseToDpc(&GetActiveSession()->lock);
*Flag = GetActiveSession()->is_session_active;
KeReleaseSpinLock(&GetActiveSession()->lock, irql);
}
VOID
SessionGetProcess(_Out_ PEPROCESS* Process)
{
PAGED_CODE();
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
*Process = GetActiveSession()->process;
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
KIRQL irql = KeAcquireSpinLockRaiseToDpc(&GetActiveSession()->lock);
*Process = GetActiveSession()->process;
KeReleaseSpinLock(&GetActiveSession()->lock, irql);
}
VOID
SessionGetProcessId(_Out_ PLONG ProcessId)
{
PAGED_CODE();
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
KIRQL irql = KeAcquireSpinLockRaiseToDpc(&GetActiveSession()->lock);
*ProcessId = GetActiveSession()->km_handle;
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
KeReleaseSpinLock(&GetActiveSession()->lock, irql);
}
VOID
SessionGetCallbackConfiguration(
_Out_ POB_CALLBACKS_CONFIG* CallbackConfiguration)
{
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
KIRQL irql = KeAcquireSpinLockRaiseToDpc(&GetActiveSession()->lock);
*CallbackConfiguration = &GetActiveSession()->callback_configuration;
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
KeReleaseSpinLock(&GetActiveSession()->lock, irql);
}
STATIC
@ -71,29 +68,29 @@ SessionTerminateHeartbeat(_In_ PHEARTBEAT_CONFIGURATION Configuration)
VOID
SessionTerminate()
{
PAGED_CODE();
DEBUG_INFO("Termination active session.");
PACTIVE_SESSION session = GetActiveSession();
KIRQL irql = {0};
ImpKeAcquireGuardedMutex(&session->lock);
KeAcquireSpinLock(&session->lock, &irql);
session->km_handle = NULL;
session->um_handle = NULL;
session->process = NULL;
session->is_session_active = FALSE;
SessionTerminateHeartbeat(&session->heartbeat_config);
ImpKeReleaseGuardedMutex(&session->lock);
CryptCloseSessionCryptObjects();
KeReleaseSpinLock(&GetActiveSession()->lock, irql);
}
NTSTATUS
SessionInitialise(_In_ PIRP Irp)
{
PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL;
PEPROCESS process = NULL;
PSESSION_INITIATION_PACKET information = NULL;
PACTIVE_SESSION session = GetActiveSession();
NTSTATUS status = STATUS_UNSUCCESSFUL;
PEPROCESS process = NULL;
PSESSION_INITIATION_PACKET initiation = NULL;
PACTIVE_SESSION session = GetActiveSession();
KIRQL irql = {0};
DEBUG_VERBOSE("Initialising new session.");
@ -104,11 +101,11 @@ SessionInitialise(_In_ PIRP Irp)
return status;
}
information = (PSESSION_INITIATION_PACKET)Irp->AssociatedIrp.SystemBuffer;
initiation = (PSESSION_INITIATION_PACKET)Irp->AssociatedIrp.SystemBuffer;
ImpKeAcquireGuardedMutex(&session->lock);
KeAcquireSpinLock(&session->lock, &irql);
session->um_handle = information->protected_process_id;
session->um_handle = initiation->process_id;
/* What if we pass an invalid handle here? not good. */
status = ImpPsLookupProcessByProcessId(session->um_handle, &process);
@ -121,11 +118,17 @@ SessionInitialise(_In_ PIRP Irp)
session->km_handle = ImpPsGetProcessId(process);
session->process = process;
session->is_session_active = TRUE;
session->session_cookie = information->session_cookie;
session->cookie = initiation->cookie;
RtlCopyMemory(session->session_aes_key,
information->session_aes_key,
AES_128_KEY_SIZE);
RtlCopyMemory(session->aes_key, initiation->aes_key, AES_256_KEY_SIZE);
RtlCopyMemory(session->iv, initiation->aes_iv, AES_256_IV_SIZE);
status = CryptInitialiseSessionCryptObjects();
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptInitialiseSessionCryptObjects: %x", status);
goto end;
}
status = InitialiseHeartbeatConfiguration(&session->heartbeat_config);
@ -135,15 +138,13 @@ SessionInitialise(_In_ PIRP Irp)
}
end:
ImpKeReleaseGuardedMutex(&session->lock);
KeReleaseSpinLock(&GetActiveSession()->lock, irql);
return status;
}
VOID
SessionTerminateProcess()
{
PAGED_CODE();
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG process_id = 0;
@ -174,23 +175,23 @@ SessionTerminateProcess()
VOID
SessionIncrementIrpsProcessedCount()
{
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
KIRQL irql = KeAcquireSpinLockRaiseToDpc(&GetActiveSession()->lock);
GetActiveSession()->irps_received;
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
KeReleaseSpinLock(&GetActiveSession()->lock, irql);
}
VOID
SessionIncrementReportCount()
{
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
KIRQL irql = KeAcquireSpinLockRaiseToDpc(&GetActiveSession()->lock);
GetActiveSession()->report_count++;
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
KeReleaseSpinLock(&GetActiveSession()->lock, irql);
}
VOID
SessionIncrementHeartbeatCount()
{
ImpKeAcquireGuardedMutex(&GetActiveSession()->lock);
KIRQL irql = KeAcquireSpinLockRaiseToDpc(&GetActiveSession()->lock);
GetActiveSession()->heartbeat_count++;
ImpKeReleaseGuardedMutex(&GetActiveSession()->lock);
KeReleaseSpinLock(&GetActiveSession()->lock, irql);
}

View file

@ -5,7 +5,7 @@
#include "driver.h"
VOID
NTSTATUS
SessionInitialiseStructure();
VOID

View file

@ -8,6 +8,7 @@
#include "queue.h"
#include "session.h"
#include "imports.h"
#include "crypt.h"
#ifdef ALLOC_PRAGMA
# pragma alloc_text(PAGE, DetectThreadsAttachedToProtectedProcess)
@ -81,8 +82,11 @@ DetectAttachedThreadsProcessCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry,
{
UNREFERENCED_PARAMETER(Context);
NTSTATUS status = STATUS_UNSUCCESSFUL;
PKAPC_STATE apc_state = NULL;
PEPROCESS protected_process = NULL;
UINT32 packet_size =
CryptRequestRequiredBufferLength(sizeof(ATTACH_PROCESS_REPORT));
SessionGetProcess(&protected_process);
@ -106,21 +110,26 @@ DetectAttachedThreadsProcessCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry,
DEBUG_WARNING("Thread is attached to our protected process: %llx",
(UINT64)ThreadListEntry->thread);
PATTACH_PROCESS_REPORT report = ImpExAllocatePool2(
POOL_FLAG_NON_PAGED, sizeof(ATTACH_PROCESS_REPORT), REPORT_POOL_TAG);
PATTACH_PROCESS_REPORT report =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, packet_size, REPORT_POOL_TAG);
if (!report)
return;
INIT_PACKET_HEADER(&report->header, PACKET_TYPE_REPORT);
INIT_REPORT_HEADER(
&report->report_header, REPORT_ILLEGAL_ATTACH_PROCESS, 0);
INIT_REPORT_PACKET(report, REPORT_ILLEGAL_ATTACH_PROCESS, 0);
report->thread_id = ImpPsGetThreadId(ThreadListEntry->thread);
report->thread_address = ThreadListEntry->thread;
if (!NT_SUCCESS(IrpQueueCompletePacket(report, sizeof(ATTACH_PROCESS_REPORT))))
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
status = CryptEncryptBuffer(report, packet_size);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptEncryptBuffer: %lx", status);
ImpExFreePoolWithTag(report, REPORT_POOL_TAG);
return;
}
IrpQueueCompletePacket(report, packet_size);
}
VOID

View file

@ -15,34 +15,54 @@
#define REPORT_INVALID_PROCESS_MODULE 140
#define REPORT_SUBTYPE_NO_BACKING_MODULE 0x0
#define REPORT_SUBTYPE_INVALID_DISPATCH 0x1
#define REPORT_SUBTYPE_INVALID_DISPATCH 0x1
#define PACKET_TYPE_REPORT 0x0
#define PACKET_TYPE_HEARTBEAT 0x1
#define INIT_PACKET_HEADER(header, type) \
{ \
(header)->packet_type = type; \
#define PACKET_MAGIC_NUMBER 0x1337
#define INIT_REPORT_PACKET(report, code, subcode) \
{ \
(report)->header.packet_header.packet_type = PACKET_TYPE_REPORT; \
(report)->header.packet_header.magic_number = PACKET_MAGIC_NUMBER; \
(report)->header.report_code = code; \
(report)->header.report_sub_type = subcode; \
}
#define INIT_REPORT_HEADER(report, code, subcode) \
{ \
(report)->report_code = code; \
(report)->report_sub_type = subcode; \
#define INIT_HEARTBEAT_PACKET(packet) \
{ \
(packet)->header.packet_header.packet_type = PACKET_TYPE_HEARTBEAT; \
(packet)->header.packet_header.magic_number = PACKET_MAGIC_NUMBER; \
}
/* use a UINT16 rather then enum to explicitly state the size */
typedef struct _PACKET_HEADER {
UINT16 packet_type;
UINT32 packet_type;
UINT32 magic_number;
} PACKET_HEADER, *PPACKET_HEADER;
/* unencrypted header structures, should always == AES block size i.e 16 */
typedef struct _REPORT_PACKET_HEADER {
UINT32 report_code;
UINT32 report_sub_type;
PACKET_HEADER packet_header;
UINT32 report_code;
UINT32 report_sub_type;
} REPORT_PACKET_HEADER, *PREPORT_PACKET_HEADER;
typedef struct _HEARTBEAT_PACKET_HEADER {
PACKET_HEADER packet_header;
UINT32 unused[2];
} HEARTBEAT_PACKET_HEADER, *PHEARTBEAT_PACKET_HEADER;
#define AES_256_BLOCK_SIZE 16
static_assert(sizeof(HEARTBEAT_PACKET_HEADER) == AES_256_BLOCK_SIZE,
"invalid heartbeat header size");
static_assert(sizeof(REPORT_PACKET_HEADER) == AES_256_BLOCK_SIZE,
"invalid report header size");
typedef enum _TABLE_ID {
HalDispatch = 0,
HalPrivateDispatch,
@ -50,8 +70,7 @@ typedef enum _TABLE_ID {
} TABLE_ID;
typedef struct _HYPERVISOR_DETECTION_REPORT {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
REPORT_PACKET_HEADER header;
UINT8 aperf_msr_timing_check;
UINT8 invd_emulation_check;
@ -60,8 +79,7 @@ typedef struct _HYPERVISOR_DETECTION_REPORT {
#define APC_STACKWALK_BUFFER_SIZE 500
typedef struct _APC_STACKWALK_REPORT {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
REPORT_PACKET_HEADER header;
UINT64 kthread_address;
UINT64 invalid_rip;
CHAR driver[APC_STACKWALK_BUFFER_SIZE];
@ -69,8 +87,7 @@ typedef struct _APC_STACKWALK_REPORT {
} APC_STACKWALK_REPORT, *PAPC_STACKWALK_REPORT;
typedef struct _DPC_STACKWALK_REPORT {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
REPORT_PACKET_HEADER header;
UINT64 kthread_address;
UINT64 invalid_rip;
CHAR driver[APC_STACKWALK_BUFFER_SIZE];
@ -78,8 +95,7 @@ typedef struct _DPC_STACKWALK_REPORT {
} DPC_STACKWALK_REPORT, *PDPC_STACKWALK_REPORT;
typedef struct _MODULE_VALIDATION_FAILURE {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
REPORT_PACKET_HEADER header;
UINT64 driver_base_address;
UINT64 driver_size;
CHAR driver_name[128];
@ -89,8 +105,7 @@ typedef struct _MODULE_VALIDATION_FAILURE {
#define DATA_TABLE_ROUTINE_BUF_SIZE 256
typedef struct _DATA_TABLE_ROUTINE_REPORT {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
REPORT_PACKET_HEADER header;
TABLE_ID table_id;
UINT64 address;
UINT32 index;
@ -99,8 +114,7 @@ typedef struct _DATA_TABLE_ROUTINE_REPORT {
} DATA_TABLE_ROUTINE_REPORT, *PDATA_TABLE_ROUTINE_REPORT;
typedef struct _NMI_CALLBACK_FAILURE {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
REPORT_PACKET_HEADER header;
UINT8 were_nmis_disabled;
UINT64 kthread_address;
UINT64 invalid_rip;
@ -110,15 +124,13 @@ typedef struct _NMI_CALLBACK_FAILURE {
#define REPORT_INVALID_PROCESS_BUFFER_SIZE 500
typedef struct _INVALID_PROCESS_ALLOCATION_REPORT {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
REPORT_PACKET_HEADER header;
CHAR process[REPORT_INVALID_PROCESS_BUFFER_SIZE];
} INVALID_PROCESS_ALLOCATION_REPORT, *PINVALID_PROCESS_ALLOCATION_REPORT;
typedef struct _HIDDEN_SYSTEM_THREAD_REPORT {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
REPORT_PACKET_HEADER header;
UINT8 found_in_kthreadlist;
UINT8 found_in_pspcidtable;
UINT64 thread_address;
@ -128,16 +140,14 @@ typedef struct _HIDDEN_SYSTEM_THREAD_REPORT {
} HIDDEN_SYSTEM_THREAD_REPORT, *PHIDDEN_SYSTEM_THREAD_REPORT;
typedef struct _ATTACH_PROCESS_REPORT {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
REPORT_PACKET_HEADER header;
UINT32 thread_id;
UINT64 thread_address;
} ATTACH_PROCESS_REPORT, *PATTACH_PROCESS_REPORT;
typedef struct _KPRCB_THREAD_VALIDATION_CTX {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
REPORT_PACKET_HEADER header;
UINT64 thread;
BOOLEAN thread_found_in_pspcidtable;
// BOOLEAN thread_found_in_kthreadlist;
@ -148,9 +158,8 @@ typedef struct _KPRCB_THREAD_VALIDATION_CTX {
#define HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH 64
typedef struct _OPEN_HANDLE_FAILURE_REPORT {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
UINT8 is_kernel_handle;
REPORT_PACKET_HEADER header;
UINT32 is_kernel_handle;
UINT32 process_id;
UINT32 thread_id;
UINT32 access;
@ -161,8 +170,7 @@ typedef struct _OPEN_HANDLE_FAILURE_REPORT {
#define MODULE_PATH_LEN 256
typedef struct _PROCESS_MODULE_VALIDATION_REPORT {
PACKET_HEADER header;
REPORT_PACKET_HEADER report_header;
REPORT_PACKET_HEADER header;
UINT64 image_base;
UINT32 image_size;
WCHAR module_path[MODULE_PATH_LEN];
@ -170,11 +178,11 @@ typedef struct _PROCESS_MODULE_VALIDATION_REPORT {
} PROCESS_MODULE_VALIDATION_REPORT, *PPROCESS_MODULE_VALIDATION_REPORT;
typedef struct _HEARTBEAT_PACKET {
PACKET_HEADER header;
UINT32 heartbeat_count;
UINT32 total_reports_completed;
UINT32 total_irps_completed;
UINT32 total_heartbeats_completed;
HEARTBEAT_PACKET_HEADER header;
UINT32 heartbeat_count;
UINT32 total_reports_completed;
UINT32 total_irps_completed;
UINT32 total_heartbeats_completed;
} HEARTBEAT_PACKET, *PHEARTBEAT_PACKET;

128
module/crypt/crypt.cpp Normal file
View file

@ -0,0 +1,128 @@
#include "crypt.h"
#include "../common.h"
#include <bcrypt.h>
#include <iomanip>
#include <iostream>
#include <stdio.h>
#include <winternl.h>
#pragma comment(lib, "bcrypt.lib")
BCRYPT_ALG_HANDLE alg_handle = NULL;
BCRYPT_KEY_HANDLE key_handle = NULL;
namespace crypt {
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
namespace globals {
#define TEST_AES_KEY_LENGTH 0x32
#define TEST_AES_IV_LENGTH 0x16
const unsigned char TEST_KEY[] = {
0xAA, 0x50, 0xA7, 0x00, 0x79, 0xF1, 0x6C, 0x2D, 0x6B, 0xAD, 0xAC,
0x19, 0x18, 0x66, 0xFB, 0xEF, 0xCA, 0x9B, 0x6D, 0x3E, 0xA3, 0x7D,
0x2D, 0xF6, 0x10, 0x95, 0xB3, 0xB3, 0x8D, 0x34, 0x69, 0xF1};
const unsigned char TEST_IV[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F};
PBCRYPT_KEY_DATA_BLOB_HEADER blob = nullptr;
static PUCHAR key_object = NULL;
static UINT32 key_object_length = 0;
} // namespace globals
boolean initialise_session_key() {
globals::blob = reinterpret_cast<PBCRYPT_KEY_DATA_BLOB_HEADER>(
malloc(sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + sizeof(globals::TEST_KEY)));
if (!globals::blob)
return false;
globals::blob->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
globals::blob->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
globals::blob->cbKeyData = sizeof(globals::TEST_KEY);
memcpy((void *)((UINT64)globals::blob + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER)),
(void *)globals::TEST_KEY, sizeof(globals::TEST_KEY));
return true;
}
boolean initialise_provider() {
UINT32 data_copied = 0;
NTSTATUS status =
BCryptOpenAlgorithmProvider(&alg_handle, BCRYPT_AES_ALGORITHM, NULL, 0);
if (!NT_SUCCESS(status)) {
LOG_ERROR("BCryptOpenAlgorithmProvider: %x", status);
return false;
}
status = BCryptGetProperty(alg_handle, BCRYPT_OBJECT_LENGTH,
(PUCHAR)&globals::key_object_length,
sizeof(UINT32), (PULONG)&data_copied, 0);
if (!NT_SUCCESS(status)) {
LOG_ERROR("BCryptGetProperty: %x", status);
return false;
}
globals::key_object = (PUCHAR)malloc(globals::key_object_length);
if (!globals::key_object)
return false;
if (!initialise_session_key())
return false;
status = BCryptImportKey(
alg_handle, NULL, BCRYPT_KEY_DATA_BLOB, &key_handle, globals::key_object,
globals::key_object_length, (PUCHAR)globals::blob,
sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + sizeof(globals::TEST_KEY), 0);
if (!NT_SUCCESS(status)) {
LOG_ERROR("BCryptImportKey: %x", status);
return false;
}
return true;
}
boolean decrypt_packet(void *packet, uint32_t packet_length) {
ULONG data_copied = 0;
unsigned char local_iv[sizeof(globals::TEST_IV)] = {0};
memcpy((void *)local_iv, (void *)globals::TEST_IV, sizeof(globals::TEST_IV));
void* buffer = (void*)((UINT64)packet + 16);
uint32_t length = packet_length - 16;
NTSTATUS status = BCryptDecrypt(
key_handle, (PUCHAR)buffer, length, NULL, (PUCHAR)local_iv,
sizeof(globals::TEST_IV), (PUCHAR)buffer, length, &data_copied, 0);
if (!NT_SUCCESS(status)) {
LOG_ERROR("BCryptDecrypt: %x", status);
return false;
}
return true;
}
uint32_t get_padded_packet_size(uint32_t original_size) {
uint32_t remainder = original_size % 16;
if (remainder != 0) {
original_size += 16 - remainder;
}
return original_size;
}
const unsigned char *get_test_key() { return globals::TEST_KEY; }
const unsigned char *get_test_iv() { return globals::TEST_IV; }
} // namespace crypt

12
module/crypt/crypt.h Normal file
View file

@ -0,0 +1,12 @@
#pragma once
#include <cstdint>
#include <windows.h>
namespace crypt {
const unsigned char *get_test_key();
const unsigned char *get_test_iv();
boolean initialise_provider();
boolean decrypt_packet(void *packet, uint32_t packet_length);
uint32_t get_padded_packet_size(uint32_t original_size);
} // namespace crypt

View file

@ -2,6 +2,7 @@
#include "../client/message_queue.h"
#include "../helper.h"
#include "../crypt/crypt.h"
#include <bcrypt.h>
#include <chrono>
@ -48,6 +49,7 @@ void dispatcher::dispatcher::run_io_port_thread() {
void dispatcher::dispatcher::run() {
// helper::generate_rand_seed();
crypt::initialise_provider();
std::srand(std::time(nullptr));
this->init_timer_callbacks();
this->run_timer_thread();

View file

@ -3,6 +3,8 @@
#include <chrono>
#include <random>
#include "crypt/crypt.h"
void helper::generate_rand_seed() { srand(time(0)); }
int helper::generate_rand_int(int max) { return std::rand() % max; }
@ -49,127 +51,143 @@ kernel_interface::report_id helper::get_kernel_report_type(void *buffer) {
}
}
void
print_report_packet(void* buffer)
{
kernel_interface::report_header* report_header =
(kernel_interface::report_header*)buffer;
LOG_INFO("report code: %lx", report_header->report_code);
LOG_INFO("report sub code: %lx", report_header->report_sub_type);
switch (report_header->report_code) {
case kernel_interface::report_id::report_nmi_callback_failure: {
kernel_interface::nmi_callback_failure* r1 =
reinterpret_cast<kernel_interface::nmi_callback_failure*>(buffer);
LOG_INFO("were_nmis_disabled: %lx", r1->were_nmis_disabled);
LOG_INFO("kthread_address: %llx", r1->kthread_address);
LOG_INFO("invalid_rip: %llx", r1->invalid_rip);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_invalid_process_allocation: {
kernel_interface::invalid_process_allocation_report* r2 =
reinterpret_cast<
kernel_interface::invalid_process_allocation_report*>(buffer);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_hidden_system_thread: {
kernel_interface::hidden_system_thread_report* r3 =
reinterpret_cast<kernel_interface::hidden_system_thread_report*>(
buffer);
LOG_INFO("found_in_kthreadlist: %lx", r3->found_in_kthreadlist);
LOG_INFO("found_in_pspcidtable: %lx", r3->found_in_pspcidtable);
LOG_INFO("thread_address: %llx", r3->thread_address);
LOG_INFO("thread_id: %lx", r3->thread_id);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_illegal_attach_process: {
kernel_interface::attach_process_report* r4 =
reinterpret_cast<kernel_interface::attach_process_report*>(buffer);
LOG_INFO("report type: attach_process_report");
LOG_INFO("report code: %lx", r4->report_code);
LOG_INFO("thread_id: %lx", r4->thread_id);
LOG_INFO("thread_address: %llx", r4->thread_address);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_illegal_handle_operation: {
kernel_interface::open_handle_failure_report* r5 =
reinterpret_cast<kernel_interface::open_handle_failure_report*>(
buffer);
LOG_INFO("is_kernel_handle: %lx", r5->is_kernel_handle);
LOG_INFO("process_id: %lx", r5->process_id);
LOG_INFO("thread_id: %lx", r5->thread_id);
LOG_INFO("access: %lx", r5->access);
LOG_INFO("process_name: %s", r5->process_name);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_invalid_process_module: {
kernel_interface::process_module_validation_report* r6 =
reinterpret_cast<
kernel_interface::process_module_validation_report*>(buffer);
LOG_INFO("image_base: %llx", r6->image_base);
LOG_INFO("image_size: %u", r6->image_size);
LOG_INFO("module_path: %ls", r6->module_path);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_apc_stackwalk: {
kernel_interface::apc_stackwalk_report* r7 =
reinterpret_cast<kernel_interface::apc_stackwalk_report*>(buffer);
LOG_INFO("kthread_address: %llx", r7->kthread_address);
LOG_INFO("invalid_rip: %llx", r7->invalid_rip);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_dpc_stackwalk: {
kernel_interface::dpc_stackwalk_report* r8 =
reinterpret_cast<kernel_interface::dpc_stackwalk_report*>(buffer);
LOG_INFO("kthread_address: %llx", r8->kthread_address);
LOG_INFO("invalid_rip: %llx", r8->invalid_rip);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_data_table_routine: {
kernel_interface::data_table_routine_report* r9 =
reinterpret_cast<kernel_interface::data_table_routine_report*>(
buffer);
LOG_INFO("id: %d", r9->id);
LOG_INFO("address: %llx", r9->address);
LOG_INFO("routine: %s", r9->routine);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_module_validation_failure: {
kernel_interface::module_validation_failure* r10 =
reinterpret_cast<kernel_interface::module_validation_failure*>(
buffer);
LOG_INFO("driver_base_address: %llx", r10->driver_base_address);
LOG_INFO("driver_size: %llx", r10->driver_size);
LOG_INFO("driver_name: %s", r10->driver_name);
LOG_INFO("********************************");
break;
}
default: LOG_INFO("Invalid report type."); break;
}
}
void
print_heartbeat_packet(void* buffer)
{
kernel_interface::heartbeat_packet* hb =
reinterpret_cast<kernel_interface::heartbeat_packet*>(buffer);
LOG_INFO("Heartbeat Count: %lx", hb->heartbeat_count);
LOG_INFO("Total Reports Completed: %lx", hb->total_reports_completed);
LOG_INFO("Total IRPs Completed: %lx", hb->total_irps_completed);
LOG_INFO("Total Heartbeats Completed: %lx", hb->total_heartbeats_completed);
LOG_INFO("********************************");
}
void helper::print_kernel_report(void *buffer) {
uint32_t size = crypt::get_padded_packet_size(
sizeof(kernel_interface::open_handle_failure_report));
crypt::decrypt_packet(buffer, size);
kernel_interface::packet_header *header =
reinterpret_cast<kernel_interface::packet_header *>(buffer);
LOG_INFO("packet type: %lx", header->packet_type);
if (header->packet_type == 1)
switch (header->packet_type)
{
kernel_interface::heartbeat_packet* hb =
reinterpret_cast<kernel_interface::heartbeat_packet*>(buffer);
LOG_INFO("Heartbeat Count: %lx", hb->heartbeat_count);
LOG_INFO("Total Reports Completed: %lx", hb->total_reports_completed);
LOG_INFO("Total IRPs Completed: %lx", hb->total_irps_completed);
LOG_INFO("Total Heartbeats Completed: %lx",
hb->total_heartbeats_completed);
LOG_INFO("********************************");
return;
}
kernel_interface::report_header *report_header =
reinterpret_cast<kernel_interface::report_header *>(
(uint64_t)buffer + sizeof(kernel_interface::packet_header));
LOG_INFO("report code: %lx", report_header->report_code);
LOG_INFO("report sub code: %lx", report_header->report_sub_type);
switch (report_header->report_code) {
case kernel_interface::report_id::report_nmi_callback_failure: {
kernel_interface::nmi_callback_failure *r1 =
reinterpret_cast<kernel_interface::nmi_callback_failure *>(buffer);
LOG_INFO("were_nmis_disabled: %lx", r1->were_nmis_disabled);
LOG_INFO("kthread_address: %llx", r1->kthread_address);
LOG_INFO("invalid_rip: %llx", r1->invalid_rip);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_invalid_process_allocation: {
kernel_interface::invalid_process_allocation_report *r2 =
reinterpret_cast<kernel_interface::invalid_process_allocation_report *>(
buffer);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_hidden_system_thread: {
kernel_interface::hidden_system_thread_report *r3 =
reinterpret_cast<kernel_interface::hidden_system_thread_report *>(
buffer);
LOG_INFO("found_in_kthreadlist: %lx", r3->found_in_kthreadlist);
LOG_INFO("found_in_pspcidtable: %lx", r3->found_in_pspcidtable);
LOG_INFO("thread_address: %llx", r3->thread_address);
LOG_INFO("thread_id: %lx", r3->thread_id);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_illegal_attach_process: {
kernel_interface::attach_process_report *r4 =
reinterpret_cast<kernel_interface::attach_process_report *>(buffer);
LOG_INFO("report type: attach_process_report");
LOG_INFO("report code: %lx", r4->report_code);
LOG_INFO("thread_id: %lx", r4->thread_id);
LOG_INFO("thread_address: %llx", r4->thread_address);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_illegal_handle_operation: {
kernel_interface::open_handle_failure_report *r5 =
reinterpret_cast<kernel_interface::open_handle_failure_report *>(
buffer);
LOG_INFO("is_kernel_handle: %lx", r5->is_kernel_handle);
LOG_INFO("process_id: %lx", r5->process_id);
LOG_INFO("thread_id: %lx", r5->thread_id);
LOG_INFO("access: %lx", r5->access);
LOG_INFO("process_name: %s", r5->process_name);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_invalid_process_module: {
kernel_interface::process_module_validation_report *r6 =
reinterpret_cast<kernel_interface::process_module_validation_report *>(
buffer);
LOG_INFO("image_base: %llx", r6->image_base);
LOG_INFO("image_size: %u", r6->image_size);
LOG_INFO("module_path: %ls", r6->module_path);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_apc_stackwalk: {
kernel_interface::apc_stackwalk_report *r7 =
reinterpret_cast<kernel_interface::apc_stackwalk_report *>(buffer);
LOG_INFO("kthread_address: %llx", r7->kthread_address);
LOG_INFO("invalid_rip: %llx", r7->invalid_rip);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_dpc_stackwalk: {
kernel_interface::dpc_stackwalk_report *r8 =
reinterpret_cast<kernel_interface::dpc_stackwalk_report *>(buffer);
LOG_INFO("kthread_address: %llx", r8->kthread_address);
LOG_INFO("invalid_rip: %llx", r8->invalid_rip);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_data_table_routine: {
kernel_interface::data_table_routine_report *r9 =
reinterpret_cast<kernel_interface::data_table_routine_report *>(buffer);
LOG_INFO("id: %d", r9->id);
LOG_INFO("address: %llx", r9->address);
LOG_INFO("routine: %s", r9->routine);
LOG_INFO("********************************");
break;
}
case kernel_interface::report_id::report_module_validation_failure: {
kernel_interface::module_validation_failure *r10 =
reinterpret_cast<kernel_interface::module_validation_failure *>(buffer);
LOG_INFO("driver_base_address: %llx", r10->driver_base_address);
LOG_INFO("driver_size: %llx", r10->driver_size);
LOG_INFO("driver_name: %s", r10->driver_name);
LOG_INFO("********************************");
break;
}
default:
LOG_INFO("Invalid report type.");
break;
case 0: print_report_packet(buffer); break;
case 1: print_heartbeat_packet(buffer); break;
}
}
unsigned __int64 helper::seconds_to_nanoseconds(int seconds) {

View file

@ -4,6 +4,7 @@
#include "../common.h"
#include "../helper.h"
#include "../crypt/crypt.h"
#include <TlHelp32.h>
#include <winternl.h>
@ -140,7 +141,10 @@ void kernel_interface::kernel_interface::generic_driver_call_apc(
void kernel_interface::kernel_interface::notify_driver_on_process_launch() {
unsigned long bytes_returned = 0;
session_initiation_packet packet = {0};
packet.protected_process_id = reinterpret_cast<void *>(GetCurrentProcessId());
packet.process_id = reinterpret_cast<void *>(GetCurrentProcessId());
packet.session_cookie = 123;
memcpy(packet.aes_key, crypt::get_test_key(), 32);
memcpy(packet.aes_iv, crypt::get_test_iv(), 16);
generic_driver_call_input(ioctl_code::NotifyDriverOnProcessLaunch, &packet,
sizeof(session_initiation_packet), &bytes_returned);
}

View file

@ -25,15 +25,27 @@ enum report_id {
report_invalid_process_module = 140
};
#define AES_256_BLOCK_SIZE 16
struct packet_header {
uint16_t packet_type;
uint32_t packet_type;
uint32_t magic_number;
};
struct heartbeat_header {
packet_header header;
uint32_t unused[2];
};
struct report_header {
struct packet_header header;
uint32_t report_code;
uint32_t report_sub_type;
};
static_assert(sizeof(heartbeat_header) == AES_256_BLOCK_SIZE);
static_assert(sizeof(report_header) == AES_256_BLOCK_SIZE);
constexpr int APC_STACKWALK_BUFFER_SIZE = 500;
constexpr int DATA_TABLE_ROUTINE_BUF_SIZE = 256;
constexpr int REPORT_INVALID_PROCESS_BUFFER_SIZE = 500;
@ -41,7 +53,6 @@ constexpr int HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH = 64;
constexpr int MODULE_PATH_LEN = 256;
struct apc_stackwalk_report {
packet_header header;
report_header report_header;
uint64_t kthread_address;
uint64_t invalid_rip;
@ -49,7 +60,6 @@ struct apc_stackwalk_report {
};
struct dpc_stackwalk_report {
packet_header header;
report_header report_header;
uint64_t kthread_address;
uint64_t invalid_rip;
@ -57,7 +67,6 @@ struct dpc_stackwalk_report {
};
struct module_validation_failure {
packet_header header;
report_header report_header;
uint64_t driver_base_address;
uint64_t driver_size;
@ -67,7 +76,6 @@ struct module_validation_failure {
enum table_id { hal_dispatch = 0, hal_private_dispatch };
struct data_table_routine_report {
packet_header header;
report_header report_header;
table_id id;
uint64_t address;
@ -76,7 +84,6 @@ struct data_table_routine_report {
};
struct nmi_callback_failure {
packet_header header;
report_header report_header;
uint8_t were_nmis_disabled;
uint64_t kthread_address;
@ -84,13 +91,11 @@ struct nmi_callback_failure {
};
struct invalid_process_allocation_report {
packet_header header;
report_header report_header;
char process[REPORT_INVALID_PROCESS_BUFFER_SIZE];
};
struct hidden_system_thread_report {
packet_header header;
report_header report_header;
uint8_t found_in_kthreadlist;
uint8_t found_in_pspcidtable;
@ -106,9 +111,8 @@ struct attach_process_report {
};
struct open_handle_failure_report {
packet_header header;
report_header report_header;
uint8_t is_kernel_handle;
uint32_t is_kernel_handle;
uint32_t process_id;
uint32_t thread_id;
uint32_t access;
@ -116,7 +120,6 @@ struct open_handle_failure_report {
};
struct process_module_validation_report {
packet_header header;
report_header report_header;
uint64_t image_base;
uint32_t image_size;
@ -124,11 +127,11 @@ struct process_module_validation_report {
};
struct heartbeat_packet {
packet_header header;
uint32_t heartbeat_count;
uint32_t total_reports_completed;
uint32_t total_irps_completed;
uint32_t total_heartbeats_completed;
heartbeat_header header;
uint32_t heartbeat_count;
uint32_t total_reports_completed;
uint32_t total_irps_completed;
uint32_t total_heartbeats_completed;
};
enum apc_operation { operation_stackwalk = 0x1 };
@ -194,8 +197,9 @@ struct event_dispatcher {
class kernel_interface {
struct session_initiation_packet {
unsigned __int32 session_cookie;
char session_aes_key[AES_128_KEY_SIZE];
void *protected_process_id;
void *process_id;
unsigned char aes_key[32];
unsigned char aes_iv[16];
};
struct hv_detection_packet {

View file

@ -5,9 +5,11 @@
#include "client/message_queue.h"
#include "dispatcher/dispatcher.h"
#include "crypt/crypt.h"
void module::run(HINSTANCE hinstDLL) {
AllocConsole();
FILE *file;
FILE *file = NULL;
freopen_s(&file, "CONOUT$", "w", stdout);
freopen_s(&file, "CONIN$", "r", stdin);

View file

@ -209,6 +209,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="crypt\crypt.cpp" />
<ClCompile Include="dispatcher\timer.cpp" />
<ClCompile Include="helper.cpp" />
<ClCompile Include="imports.cpp" />
@ -223,6 +224,7 @@
<ItemGroup>
<ClInclude Include="client\message_queue.h" />
<ClInclude Include="client\pipe.h" />
<ClInclude Include="crypt\crypt.h" />
<ClInclude Include="dispatcher\dispatcher.h" />
<ClInclude Include="dispatcher\threadpool.h" />
<ClInclude Include="common.h" />

View file

@ -11,6 +11,7 @@
<ClCompile Include="dispatcher\threadpool.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="kernel_interface\kernel_interface.cpp" />
<ClCompile Include="crypt\crypt.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="client\message_queue.h" />
@ -23,5 +24,6 @@
<ClInclude Include="imports.h" />
<ClInclude Include="kernel_interface\kernel_interface.h" />
<ClInclude Include="module.h" />
<ClInclude Include="crypt\crypt.h" />
</ItemGroup>
</Project>