mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
code cleanup
This commit is contained in:
parent
c3e0dc65b0
commit
49c7ff65f1
5 changed files with 570 additions and 717 deletions
|
@ -510,7 +510,6 @@ ProcessCreateNotifyRoutine(_In_ HANDLE ParentId,
|
|||
* any x86 modules that werent hashed.
|
||||
*/
|
||||
if (!strcmp(process_name, "winlogon.exe")) {
|
||||
DEBUG_VERBOSE("Winlogon process has started");
|
||||
driver_list->can_hash_x86 = TRUE;
|
||||
IoQueueWorkItem(driver_list->deferred_work_item,
|
||||
DeferredModuleHashingCallback,
|
||||
|
@ -644,77 +643,75 @@ ObPreOpCallbackRoutine(_In_ PVOID RegistrationContext,
|
|||
if (!protected_process_name || !target_process_name)
|
||||
goto end;
|
||||
|
||||
if (!strcmp(protected_process_name, target_process_name)) {
|
||||
if (strcmp(protected_process_name, target_process_name))
|
||||
goto end;
|
||||
/*
|
||||
* WerFault is some windows 11 application that cries when it
|
||||
* cant get a handle, so well allow it for now... todo; learn
|
||||
* more about it
|
||||
*
|
||||
* 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") ||
|
||||
!strcmp(process_creator_name, target_process_name)) {
|
||||
/* We will downgrade these handles later */
|
||||
// DEBUG_LOG("Handles created by CSRSS, LSASS and
|
||||
// WerFault are allowed for now...");
|
||||
}
|
||||
else if (target_process == process_creator) {
|
||||
// DEBUG_LOG("handles made by NOTEPAD r okay :)");
|
||||
/* handles created by the game (notepad) are okay */
|
||||
}
|
||||
else {
|
||||
OperationInformation->Parameters->CreateHandleInformation
|
||||
.DesiredAccess = deny_access;
|
||||
OperationInformation->Parameters->DuplicateHandleInformation
|
||||
.DesiredAccess = deny_access;
|
||||
|
||||
/*
|
||||
* WerFault is some windows 11 application that cries when it
|
||||
* cant get a handle, so well allow it for now... todo; learn
|
||||
* more about it
|
||||
*
|
||||
* todo: perform stricter checks rather then the image name.
|
||||
* perhapds check some certificate or something.
|
||||
* These processes will constantly open handles to any
|
||||
* open process for various reasons, so we will still
|
||||
* strip them but we won't report them.. for now
|
||||
* atleast.
|
||||
*/
|
||||
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") ||
|
||||
!strcmp(process_creator_name, target_process_name)) {
|
||||
/* We will downgrade these handles later */
|
||||
// DEBUG_LOG("Handles created by CSRSS, LSASS and
|
||||
// WerFault are allowed for now...");
|
||||
}
|
||||
else if (target_process == process_creator) {
|
||||
// DEBUG_LOG("handles made by NOTEPAD r okay :)");
|
||||
/* handles created by the game (notepad) are okay */
|
||||
}
|
||||
else {
|
||||
OperationInformation->Parameters
|
||||
->CreateHandleInformation.DesiredAccess =
|
||||
deny_access;
|
||||
OperationInformation->Parameters
|
||||
->DuplicateHandleInformation.DesiredAccess =
|
||||
deny_access;
|
||||
|
||||
/*
|
||||
* These processes will constantly open handles to any
|
||||
* open process for various reasons, so we will still
|
||||
* strip them but we won't report them.. for now
|
||||
* atleast.
|
||||
*/
|
||||
if (!strcmp(process_creator_name, "Discord.exe") ||
|
||||
!strcmp(process_creator_name, "svchost.exe") ||
|
||||
!strcmp(process_creator_name, "explorer.exe"))
|
||||
goto end;
|
||||
|
||||
if (!strcmp(process_creator_name, "Discord.exe") ||
|
||||
!strcmp(process_creator_name, "svchost.exe") ||
|
||||
!strcmp(process_creator_name, "explorer.exe"))
|
||||
goto end;
|
||||
// POPEN_HANDLE_FAILURE_REPORT report =
|
||||
// ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
// sizeof(OPEN_HANDLE_FAILURE_REPORT),
|
||||
// REPORT_POOL_TAG);
|
||||
|
||||
// POPEN_HANDLE_FAILURE_REPORT report =
|
||||
// ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
// sizeof(OPEN_HANDLE_FAILURE_REPORT),
|
||||
// REPORT_POOL_TAG);
|
||||
// if (!report)
|
||||
// goto end;
|
||||
|
||||
// if (!report)
|
||||
// goto end;
|
||||
// report->report_code =
|
||||
// REPORT_ILLEGAL_HANDLE_OPERATION;
|
||||
// report->is_kernel_handle =
|
||||
// OperationInformation->KernelHandle;
|
||||
// report->process_id = process_creator_id;
|
||||
// report->thread_id = ImpPsGetCurrentThreadId();
|
||||
// report->access =
|
||||
// OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
|
||||
|
||||
// report->report_code =
|
||||
// REPORT_ILLEGAL_HANDLE_OPERATION;
|
||||
// report->is_kernel_handle =
|
||||
// OperationInformation->KernelHandle;
|
||||
// report->process_id = process_creator_id;
|
||||
// report->thread_id = ImpPsGetCurrentThreadId();
|
||||
// report->access =
|
||||
// OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
|
||||
// RtlCopyMemory(report->process_name,
|
||||
// process_creator_name,
|
||||
// HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
||||
|
||||
// RtlCopyMemory(report->process_name,
|
||||
// process_creator_name,
|
||||
// HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
||||
|
||||
// if (!NT_SUCCESS(
|
||||
// IrpQueueCompleteIrp(report,
|
||||
// sizeof(OPEN_HANDLE_FAILURE_REPORT))))
|
||||
//{
|
||||
// DEBUG_ERROR("IrpQueueCompleteIrp failed with
|
||||
// no status."); goto end;
|
||||
// }
|
||||
}
|
||||
// if (!NT_SUCCESS(
|
||||
// IrpQueueCompleteIrp(report,
|
||||
// sizeof(OPEN_HANDLE_FAILURE_REPORT))))
|
||||
//{
|
||||
// DEBUG_ERROR("IrpQueueCompleteIrp failed with
|
||||
// no status."); goto end;
|
||||
// }
|
||||
}
|
||||
|
||||
end:
|
||||
|
@ -768,130 +765,129 @@ EnumHandleCallback(_In_ PHANDLE_TABLE HandleTable,
|
|||
object_type = ImpObGetObjectType(object);
|
||||
|
||||
/* TODO: check for threads aswell */
|
||||
if (!ImpRtlCompareUnicodeString(
|
||||
if (ImpRtlCompareUnicodeString(
|
||||
&object_type->Name, &OBJECT_TYPE_PROCESS, TRUE)) {
|
||||
process = (PEPROCESS)object;
|
||||
process_name = ImpPsGetProcessImageFileName(process);
|
||||
goto end;
|
||||
}
|
||||
|
||||
SessionGetProcess(&protected_process);
|
||||
process = (PEPROCESS)object;
|
||||
process_name = ImpPsGetProcessImageFileName(process);
|
||||
|
||||
protected_process_name =
|
||||
ImpPsGetProcessImageFileName(protected_process);
|
||||
SessionGetProcess(&protected_process);
|
||||
|
||||
if (strcmp(process_name, protected_process_name))
|
||||
goto end;
|
||||
protected_process_name =
|
||||
ImpPsGetProcessImageFileName(protected_process);
|
||||
|
||||
if (strcmp(process_name, protected_process_name))
|
||||
goto end;
|
||||
|
||||
DEBUG_VERBOSE(
|
||||
"Handle references our protected process with access mask: %lx",
|
||||
(ACCESS_MASK)Entry->GrantedAccessBits);
|
||||
|
||||
handle_access_mask = (ACCESS_MASK)Entry->GrantedAccessBits;
|
||||
|
||||
/* These permissions can be stripped from every process
|
||||
* including CSRSS and LSASS */
|
||||
if (handle_access_mask & PROCESS_CREATE_PROCESS) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_CREATE_PROCESS;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_CREATE_PROCESS");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_CREATE_THREAD) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_CREATE_THREAD;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_CREATE_THREAD");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_DUP_HANDLE) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_DUP_HANDLE;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_DUP_HANDLE");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_QUERY_INFORMATION) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_QUERY_INFORMATION;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_QUERY_INFORMATION");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_QUERY_LIMITED_INFORMATION) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_QUERY_LIMITED_INFORMATION;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_QUERY_LIMITED_INFORMATION");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_VM_READ) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_VM_READ;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_VM_READ");
|
||||
}
|
||||
|
||||
if (!strcmp(process_name, "csrss.exe") ||
|
||||
!strcmp(process_name, "lsass.exe")) {
|
||||
DEBUG_VERBOSE(
|
||||
"Handle references our protected process with access mask: %lx",
|
||||
(ACCESS_MASK)Entry->GrantedAccessBits);
|
||||
"Required system process allowed, only stripping some permissions");
|
||||
goto end;
|
||||
}
|
||||
|
||||
handle_access_mask = (ACCESS_MASK)Entry->GrantedAccessBits;
|
||||
/* Permissions beyond here can only be stripped from non
|
||||
* critical processes */
|
||||
if (handle_access_mask & PROCESS_SET_INFORMATION) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_SET_INFORMATION;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_SET_INFORMATION");
|
||||
}
|
||||
|
||||
/* These permissions can be stripped from every process
|
||||
* including CSRSS and LSASS */
|
||||
if (handle_access_mask & PROCESS_CREATE_PROCESS) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_CREATE_PROCESS;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_CREATE_PROCESS");
|
||||
}
|
||||
if (handle_access_mask & PROCESS_SET_QUOTA) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_SET_QUOTA;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_SET_QUOTA");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_CREATE_THREAD) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_CREATE_THREAD;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_CREATE_THREAD");
|
||||
}
|
||||
if (handle_access_mask & PROCESS_SUSPEND_RESUME) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_SUSPEND_RESUME;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_SUSPEND_RESUME ");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_DUP_HANDLE) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_DUP_HANDLE;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_DUP_HANDLE");
|
||||
}
|
||||
if (handle_access_mask & PROCESS_TERMINATE) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_TERMINATE;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_TERMINATE");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_QUERY_INFORMATION) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_QUERY_INFORMATION;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_QUERY_INFORMATION");
|
||||
}
|
||||
if (handle_access_mask & PROCESS_VM_OPERATION) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_VM_OPERATION;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_VM_OPERATION");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_QUERY_LIMITED_INFORMATION) {
|
||||
Entry->GrantedAccessBits &=
|
||||
~PROCESS_QUERY_LIMITED_INFORMATION;
|
||||
DEBUG_VERBOSE(
|
||||
"Stripped PROCESS_QUERY_LIMITED_INFORMATION");
|
||||
}
|
||||
if (handle_access_mask & PROCESS_VM_WRITE) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_VM_WRITE;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_VM_WRITE");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_VM_READ) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_VM_READ;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_VM_READ");
|
||||
}
|
||||
POPEN_HANDLE_FAILURE_REPORT report =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
sizeof(OPEN_HANDLE_FAILURE_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
if (!strcmp(process_name, "csrss.exe") ||
|
||||
!strcmp(process_name, "lsass.exe")) {
|
||||
DEBUG_VERBOSE(
|
||||
"Required system process allowed, only stripping some permissions");
|
||||
goto end;
|
||||
}
|
||||
if (!report)
|
||||
goto end;
|
||||
|
||||
/* Permissions beyond here can only be stripped from non
|
||||
* critical processes */
|
||||
if (handle_access_mask & PROCESS_SET_INFORMATION) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_SET_INFORMATION;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_SET_INFORMATION");
|
||||
}
|
||||
/*
|
||||
* Using the same report structure as the ObRegisterCallbacks
|
||||
* report since both of these reports are closely related by the
|
||||
* fact they are triggered by a process either opening a handle
|
||||
* to our protected process or have a valid open handle to it. I
|
||||
* also don't think its worth creating another queue
|
||||
* specifically for open handle reports since they will be rare.
|
||||
*/
|
||||
report->report_code = REPORT_ILLEGAL_HANDLE_OPERATION;
|
||||
report->is_kernel_handle = 0;
|
||||
report->process_id = ImpPsGetProcessId(process);
|
||||
report->thread_id = 0;
|
||||
report->access = handle_access_mask;
|
||||
|
||||
if (handle_access_mask & PROCESS_SET_QUOTA) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_SET_QUOTA;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_SET_QUOTA");
|
||||
}
|
||||
RtlCopyMemory(&report->process_name,
|
||||
process_name,
|
||||
HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
||||
|
||||
if (handle_access_mask & PROCESS_SUSPEND_RESUME) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_SUSPEND_RESUME;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_SUSPEND_RESUME ");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_TERMINATE) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_TERMINATE;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_TERMINATE");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_VM_OPERATION) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_VM_OPERATION;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_VM_OPERATION");
|
||||
}
|
||||
|
||||
if (handle_access_mask & PROCESS_VM_WRITE) {
|
||||
Entry->GrantedAccessBits &= ~PROCESS_VM_WRITE;
|
||||
DEBUG_VERBOSE("Stripped PROCESS_VM_WRITE");
|
||||
}
|
||||
|
||||
POPEN_HANDLE_FAILURE_REPORT report =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
sizeof(OPEN_HANDLE_FAILURE_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* Using the same report structure as the ObRegisterCallbacks
|
||||
* report since both of these reports are closely related by the
|
||||
* fact they are triggered by a process either opening a handle
|
||||
* to our protected process or have a valid open handle to it. I
|
||||
* also don't think its worth creating another queue
|
||||
* specifically for open handle reports since they will be rare.
|
||||
*/
|
||||
report->report_code = REPORT_ILLEGAL_HANDLE_OPERATION;
|
||||
report->is_kernel_handle = 0;
|
||||
report->process_id = ImpPsGetProcessId(process);
|
||||
report->thread_id = 0;
|
||||
report->access = handle_access_mask;
|
||||
|
||||
RtlCopyMemory(&report->process_name,
|
||||
process_name,
|
||||
HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH);
|
||||
|
||||
if (!NT_SUCCESS(IrpQueueCompleteIrp(
|
||||
report, sizeof(OPEN_HANDLE_FAILURE_REPORT)))) {
|
||||
DEBUG_ERROR(
|
||||
"IrpQueueCompleteIrp failed with no status.");
|
||||
goto end;
|
||||
}
|
||||
if (!NT_SUCCESS(IrpQueueCompleteIrp(
|
||||
report, sizeof(OPEN_HANDLE_FAILURE_REPORT)))) {
|
||||
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
|
|
|
@ -271,57 +271,50 @@ StoreModuleExecutableRegionsInBuffer(_Outptr_result_bytebuffer_(*BytesWritten)
|
|||
buffer_base = (UINT64)*Buffer + sizeof(INTEGRITY_CHECK_HEADER);
|
||||
|
||||
for (ULONG index = 0; index < num_sections - 1; index++) {
|
||||
/* create a function for this instead, check for writeable
|
||||
* sections use !*/
|
||||
if (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) {
|
||||
/*
|
||||
* Note: MmCopyMemory will fail on discardable sections.
|
||||
*/
|
||||
address.VirtualAddress = section;
|
||||
|
||||
status = ImpMmCopyMemory((UINT64)buffer_base +
|
||||
total_packet_size,
|
||||
address,
|
||||
sizeof(IMAGE_SECTION_HEADER),
|
||||
MM_COPY_MEMORY_VIRTUAL,
|
||||
&bytes_returned);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"MmCopyMemory failed with status %x",
|
||||
status);
|
||||
ImpExFreePoolWithTag(*Buffer,
|
||||
POOL_TAG_INTEGRITY);
|
||||
*Buffer = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
address.VirtualAddress =
|
||||
(UINT64)ModuleBase + section->PointerToRawData;
|
||||
|
||||
status = ImpMmCopyMemory(
|
||||
(UINT64)buffer_base + total_packet_size +
|
||||
sizeof(IMAGE_SECTION_HEADER),
|
||||
address,
|
||||
section->SizeOfRawData,
|
||||
MM_COPY_MEMORY_VIRTUAL,
|
||||
&bytes_returned);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"MmCopyMemory failed with status %x",
|
||||
status);
|
||||
ImpExFreePoolWithTag(*Buffer,
|
||||
POOL_TAG_INTEGRITY);
|
||||
*Buffer = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
total_packet_size += section->SizeOfRawData +
|
||||
sizeof(IMAGE_SECTION_HEADER);
|
||||
num_executable_sections += 1;
|
||||
if (!(section->Characteristics & IMAGE_SCN_MEM_EXECUTE)) {
|
||||
section++;
|
||||
continue;
|
||||
}
|
||||
|
||||
address.VirtualAddress = section;
|
||||
|
||||
status =
|
||||
ImpMmCopyMemory((UINT64)buffer_base + total_packet_size,
|
||||
address,
|
||||
sizeof(IMAGE_SECTION_HEADER),
|
||||
MM_COPY_MEMORY_VIRTUAL,
|
||||
&bytes_returned);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("MmCopyMemory failed with status %x",
|
||||
status);
|
||||
ImpExFreePoolWithTag(*Buffer, POOL_TAG_INTEGRITY);
|
||||
*Buffer = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
address.VirtualAddress =
|
||||
(UINT64)ModuleBase + section->PointerToRawData;
|
||||
|
||||
status =
|
||||
ImpMmCopyMemory((UINT64)buffer_base + total_packet_size +
|
||||
sizeof(IMAGE_SECTION_HEADER),
|
||||
address,
|
||||
section->SizeOfRawData,
|
||||
MM_COPY_MEMORY_VIRTUAL,
|
||||
&bytes_returned);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("MmCopyMemory failed with status %x",
|
||||
status);
|
||||
ImpExFreePoolWithTag(*Buffer, POOL_TAG_INTEGRITY);
|
||||
*Buffer = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
total_packet_size +=
|
||||
section->SizeOfRawData + sizeof(IMAGE_SECTION_HEADER);
|
||||
num_executable_sections += 1;
|
||||
section++;
|
||||
}
|
||||
|
||||
|
@ -329,8 +322,8 @@ StoreModuleExecutableRegionsInBuffer(_Outptr_result_bytebuffer_(*BytesWritten)
|
|||
header.executable_section_count = num_executable_sections;
|
||||
header.total_packet_size =
|
||||
total_packet_size + sizeof(INTEGRITY_CHECK_HEADER);
|
||||
RtlCopyMemory(*Buffer, &header, sizeof(INTEGRITY_CHECK_HEADER));
|
||||
|
||||
RtlCopyMemory(*Buffer, &header, sizeof(INTEGRITY_CHECK_HEADER));
|
||||
*BytesWritten = total_packet_size + sizeof(INTEGRITY_CHECK_HEADER);
|
||||
return status;
|
||||
}
|
||||
|
@ -416,8 +409,6 @@ MapDiskImageIntoVirtualAddressSpace(_Inout_ PHANDLE SectionHandle,
|
|||
PAGE_READONLY);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
/* caller is responsible for closing handle on success,
|
||||
* therefore null it */
|
||||
DEBUG_ERROR("ZwMapViewOfSection failed with status %x", status);
|
||||
ImpZwClose(file_handle);
|
||||
ImpZwClose(*SectionHandle);
|
||||
|
@ -608,11 +599,9 @@ RetrieveInMemoryModuleExecutableSections(_Inout_ PIRP Irp)
|
|||
}
|
||||
|
||||
Irp->IoStatus.Information = bytes_written;
|
||||
|
||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, buffer, bytes_written);
|
||||
|
||||
end:
|
||||
|
||||
if (buffer)
|
||||
ImpExFreePoolWithTag(buffer, POOL_TAG_INTEGRITY);
|
||||
|
||||
|
@ -653,9 +642,7 @@ GetNextSMBIOSStructureInTable(_Inout_ PSMBIOS_TABLE_HEADER* CurrentStructure)
|
|||
if (*current_char_in_strings == NULL_TERMINATOR &&
|
||||
*next_char_in_strings == NULL_TERMINATOR) {
|
||||
*CurrentStructure =
|
||||
(PSMBIOS_TABLE_HEADER)((UINT64)
|
||||
next_char_in_strings +
|
||||
1);
|
||||
(PSMBIOS_TABLE_HEADER)(next_char_in_strings + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -703,11 +690,10 @@ GetStringAtIndexFromSMBIOSTable(_In_ PSMBIOS_TABLE_HEADER Table,
|
|||
if (*current_string_char == NULL_TERMINATOR)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
RtlCopyMemory((UINT64)Buffer +
|
||||
current_string_char_index,
|
||||
current_string_char,
|
||||
sizeof(CHAR));
|
||||
UINT64 dest =
|
||||
(UINT64)Buffer + current_string_char_index;
|
||||
|
||||
RtlCopyMemory(dest, current_string_char, sizeof(CHAR));
|
||||
current_string_char_index++;
|
||||
goto increment;
|
||||
}
|
||||
|
@ -718,7 +704,6 @@ GetStringAtIndexFromSMBIOSTable(_In_ PSMBIOS_TABLE_HEADER Table,
|
|||
}
|
||||
|
||||
increment:
|
||||
|
||||
current_string_char++;
|
||||
next_string_char++;
|
||||
}
|
||||
|
@ -880,6 +865,28 @@ typedef struct _VAL_INTEGRITY_HEADER {
|
|||
|
||||
} VAL_INTEGRITY_HEADER, *PVAL_INTEGRITY_HEADER;
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
ReportInvalidProcessModule(_In_ PPROCESS_MODULE_INFORMATION Module)
|
||||
{
|
||||
PPROCESS_MODULE_VALIDATION_REPORT report =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
sizeof(PROCESS_MODULE_VALIDATION_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
return;
|
||||
|
||||
report->report_code = REPORT_INVALID_PROCESS_MODULE;
|
||||
report->image_base = Module->module_base;
|
||||
report->image_size = Module->module_size;
|
||||
RtlCopyMemory(report->module_path,
|
||||
Module->module_path,
|
||||
sizeof(report->module_path));
|
||||
|
||||
IrpQueueCompleteIrp(report, sizeof(PROCESS_MODULE_VALIDATION_REPORT));
|
||||
}
|
||||
|
||||
/*
|
||||
* Because the infrastructure has already been setup to validate modules in the
|
||||
* driver, that is how I will validate the usermode modules as well. Another
|
||||
|
@ -991,31 +998,8 @@ ValidateProcessLoadedModule(_Inout_ PIRP Irp)
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (!CompareHashes(disk_hash, memory_hash, memory_hash_size)) {
|
||||
PPROCESS_MODULE_VALIDATION_REPORT report =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
sizeof(PROCESS_MODULE_VALIDATION_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
goto end;
|
||||
|
||||
report->report_code = REPORT_INVALID_PROCESS_MODULE;
|
||||
report->image_base = module_info->module_base;
|
||||
report->image_size = module_info->module_size;
|
||||
RtlCopyMemory(report->module_path,
|
||||
module_info->module_path,
|
||||
sizeof(report->module_path));
|
||||
|
||||
status = IrpQueueCompleteIrp(
|
||||
report, sizeof(PROCESS_MODULE_VALIDATION_REPORT));
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("IrpQueueCompleteIrp failed with status %x",
|
||||
status);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (!CompareHashes(disk_hash, memory_hash, memory_hash_size))
|
||||
ReportInvalidProcessModule(module_info);
|
||||
|
||||
end:
|
||||
|
||||
|
@ -1132,25 +1116,20 @@ GetHardDiskDriveSerialNumber(_Inout_ PVOID ConfigDrive0Serial,
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (device_descriptor->SerialNumberOffset > 0) {
|
||||
serial_number = (PCHAR)((UINT64)device_descriptor +
|
||||
device_descriptor->SerialNumberOffset);
|
||||
serial_length = strnlen_s(serial_number,
|
||||
DEVICE_DRIVE_0_SERIAL_CODE_LENGTH) +
|
||||
1;
|
||||
if (!device_descriptor->SerialNumberOffset)
|
||||
goto end;
|
||||
|
||||
if (serial_length > ConfigDrive0MaxSize) {
|
||||
DEBUG_ERROR(
|
||||
"Serial length is greater then the allocated buffer size for the drives serial number.");
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
goto end;
|
||||
}
|
||||
serial_number = (PCHAR)((UINT64)device_descriptor +
|
||||
device_descriptor->SerialNumberOffset);
|
||||
serial_length =
|
||||
strnlen_s(serial_number, DEVICE_DRIVE_0_SERIAL_CODE_LENGTH) + 1;
|
||||
|
||||
RtlCopyMemory(ConfigDrive0Serial, serial_number, serial_length);
|
||||
|
||||
DEBUG_VERBOSE(
|
||||
"Successfully retrieved hard disk serial number.");
|
||||
if (serial_length > ConfigDrive0MaxSize) {
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
RtlCopyMemory(ConfigDrive0Serial, serial_number, serial_length);
|
||||
end:
|
||||
|
||||
if (handle)
|
||||
|
@ -1161,54 +1140,6 @@ end:
|
|||
|
||||
return status;
|
||||
}
|
||||
|
||||
// VOID
|
||||
// EnumeratePciDevices()
|
||||
//{
|
||||
// NTSTATUS status;
|
||||
// PZZWSTR device_interfaces;
|
||||
// PWSTR list_base;
|
||||
// DEVPROPKEY key = { 0 };
|
||||
// UNICODE_STRING symbolic_link = { 0 };
|
||||
// WCHAR device_id[ 512 ];
|
||||
// PZZWSTR current_string = NULL;
|
||||
// SIZE_T string_length = 0;
|
||||
//
|
||||
// /* PCI guid */
|
||||
// CONST GUID guid = { 0x5b45201d, 0xf2f2, 0x4f3b, 0x85, 0xbb, 0x30, 0xff,
|
||||
// 0x1f, 0x95, 0x35, 0x99 };
|
||||
//
|
||||
// status = IoGetDeviceInterfaces(
|
||||
// &guid,
|
||||
// NULL,
|
||||
// NULL,
|
||||
// &device_interfaces
|
||||
// );
|
||||
//
|
||||
// if ( !NT_SUCCESS( status ) )
|
||||
// {
|
||||
// DEBUG_VERBOSE( "IoGetDeviceInterfaces failed with status %x", status
|
||||
// ); return;
|
||||
// }
|
||||
//
|
||||
// current_string = device_interfaces;
|
||||
//
|
||||
// while ( *current_string != NULL_TERMINATOR )
|
||||
// {
|
||||
// string_length = wcslen( current_string );
|
||||
//
|
||||
// symbolic_link.Buffer = current_string;
|
||||
// symbolic_link.Length = string_length;
|
||||
// symbolic_link.MaximumLength = string_length;
|
||||
//
|
||||
// DEBUG_VERBOSE( "Device Interface: %wZ", symbolic_link );
|
||||
//
|
||||
// current_string += symbolic_link.Length + 1;
|
||||
// }
|
||||
//
|
||||
// ImpExFreePoolWithTag( device_interfaces, NULL );
|
||||
// }
|
||||
|
||||
PVOID
|
||||
ScanForSignature(_In_ PVOID BaseAddress,
|
||||
_In_ SIZE_T MaxLength,
|
||||
|
@ -1221,13 +1152,12 @@ ScanForSignature(_In_ PVOID BaseAddress,
|
|||
CHAR current_sig_char = 0;
|
||||
|
||||
for (INT index = 0; index < MaxLength; index++) {
|
||||
for (INT sig_index = 0; sig_index < SignatureLength + 1;
|
||||
sig_index++) {
|
||||
for (INT sig = 0; sig < SignatureLength + 1; sig++) {
|
||||
current_char =
|
||||
*(PCHAR)((UINT64)BaseAddress + index + sig_index);
|
||||
current_sig_char = Signature[sig_index];
|
||||
*(PCHAR)((UINT64)BaseAddress + index + sig);
|
||||
current_sig_char = Signature[sig];
|
||||
|
||||
if (sig_index == SignatureLength)
|
||||
if (sig == SignatureLength)
|
||||
return (PVOID)((UINT64)BaseAddress + index);
|
||||
|
||||
if (current_char != current_sig_char)
|
||||
|
@ -1454,10 +1384,6 @@ DetectEptHooksInKeyFunctions()
|
|||
|
||||
/* close game etc. */
|
||||
}
|
||||
else {
|
||||
DEBUG_INFO("No ept hook detected at function: %llx",
|
||||
PROTECTED_FUNCTION_ADDRESSES[index]);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -1830,6 +1756,7 @@ InitialiseSystemModuleVerificationContext(PSYS_MODULE_VAL_CONTEXT Context)
|
|||
POOL_FLAG_NON_PAGED,
|
||||
modules.module_count * sizeof(MODULE_DISPATCHER_HEADER),
|
||||
POOL_TAG_INTEGRITY);
|
||||
|
||||
if (!dispatcher_array) {
|
||||
ImpExFreePoolWithTag(modules.address, SYSTEM_MODULES_POOL);
|
||||
return STATUS_MEMORY_NOT_ALLOCATED;
|
||||
|
|
657
driver/modules.c
657
driver/modules.c
|
@ -127,8 +127,9 @@ ValidateDriverObjectHasBackingModule(_In_ PSYSTEM_MODULES ModuleInformation,
|
|||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
ValidateDriverObjects(_In_ PSYSTEM_MODULES SystemModules,
|
||||
_Inout_ PINVALID_DRIVERS_HEAD InvalidDriverListHead);
|
||||
ValidateDriverObjectsWrapper(_In_ PSYSTEM_MODULES SystemModules,
|
||||
_Inout_ PINVALID_DRIVERS_HEAD
|
||||
InvalidDriverListHead);
|
||||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
|
@ -172,7 +173,7 @@ ValidateThreadViaKernelApcCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry,
|
|||
# pragma alloc_text(PAGE, EnumerateInvalidDrivers)
|
||||
# pragma alloc_text(PAGE, ValidateDriverObjectHasBackingModule)
|
||||
# pragma alloc_text(PAGE, GetSystemModuleInformation)
|
||||
# pragma alloc_text(PAGE, ValidateDriverObjects)
|
||||
# pragma alloc_text(PAGE, ValidateDriverObjectsWrapper)
|
||||
# pragma alloc_text(PAGE, HandleValidateDriversIOCTL)
|
||||
# pragma alloc_text(PAGE, IsInstructionPointerInInvalidRegion)
|
||||
# pragma alloc_text(PAGE, AnalyseNmiData)
|
||||
|
@ -201,16 +202,12 @@ FindSystemModuleByName(_In_ LPCSTR ModuleName,
|
|||
if (!ModuleName || !SystemModules)
|
||||
return NULL;
|
||||
|
||||
for (INT index = 0; index < SystemModules->module_count; index++) {
|
||||
PRTL_MODULE_EXTENDED_INFO system_module =
|
||||
(PRTL_MODULE_EXTENDED_INFO)((uintptr_t)
|
||||
SystemModules->address +
|
||||
index *
|
||||
sizeof(
|
||||
RTL_MODULE_EXTENDED_INFO));
|
||||
PRTL_MODULE_EXTENDED_INFO modules =
|
||||
(PRTL_MODULE_EXTENDED_INFO)SystemModules->address;
|
||||
|
||||
if (strstr(system_module->FullPathName, ModuleName)) {
|
||||
return system_module;
|
||||
for (INT index = 0; index < SystemModules->module_count; index++) {
|
||||
if (strstr(modules[index].FullPathName, ModuleName)) {
|
||||
return &modules[index];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,10 +238,10 @@ PopulateWhitelistedModuleBuffer(_Inout_ PVOID Buffer,
|
|||
region.base = (UINT64)module->ImageBase;
|
||||
region.end = region.base + module->ImageSize;
|
||||
|
||||
RtlCopyMemory((UINT64)Buffer +
|
||||
index * sizeof(WHITELISTED_REGIONS),
|
||||
®ion,
|
||||
sizeof(WHITELISTED_REGIONS));
|
||||
UINT64 destination =
|
||||
(UINT64)Buffer + index * sizeof(WHITELISTED_REGIONS);
|
||||
RtlCopyMemory(
|
||||
destination, ®ion, sizeof(WHITELISTED_REGIONS));
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -273,14 +270,11 @@ ValidateDriverIOCTLDispatchRegion(_In_ PDRIVER_OBJECT Driver,
|
|||
if (dispatch_function == NULL)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
for (INT index = 0; index < Modules->module_count; index++) {
|
||||
PRTL_MODULE_EXTENDED_INFO system_module =
|
||||
(PRTL_MODULE_EXTENDED_INFO)((UINT64)Modules->address +
|
||||
index *
|
||||
sizeof(
|
||||
RTL_MODULE_EXTENDED_INFO));
|
||||
PRTL_MODULE_EXTENDED_INFO module =
|
||||
(PRTL_MODULE_EXTENDED_INFO)Modules->address;
|
||||
|
||||
if (system_module->ImageBase != Driver->DriverStart)
|
||||
for (INT index = 0; index < Modules->module_count; index++) {
|
||||
if (module[index].ImageBase != Driver->DriverStart)
|
||||
continue;
|
||||
|
||||
/* make sure our driver has a device object which is required
|
||||
|
@ -288,8 +282,8 @@ ValidateDriverIOCTLDispatchRegion(_In_ PDRIVER_OBJECT Driver,
|
|||
if (Driver->DeviceObject == NULL)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
module_base = (UINT64)system_module->ImageBase;
|
||||
module_end = module_base + system_module->ImageSize;
|
||||
module_base = (UINT64)module[index].ImageBase;
|
||||
module_end = module_base + module[index].ImageSize;
|
||||
|
||||
/* firstly, check if its inside its own module */
|
||||
if (dispatch_function >= module_base &&
|
||||
|
@ -320,7 +314,7 @@ ValidateDriverIOCTLDispatchRegion(_In_ PDRIVER_OBJECT Driver,
|
|||
}
|
||||
|
||||
DEBUG_WARNING("Driver with invalid dispatch routine found: %s",
|
||||
system_module->FullPathName);
|
||||
module[index].FullPathName);
|
||||
|
||||
*Flag = FALSE;
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -402,18 +396,15 @@ ValidateDriverObjectHasBackingModule(_In_ PSYSTEM_MODULES ModuleInformation,
|
|||
if (!ModuleInformation || !DriverObject || !Result)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
for (INT i = 0; i < ModuleInformation->module_count; i++) {
|
||||
PRTL_MODULE_EXTENDED_INFO system_module =
|
||||
(PRTL_MODULE_EXTENDED_INFO)((uintptr_t)
|
||||
ModuleInformation->address +
|
||||
i * sizeof(
|
||||
RTL_MODULE_EXTENDED_INFO));
|
||||
PRTL_MODULE_EXTENDED_INFO module =
|
||||
(PRTL_MODULE_EXTENDED_INFO)ModuleInformation->address;
|
||||
|
||||
if (system_module->ImageSize == 0 ||
|
||||
system_module->ImageBase == 0)
|
||||
for (INT index = 0; index < ModuleInformation->module_count; index++) {
|
||||
if (module[index].ImageSize == 0 ||
|
||||
module[index].ImageBase == 0)
|
||||
return STATUS_INVALID_MEMBER;
|
||||
|
||||
if (system_module->ImageBase == DriverObject->DriverStart) {
|
||||
if (module[index].ImageBase == DriverObject->DriverStart) {
|
||||
*Result = TRUE;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -439,10 +430,6 @@ GetSystemModuleInformation(_Out_ PSYSTEM_MODULES ModuleInformation)
|
|||
ULONG size = 0;
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
/*
|
||||
* query system module information without an output buffer to get
|
||||
* number of bytes required to store all module info structures
|
||||
*/
|
||||
status = RtlQueryModuleInformation(
|
||||
&size, sizeof(RTL_MODULE_EXTENDED_INFO), NULL);
|
||||
|
||||
|
@ -452,8 +439,6 @@ GetSystemModuleInformation(_Out_ PSYSTEM_MODULES ModuleInformation)
|
|||
return status;
|
||||
}
|
||||
|
||||
/* Allocate a pool equal to the output size of RtlQueryModuleInformation
|
||||
*/
|
||||
PRTL_MODULE_EXTENDED_INFO driver_information =
|
||||
ExAllocatePool2(POOL_FLAG_NON_PAGED, size, SYSTEM_MODULES_POOL);
|
||||
|
||||
|
@ -462,8 +447,6 @@ GetSystemModuleInformation(_Out_ PSYSTEM_MODULES ModuleInformation)
|
|||
return STATUS_MEMORY_NOT_ALLOCATED;
|
||||
}
|
||||
|
||||
/* Query the modules again this time passing a pointer to the allocated
|
||||
* buffer */
|
||||
status = RtlQueryModuleInformation(
|
||||
&size, sizeof(RTL_MODULE_EXTENDED_INFO), driver_information);
|
||||
|
||||
|
@ -481,16 +464,76 @@ GetSystemModuleInformation(_Out_ PSYSTEM_MODULES ModuleInformation)
|
|||
return status;
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
ValidateDriverObjects(_In_ PSYSTEM_MODULES SystemModules,
|
||||
_In_ POBJECT_DIRECTORY_ENTRY Entry,
|
||||
_Inout_ PINVALID_DRIVERS_HEAD Head,
|
||||
_In_ PVOID Whitelist)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (!Entry)
|
||||
return;
|
||||
|
||||
POBJECT_DIRECTORY_ENTRY sub_entry = Entry;
|
||||
|
||||
while (sub_entry) {
|
||||
BOOLEAN flag = FALSE;
|
||||
PDRIVER_OBJECT current_driver = sub_entry->Object;
|
||||
|
||||
status = ValidateDriverObjectHasBackingModule(
|
||||
SystemModules, current_driver, &flag);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"ValidateDriverObjectHasBackingModule failed with status %x",
|
||||
status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
status = AddDriverToList(
|
||||
Head, current_driver, REASON_NO_BACKING_MODULE);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
Head->count += 1;
|
||||
}
|
||||
|
||||
status = ValidateDriverIOCTLDispatchRegion(
|
||||
current_driver, SystemModules, Whitelist, &flag);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"ValidateDriverIOCTLDispatchRegion failed with status %x",
|
||||
status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
status = AddDriverToList(Head,
|
||||
current_driver,
|
||||
REASON_INVALID_IOCTL_DISPATCH);
|
||||
if (NT_SUCCESS(status))
|
||||
Head->count += 1;
|
||||
}
|
||||
|
||||
sub_entry = sub_entry->ChainLink;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: this function needs to be rewritten. Infact, this entire file needs to
|
||||
* be rewritten. */
|
||||
* be rewritten.
|
||||
* god this is so bad.
|
||||
*/
|
||||
STATIC
|
||||
NTSTATUS
|
||||
ValidateDriverObjects(_In_ PSYSTEM_MODULES SystemModules,
|
||||
_Inout_ PINVALID_DRIVERS_HEAD InvalidDriverListHead)
|
||||
ValidateDriverObjectsWrapper(_In_ PSYSTEM_MODULES SystemModules,
|
||||
_Inout_ PINVALID_DRIVERS_HEAD Head)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (!SystemModules || !InvalidDriverListHead)
|
||||
if (!SystemModules || !Head)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
HANDLE handle = NULL;
|
||||
|
@ -563,73 +606,8 @@ ValidateDriverObjects(_In_ PSYSTEM_MODULES SystemModules,
|
|||
for (INT index = 0; index < NUMBER_HASH_BUCKETS; index++) {
|
||||
POBJECT_DIRECTORY_ENTRY entry =
|
||||
directory_object->HashBuckets[index];
|
||||
|
||||
if (!entry)
|
||||
continue;
|
||||
|
||||
POBJECT_DIRECTORY_ENTRY sub_entry = entry;
|
||||
|
||||
while (sub_entry) {
|
||||
BOOLEAN flag = FALSE;
|
||||
PDRIVER_OBJECT current_driver = sub_entry->Object;
|
||||
|
||||
/* validate driver has backing module */
|
||||
|
||||
status = ValidateDriverObjectHasBackingModule(
|
||||
SystemModules, current_driver, &flag);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"ValidateDriverObjectHasBackingModule failed with status %x",
|
||||
status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
status =
|
||||
AddDriverToList(InvalidDriverListHead,
|
||||
current_driver,
|
||||
REASON_NO_BACKING_MODULE);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR(
|
||||
"AddDriverToList failed with status %x",
|
||||
status);
|
||||
else
|
||||
InvalidDriverListHead->count += 1;
|
||||
}
|
||||
|
||||
/* validate drivers IOCTL dispatch routines */
|
||||
|
||||
status = ValidateDriverIOCTLDispatchRegion(
|
||||
current_driver,
|
||||
SystemModules,
|
||||
whitelisted_regions_buffer,
|
||||
&flag);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"ValidateDriverIOCTLDispatchRegion failed with status %x",
|
||||
status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
status = AddDriverToList(
|
||||
InvalidDriverListHead,
|
||||
current_driver,
|
||||
REASON_INVALID_IOCTL_DISPATCH);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR(
|
||||
"AddDriverToList failed with status %x",
|
||||
status);
|
||||
else
|
||||
InvalidDriverListHead->count += 1;
|
||||
}
|
||||
|
||||
sub_entry = sub_entry->ChainLink;
|
||||
}
|
||||
ValidateDriverObjects(
|
||||
SystemModules, entry, Head, whitelisted_regions_buffer);
|
||||
}
|
||||
|
||||
end:
|
||||
|
@ -685,7 +663,7 @@ HandleValidateDriversIOCTL()
|
|||
|
||||
InitDriverList(head);
|
||||
|
||||
status = ValidateDriverObjects(&system_modules, head);
|
||||
status = ValidateDriverObjectsWrapper(&system_modules, head);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("ValidateDriverObjects failed with status %x",
|
||||
|
@ -698,67 +676,59 @@ HandleValidateDriversIOCTL()
|
|||
? MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT
|
||||
: head->count;
|
||||
|
||||
if (head->count > 0) {
|
||||
DEBUG_VERBOSE("System has an invalid driver count of: %i",
|
||||
head->count);
|
||||
|
||||
for (INT index = 0; index < head->count; index++) {
|
||||
/* make sure we free any non reported modules */
|
||||
if (index >=
|
||||
MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT) {
|
||||
RemoveInvalidDriverFromList(head);
|
||||
continue;
|
||||
}
|
||||
|
||||
PMODULE_VALIDATION_FAILURE report = ImpExAllocatePool2(
|
||||
POOL_FLAG_NON_PAGED,
|
||||
sizeof(MODULE_VALIDATION_FAILURE),
|
||||
POOL_TAG_INTEGRITY);
|
||||
|
||||
if (!report)
|
||||
continue;
|
||||
|
||||
report->report_code = REPORT_MODULE_VALIDATION_FAILURE;
|
||||
report->report_type = head->first_entry->reason;
|
||||
report->driver_base_address =
|
||||
head->first_entry->driver->DriverStart;
|
||||
report->driver_size =
|
||||
head->first_entry->driver->DriverSize;
|
||||
|
||||
ANSI_STRING string = {0};
|
||||
string.Length = 0;
|
||||
string.MaximumLength =
|
||||
MODULE_REPORT_DRIVER_NAME_BUFFER_SIZE;
|
||||
string.Buffer = &report->driver_name;
|
||||
|
||||
status = ImpRtlUnicodeStringToAnsiString(
|
||||
&string,
|
||||
&head->first_entry->driver->DriverName,
|
||||
FALSE);
|
||||
|
||||
/* still continue if we fail to get the driver name */
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR(
|
||||
"RtlUnicodeStringToAnsiString failed with status %x",
|
||||
status);
|
||||
|
||||
status = IrpQueueCompleteIrp(
|
||||
report, sizeof(MODULE_VALIDATION_FAILURE));
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"IrpQueueCompleteIrp failed with status %x",
|
||||
status);
|
||||
continue;
|
||||
}
|
||||
|
||||
RemoveInvalidDriverFromList(head);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (head->count == 0) {
|
||||
DEBUG_INFO("Found no invalid drivers on the system.");
|
||||
goto end;
|
||||
}
|
||||
|
||||
DEBUG_VERBOSE("System has an invalid driver count of: %i", head->count);
|
||||
|
||||
for (INT index = 0; index < head->count; index++) {
|
||||
/* make sure we free any non reported modules */
|
||||
if (index >= MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT) {
|
||||
RemoveInvalidDriverFromList(head);
|
||||
continue;
|
||||
}
|
||||
|
||||
PMODULE_VALIDATION_FAILURE report =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
sizeof(MODULE_VALIDATION_FAILURE),
|
||||
POOL_TAG_INTEGRITY);
|
||||
|
||||
if (!report)
|
||||
continue;
|
||||
|
||||
report->report_code = REPORT_MODULE_VALIDATION_FAILURE;
|
||||
report->report_type = head->first_entry->reason;
|
||||
report->driver_base_address =
|
||||
head->first_entry->driver->DriverStart;
|
||||
report->driver_size = head->first_entry->driver->DriverSize;
|
||||
|
||||
ANSI_STRING string = {0};
|
||||
string.Length = 0;
|
||||
string.MaximumLength = MODULE_REPORT_DRIVER_NAME_BUFFER_SIZE;
|
||||
string.Buffer = &report->driver_name;
|
||||
|
||||
status = ImpRtlUnicodeStringToAnsiString(
|
||||
&string, &head->first_entry->driver->DriverName, FALSE);
|
||||
|
||||
/* still continue if we fail to get the driver name */
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR(
|
||||
"RtlUnicodeStringToAnsiString failed with status %x",
|
||||
status);
|
||||
|
||||
status = IrpQueueCompleteIrp(report,
|
||||
sizeof(MODULE_VALIDATION_FAILURE));
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("IrpQueueCompleteIrp failed with status %x",
|
||||
status);
|
||||
continue;
|
||||
}
|
||||
|
||||
RemoveInvalidDriverFromList(head);
|
||||
}
|
||||
end:
|
||||
ImpExFreePoolWithTag(head, INVALID_DRIVER_LIST_HEAD_POOL);
|
||||
ImpExFreePoolWithTag(system_modules.address, SYSTEM_MODULES_POOL);
|
||||
|
@ -780,16 +750,13 @@ IsInstructionPointerInInvalidRegion(_In_ UINT64 RIP,
|
|||
if (!RIP || !SystemModules || !Result)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Note that this does not check for HAL or PatchGuard Execution */
|
||||
for (INT i = 0; i < SystemModules->module_count; i++) {
|
||||
PRTL_MODULE_EXTENDED_INFO system_module =
|
||||
(PRTL_MODULE_EXTENDED_INFO)((uintptr_t)
|
||||
SystemModules->address +
|
||||
i * sizeof(
|
||||
RTL_MODULE_EXTENDED_INFO));
|
||||
PRTL_MODULE_EXTENDED_INFO modules =
|
||||
(PRTL_MODULE_EXTENDED_INFO)SystemModules->address;
|
||||
|
||||
UINT64 base = (UINT64)system_module->ImageBase;
|
||||
UINT64 end = base + system_module->ImageSize;
|
||||
/* Note that this does not check for HAL or PatchGuard Execution */
|
||||
for (INT index = 0; index < SystemModules->module_count; index++) {
|
||||
UINT64 base = (UINT64)modules[index].ImageBase;
|
||||
UINT64 end = base + modules[index].ImageSize;
|
||||
|
||||
if (RIP >= base && RIP <= end) {
|
||||
*Result = TRUE;
|
||||
|
@ -806,11 +773,6 @@ IsInstructionPointerInsideModule(_In_ UINT64 Rip,
|
|||
_In_ PRTL_MODULE_EXTENDED_INFO Module,
|
||||
_Out_ PBOOLEAN Result)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (!Rip || !Module || !Result)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
UINT64 base = (UINT64)Module->ImageBase;
|
||||
UINT64 end = base + Module->ImageSize;
|
||||
|
||||
|
@ -823,6 +785,66 @@ IsInstructionPointerInsideModule(_In_ UINT64 Rip,
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
ReportNmiBlocking()
|
||||
{
|
||||
PNMI_CALLBACK_FAILURE report = ImpExAllocatePool2(
|
||||
POOL_FLAG_NON_PAGED, sizeof(NMI_CALLBACK_FAILURE), REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
report->report_code = REPORT_NMI_CALLBACK_FAILURE;
|
||||
report->kthread_address = NULL;
|
||||
report->invalid_rip = NULL;
|
||||
report->were_nmis_disabled = TRUE;
|
||||
|
||||
IrpQueueCompleteIrp(report, sizeof(NMI_CALLBACK_FAILURE));
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
ReportMissingCidTableEntry(_In_ PNMI_CONTEXT Context)
|
||||
{
|
||||
DEBUG_WARNING("Thread: %llx was not found in the pspcid table.",
|
||||
Context->kthread);
|
||||
|
||||
PHIDDEN_SYSTEM_THREAD_REPORT report =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
sizeof(HIDDEN_SYSTEM_THREAD_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
return;
|
||||
|
||||
report->report_code = REPORT_HIDDEN_SYSTEM_THREAD;
|
||||
report->found_in_kthreadlist = FALSE; // wip
|
||||
report->found_in_pspcidtable = FALSE;
|
||||
report->thread_id = ImpPsGetThreadId(Context->kthread);
|
||||
report->thread_address = Context->kthread;
|
||||
|
||||
RtlCopyMemory(report->thread, Context->kthread, sizeof(report->thread));
|
||||
IrpQueueCompleteIrp(report, sizeof(HIDDEN_SYSTEM_THREAD_REPORT));
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
ReportInvalidRipFoundDuringNmi(_In_ PNMI_CONTEXT Context)
|
||||
{
|
||||
PNMI_CALLBACK_FAILURE report =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
sizeof(HIDDEN_SYSTEM_THREAD_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
report->report_code = REPORT_NMI_CALLBACK_FAILURE;
|
||||
report->kthread_address = Context->kthread;
|
||||
report->invalid_rip = Context->interrupted_rip;
|
||||
report->were_nmis_disabled = FALSE;
|
||||
|
||||
IrpQueueCompleteIrp(report, sizeof(HIDDEN_SYSTEM_THREAD_REPORT));
|
||||
}
|
||||
|
||||
/*
|
||||
* todo: i think we should split this function up into each analysis i.e one for
|
||||
* the interrupted rip, one for the cid etc.
|
||||
|
@ -842,29 +864,7 @@ AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules)
|
|||
for (INT core = 0; core < ImpKeQueryActiveProcessorCount(0); core++) {
|
||||
/* Make sure our NMIs were run */
|
||||
if (!NmiContext[core].callback_count) {
|
||||
PNMI_CALLBACK_FAILURE report =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
sizeof(NMI_CALLBACK_FAILURE),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
report->report_code = REPORT_NMI_CALLBACK_FAILURE;
|
||||
report->kthread_address = NULL;
|
||||
report->invalid_rip = NULL;
|
||||
report->were_nmis_disabled = TRUE;
|
||||
|
||||
status = IrpQueueCompleteIrp(
|
||||
report, sizeof(NMI_CALLBACK_FAILURE));
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"IrpQueueCompleteIrp failed with status %x",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReportNmiBlocking();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -898,40 +898,7 @@ AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules)
|
|||
|
||||
if (!ValidateThreadsPspCidTableEntry(
|
||||
NmiContext[core].kthread)) {
|
||||
DEBUG_WARNING(
|
||||
"Thread: %llx was not found in the pspcid table.",
|
||||
NmiContext[core].kthread);
|
||||
|
||||
PHIDDEN_SYSTEM_THREAD_REPORT report =
|
||||
ImpExAllocatePool2(
|
||||
POOL_FLAG_NON_PAGED,
|
||||
sizeof(HIDDEN_SYSTEM_THREAD_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
continue;
|
||||
|
||||
report->report_code = REPORT_HIDDEN_SYSTEM_THREAD;
|
||||
report->found_in_kthreadlist = FALSE; // wip
|
||||
report->found_in_pspcidtable = FALSE;
|
||||
report->thread_id =
|
||||
ImpPsGetThreadId(NmiContext[core].kthread);
|
||||
report->thread_address = NmiContext[core].kthread;
|
||||
|
||||
RtlCopyMemory(report->thread,
|
||||
NmiContext[core].kthread,
|
||||
sizeof(report->thread));
|
||||
|
||||
if (!NT_SUCCESS(IrpQueueCompleteIrp(
|
||||
report, sizeof(HIDDEN_SYSTEM_THREAD_REPORT)))) {
|
||||
DEBUG_ERROR(
|
||||
"IrpQueueCompleteIrp failed with no status.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DEBUG_VERBOSE("Thread: %llx was found in PspCidTable",
|
||||
NmiContext[core].kthread);
|
||||
ReportMissingCidTableEntry(&NmiContext[core]);
|
||||
}
|
||||
|
||||
if (NmiContext[core].user_thread)
|
||||
|
@ -941,33 +908,11 @@ AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules)
|
|||
NmiContext[core].interrupted_rip, SystemModules, &flag);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"IsInstructionPointerInInvalidRegion failed with status %x",
|
||||
status);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
PNMI_CALLBACK_FAILURE report = ImpExAllocatePool2(
|
||||
POOL_FLAG_NON_PAGED,
|
||||
sizeof(HIDDEN_SYSTEM_THREAD_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
report->report_code = REPORT_NMI_CALLBACK_FAILURE;
|
||||
report->kthread_address = NmiContext[core].kthread;
|
||||
report->invalid_rip = NmiContext[core].interrupted_rip;
|
||||
report->were_nmis_disabled = FALSE;
|
||||
|
||||
status = IrpQueueCompleteIrp(
|
||||
report, sizeof(HIDDEN_SYSTEM_THREAD_REPORT));
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"IrpQueueCompleteIrp failed with status %x",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
ReportInvalidRipFoundDuringNmi(&NmiContext[core]);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -981,8 +926,8 @@ NmiCallback(_Inout_opt_ PVOID Context, _In_ BOOLEAN Handled)
|
|||
{
|
||||
UNREFERENCED_PARAMETER(Handled);
|
||||
|
||||
PNMI_CONTEXT nmi_context = (PNMI_CONTEXT)Context;
|
||||
ULONG proc_num = KeGetCurrentProcessorNumber();
|
||||
PNMI_CONTEXT context = (PNMI_CONTEXT)Context;
|
||||
ULONG core = KeGetCurrentProcessorNumber();
|
||||
UINT64 kpcr = 0;
|
||||
TASK_STATE_SEGMENT_64* tss = NULL;
|
||||
PMACHINE_FRAME machine_frame = NULL;
|
||||
|
@ -1004,16 +949,16 @@ NmiCallback(_Inout_opt_ PVOID Context, _In_ BOOLEAN Handled)
|
|||
machine_frame = tss->Ist3 - sizeof(MACHINE_FRAME);
|
||||
|
||||
if (machine_frame->rip <= WINDOWS_USERMODE_MAX_ADDRESS)
|
||||
nmi_context[proc_num].user_thread = TRUE;
|
||||
context[core].user_thread = TRUE;
|
||||
|
||||
nmi_context[proc_num].interrupted_rip = machine_frame->rip;
|
||||
nmi_context[proc_num].interrupted_rsp = machine_frame->rsp;
|
||||
nmi_context[proc_num].kthread = PsGetCurrentThread();
|
||||
nmi_context[proc_num].callback_count += 1;
|
||||
context[core].interrupted_rip = machine_frame->rip;
|
||||
context[core].interrupted_rsp = machine_frame->rsp;
|
||||
context[core].kthread = PsGetCurrentThread();
|
||||
context[core].callback_count++;
|
||||
|
||||
DEBUG_VERBOSE(
|
||||
"[NMI CALLBACK]: Core Number: %lx, Interrupted RIP: %llx, Interrupted RSP: %llx",
|
||||
proc_num,
|
||||
core,
|
||||
machine_frame->rip,
|
||||
machine_frame->rsp);
|
||||
|
||||
|
@ -1041,7 +986,6 @@ LaunchNonMaskableInterrupt()
|
|||
ImpKeInitializeAffinityEx(ProcAffinityPool);
|
||||
ImpKeAddProcessorAffinityEx(ProcAffinityPool, core);
|
||||
|
||||
DEBUG_VERBOSE("Sending NMI");
|
||||
HalSendNMI(ProcAffinityPool);
|
||||
|
||||
/*
|
||||
|
@ -1053,7 +997,6 @@ LaunchNonMaskableInterrupt()
|
|||
}
|
||||
|
||||
ImpExFreePoolWithTag(ProcAffinityPool, PROC_AFFINITY_POOL);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1067,6 +1010,8 @@ HandleNmiIOCTL()
|
|||
SYSTEM_MODULES system_modules = {0};
|
||||
PNMI_CONTEXT nmi_context = NULL;
|
||||
|
||||
UINT32 size = ImpKeQueryActiveProcessorCount(0) * sizeof(NMI_CONTEXT);
|
||||
|
||||
if (IsNmiInProgress())
|
||||
return STATUS_ALREADY_COMMITTED;
|
||||
|
||||
|
@ -1077,10 +1022,8 @@ HandleNmiIOCTL()
|
|||
DEBUG_ERROR("ValidateHalDispatchTables failed with status %x",
|
||||
status);
|
||||
|
||||
nmi_context = ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
ImpKeQueryActiveProcessorCount(0) *
|
||||
sizeof(NMI_CONTEXT),
|
||||
NMI_CONTEXT_POOL);
|
||||
nmi_context =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, size, NMI_CONTEXT_POOL);
|
||||
|
||||
if (!nmi_context) {
|
||||
UnsetNmiInProgressFlag();
|
||||
|
@ -1135,7 +1078,6 @@ HandleNmiIOCTL()
|
|||
ImpExFreePoolWithTag(system_modules.address, SYSTEM_MODULES_POOL);
|
||||
ImpExFreePoolWithTag(nmi_context, NMI_CONTEXT_POOL);
|
||||
ImpKeDeregisterNmiCallback(callback_handle);
|
||||
|
||||
UnsetNmiInProgressFlag();
|
||||
return status;
|
||||
}
|
||||
|
@ -1149,10 +1091,26 @@ VOID
|
|||
ApcRundownRoutine(_In_ PRKAPC Apc)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FreeApcAndDecrementApcCount(Apc, APC_CONTEXT_ID_STACKWALK);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
ReportApcStackwalkViolation(_In_ UINT64 Rip)
|
||||
{
|
||||
PAPC_STACKWALK_REPORT report = ImpExAllocatePool2(
|
||||
POOL_FLAG_NON_PAGED, sizeof(APC_STACKWALK_REPORT), REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
return;
|
||||
|
||||
report->report_code = REPORT_APC_STACKWALK;
|
||||
report->kthread_address = (UINT64)KeGetCurrentThread();
|
||||
report->invalid_rip = Rip;
|
||||
|
||||
IrpQueueCompleteIrp(report, sizeof(APC_STACKWALK_REPORT));
|
||||
}
|
||||
|
||||
/*
|
||||
* The KernelRoutine is executed in kernel mode at APC_LEVEL before the APC is
|
||||
* delivered. This is also where we want to free our APC object.
|
||||
|
@ -1170,7 +1128,7 @@ ApcKernelRoutine(_In_ PRKAPC Apc,
|
|||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
PVOID buffer = NULL;
|
||||
INT frames_captured = 0;
|
||||
UINT64 stack_frame = 0;
|
||||
PUINT64 frames = 0;
|
||||
BOOLEAN flag = FALSE;
|
||||
PAPC_STACKWALK_CONTEXT context = NULL;
|
||||
PTHREAD_LIST_ENTRY thread_list_entry = NULL;
|
||||
|
@ -1196,8 +1154,7 @@ ApcKernelRoutine(_In_ PRKAPC Apc,
|
|||
goto free;
|
||||
|
||||
for (INT index = 0; index < frames_captured; index++) {
|
||||
stack_frame =
|
||||
*(UINT64*)((UINT64)buffer + index * sizeof(UINT64));
|
||||
frames = (PUINT64)buffer;
|
||||
|
||||
/*
|
||||
* Apc->NormalContext holds the address of our context data
|
||||
|
@ -1205,35 +1162,14 @@ ApcKernelRoutine(_In_ PRKAPC Apc,
|
|||
* argument.
|
||||
*/
|
||||
status = IsInstructionPointerInInvalidRegion(
|
||||
stack_frame, context->modules, &flag);
|
||||
frames[index], context->modules, &flag);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"IsInstructionPointerInInvalidRegion failed with status %x",
|
||||
status);
|
||||
goto free;
|
||||
}
|
||||
|
||||
if (flag == FALSE) {
|
||||
PAPC_STACKWALK_REPORT report =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
sizeof(APC_STACKWALK_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
goto free;
|
||||
|
||||
report->report_code = REPORT_APC_STACKWALK;
|
||||
report->kthread_address = (UINT64)KeGetCurrentThread();
|
||||
report->invalid_rip = stack_frame;
|
||||
|
||||
if (!NT_SUCCESS(IrpQueueCompleteIrp(
|
||||
report, sizeof(APC_STACKWALK_REPORT)))) {
|
||||
DEBUG_ERROR(
|
||||
"IrpQueueCompleteIrp failed with no status.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!flag)
|
||||
ReportApcStackwalkViolation(frames[index]);
|
||||
}
|
||||
|
||||
free:
|
||||
|
@ -1410,7 +1346,6 @@ FreeApcStackwalkApcContextInformation(_Inout_ PAPC_STACKWALK_CONTEXT Context)
|
|||
if (Context->modules->address)
|
||||
ImpExFreePoolWithTag(Context->modules->address,
|
||||
SYSTEM_MODULES_POOL);
|
||||
|
||||
if (Context->modules)
|
||||
ImpExFreePoolWithTag(Context->modules, POOL_TAG_APC);
|
||||
}
|
||||
|
@ -1464,59 +1399,59 @@ CheckForDpcCompletion(_In_ PDPC_CONTEXT Context)
|
|||
}
|
||||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
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);
|
||||
|
||||
if (!report)
|
||||
return;
|
||||
|
||||
report->report_code = REPORT_DPC_STACKWALK;
|
||||
report->kthread_address = PsGetCurrentThread();
|
||||
report->invalid_rip = Frame;
|
||||
|
||||
// RtlCopyMemory(report->driver,
|
||||
// (UINT64)Context[core].stack_frame[frame]
|
||||
// - 0x50,
|
||||
// APC_STACKWALK_BUFFER_SIZE);
|
||||
|
||||
IrpQueueCompleteIrp(report, sizeof(DPC_STACKWALK_REPORT));
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
ValidateDpcStackFrame(_In_ PDPC_CONTEXT Context, _In_ PSYSTEM_MODULES Modules)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
BOOLEAN flag = FALSE;
|
||||
|
||||
for (UINT32 frame = 0; frame < Context->frames_captured; frame++) {
|
||||
UINT64 rip = Context->stack_frame[frame];
|
||||
status =
|
||||
IsInstructionPointerInInvalidRegion(rip, Modules, &flag);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return;
|
||||
|
||||
if (!flag)
|
||||
ReportDpcStackwalkViolation(Context, rip);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
ValidateDpcCapturedStack(_In_ PSYSTEM_MODULES Modules,
|
||||
_In_ PDPC_CONTEXT Context)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
BOOLEAN flag = FALSE;
|
||||
PDPC_STACKWALK_REPORT report = NULL;
|
||||
UINT32 count = ImpKeQueryActiveProcessorCount(0);
|
||||
|
||||
for (UINT32 core = 0; core < ImpKeQueryActiveProcessorCount(0);
|
||||
core++) {
|
||||
for (UINT32 frame = 0; frame < Context[core].frames_captured;
|
||||
frame++) {
|
||||
status = IsInstructionPointerInInvalidRegion(
|
||||
Context[core].stack_frame[frame], Modules, &flag);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR(
|
||||
"IsInstructionPointerInInvalidRegion failed with status %x",
|
||||
status);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
report = ImpExAllocatePool2(
|
||||
POOL_FLAG_NON_PAGED,
|
||||
sizeof(DPC_STACKWALK_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
continue;
|
||||
|
||||
report->report_code = REPORT_DPC_STACKWALK;
|
||||
report->kthread_address = PsGetCurrentThread();
|
||||
report->invalid_rip =
|
||||
Context[core].stack_frame[frame];
|
||||
|
||||
// RtlCopyMemory(report->driver,
|
||||
// (UINT64)Context[core].stack_frame[frame]
|
||||
// - 0x50,
|
||||
// APC_STACKWALK_BUFFER_SIZE);
|
||||
|
||||
if (!NT_SUCCESS(IrpQueueCompleteIrp(
|
||||
report,
|
||||
sizeof(DPC_STACKWALK_REPORT)))) {
|
||||
DEBUG_ERROR(
|
||||
"IrpQueueCompleteIrp failed with no status.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (UINT32 core = 0; core < count; core++) {
|
||||
ValidateDpcStackFrame(&Context[core], Modules);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1557,13 +1492,7 @@ DispatchStackwalkToEachCpuViaDpc()
|
|||
while (!CheckForDpcCompletion(context))
|
||||
YieldProcessor();
|
||||
|
||||
status = ValidateDpcCapturedStack(&modules, context);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DEBUG_ERROR("ValidateDpcCapturedStack failed with status %x",
|
||||
status);
|
||||
goto end;
|
||||
}
|
||||
ValidateDpcCapturedStack(&modules, context);
|
||||
|
||||
DEBUG_VERBOSE("Finished validating cores via dpc");
|
||||
end:
|
||||
|
|
|
@ -116,6 +116,7 @@ SessionInitialise(_In_ PIRP Irp)
|
|||
session->process = process;
|
||||
session->is_session_active = TRUE;
|
||||
session->session_cookie = information->session_cookie;
|
||||
|
||||
RtlCopyMemory(session->session_aes_key,
|
||||
information->session_aes_key,
|
||||
AES_128_KEY_SIZE);
|
||||
|
|
|
@ -98,29 +98,29 @@ DetectAttachedThreadsProcessCallback(_In_ PTHREAD_LIST_ENTRY ThreadListEntry,
|
|||
* todo: this is filterless and will just report anything, need to have
|
||||
* a look into what processes actually attach to real games
|
||||
*/
|
||||
if (apc_state->Process == protected_process &&
|
||||
ThreadListEntry->owning_process != protected_process) {
|
||||
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);
|
||||
|
||||
if (!report)
|
||||
return;
|
||||
|
||||
report->report_code = REPORT_ILLEGAL_ATTACH_PROCESS;
|
||||
report->thread_id = ImpPsGetThreadId(ThreadListEntry->thread);
|
||||
report->thread_address = ThreadListEntry->thread;
|
||||
|
||||
if (!NT_SUCCESS(IrpQueueCompleteIrp(
|
||||
report, sizeof(ATTACH_PROCESS_REPORT))))
|
||||
DEBUG_ERROR(
|
||||
"IrpQueueCompleteIrp failed with no status.");
|
||||
if (!(apc_state->Process == protected_process &&
|
||||
ThreadListEntry->owning_process != protected_process)) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!report)
|
||||
return;
|
||||
|
||||
report->report_code = REPORT_ILLEGAL_ATTACH_PROCESS;
|
||||
report->thread_id = ImpPsGetThreadId(ThreadListEntry->thread);
|
||||
report->thread_address = ThreadListEntry->thread;
|
||||
|
||||
if (!NT_SUCCESS(
|
||||
IrpQueueCompleteIrp(report, sizeof(ATTACH_PROCESS_REPORT))))
|
||||
DEBUG_ERROR("IrpQueueCompleteIrp failed with no status.");
|
||||
}
|
||||
|
||||
VOID
|
||||
|
|
Loading…
Reference in a new issue