mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
simple exception hooking detection
This commit is contained in:
parent
08b059bee9
commit
0b729a6fa0
4 changed files with 63 additions and 20 deletions
|
@ -9,6 +9,8 @@ open source anti cheat (lol) which I made for fun.
|
|||
- NMI stackwalking via isr iretq
|
||||
- APC stackwalking via RtlCaptureStackBackTrace
|
||||
- DPC stackwalking via RtlCaptureStackBackTrace
|
||||
- Return address exception hooking detection
|
||||
- Chained .data pointer detection (iffy)
|
||||
- Handle stripping via obj callbacks
|
||||
- Process handle table enumeration
|
||||
- System module device object verification
|
||||
|
@ -27,7 +29,7 @@ open source anti cheat (lol) which I made for fun.
|
|||
|
||||
# architecuture
|
||||
|
||||
For an overview of the architecture, see architecture.md.
|
||||
- todo!
|
||||
|
||||
# planned features
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ IrpQueueAllocateDeferredPacket(_In_ PVOID Buffer, _In_ UINT32 BufferSize)
|
|||
return report;
|
||||
}
|
||||
|
||||
#define MAX_DEFERRED_REPORTS_COUNT 100
|
||||
#define MAX_DEFERRED_REPORTS_COUNT 256
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
|
|
|
@ -497,6 +497,14 @@ end:
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
STATIC
|
||||
BOOLEAN
|
||||
IsUserModeAddress(_In_ UINT64 Rip)
|
||||
{
|
||||
return Rip <= WINDOWS_USERMODE_MAX_ADDRESS ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HandleValidateDriversIOCTL()
|
||||
{
|
||||
|
@ -638,7 +646,8 @@ ReportMissingCidTableEntry(_In_ PNMI_CONTEXT Context)
|
|||
|
||||
STATIC
|
||||
VOID
|
||||
ReportInvalidRipFoundDuringNmi(_In_ PNMI_CONTEXT Context)
|
||||
ReportInvalidRipFoundDuringNmi(_In_ PNMI_CONTEXT Context,
|
||||
_In_ UINT32 ReportSubCode)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
UINT32 packet_size =
|
||||
|
@ -650,7 +659,7 @@ ReportInvalidRipFoundDuringNmi(_In_ PNMI_CONTEXT Context)
|
|||
if (!report)
|
||||
return;
|
||||
|
||||
INIT_REPORT_PACKET(report, REPORT_NMI_CALLBACK_FAILURE, 0);
|
||||
INIT_REPORT_PACKET(report, REPORT_NMI_CALLBACK_FAILURE, ReportSubCode);
|
||||
|
||||
report->kthread_address = Context->kthread;
|
||||
report->invalid_rip = Context->interrupted_rip;
|
||||
|
@ -667,6 +676,34 @@ ReportInvalidRipFoundDuringNmi(_In_ PNMI_CONTEXT Context)
|
|||
IrpQueueSchedulePacket(report, packet_size);
|
||||
}
|
||||
|
||||
#define INSTRUCTION_UD2_BYTE_1 0x0F
|
||||
#define INSTRUCTION_UD2_BYTE_2 0x0B
|
||||
#define INSTRUCTION_INT3_BYTE_1 0xCC
|
||||
|
||||
STATIC
|
||||
BOOLEAN
|
||||
DoesRetInstructionCauseException(_In_ UINT64 ReturnAddress)
|
||||
{
|
||||
/* UD2 instruction is 2 bytes*/
|
||||
UCHAR opcodes[2] = {0};
|
||||
|
||||
/* we deal with um later */
|
||||
if (IsUserModeAddress(ReturnAddress))
|
||||
return FALSE;
|
||||
|
||||
RtlCopyMemory(&opcodes, ReturnAddress, sizeof(opcodes));
|
||||
|
||||
if (opcodes[0] == INSTRUCTION_UD2_BYTE_1 &&
|
||||
opcodes[1] == INSTRUCTION_UD2_BYTE_2)
|
||||
return TRUE;
|
||||
|
||||
if (opcodes[0] == INSTRUCTION_INT3_BYTE_1)
|
||||
return TRUE;
|
||||
|
||||
DEBUG_VERBOSE("Ret address instruction doesnt throw exception");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* todo: i think we should split this function up into each analysis i.e one for
|
||||
* the interrupted rip, one for the cid etc.
|
||||
|
@ -718,16 +755,19 @@ AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules)
|
|||
* PsGetNextProcess ?
|
||||
*/
|
||||
|
||||
if (!DoesThreadHaveValidCidEntry(NmiContext[core].kthread)) {
|
||||
if (!DoesThreadHaveValidCidEntry(NmiContext[core].kthread))
|
||||
ReportMissingCidTableEntry(&NmiContext[core]);
|
||||
}
|
||||
|
||||
if (NmiContext[core].user_thread)
|
||||
continue;
|
||||
|
||||
if (DoesRetInstructionCauseException(NmiContext[core].interrupted_rip))
|
||||
ReportInvalidRipFoundDuringNmi(
|
||||
&NmiContext[core], REPORT_SUBTYPE_EXCEPTION_THROWING_RET);
|
||||
|
||||
if (IsInstructionPointerInInvalidRegion(
|
||||
NmiContext[core].interrupted_rip, SystemModules))
|
||||
ReportInvalidRipFoundDuringNmi(&NmiContext[core]);
|
||||
ReportInvalidRipFoundDuringNmi(&NmiContext[core], 0);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -749,14 +789,6 @@ GetIsrMachineFrame(_In_ TASK_STATE_SEGMENT_64* TaskStateSegment)
|
|||
return TaskStateSegment->Ist3 - sizeof(MACHINE_FRAME);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
STATIC
|
||||
BOOLEAN
|
||||
IsUserModeAddress(_In_ UINT64 Rip)
|
||||
{
|
||||
return Rip <= WINDOWS_USERMODE_MAX_ADDRESS ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
STATIC BOOLEAN
|
||||
NmiCallback(_Inout_opt_ PVOID Context, _In_ BOOLEAN Handled)
|
||||
{
|
||||
|
@ -1266,7 +1298,9 @@ CheckForDpcCompletion(_In_ PDPC_CONTEXT Context)
|
|||
|
||||
STATIC
|
||||
VOID
|
||||
ReportDpcStackwalkViolation(_In_ PDPC_CONTEXT Context, _In_ UINT64 Frame)
|
||||
ReportDpcStackwalkViolation(_In_ PDPC_CONTEXT Context,
|
||||
_In_ UINT64 Frame,
|
||||
_In_ UINT32 ReportSubtype)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
UINT32 packet_size =
|
||||
|
@ -1278,7 +1312,7 @@ ReportDpcStackwalkViolation(_In_ PDPC_CONTEXT Context, _In_ UINT64 Frame)
|
|||
if (!report)
|
||||
return;
|
||||
|
||||
INIT_REPORT_PACKET(report, REPORT_DPC_STACKWALK, 0);
|
||||
INIT_REPORT_PACKET(report, REPORT_DPC_STACKWALK, ReportSubtype);
|
||||
|
||||
report->kthread_address = PsGetCurrentThread();
|
||||
report->invalid_rip = Frame;
|
||||
|
@ -1306,11 +1340,17 @@ ValidateDpcStackFrame(_In_ PDPC_CONTEXT Context, _In_ PSYSTEM_MODULES Modules)
|
|||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
BOOLEAN flag = FALSE;
|
||||
|
||||
/* With regards to this, lets only check the interrupted rip */
|
||||
if (DoesRetInstructionCauseException(Context->stack_frame[0]))
|
||||
ReportDpcStackwalkViolation(Context,
|
||||
Context->stack_frame[0],
|
||||
REPORT_SUBTYPE_EXCEPTION_THROWING_RET);
|
||||
|
||||
for (UINT32 frame = 0; frame < Context->frames_captured; frame++) {
|
||||
UINT64 rip = Context->stack_frame[frame];
|
||||
|
||||
if (IsInstructionPointerInInvalidRegion(rip, Modules))
|
||||
ReportDpcStackwalkViolation(Context, rip);
|
||||
ReportDpcStackwalkViolation(Context, rip, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
#define REPORT_SELF_DRIVER_PATCHED 160
|
||||
#define REPORT_BLACKLISTED_PCIE_DEVICE 170
|
||||
|
||||
#define REPORT_SUBTYPE_NO_BACKING_MODULE 0x0
|
||||
#define REPORT_SUBTYPE_INVALID_DISPATCH 0x1
|
||||
#define REPORT_SUBTYPE_NO_BACKING_MODULE 0x0
|
||||
#define REPORT_SUBTYPE_INVALID_DISPATCH 0x1
|
||||
#define REPORT_SUBTYPE_EXCEPTION_THROWING_RET 0x2
|
||||
|
||||
#define PACKET_TYPE_REPORT 0x0
|
||||
#define PACKET_TYPE_HEARTBEAT 0x1
|
||||
|
|
Loading…
Reference in a new issue