This commit is contained in:
lhodges1 2023-09-02 23:47:15 +10:00
parent 5e8eeb4bf0
commit af45bc923f
30 changed files with 902 additions and 955 deletions

View file

@ -6,7 +6,7 @@
#include "pool.h"
#include "thread.h"
CALLBACK_CONFIGURATION configuration;
CALLBACK_CONFIGURATION configuration = { 0 };
VOID ObPostOpCallbackRoutine(
_In_ PVOID RegistrationContext,

View file

@ -6,13 +6,8 @@
#include <wdf.h>
#include "common.h"
#define REPORT_ILLEGAL_HANDLE_OPERATION 70
#define HANDLE_REPORT_PROCESS_NAME_MAX_LENGTH 64
VOID UnregisterCallbacksOnProcessTermination();
typedef struct _OPEN_HANDLE_FAILURE_REPORT
{
INT report_code;
@ -90,4 +85,6 @@ NTSTATUS InitiateDriverCallbacks();
VOID UnregisterCallbacksOnProcessTermination();
VOID UnregisterCallbacksOnProcessTermination();
#endif

View file

@ -3,7 +3,6 @@
#include <ntifs.h>
#include <wdftypes.h>
#include <wdf.h>
#define DEBUG_LOG(fmt, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[+] " fmt "\n", ##__VA_ARGS__)
#define DEBUG_ERROR(fmt, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "[-] " fmt "\n", ##__VA_ARGS__)
@ -16,6 +15,16 @@
#define THREAD_DATA_POOL 'doof'
#define PROC_AFFINITY_POOL 'eeee'
#define TEMP_BUFFER_POOL 'ffff'
#define DRIVER_PATH_POOL_TAG 'path'
#define POOL_TAG_INTEGRITY 'intg'
#define POOL_DUMP_BLOCK_TAG 'dump'
#define POOL_DEBUGGER_DATA_TAG 'data'
#define PROCESS_ADDRESS_LIST_TAG 'addr'
#define ANALYSE_PROCESS_TAG 'anls'
#define INVALID_PROCESS_REPORT_TAG 'invd'
#define QUEUE_POOL_TAG 'qqqq'
#define REPORT_QUEUE_TEMP_BUFFER_TAG 'temp'
#define REPORT_POOL_TAG 'repo'
#define ERROR -1
#define STACK_FRAME_POOL_SIZE 0x200
@ -23,8 +32,49 @@
#define KTHREAD_STACK_BASE_OFFSET 0x030
#define KTHREAD_STACK_LIMIT_OFFSET 0x038
#define KTHREAD_THREADLIST_OFFSET 0x2f8
#define KTHREAD_APC_STATE_OFFSET 0x258
#define KTHREAD_START_ADDRESS_OFFSET 0x450
#define EPROCESS_VIRTUAL_SIZE_OFFSET 0x498
#define EPROCESS_IMAGE_NAME_OFFSET 0x5a8
#define KPROCESS_THREADLIST_OFFSET 0x030
#define KPCRB_CURRENT_THREAD 0x8
#define IA32_GS_BASE 0xc0000101
#define KPRCB_OFFSET_FROM_GS_BASE 0x180
#define MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT 20
#define REPORT_NMI_CALLBACK_FAILURE 50
#define REPORT_MODULE_VALIDATION_FAILURE 60
#define REPORT_ILLEGAL_HANDLE_OPERATION 70
#define REPORT_INVALID_PROCESS_ALLOCATION 80
#define REPORT_HIDDEN_SYSTEM_THREAD 90
#define REPORT_ILLEGAL_ATTACH_PROCESS 100
/*
* Generic macros that allow you to quickly determine whether
* or not a page table entry is present or may forward to a
* large page of data, rather than another page table (applies
* only to PDPTEs and PDEs)
*
* Some nice macros courtesy of:
* https://www.unknowncheats.me/forum/general-programming-and-reversing/523359-introduction-physical-memory.html
*/
#define IS_LARGE_PAGE(x) ( (BOOLEAN)((x >> 7) & 1) )
#define IS_PAGE_PRESENT(x) ( (BOOLEAN)(x & 1) )
#define PAGE_1GB_SHIFT 30
#define PAGE_1GB_OFFSET(x) ( x & (~(MAXUINT64 << PAGE_1GB_SHIFT)) )
#define PAGE_2MB_SHIFT 21
#define PAGE_2MB_OFFSET(x) ( x & (~(MAXUINT64 << PAGE_2MB_SHIFT)) )
#define PAGE_4KB_SHIFT 12
#define PAGE_4KB_OFFSET(x) ( x & (~(MAXUINT64 << PAGE_4KB_SHIFT)) )
typedef struct _KAFFINITY_EX
{
USHORT Count;
@ -72,27 +122,6 @@ typedef struct _RTL_MODULE_EXTENDED_INFO
} RTL_MODULE_EXTENDED_INFO, * PRTL_MODULE_EXTENDED_INFO;
/* undocumented functions */
EXTERN_C VOID KeInitializeAffinityEx(
PKAFFINITY_EX affinity
);
EXTERN_C VOID KeAddProcessorAffinityEx(
PKAFFINITY_EX affinity,
INT num
);
EXTERN_C VOID HalSendNMI(
PKAFFINITY_EX affinity
);
NTSTATUS
RtlQueryModuleInformation(
ULONG* InformationLength,
ULONG SizePerModule,
PVOID InformationBuffer );
/*
Thread Information Block: (GS register)
@ -116,11 +145,6 @@ Thread Information Block: (GS register)
...
*/
#pragma once
#include <ntifs.h>
#include <wdftypes.h>
typedef struct _OBJECT_TYPE
{
LIST_ENTRY TypeList;
@ -326,8 +350,6 @@ typedef struct _HANDLE_TRACE_DB_ENTRY
} HANDLE_TRACE_DB_ENTRY, * PHANDLE_TRACE_DB_ENTRY;
typedef struct _HANDLE_TRACE_DEBUG_INFO
{
LONG RefCount;
@ -427,6 +449,494 @@ typedef struct _OBJECT_HEADER
QUAD Body;
} OBJECT_HEADER, * POBJECT_HEADER;
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER {
unsigned char Name[ IMAGE_SIZEOF_SHORT_NAME ];
union {
unsigned long PhysicalAddress;
unsigned long VirtualSize;
} Misc;
unsigned long VirtualAddress;
unsigned long SizeOfRawData;
unsigned long PointerToRawData;
unsigned long PointerToRelocations;
unsigned long PointerToLinenumbers;
unsigned short NumberOfRelocations;
unsigned short NumberOfLinenumbers;
unsigned long Characteristics;
} IMAGE_SECTION_HEADER, * PIMAGE_SECTION_HEADER;
typedef struct _IMAGE_FILE_HEADER {
unsigned short Machine;
unsigned short NumberOfSections;
unsigned long TimeDateStamp;
unsigned long PointerToSymbolTable;
unsigned long NumberOfSymbols;
unsigned short SizeOfOptionalHeader;
unsigned short Characteristics;
} IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER;
typedef struct _IMAGE_DATA_DIRECTORY {
unsigned long VirtualAddress;
unsigned long Size;
} IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY;
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
typedef struct _IMAGE_OPTIONAL_HEADER64 {
unsigned short Magic;
unsigned char MajorLinkerVersion;
unsigned char MinorLinkerVersion;
unsigned long SizeOfCode;
unsigned long SizeOfInitializedData;
unsigned long SizeOfUninitializedData;
unsigned long AddressOfEntryPoint;
unsigned long BaseOfCode;
ULONGLONG ImageBase;
unsigned long SectionAlignment;
unsigned long FileAlignment;
unsigned short MajorOperatingSystemVersion;
unsigned short MinorOperatingSystemVersion;
unsigned short MajorImageVersion;
unsigned short MinorImageVersion;
unsigned short MajorSubsystemVersion;
unsigned short MinorSubsystemVersion;
unsigned long Win32VersionValue;
unsigned long SizeOfImage;
unsigned long SizeOfHeaders;
unsigned long CheckSum;
unsigned short Subsystem;
unsigned short DllCharacteristics;
ULONGLONG SizeOfStackReserve;
ULONGLONG SizeOfStackCommit;
ULONGLONG SizeOfHeapReserve;
ULONGLONG SizeOfHeapCommit;
unsigned long LoaderFlags;
unsigned long NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[ IMAGE_NUMBEROF_DIRECTORY_ENTRIES ];
} IMAGE_OPTIONAL_HEADER64, * PIMAGE_OPTIONAL_HEADER64;
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
unsigned short e_magic; // Magic number
unsigned short e_cblp; // Bytes on last page of file
unsigned short e_cp; // Pages in file
unsigned short e_crlc; // Relocations
unsigned short e_cparhdr; // Size of header in paragraphs
unsigned short e_minalloc; // Minimum extra paragraphs needed
unsigned short e_maxalloc; // Maximum extra paragraphs needed
unsigned short e_ss; // Initial (relative) SS value
unsigned short e_sp; // Initial SP value
unsigned short e_csum; // Checksum
unsigned short e_ip; // Initial IP value
unsigned short e_cs; // Initial (relative) CS value
unsigned short e_lfarlc; // File address of relocation table
unsigned short e_ovno; // Overlay number
unsigned short e_res[ 4 ]; // Reserved words
unsigned short e_oemid; // OEM identifier (for e_oeminfo)
unsigned short e_oeminfo; // OEM information; e_oemid specific
unsigned short e_res2[ 10 ]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER;
typedef struct _LOCAL_NT_HEADER {
unsigned long Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} LOCAL_NT_HEADER, * PLOCAL_NT_HEADER;
#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \
((ULONG_PTR)(ntheader) + \
FIELD_OFFSET( LOCAL_NT_HEADER, OptionalHeader ) + \
((ntheader))->FileHeader.SizeOfOptionalHeader \
))
/* creds: https://www.unknowncheats.me/forum/2602838-post2.html */
typedef struct _DBGKD_DEBUG_DATA_HEADER64
{
LIST_ENTRY64 List;
ULONG OwnerTag;
ULONG Size;
} DBGKD_DEBUG_DATA_HEADER64, * PDBGKD_DEBUG_DATA_HEADER64;
typedef struct _KDDEBUGGER_DATA64
{
DBGKD_DEBUG_DATA_HEADER64 Header;
ULONG64 KernBase;
ULONG64 BreakpointWithStatus;
ULONG64 SavedContext;
USHORT ThCallbackStack;
USHORT NextCallback;
USHORT FramePointer;
USHORT PaeEnabled;
ULONG64 KiCallUserMode;
ULONG64 KeUserCallbackDispatcher;
ULONG64 PsLoadedModuleList;
ULONG64 PsActiveProcessHead;
ULONG64 PspCidTable;
ULONG64 ExpSystemResourcesList;
ULONG64 ExpPagedPoolDescriptor;
ULONG64 ExpNumberOfPagedPools;
ULONG64 KeTimeIncrement;
ULONG64 KeBugCheckCallbackListHead;
ULONG64 KiBugcheckData;
ULONG64 IopErrorLogListHead;
ULONG64 ObpRootDirectoryObject;
ULONG64 ObpTypeObjectType;
ULONG64 MmSystemCacheStart;
ULONG64 MmSystemCacheEnd;
ULONG64 MmSystemCacheWs;
ULONG64 MmPfnDatabase;
ULONG64 MmSystemPtesStart;
ULONG64 MmSystemPtesEnd;
ULONG64 MmSubsectionBase;
ULONG64 MmNumberOfPagingFiles;
ULONG64 MmLowestPhysicalPage;
ULONG64 MmHighestPhysicalPage;
ULONG64 MmNumberOfPhysicalPages;
ULONG64 MmMaximumNonPagedPoolInBytes;
ULONG64 MmNonPagedSystemStart;
ULONG64 MmNonPagedPoolStart;
ULONG64 MmNonPagedPoolEnd;
ULONG64 MmPagedPoolStart;
ULONG64 MmPagedPoolEnd;
ULONG64 MmPagedPoolInformation;
ULONG64 MmPageSize;
ULONG64 MmSizeOfPagedPoolInBytes;
ULONG64 MmTotalCommitLimit;
ULONG64 MmTotalCommittedPages;
ULONG64 MmSharedCommit;
ULONG64 MmDriverCommit;
ULONG64 MmProcessCommit;
ULONG64 MmPagedPoolCommit;
ULONG64 MmExtendedCommit;
ULONG64 MmZeroedPageListHead;
ULONG64 MmFreePageListHead;
ULONG64 MmStandbyPageListHead;
ULONG64 MmModifiedPageListHead;
ULONG64 MmModifiedNoWritePageListHead;
ULONG64 MmAvailablePages;
ULONG64 MmResidentAvailablePages;
ULONG64 PoolTrackTable;
ULONG64 NonPagedPoolDescriptor;
ULONG64 MmHighestUserAddress;
ULONG64 MmSystemRangeStart;
ULONG64 MmUserProbeAddress;
ULONG64 KdPrintCircularBuffer;
ULONG64 KdPrintCircularBufferEnd;
ULONG64 KdPrintWritePointer;
ULONG64 KdPrintRolloverCount;
ULONG64 MmLoadedUserImageList;
ULONG64 NtBuildLab;
ULONG64 KiNormalSystemCall;
ULONG64 KiProcessorBlock;
ULONG64 MmUnloadedDrivers;
ULONG64 MmLastUnloadedDriver;
ULONG64 MmTriageActionTaken;
ULONG64 MmSpecialPoolTag;
ULONG64 KernelVerifier;
ULONG64 MmVerifierData;
ULONG64 MmAllocatedNonPagedPool;
ULONG64 MmPeakCommitment;
ULONG64 MmTotalCommitLimitMaximum;
ULONG64 CmNtCSDVersion;
ULONG64 MmPhysicalMemoryBlock;
ULONG64 MmSessionBase;
ULONG64 MmSessionSize;
ULONG64 MmSystemParentTablePage;
ULONG64 MmVirtualTranslationBase;
USHORT OffsetKThreadNextProcessor;
USHORT OffsetKThreadTeb;
USHORT OffsetKThreadKernelStack;
USHORT OffsetKThreadInitialStack;
USHORT OffsetKThreadApcProcess;
USHORT OffsetKThreadState;
USHORT OffsetKThreadBStore;
USHORT OffsetKThreadBStoreLimit;
USHORT SizeEProcess;
USHORT OffsetEprocessPeb;
USHORT OffsetEprocessParentCID;
USHORT OffsetEprocessDirectoryTableBase;
USHORT SizePrcb;
USHORT OffsetPrcbDpcRoutine;
USHORT OffsetPrcbCurrentThread;
USHORT OffsetPrcbMhz;
USHORT OffsetPrcbCpuType;
USHORT OffsetPrcbVendorString;
USHORT OffsetPrcbProcStateContext;
USHORT OffsetPrcbNumber;
USHORT SizeEThread;
ULONG64 KdPrintCircularBufferPtr;
ULONG64 KdPrintBufferSize;
ULONG64 KeLoaderBlock;
USHORT SizePcr;
USHORT OffsetPcrSelfPcr;
USHORT OffsetPcrCurrentPrcb;
USHORT OffsetPcrContainedPrcb;
USHORT OffsetPcrInitialBStore;
USHORT OffsetPcrBStoreLimit;
USHORT OffsetPcrInitialStack;
USHORT OffsetPcrStackLimit;
USHORT OffsetPrcbPcrPage;
USHORT OffsetPrcbProcStateSpecialReg;
USHORT GdtR0Code;
USHORT GdtR0Data;
USHORT GdtR0Pcr;
USHORT GdtR3Code;
USHORT GdtR3Data;
USHORT GdtR3Teb;
USHORT GdtLdt;
USHORT GdtTss;
USHORT Gdt64R3CmCode;
USHORT Gdt64R3CmTeb;
ULONG64 IopNumTriageDumpDataBlocks;
ULONG64 IopTriageDumpDataBlocks;
} KDDEBUGGER_DATA64, * PKDDEBUGGER_DATA64;
typedef struct _KDDEBUGGER_DATA_ADDITION64
{
ULONG64 VfCrashDataBlock;
ULONG64 MmBadPagesDetected;
ULONG64 MmZeroedPageSingleBitErrorsDetected;
ULONG64 EtwpDebuggerData;
USHORT OffsetPrcbContext;
USHORT OffsetPrcbMaxBreakpoints;
USHORT OffsetPrcbMaxWatchpoints;
ULONG OffsetKThreadStackLimit;
ULONG OffsetKThreadStackBase;
ULONG OffsetKThreadQueueListEntry;
ULONG OffsetEThreadIrpList;
USHORT OffsetPrcbIdleThread;
USHORT OffsetPrcbNormalDpcState;
USHORT OffsetPrcbDpcStack;
USHORT OffsetPrcbIsrStack;
USHORT SizeKDPC_STACK_FRAME;
USHORT OffsetKPriQueueThreadListHead;
USHORT OffsetKThreadWaitReason;
USHORT Padding;
ULONG64 PteBase;
ULONG64 RetpolineStubFunctionTable;
ULONG RetpolineStubFunctionTableSize;
ULONG RetpolineStubOffset;
ULONG RetpolineStubSize;
}KDDEBUGGER_DATA_ADDITION64, * PKDDEBUGGER_DATA_ADDITION64;
typedef struct _DUMP_HEADER
{
ULONG Signature;
ULONG ValidDump;
ULONG MajorVersion;
ULONG MinorVersion;
ULONG_PTR DirectoryTableBase;
ULONG_PTR PfnDataBase;
PLIST_ENTRY PsLoadedModuleList;
PLIST_ENTRY PsActiveProcessHead;
ULONG MachineImageType;
ULONG NumberProcessors;
ULONG BugCheckCode;
ULONG_PTR BugCheckParameter1;
ULONG_PTR BugCheckParameter2;
ULONG_PTR BugCheckParameter3;
ULONG_PTR BugCheckParameter4;
CHAR VersionUser[ 32 ];
struct _KDDEBUGGER_DATA64* KdDebuggerDataBlock;
} DUMP_HEADER, * PDUMP_HEADER;
typedef union _DIRECTORY_TABLE_BASE
{
struct
{
UINT64 Ignored0 : 3; /* 2:0 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 _Ignored1 : 7; /* 11:5 */
UINT64 PhysicalAddress : 36; /* 47:12 */
UINT64 _Reserved0 : 16; /* 63:48 */
} Bits;
UINT64 BitAddress;
} CR3, DIR_TABLE_BASE;
typedef union _VIRTUAL_MEMORY_ADDRESS
{
struct
{
UINT64 PageIndex : 12; /* 0:11 */
UINT64 PtIndex : 9; /* 12:20 */
UINT64 PdIndex : 9; /* 21:29 */
UINT64 PdptIndex : 9; /* 30:38 */
UINT64 Pml4Index : 9; /* 39:47 */
UINT64 Unused : 16; /* 48:63 */
} Bits;
UINT64 BitAddress;
} VIRTUAL_ADDRESS, * PVIRTUAL_ADDRESS;
typedef union _PML4_ENTRY
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 _Ignored0 : 1; /* 6 */
UINT64 _Reserved0 : 1; /* 7 */
UINT64 _Ignored1 : 4; /* 11:8 */
UINT64 PhysicalAddress : 40; /* 51:12 */
UINT64 _Ignored2 : 11; /* 62:52 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PML4E;
typedef union _PDPT_ENTRY
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 _Ignored0 : 1; /* 6 */
UINT64 PageSize : 1; /* 7 */
UINT64 _Ignored1 : 4; /* 11:8 */
UINT64 PhysicalAddress : 40; /* 51:12 */
UINT64 _Ignored2 : 11; /* 62:52 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PDPTE;
typedef union _PD_ENTRY
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 _Ignored0 : 1; /* 6 */
UINT64 PageSize : 1; /* 7 */
UINT64 _Ignored1 : 4; /* 11:8 */
UINT64 PhysicalAddress : 38; /* 49:12 */
UINT64 _Reserved0 : 2; /* 51:50 */
UINT64 _Ignored2 : 11; /* 62:52 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PDE;
typedef union _PT_ENTRY
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 Dirty : 1; /* 6 */
UINT64 PageAttributeTable : 1; /* 7 */
UINT64 Global : 1; /* 8 */
UINT64 _Ignored0 : 3; /* 11:9 */
UINT64 PhysicalAddress : 38; /* 49:12 */
UINT64 _Reserved0 : 2; /* 51:50 */
UINT64 _Ignored1 : 7; /* 58:52 */
UINT64 ProtectionKey : 4; /* 62:59 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PTE;
typedef union _PDPT_ENTRY_LARGE
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 Dirty : 1; /* 6 */
UINT64 PageSize : 1; /* 7 */
UINT64 Global : 1; /* 8 */
UINT64 _Ignored0 : 3; /* 11:9 */
UINT64 PageAttributeTable : 1; /* 12 */
UINT64 _Reserved0 : 17; /* 29:13 */
UINT64 PhysicalAddress : 22; /* 51:30 */
UINT64 _Ignored1 : 7; /* 58:52 */
UINT64 ProtectionKey : 4; /* 62:59 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PDPTE_LARGE;
typedef union _PD_ENTRY_LARGE
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 Dirty : 1; /* 6 */
UINT64 PageSize : 1; /* 7 */
UINT64 Global : 1; /* 8 */
UINT64 _Ignored0 : 3; /* 11:9 */
UINT64 PageAttributeTalbe : 1; /* 12 */
UINT64 _Reserved0 : 8; /* 20:13 */
UINT64 PhysicalAddress : 29; /* 49:21 */
UINT64 _Reserved1 : 2; /* 51:50 */
UINT64 _Ignored1 : 7; /* 58:52 */
UINT64 ProtectionKey : 4; /* 62:59 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PDE_LARGE;
//typedef struct _KAPC_STATE
//{
// LIST_ENTRY ApcListHead[ MaximumMode ];
// struct _KPROCESS* Process;
// union {
// UCHAR InProgressFlags;
// struct
// {
// BOOLEAN KernelApcInProgress : 1;
// BOOLEAN SpecialApcInProgress : 1;
// };
// };
//
// BOOLEAN KernelApcPending;
// union {
// BOOLEAN UserApcPendingAll;
// struct
// {
// BOOLEAN SpecialUserApcPending : 1;
// BOOLEAN UserApcPending : 1;
// };
// };
//} KAPC_STATE, * PKAPC_STATE, * PRKAPC_STATE;
NTKERNELAPI
BOOLEAN
ExEnumHandleTable(
@ -460,4 +970,76 @@ PsGetProcessImageFileName(
PEPROCESS Process
);
EXTERN_C VOID KeInitializeAffinityEx(
PKAFFINITY_EX affinity
);
EXTERN_C VOID KeAddProcessorAffinityEx(
PKAFFINITY_EX affinity,
INT num
);
EXTERN_C VOID HalSendNMI(
PKAFFINITY_EX affinity
);
NTSTATUS
RtlQueryModuleInformation(
ULONG* InformationLength,
ULONG SizePerModule,
PVOID InformationBuffer
);
NTSTATUS
NTAPI
NtSetInformationProcess(
_In_ HANDLE ProcessHandle,
_In_ PROCESSINFOCLASS ProcessInformationClass,
_In_ PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength
);
NTSYSAPI
ULONG
NTAPI
KeCapturePersistentThreadState(
__in PCONTEXT Context,
__in_opt PKTHREAD Thread,
__in ULONG BugCheckCode,
__in ULONG_PTR BugCheckParameter1,
__in ULONG_PTR BugCheckParameter2,
__in ULONG_PTR BugCheckParameter3,
__in ULONG_PTR BugCheckParameter4,
__in PDUMP_HEADER DumpHeader
);
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, Signature ) == 0 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, ValidDump ) == 4 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MajorVersion ) == 8 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MinorVersion ) == 0xc );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, DirectoryTableBase ) == 0x10 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PfnDataBase ) == 0x18 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PsLoadedModuleList ) == 0x20 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PsActiveProcessHead ) == 0x28 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MachineImageType ) == 0x30 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, NumberProcessors ) == 0x34 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckCode ) == 0x38 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter1 ) == 0x40 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter2 ) == 0x48 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter3 ) == 0x50 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter4 ) == 0x58 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, KdDebuggerDataBlock ) == 0x80 );
#ifndef _WIN64
#define KDDEBUGGER_DATA_OFFSET 0x1068
#else
#define KDDEBUGGER_DATA_OFFSET 0x2080
#endif
#ifndef _WIN64
#define DUMP_BLOCK_SIZE 0x20000
#else
#define DUMP_BLOCK_SIZE 0x40000
#endif
#endif

View file

@ -4,9 +4,9 @@
#include <ntifs.h>
#include <wdftypes.h>
#include <wdf.h>
#include "common.h"
#define DRIVER_PATH_MAX_LENGTH 512
#define DRIVER_PATH_POOL_TAG 'path'
/*
* This structure is strictly for driver related stuff

View file

@ -2,6 +2,7 @@
#define HV_H
#include <ntifs.h>
#include "common.h"
typedef struct _HYPERVISOR_DETECTION_REPORT
{

View file

@ -2,8 +2,7 @@
#define INTEGRITY_H
#include <ntifs.h>
#define POOL_TAG_INTEGRITY 'intg'
#include "common.h"
NTSTATUS CopyDriverExecutableRegions(
_In_ PIRP Irp
@ -21,118 +20,4 @@ NTSTATUS RetrieveInMemoryModuleExecutableSections(
_In_ PIRP Irp
);
NTSTATUS
NTAPI
NtSetInformationProcess(
_In_ HANDLE ProcessHandle,
_In_ PROCESSINFOCLASS ProcessInformationClass,
_In_ PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength
);
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER {
unsigned char Name[ IMAGE_SIZEOF_SHORT_NAME ];
union {
unsigned long PhysicalAddress;
unsigned long VirtualSize;
} Misc;
unsigned long VirtualAddress;
unsigned long SizeOfRawData;
unsigned long PointerToRawData;
unsigned long PointerToRelocations;
unsigned long PointerToLinenumbers;
unsigned short NumberOfRelocations;
unsigned short NumberOfLinenumbers;
unsigned long Characteristics;
} IMAGE_SECTION_HEADER, * PIMAGE_SECTION_HEADER;
typedef struct _IMAGE_FILE_HEADER {
unsigned short Machine;
unsigned short NumberOfSections;
unsigned long TimeDateStamp;
unsigned long PointerToSymbolTable;
unsigned long NumberOfSymbols;
unsigned short SizeOfOptionalHeader;
unsigned short Characteristics;
} IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER;
typedef struct _IMAGE_DATA_DIRECTORY {
unsigned long VirtualAddress;
unsigned long Size;
} IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY;
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
typedef struct _IMAGE_OPTIONAL_HEADER64 {
unsigned short Magic;
unsigned char MajorLinkerVersion;
unsigned char MinorLinkerVersion;
unsigned long SizeOfCode;
unsigned long SizeOfInitializedData;
unsigned long SizeOfUninitializedData;
unsigned long AddressOfEntryPoint;
unsigned long BaseOfCode;
ULONGLONG ImageBase;
unsigned long SectionAlignment;
unsigned long FileAlignment;
unsigned short MajorOperatingSystemVersion;
unsigned short MinorOperatingSystemVersion;
unsigned short MajorImageVersion;
unsigned short MinorImageVersion;
unsigned short MajorSubsystemVersion;
unsigned short MinorSubsystemVersion;
unsigned long Win32VersionValue;
unsigned long SizeOfImage;
unsigned long SizeOfHeaders;
unsigned long CheckSum;
unsigned short Subsystem;
unsigned short DllCharacteristics;
ULONGLONG SizeOfStackReserve;
ULONGLONG SizeOfStackCommit;
ULONGLONG SizeOfHeapReserve;
ULONGLONG SizeOfHeapCommit;
unsigned long LoaderFlags;
unsigned long NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[ IMAGE_NUMBEROF_DIRECTORY_ENTRIES ];
} IMAGE_OPTIONAL_HEADER64, * PIMAGE_OPTIONAL_HEADER64;
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
unsigned short e_magic; // Magic number
unsigned short e_cblp; // Bytes on last page of file
unsigned short e_cp; // Pages in file
unsigned short e_crlc; // Relocations
unsigned short e_cparhdr; // Size of header in paragraphs
unsigned short e_minalloc; // Minimum extra paragraphs needed
unsigned short e_maxalloc; // Maximum extra paragraphs needed
unsigned short e_ss; // Initial (relative) SS value
unsigned short e_sp; // Initial SP value
unsigned short e_csum; // Checksum
unsigned short e_ip; // Initial IP value
unsigned short e_cs; // Initial (relative) CS value
unsigned short e_lfarlc; // File address of relocation table
unsigned short e_ovno; // Overlay number
unsigned short e_res[ 4 ]; // Reserved words
unsigned short e_oemid; // OEM identifier (for e_oeminfo)
unsigned short e_oeminfo; // OEM information; e_oemid specific
unsigned short e_res2[ 10 ]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, * PIMAGE_DOS_HEADER;
typedef struct _LOCAL_NT_HEADER {
unsigned long Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} LOCAL_NT_HEADER, * PLOCAL_NT_HEADER;
#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \
((ULONG_PTR)(ntheader) + \
FIELD_OFFSET( LOCAL_NT_HEADER, OptionalHeader ) + \
((ntheader))->FileHeader.SizeOfOptionalHeader \
))
#endif

View file

@ -235,6 +235,12 @@ NTSTATUS DeviceControl(
break;
case IOCTL_DETECT_ATTACHED_THREADS:
DetectThreadsAttachedToProtectedProcess();
break;
default:
DEBUG_ERROR( "Invalid IOCTL passed to driver" );
break;

View file

@ -4,6 +4,7 @@
#include <ntifs.h>
#include <wdftypes.h>
#include <wdf.h>
#include "common.h"
#define IOCCTL_RUN_NMI_CALLBACKS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2001, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_VALIDATE_DRIVER_OBJECTS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2002, METHOD_BUFFERED, FILE_ANY_ACCESS)
@ -17,6 +18,7 @@
#define IOCTL_SCAN_FOR_UNLINKED_PROCESS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2011, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_VALIDATE_KPRCB_CURRENT_THREAD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2012, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_PERFORM_INTEGRITY_CHECK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2013, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DETECT_ATTACHED_THREADS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2014, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct _DRIVER_INITIATION_INFORMATION
{

View file

@ -5,20 +5,11 @@
#include <intrin.h>
#include "common.h"
#define REPORT_MODULE_VALIDATION_FAILURE 60
#define MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT 20
#define MODULE_REPORT_DRIVER_NAME_BUFFER_SIZE 128
#define REASON_NO_BACKING_MODULE 1
#define REASON_INVALID_IOCTL_DISPATCH 2
#define REPORT_NMI_CALLBACK_FAILURE 50
NTSTATUS HandleNmiIOCTL(
_In_ PIRP Irp
);
typedef struct _WHITELISTED_REGIONS
{
UINT64 base;
@ -115,4 +106,8 @@ PRTL_MODULE_EXTENDED_INFO FindSystemModuleByName(
_In_ PSYSTEM_MODULES SystemModules
);
NTSTATUS HandleNmiIOCTL(
_In_ PIRP Irp
);
#endif

View file

@ -2,29 +2,20 @@
#define POOL_H
#include <ntifs.h>
#include "common.h"
#define REPORT_INVALID_PROCESS_ALLOCATION 80
#define REPORT_INVALID_PROCESS_BUFFER_SIZE 4096
#define POOL_DUMP_BLOCK_TAG 'dump'
#define POOL_DEBUGGER_DATA_TAG 'data'
#define PROCESS_ADDRESS_LIST_TAG 'addr'
#define ANALYSE_PROCESS_TAG 'anls'
#define INVALID_PROCESS_REPORT_TAG 'invd'
#define PAGE_BASE_SIZE 0x1000
#define POOL_TAG_SIZE 0x004
#define PML4_ENTRY_COUNT 512
#define PDPT_ENTRY_COUNT 512
#define PD_ENTRY_COUNT 512
#define PT_ENTRY_COUNT 512
#define PAGE_BASE_SIZE 0x1000
#define POOL_TAG_SIZE 0x004
#define PROCESS_OBJECT_ALLOCATION_MARGIN 0x90
#define EPROCESS_VIRTUAL_SIZE_OFFSET 0x498
#define EPROCESS_IMAGE_NAME_OFFSET 0x5a8
/* SIZE_2 = first alloc + 0x10 */
#define WIN_PROCESS_ALLOCATION_SIZE 0xcf0
#define WIN_PROCESS_ALLOCATION_SIZE_2 0xd00
@ -46,432 +37,6 @@ VOID GetPsActiveProcessHead(
_In_ PUINT64 Address
);
/* creds: https://www.unknowncheats.me/forum/2602838-post2.html */
typedef struct _DBGKD_DEBUG_DATA_HEADER64
{
LIST_ENTRY64 List;
ULONG OwnerTag;
ULONG Size;
} DBGKD_DEBUG_DATA_HEADER64, * PDBGKD_DEBUG_DATA_HEADER64;
typedef struct _KDDEBUGGER_DATA64
{
DBGKD_DEBUG_DATA_HEADER64 Header;
ULONG64 KernBase;
ULONG64 BreakpointWithStatus;
ULONG64 SavedContext;
USHORT ThCallbackStack;
USHORT NextCallback;
USHORT FramePointer;
USHORT PaeEnabled;
ULONG64 KiCallUserMode;
ULONG64 KeUserCallbackDispatcher;
ULONG64 PsLoadedModuleList;
ULONG64 PsActiveProcessHead;
ULONG64 PspCidTable;
ULONG64 ExpSystemResourcesList;
ULONG64 ExpPagedPoolDescriptor;
ULONG64 ExpNumberOfPagedPools;
ULONG64 KeTimeIncrement;
ULONG64 KeBugCheckCallbackListHead;
ULONG64 KiBugcheckData;
ULONG64 IopErrorLogListHead;
ULONG64 ObpRootDirectoryObject;
ULONG64 ObpTypeObjectType;
ULONG64 MmSystemCacheStart;
ULONG64 MmSystemCacheEnd;
ULONG64 MmSystemCacheWs;
ULONG64 MmPfnDatabase;
ULONG64 MmSystemPtesStart;
ULONG64 MmSystemPtesEnd;
ULONG64 MmSubsectionBase;
ULONG64 MmNumberOfPagingFiles;
ULONG64 MmLowestPhysicalPage;
ULONG64 MmHighestPhysicalPage;
ULONG64 MmNumberOfPhysicalPages;
ULONG64 MmMaximumNonPagedPoolInBytes;
ULONG64 MmNonPagedSystemStart;
ULONG64 MmNonPagedPoolStart;
ULONG64 MmNonPagedPoolEnd;
ULONG64 MmPagedPoolStart;
ULONG64 MmPagedPoolEnd;
ULONG64 MmPagedPoolInformation;
ULONG64 MmPageSize;
ULONG64 MmSizeOfPagedPoolInBytes;
ULONG64 MmTotalCommitLimit;
ULONG64 MmTotalCommittedPages;
ULONG64 MmSharedCommit;
ULONG64 MmDriverCommit;
ULONG64 MmProcessCommit;
ULONG64 MmPagedPoolCommit;
ULONG64 MmExtendedCommit;
ULONG64 MmZeroedPageListHead;
ULONG64 MmFreePageListHead;
ULONG64 MmStandbyPageListHead;
ULONG64 MmModifiedPageListHead;
ULONG64 MmModifiedNoWritePageListHead;
ULONG64 MmAvailablePages;
ULONG64 MmResidentAvailablePages;
ULONG64 PoolTrackTable;
ULONG64 NonPagedPoolDescriptor;
ULONG64 MmHighestUserAddress;
ULONG64 MmSystemRangeStart;
ULONG64 MmUserProbeAddress;
ULONG64 KdPrintCircularBuffer;
ULONG64 KdPrintCircularBufferEnd;
ULONG64 KdPrintWritePointer;
ULONG64 KdPrintRolloverCount;
ULONG64 MmLoadedUserImageList;
ULONG64 NtBuildLab;
ULONG64 KiNormalSystemCall;
ULONG64 KiProcessorBlock;
ULONG64 MmUnloadedDrivers;
ULONG64 MmLastUnloadedDriver;
ULONG64 MmTriageActionTaken;
ULONG64 MmSpecialPoolTag;
ULONG64 KernelVerifier;
ULONG64 MmVerifierData;
ULONG64 MmAllocatedNonPagedPool;
ULONG64 MmPeakCommitment;
ULONG64 MmTotalCommitLimitMaximum;
ULONG64 CmNtCSDVersion;
ULONG64 MmPhysicalMemoryBlock;
ULONG64 MmSessionBase;
ULONG64 MmSessionSize;
ULONG64 MmSystemParentTablePage;
ULONG64 MmVirtualTranslationBase;
USHORT OffsetKThreadNextProcessor;
USHORT OffsetKThreadTeb;
USHORT OffsetKThreadKernelStack;
USHORT OffsetKThreadInitialStack;
USHORT OffsetKThreadApcProcess;
USHORT OffsetKThreadState;
USHORT OffsetKThreadBStore;
USHORT OffsetKThreadBStoreLimit;
USHORT SizeEProcess;
USHORT OffsetEprocessPeb;
USHORT OffsetEprocessParentCID;
USHORT OffsetEprocessDirectoryTableBase;
USHORT SizePrcb;
USHORT OffsetPrcbDpcRoutine;
USHORT OffsetPrcbCurrentThread;
USHORT OffsetPrcbMhz;
USHORT OffsetPrcbCpuType;
USHORT OffsetPrcbVendorString;
USHORT OffsetPrcbProcStateContext;
USHORT OffsetPrcbNumber;
USHORT SizeEThread;
ULONG64 KdPrintCircularBufferPtr;
ULONG64 KdPrintBufferSize;
ULONG64 KeLoaderBlock;
USHORT SizePcr;
USHORT OffsetPcrSelfPcr;
USHORT OffsetPcrCurrentPrcb;
USHORT OffsetPcrContainedPrcb;
USHORT OffsetPcrInitialBStore;
USHORT OffsetPcrBStoreLimit;
USHORT OffsetPcrInitialStack;
USHORT OffsetPcrStackLimit;
USHORT OffsetPrcbPcrPage;
USHORT OffsetPrcbProcStateSpecialReg;
USHORT GdtR0Code;
USHORT GdtR0Data;
USHORT GdtR0Pcr;
USHORT GdtR3Code;
USHORT GdtR3Data;
USHORT GdtR3Teb;
USHORT GdtLdt;
USHORT GdtTss;
USHORT Gdt64R3CmCode;
USHORT Gdt64R3CmTeb;
ULONG64 IopNumTriageDumpDataBlocks;
ULONG64 IopTriageDumpDataBlocks;
} KDDEBUGGER_DATA64, * PKDDEBUGGER_DATA64;
typedef struct _KDDEBUGGER_DATA_ADDITION64
{
ULONG64 VfCrashDataBlock;
ULONG64 MmBadPagesDetected;
ULONG64 MmZeroedPageSingleBitErrorsDetected;
ULONG64 EtwpDebuggerData;
USHORT OffsetPrcbContext;
USHORT OffsetPrcbMaxBreakpoints;
USHORT OffsetPrcbMaxWatchpoints;
ULONG OffsetKThreadStackLimit;
ULONG OffsetKThreadStackBase;
ULONG OffsetKThreadQueueListEntry;
ULONG OffsetEThreadIrpList;
USHORT OffsetPrcbIdleThread;
USHORT OffsetPrcbNormalDpcState;
USHORT OffsetPrcbDpcStack;
USHORT OffsetPrcbIsrStack;
USHORT SizeKDPC_STACK_FRAME;
USHORT OffsetKPriQueueThreadListHead;
USHORT OffsetKThreadWaitReason;
USHORT Padding;
ULONG64 PteBase;
ULONG64 RetpolineStubFunctionTable;
ULONG RetpolineStubFunctionTableSize;
ULONG RetpolineStubOffset;
ULONG RetpolineStubSize;
}KDDEBUGGER_DATA_ADDITION64, * PKDDEBUGGER_DATA_ADDITION64;
typedef struct _DUMP_HEADER
{
ULONG Signature;
ULONG ValidDump;
ULONG MajorVersion;
ULONG MinorVersion;
ULONG_PTR DirectoryTableBase;
ULONG_PTR PfnDataBase;
PLIST_ENTRY PsLoadedModuleList;
PLIST_ENTRY PsActiveProcessHead;
ULONG MachineImageType;
ULONG NumberProcessors;
ULONG BugCheckCode;
ULONG_PTR BugCheckParameter1;
ULONG_PTR BugCheckParameter2;
ULONG_PTR BugCheckParameter3;
ULONG_PTR BugCheckParameter4;
CHAR VersionUser[ 32 ];
struct _KDDEBUGGER_DATA64* KdDebuggerDataBlock;
} DUMP_HEADER, * PDUMP_HEADER;
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, Signature ) == 0 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, ValidDump ) == 4 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MajorVersion ) == 8 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MinorVersion ) == 0xc );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, DirectoryTableBase ) == 0x10 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PfnDataBase ) == 0x18 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PsLoadedModuleList ) == 0x20 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, PsActiveProcessHead ) == 0x28 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, MachineImageType ) == 0x30 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, NumberProcessors ) == 0x34 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckCode ) == 0x38 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter1 ) == 0x40 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter2 ) == 0x48 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter3 ) == 0x50 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, BugCheckParameter4 ) == 0x58 );
C_ASSERT( FIELD_OFFSET( DUMP_HEADER, KdDebuggerDataBlock ) == 0x80 );
#ifndef _WIN64
#define KDDEBUGGER_DATA_OFFSET 0x1068
#else
#define KDDEBUGGER_DATA_OFFSET 0x2080
#endif
#ifndef _WIN64
#define DUMP_BLOCK_SIZE 0x20000
#else
#define DUMP_BLOCK_SIZE 0x40000
#endif
NTSYSAPI
ULONG
NTAPI
KeCapturePersistentThreadState(
__in PCONTEXT Context,
__in_opt PKTHREAD Thread,
__in ULONG BugCheckCode,
__in ULONG_PTR BugCheckParameter1,
__in ULONG_PTR BugCheckParameter2,
__in ULONG_PTR BugCheckParameter3,
__in ULONG_PTR BugCheckParameter4,
__in PDUMP_HEADER DumpHeader
);
VOID ScanNonPagedPoolForProcessTags();
typedef union _DIRECTORY_TABLE_BASE
{
struct
{
UINT64 Ignored0 : 3; /* 2:0 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 _Ignored1 : 7; /* 11:5 */
UINT64 PhysicalAddress : 36; /* 47:12 */
UINT64 _Reserved0 : 16; /* 63:48 */
} Bits;
UINT64 BitAddress;
} CR3, DIR_TABLE_BASE;
typedef union _VIRTUAL_MEMORY_ADDRESS
{
struct
{
UINT64 PageIndex : 12; /* 0:11 */
UINT64 PtIndex : 9; /* 12:20 */
UINT64 PdIndex : 9; /* 21:29 */
UINT64 PdptIndex : 9; /* 30:38 */
UINT64 Pml4Index : 9; /* 39:47 */
UINT64 Unused : 16; /* 48:63 */
} Bits;
UINT64 BitAddress;
} VIRTUAL_ADDRESS, * PVIRTUAL_ADDRESS;
typedef union _PML4_ENTRY
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 _Ignored0 : 1; /* 6 */
UINT64 _Reserved0 : 1; /* 7 */
UINT64 _Ignored1 : 4; /* 11:8 */
UINT64 PhysicalAddress : 40; /* 51:12 */
UINT64 _Ignored2 : 11; /* 62:52 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PML4E;
typedef union _PDPT_ENTRY
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 _Ignored0 : 1; /* 6 */
UINT64 PageSize : 1; /* 7 */
UINT64 _Ignored1 : 4; /* 11:8 */
UINT64 PhysicalAddress : 40; /* 51:12 */
UINT64 _Ignored2 : 11; /* 62:52 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PDPTE;
typedef union _PD_ENTRY
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 _Ignored0 : 1; /* 6 */
UINT64 PageSize : 1; /* 7 */
UINT64 _Ignored1 : 4; /* 11:8 */
UINT64 PhysicalAddress : 38; /* 49:12 */
UINT64 _Reserved0 : 2; /* 51:50 */
UINT64 _Ignored2 : 11; /* 62:52 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PDE;
typedef union _PT_ENTRY
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 Dirty : 1; /* 6 */
UINT64 PageAttributeTable : 1; /* 7 */
UINT64 Global : 1; /* 8 */
UINT64 _Ignored0 : 3; /* 11:9 */
UINT64 PhysicalAddress : 38; /* 49:12 */
UINT64 _Reserved0 : 2; /* 51:50 */
UINT64 _Ignored1 : 7; /* 58:52 */
UINT64 ProtectionKey : 4; /* 62:59 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PTE;
typedef union _PDPT_ENTRY_LARGE
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 Dirty : 1; /* 6 */
UINT64 PageSize : 1; /* 7 */
UINT64 Global : 1; /* 8 */
UINT64 _Ignored0 : 3; /* 11:9 */
UINT64 PageAttributeTable : 1; /* 12 */
UINT64 _Reserved0 : 17; /* 29:13 */
UINT64 PhysicalAddress : 22; /* 51:30 */
UINT64 _Ignored1 : 7; /* 58:52 */
UINT64 ProtectionKey : 4; /* 62:59 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PDPTE_LARGE;
typedef union _PD_ENTRY_LARGE
{
struct
{
UINT64 Present : 1; /* 0 */
UINT64 ReadWrite : 1; /* 1 */
UINT64 UserSupervisor : 1; /* 2 */
UINT64 PageWriteThrough : 1; /* 3 */
UINT64 PageCacheDisable : 1; /* 4 */
UINT64 Accessed : 1; /* 5 */
UINT64 Dirty : 1; /* 6 */
UINT64 PageSize : 1; /* 7 */
UINT64 Global : 1; /* 8 */
UINT64 _Ignored0 : 3; /* 11:9 */
UINT64 PageAttributeTalbe : 1; /* 12 */
UINT64 _Reserved0 : 8; /* 20:13 */
UINT64 PhysicalAddress : 29; /* 49:21 */
UINT64 _Reserved1 : 2; /* 51:50 */
UINT64 _Ignored1 : 7; /* 58:52 */
UINT64 ProtectionKey : 4; /* 62:59 */
UINT64 ExecuteDisable : 1; /* 63 */
} Bits;
UINT64 BitAddress;
} PDE_LARGE;
/*
* Generic macros that allow you to quickly determine whether
* or not a page table entry is present or may forward to a
* large page of data, rather than another page table (applies
* only to PDPTEs and PDEs)
*
* Some nice macros courtesy of:
* https://www.unknowncheats.me/forum/general-programming-and-reversing/523359-introduction-physical-memory.html
*/
#define IS_LARGE_PAGE(x) ( (BOOLEAN)((x >> 7) & 1) )
#define IS_PAGE_PRESENT(x) ( (BOOLEAN)(x & 1) )
#define PAGE_1GB_SHIFT 30
#define PAGE_1GB_OFFSET(x) ( x & (~(MAXUINT64 << PAGE_1GB_SHIFT)) )
#define PAGE_2MB_SHIFT 21
#define PAGE_2MB_OFFSET(x) ( x & (~(MAXUINT64 << PAGE_2MB_SHIFT)) )
#define PAGE_4KB_SHIFT 12
#define PAGE_4KB_OFFSET(x) ( x & (~(MAXUINT64 << PAGE_4KB_SHIFT)) )
PKDDEBUGGER_DATA64 GetGlobalDebuggerData();
#endif

