mirror-ac/driver/session.c
2024-08-04 16:34:52 +10:00

250 lines
No EOL
6.3 KiB
C

#include "session.h"
#include "crypt.h"
#include "imports.h"
#include "util.h"
#include "lib/stdlib.h"
NTSTATUS
SessionInitialiseStructure()
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PACTIVE_SESSION session = GetActiveSession();
KeInitializeGuardedMutex(&session->lock);
status = CryptInitialiseProvider();
if (!NT_SUCCESS(status))
DEBUG_ERROR("CryptInitialiseProvider: %x", status);
return status;
}
VOID
SessionInitialiseCallbackConfiguration()
{
InitialiseObCallbacksConfiguration(GetActiveSession());
}
VOID
SessionIsActive(_Out_ PBOOLEAN Flag)
{
KeAcquireGuardedMutex(&GetActiveSession()->lock);
*Flag = GetActiveSession()->is_session_active;
KeReleaseGuardedMutex(&GetActiveSession()->lock);
}
VOID
SessionGetProcess(_Out_ PEPROCESS* Process)
{
KeAcquireGuardedMutex(&GetActiveSession()->lock);
*Process = GetActiveSession()->process;
KeReleaseGuardedMutex(&GetActiveSession()->lock);
}
VOID
SessionGetProcessId(_Out_ PLONG ProcessId)
{
KeAcquireGuardedMutex(&GetActiveSession()->lock);
*ProcessId = GetActiveSession()->km_handle;
KeReleaseGuardedMutex(&GetActiveSession()->lock);
}
VOID
SessionGetCallbackConfiguration(
_Out_ POB_CALLBACKS_CONFIG* CallbackConfiguration)
{
KeAcquireGuardedMutex(&GetActiveSession()->lock);
*CallbackConfiguration = &GetActiveSession()->callback_configuration;
KeReleaseGuardedMutex(&GetActiveSession()->lock);
}
STATIC
VOID
SessionTerminateHeartbeat(_In_ PHEARTBEAT_CONFIGURATION Configuration)
{
FreeHeartbeatConfiguration(Configuration);
}
VOID
SessionTerminate()
{
DEBUG_INFO("Termination active session.");
PACTIVE_SESSION session = GetActiveSession();
KIRQL irql = {0};
KeAcquireGuardedMutex(&session->lock);
session->km_handle = NULL;
session->um_handle = NULL;
session->process = NULL;
session->is_session_active = FALSE;
RtlZeroMemory(&session->module, sizeof(MODULE_INFORMATION));
SessionTerminateHeartbeat(&session->heartbeat_config);
CryptCloseSessionCryptObjects();
KeReleaseGuardedMutex(&session->lock);
}
/* Return type for this doesnt matter */
STATIC
BOOLEAN
HashOurUserModuleOnEntryCallback(
_In_ PPROCESS_MAP_MODULE_ENTRY Entry, _In_opt_ PVOID Context)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PACTIVE_SESSION session = (PACTIVE_SESSION)Context;
if (!ARGUMENT_PRESENT(Context))
return FALSE;
status = HashUserModule(
Entry,
session->module.module_hash,
sizeof(session->module.module_hash));
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("HashUserModule: %lx", status);
return FALSE;
}
DEBUG_VERBOSE("User module hashed!");
DumpBufferToKernelDebugger(
session->module.module_hash,
sizeof(session->module.module_hash));
return TRUE;
}
NTSTATUS
SessionInitialise(_In_ PIRP Irp)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PEPROCESS process = NULL;
PSESSION_INITIATION_PACKET initiation = NULL;
PACTIVE_SESSION session = GetActiveSession();
KIRQL irql = {0};
DEBUG_VERBOSE("Initialising new session.");
status = ValidateIrpInputBuffer(
Irp,
sizeof(SESSION_INITIATION_PACKET) - SHA_256_HASH_LENGTH);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("ValidateIrpInputBuffer failed with status %x", status);
return status;
}
initiation = (PSESSION_INITIATION_PACKET)Irp->AssociatedIrp.SystemBuffer;
KeAcquireGuardedMutex(&session->lock);
session->um_handle = initiation->process_id;
/* What if we pass an invalid handle here? not good. */
status = ImpPsLookupProcessByProcessId(session->um_handle, &process);
if (!NT_SUCCESS(status)) {
status = STATUS_INVALID_PARAMETER;
goto end;
}
session->km_handle = ImpPsGetProcessId(process);
session->process = process;
session->cookie = initiation->cookie;
IntCopyMemory(session->aes_key, initiation->aes_key, AES_256_KEY_SIZE);
IntCopyMemory(session->iv, initiation->aes_iv, AES_256_IV_SIZE);
session->module.base_address = initiation->module_info.base_address;
session->module.size = initiation->module_info.size;
IntCopyMemory(
session->module.path,
initiation->module_info.path,
MAX_MODULE_PATH);
DEBUG_VERBOSE("Module base: %llx", session->module.base_address);
DEBUG_VERBOSE("Module size: %lx ", session->module.size);
DEBUG_VERBOSE("Module path: %s", session->module.path);
status = CryptInitialiseSessionCryptObjects();
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("CryptInitialiseSessionCryptObjects: %x", status);
goto end;
}
status = InitialiseHeartbeatConfiguration(&session->heartbeat_config);
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("InitialiseHeartbeatConfiguration %x", status);
goto end;
}
FindOurUserModeModuleEntry(HashOurUserModuleOnEntryCallback, session);
session->is_session_active = TRUE;
end:
KeReleaseGuardedMutex(&session->lock);
return status;
}
VOID
SessionTerminateProcess()
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG process_id = 0;
SessionGetProcessId(&process_id);
if (!process_id) {
DEBUG_ERROR("Failed to terminate process as process id is null");
return;
}
/* Make sure we pass a km handle to ZwTerminateProcess and NOT a
* usermode handle. */
status = ZwTerminateProcess(
process_id,
STATUS_SYSTEM_INTEGRITY_POLICY_VIOLATION);
if (!NT_SUCCESS(status)) {
/*
* We don't want to clear the process config if
* ZwTerminateProcess fails so we can try again.
*/
DEBUG_ERROR("ZwTerminateProcess failed with status %x", status);
return;
}
/* this wont be needed when procloadstuff is implemented */
SessionTerminate();
}
VOID
SessionIncrementIrpsProcessedCount()
{
KeAcquireGuardedMutex(&GetActiveSession()->lock);
GetActiveSession()->irps_received;
KeReleaseGuardedMutex(&GetActiveSession()->lock);
}
VOID
SessionIncrementReportCount()
{
KeAcquireGuardedMutex(&GetActiveSession()->lock);
GetActiveSession()->report_count++;
KeReleaseGuardedMutex(&GetActiveSession()->lock);
}
VOID
SessionIncrementHeartbeatCount()
{
KeAcquireGuardedMutex(&GetActiveSession()->lock);
GetActiveSession()->heartbeat_count++;
KeReleaseGuardedMutex(&GetActiveSession()->lock);
}