View file

@ -9,12 +9,6 @@
#include "thread.h"
#include "common.h"
typedef struct _REPORT_HEADER
{
INT report_id;
}REPORT_HEADER, * PREPORT_HEADER;
/*
* This mutex is to prevent a new item being pushed to the queue
* while the HandlePeriodicCallbackReportQueue is iterating through
@ -23,7 +17,6 @@ typedef struct _REPORT_HEADER
* can be pushed into the queue before the next iteration can take ownership
* of the spinlock.
*/
typedef struct _REPORT_QUEUE_CONFIGURATION
{
QUEUE_HEAD head;
@ -200,7 +193,6 @@ NTSTATUS HandlePeriodicGlobalReportQueueQuery(
);
total_size += sizeof( OPEN_HANDLE_FAILURE_REPORT );
break;
case REPORT_ILLEGAL_ATTACH_PROCESS:
@ -212,7 +204,6 @@ NTSTATUS HandlePeriodicGlobalReportQueueQuery(
);
total_size += sizeof( ATTACH_PROCESS_REPORT );
break;
}

View file

@ -2,11 +2,7 @@
#define QUEUE_H
#include <ntifs.h>
#define QUEUE_POOL_TAG 'qqqq'
#define REPORT_QUEUE_TEMP_BUFFER_TAG 'temp'
#define REPORT_POOL_TAG 'repo'
#include "common.h"
#define MAX_REPORTS_PER_IRP 20
@ -32,6 +28,12 @@ typedef struct _GLOBAL_REPORT_QUEUE_HEADER
}GLOBAL_REPORT_QUEUE_HEADER, * PGLOBAL_REPORT_QUEUE_HEADER;
typedef struct _REPORT_HEADER
{
INT report_id;
}REPORT_HEADER, * PREPORT_HEADER;
VOID QueuePush(
_In_ PQUEUE_HEAD Head,
_In_ PVOID Data

View file

@ -2,6 +2,8 @@
#include "pool.h"
#include "callbacks.h"
#include "driver.h"
#include "queue.h"
#include <intrin.h>
@ -131,8 +133,12 @@ VOID DetectAttachedThreadsProcessCallback(
PLIST_ENTRY thread_list_entry;
PETHREAD current_thread;
UINT32 thread_id;
PKAPC_STATE apc_state;
PEPROCESS protected_process = NULL;
if ( finished == TRUE )
GetProtectedProcessEProcess( &protected_process );
if ( protected_process == NULL )
return;
thread_list_head = ( PLIST_ENTRY )( ( UINT64 )Process + KPROCESS_THREADLIST_OFFSET );
@ -142,7 +148,23 @@ VOID DetectAttachedThreadsProcessCallback(
{
current_thread = ( PETHREAD )( ( UINT64 )thread_list_entry - KTHREAD_THREADLIST_OFFSET );
apc_state = ( PKAPC_STATE )( ( UINT64 )current_thread + KTHREAD_APC_STATE_OFFSET );
if ( apc_state->Process == protected_process )
{
DEBUG_LOG( "Program attached to notepad: %llx", ( UINT64 )current_thread );
PATTACH_PROCESS_REPORT report = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( ATTACH_PROCESS_REPORT ), REPORT_POOL_TAG );
if ( !report )
return;
report->report_code = REPORT_ILLEGAL_ATTACH_PROCESS;
report->thread_id = PsGetThreadId( current_thread );
report->thread_address = current_thread;
InsertReportToQueue( report );
}
thread_list_entry = thread_list_entry->Flink;
}
@ -155,16 +177,16 @@ VOID DetectAttachedThreadsProcessCallback(
* https://github.com/KANKOSHEV/Detect-KeAttachProcess/tree/main
* https://doxygen.reactos.org/d0/dc9/procobj_8c.html#adec6dc539d4a5c0ee7d0f48e24ef0933
*
* Then from here you can see that the _KAPC_STATE structure in the KTHREAD stores the
* APC state for the thread. The Process field in this structure is the offset referred to
* in KANKOSHEV's proof of concept. This the field that is updated by KiAttachProcess when
* calling KeStackAttachProcess.
* To expand on his writeup a little, the offset that he provides is equivalent to PKAPC_STATE->Process.
* This is where KiAttachProcess writes the process that thread is attaching to when it's called.
* The APC_STATE structure holds relevant information about the thread's APC state and is quite
* important during context switch scenarios as it's how the thread determines if it has any APC's
* queued.
*/
VOID DetectThreadsAttachedToProtectedProcess(
_In_ PIRP Irp
)
VOID DetectThreadsAttachedToProtectedProcess()
{
EnumerateProcessListWithCallbackFunction(
DetectAttachedThreadsProcessCallback
);
}

View file

@ -5,20 +5,6 @@
#include "common.h"
#define IA32_GS_BASE 0xc0000101
#define KPRCB_OFFSET_FROM_GS_BASE 0x180
#define KPCRB_CURRENT_THREAD 0x8
#define KPROCESS_THREADLIST_OFFSET 0x030
#define KTHREAD_THREADLIST_OFFSET 0x2f8
#define REPORT_HIDDEN_SYSTEM_THREAD 90
#define REPORT_ILLEGAL_ATTACH_PROCESS 100
VOID ValidateKPCRBThreads(
_In_ PIRP Irp
);
typedef struct _HIDDEN_SYSTEM_THREAD_REPORT
{
INT report_code;
@ -33,7 +19,15 @@ typedef struct _HIDDEN_SYSTEM_THREAD_REPORT
typedef struct _ATTACH_PROCESS_REPORT
{
INT report_code;
UINT32 thread_id;
UINT64 thread_address;
}ATTACH_PROCESS_REPORT, *PATTACH_PROCESS_REPORT;
VOID ValidateKPCRBThreads(
_In_ PIRP Irp
);
VOID DetectThreadsAttachedToProtectedProcess();
#endif

30
server/Dispatch.cs Normal file
View file

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace server
{
public class Dispatch
{
private TcpClient _client;
private NetworkStream _stream;
private byte[] _buffer;
public Dispatch(TcpClient client, NetworkStream stream)
{
_client = client;
_stream = stream;
_buffer = new byte[1024];
this.AcceptMessage();
}
private void AcceptMessage()
{
_stream.BeginRead(_buffer, 0, 1024, null, null);
}
}
}

67
server/Message.cs Normal file
View file

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using Serilog;
namespace server
{
public class Message
{
private byte[] _buffer;
private int _bufferSize;
private int _messageType;
private enum MESSAGE_TYPE
{
MESSAGE_TYPE_REPORT = 1,
MESSAGE_TYPE_SEND = 2,
MESSAGE_TYPE_RECEIVE = 3
}
struct PACKET_HEADER
{
int messageType;
}
struct REPORT_PACKET_HEADER
{
int reportId;
}
public Message(byte[] buffer, int bufferSize)
{
_buffer = buffer;
_bufferSize = bufferSize;
this.GetMessageType();
switch (_messageType)
{
case (int)MESSAGE_TYPE.MESSAGE_TYPE_REPORT:
this.HandleReportMessage(this.GetReportType());
break;
default:
Log.Logger.Information("This message type is not accepted at the moment.");
break;
}
}
private void GetMessageType()
{
_messageType = BitConverter.ToInt32(_buffer, 0);
}
private int GetReportType()
{
return BitConverter.ToInt32(_buffer, sizeof(int));
}
private void HandleReportMessage(int reportId)
{
Log.Logger.Information("Report id: {0}", reportId);
}
}
}

30
server/Server.cs Normal file
View file

@ -0,0 +1,30 @@
using System.Net;
using System.Net.Sockets;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using server;
namespace server
{
public class Server
{
private IPEndPoint _ipEndPoint;
private TcpListener _tcpListener;
public Server()
{
_ipEndPoint = new IPEndPoint(IPAddress.Any, 8888);
_tcpListener = new TcpListener(_ipEndPoint);
}
public async Task Listen()
{
_tcpListener.Start();
using TcpClient _client = await _tcpListener.AcceptTcpClientAsync();
Thread dispatchThread = new Thread(() => new Dispatch(_client, _client.GetStream()));
dispatchThread.Start();
}
}
}

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
@ -7,4 +7,8 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="3.0.1" />
</ItemGroup>
</Project>

View file

@ -3,39 +3,30 @@ using System.Net;
using System.Net.Sockets;
using System.Text;
using Serilog;
using Microsoft.AspNetCore.Http;
namespace service
{
public class Client
{
public static async Task SendToServer()
private IPEndPoint _ipEndPoint;
private TcpClient _tcpClient;
private byte[] _buffer;
private int _bufferSize;
public Client(byte[] buffer, int bufferSize)
{
var ipEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
using TcpClient client = new();
await client.ConnectAsync(ipEndPoint);
await using NetworkStream stream = client.GetStream();
var testMessage = "Hello from client";
stream.BeginWrite(Encoding.UTF8.GetBytes(testMessage), 0, testMessage.Length, Callback, null);
byte[] buffer = new byte[1024];
int received = await stream.ReadAsync(buffer);
var message = Encoding.UTF8.GetString(buffer, 0, received);
Console.WriteLine($"Message received: \"{message}\"");
while (true)
{
}
_ipEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888);
_tcpClient = new TcpClient();
_buffer = buffer;
_bufferSize = bufferSize;
}
private static void Callback(IAsyncResult ar)
public void SendMessageToServer()
{
Log.Information("Sent message lolz");
_tcpClient.Connect(_ipEndPoint);
NetworkStream stream = _tcpClient.GetStream();
stream.BeginWrite(_buffer, 0, _bufferSize, null, null);
}
}

40
service/Message.cs Normal file
View file

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO.Pipes;
using service;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace service
{
public class Message
{
private NamedPipeServerStream _pipeServer;
private byte[] _buffer;
private int _bufferSize;
public Message(NamedPipeServerStream pipeServer)
{
_pipeServer = pipeServer;
_bufferSize = _pipeServer.InBufferSize;
_buffer = new byte[_bufferSize];
}
public async Task ReadPipeBuffer()
{
await _pipeServer.ReadAsync(_buffer, 0, _bufferSize);
}
public void SendMessageToServer()
{
Client client = new Client(_buffer, _bufferSize);
client.SendMessageToServer();
}
public T GetPacketHeader<T>(ref byte[] buffer)
{
return Helper.BytesToStructure<T>(ref buffer);
}
}
}

View file

@ -2,8 +2,8 @@ using System.IO.Pipes;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using service.Types;
using service.messages;
using System;
using System.Reflection.PortableExecutable;
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
#pragma warning disable CS8600
@ -57,24 +57,13 @@ namespace service
{
try
{
if (_pipeServer.Read(_header, 0, _headerSize) > 0)
if (_pipeServer.InBufferSize > 0)
{
// for now the header is only an int... LOL
int header = BitConverter.ToInt32(_header, 0);
_logger.LogInformation("Message received at pipe server");
_logger.LogInformation("Message received with id: {0}", header);
switch (header)
{
case (int)MESSAGE_TYPE.MESSAGE_TYPE_REPORT:
_logger.LogDebug("We are inside the message report case");
Report report = new Report(_pipeServer, _headerSize);
break;
case (int)MESSAGE_TYPE.MESSAGE_TYPE_RECEIVE:
Receive receive = new Receive(_pipeServer, _headerSize);
break;
}
Message message = new Message(_pipeServer);
await message.ReadPipeBuffer();
message.SendMessageToServer();
}
}
catch (Exception ex)

View file

@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace service.messages
{
public class Message
{
private NamedPipeServerStream _pipeServer;
private int _packetHeaderSize;
public Message(NamedPipeServerStream pipeServer, int packetHeaderSize)
{
_pipeServer = pipeServer;
_packetHeaderSize = packetHeaderSize;
}
public void ReadPipeBuffer(ref byte[] buffer, int bufferSize )
{
_pipeServer.Read(buffer, 0, bufferSize - _packetHeaderSize);
}
public T GetPacketHeader<T>(ref byte[] buffer)
{
return Helper.BytesToStructure<T>(ref buffer);
}
}
}

View file

@ -1,50 +0,0 @@
using Serilog;
using System;
using System.Collections.Generic;
using System.IO.Pipes;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace service.messages
{
public class Receive : Message
{
private byte[] _buffer;
private static int RECEIVE_BUFFER_SIZE = 8192;
private enum RECEIVE_TYPE
{
SERVER_SEND_MODULE_INTEGRITY_CHECK = 10
}
public Receive(NamedPipeServerStream pipeServer, int pipePacketHeaderSize)
: base(pipeServer, pipePacketHeaderSize)
{
_buffer = new byte[RECEIVE_BUFFER_SIZE];
StoreMessage();
}
public void StoreMessage()
{
ReadPipeBuffer(ref _buffer, RECEIVE_BUFFER_SIZE);
Types.Receive.PIPE_PACKET_SEND_EXTENSION_HEADER header =
GetPacketHeader<Types.Receive.PIPE_PACKET_SEND_EXTENSION_HEADER>(ref _buffer);
PrintPacketInformation(header);
}
private void PrintPacketInformation(Types.Receive.PIPE_PACKET_SEND_EXTENSION_HEADER header)
{
Log.Information("Incoming packet count: {0:x}, current packet num: {1:x}, current packet size: {2:x}, total packet size: {3:x}",
header.total_incoming_packet_count,
header.current_packet_number,
header.packet_size,
header.total_incoming_packet_size);
}
}
}

View file

@ -1,164 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO.Pipes;
using System.Linq;
using service;
using System.Runtime.ConstrainedExecution;
using System.Text;
using System.Threading.Tasks;
using service.Types.Reports;
using Serilog;
namespace service.messages
{
public class Report : Message
{
private byte[] _buffer;
private static int REPORT_BUFFER_SIZE = 1024;
private enum REPORT_TYPE
{
REPORT_PROCESS_MODULE_FAILURE = 10,
REPORT_PROCESS_THREAD_START_ADDRESS_FAILURE = 20,
REPORT_PAGE_PROTECTION_VERIFICATION = 30,
REPORT_PATTERN_SCAN_FAILURE = 40,
REPORT_NMI_CALLBACK_FAILURE = 50,
REPORT_KERNEL_MODULE_FAILURE = 60,
REPORT_OPEN_HANDLE_FAILURE_REPORT = 70
}
public Report(NamedPipeServerStream pipeServer, int pipePacketHeaderSize)
: base(pipeServer, pipePacketHeaderSize)
{
_buffer = new byte[REPORT_BUFFER_SIZE];
ReadPipeBuffer(ref _buffer, REPORT_BUFFER_SIZE);
ConvertByteReportIntoStructure();
}
// This is fine for now as the report header is only an int
private int GetReportType()
{
return BitConverter.ToInt32( _buffer, 0 );
}
private Task ConvertByteReportIntoStructure()
{
int reportType = GetReportType();
Log.Information("REport type: {0}", reportType);
if (!Enum.IsDefined(typeof(REPORT_TYPE), reportType))
{
Log.Error("Enum value of {0} is invalid.", reportType);
return Task.CompletedTask;
}
switch(reportType)
{
case (int)REPORT_TYPE.REPORT_PROCESS_MODULE_FAILURE:
PrintProcessModuleFailureReport();
break;
case (int)REPORT_TYPE.REPORT_PROCESS_THREAD_START_ADDRESS_FAILURE:
PrintStartAddressFailure();
break;
case (int)REPORT_TYPE.REPORT_PAGE_PROTECTION_VERIFICATION:
PrintPageProtectionFailure();
break;
case (int)REPORT_TYPE.REPORT_PATTERN_SCAN_FAILURE:
PrintPatternScanFailure();
break;
case (int)REPORT_TYPE.REPORT_NMI_CALLBACK_FAILURE:
PrintNmiCallbackFailure();
break;
case (int)REPORT_TYPE.REPORT_KERNEL_MODULE_FAILURE:
PrintKernelModuleFailure();
break;
case (int)REPORT_TYPE.REPORT_OPEN_HANDLE_FAILURE_REPORT:
PrintOpenHandleFailure();
break;
default:
break;
}
return Task.CompletedTask;
}
private void PrintProcessModuleFailureReport()
{
MODULE_VERIFICATION_CHECKSUM_FAILURE report = Helper.BytesToStructure<MODULE_VERIFICATION_CHECKSUM_FAILURE>(ref _buffer);
Log.Information("Report code: {0}, Base address: {1:x}, Size: {2:x}, Name: ",
report.ReportCode,
report.ModuleBaseAddress,
report.ModuleSize);
}
private void PrintStartAddressFailure()
{
PROCESS_THREAD_START_FAILURE report = Helper.BytesToStructure<PROCESS_THREAD_START_FAILURE>(ref _buffer);
Log.Information("Report code: {0}, Thread Id: {1:x}, Start Address: {2:x}",
report.ReportCode,
report.ThreadId,
report.StartAddress);
}
private void PrintPageProtectionFailure()
{
PAGE_PROTECTION_FAILURE report = Helper.BytesToStructure<PAGE_PROTECTION_FAILURE>(ref _buffer);
Log.Information("Report code: {0}, page base address: {1:x}, allocation protection {2:x}, allocation state: {3:x}, allocation type: {4:x}",
report.ReportCode,
report.PageBaseAddress,
report.AllocationProtection,
report.AllocationState,
report.AllocationType);
}
private void PrintPatternScanFailure()
{
PATTERN_SCAN_FAILURE report = Helper.BytesToStructure<PATTERN_SCAN_FAILURE>(ref _buffer);
Log.Information("Report code: {0}, signature id: {1:x}, Address: {2:x}",
report.ReportCode,
report.SignatureId,
report.Address);
}
private void PrintNmiCallbackFailure()
{
NMI_CALLBACK_FAILURE report = Helper.BytesToStructure<NMI_CALLBACK_FAILURE>(ref _buffer);
Log.Information("Report code: {0}, WereNmisDisabled: {1:x}, KThreadAddress: {2:x}, InvalidRip: {3:x}",
report.ReportCode,
report.WereNmisDisabled,
report.KThreadAddress,
report.InvalidRip);
}
private void PrintKernelModuleFailure()
{
MODULE_VALIDATION_FAILURE report = Helper.BytesToStructure<MODULE_VALIDATION_FAILURE>(ref _buffer);
Log.Information("Report code: {0}, REportType: {1:x}, DriverBaseAddress: {2:x}, DriverSize: {3:x}",
report.ReportCode,
report.ReportType,
report.DriverBaseAddress,
report.DriverSize);
}
private void PrintOpenHandleFailure()
{
OPEN_HANDLE_FAILURE_REPORT report = Helper.BytesToStructure<OPEN_HANDLE_FAILURE_REPORT>(ref _buffer);
Log.Information("Report code: {0}, ProcessID: {1:x}, ThreadId: {2:x}, DesiredAccess{3:x}",
report.ReportCode,
report.ProcessId,
report.ThreadId,
report.DesiredAccess);
}
}
}

View file

@ -1,27 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace service.messages
{
public class Send : Message
{
private byte[] _buffer;
private static int SEND_BUFFER_SIZE = 8192;
private enum SEND_TYPE
{
SEND_SIGNATURES_TO_SCAN = 10
}
public Send(NamedPipeServerStream pipeServer, int pipePacketHeaderSize)
: base(pipeServer, pipePacketHeaderSize)
{
_buffer = new byte[SEND_BUFFER_SIZE];
}
}
}

View file

@ -174,6 +174,8 @@ namespace global
struct ATTACH_PROCESS_REPORT
{
INT report_code;
UINT32 thread_id;
UINT64 thread_address;
};
}
}

View file

@ -201,13 +201,10 @@ VOID kernelmode::Driver::QueryReportQueue()
if ( header->count == 0 )
goto end;
LOG_INFO( "report count: %i", header->count );
for ( int i = 0; i < header->count; i++ )
for ( INT i = 0; i < header->count; i++ )
{
report_header = (REPORT_ID*)( ( UINT64 )buffer + sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT_HEADER ) + total_size );
LOG_INFO( "REport id: %i", report_header->report_id );
report_header = (REPORT_ID*)( ( UINT64 )buffer +
sizeof( global::report_structures::OPEN_HANDLE_FAILURE_REPORT_HEADER ) + total_size );
switch ( report_header->report_id )
{
@ -484,6 +481,25 @@ VOID kernelmode::Driver::ValidateKPRCBThreads()
this->report_interface->ServerSend( &report, bytes_returned, SERVER_SEND_MODULE_INTEGRITY_CHECK );
}
VOID kernelmode::Driver::CheckForAttachedThreads()
{
BOOLEAN status;
status = DeviceIoControl(
this->driver_handle,
IOCTL_DETECT_ATTACHED_THREADS,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
);
if ( status == NULL )
LOG_ERROR( "failed to check for attached threads %x", GetLastError() );
}
VOID kernelmode::Driver::CheckDriverHeartbeat()
{

View file

@ -18,6 +18,7 @@
#define IOCTL_SCAN_FOR_UNLINKED_PROCESS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2011, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_VALIDATE_KPRCB_CURRENT_THREAD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2012, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_PERFORM_INTEGRITY_CHECK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2013, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DETECT_ATTACHED_THREADS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x2014, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define MAX_REPORTS_PER_IRP 20
@ -49,6 +50,7 @@ namespace kernelmode
VOID RequestModuleExecutableRegions();
VOID ScanForUnlinkedProcess();
VOID PerformIntegrityCheck();
VOID CheckForAttachedThreads();
};
struct DRIVER_INITIATION_INFORMATION

View file

@ -45,3 +45,8 @@ VOID kernelmode::KManager::PerformIntegrityCheck()
{
this->thread_pool->QueueJob( [ this ]() { this->driver_interface->PerformIntegrityCheck(); } );
}
VOID kernelmode::KManager::CheckForAttachedThreads()
{
this->thread_pool->QueueJob( [ this ]() { this->driver_interface->CheckForAttachedThreads(); } );
}

View file

@ -25,6 +25,7 @@ namespace kernelmode
VOID RequestModuleExecutableRegionsForIntegrityCheck();
VOID ScanPoolsForUnlinkedProcesses();
VOID PerformIntegrityCheck();
VOID CheckForAttachedThreads();
};
}