#include <ntifs.h>
#include <wmistr.h>
#include <intrin.h>
#include <ntimage.h>
#define EtwpStartTrace 1
#define EtwpStopTrace 2
#define EtwpQueryTrace 3
#define EtwpUpdateTrace 4
#define EtwpFlushTrace 5
#define EVENT_TRACE_SYSTEM_LOGGER_MODE 0x02000000
#define WNODE_FLAG_TRACED_GUID 0x00020000
#define EVENT_TRACE_BUFFERING_MODE 0x00000400
#define EVENT_TRACE_FLAG_SYSTEMCALL 0x00000080
#define IA32_LSTAR_MSR 0xC0000082
typedef struct _WMI_LOGGER_INFORMATION
{
WNODE_HEADER Wnode; // WNODE_HEADER是公开的,这里就不贴上来了
ULONG BufferSize;
ULONG MinimumBuffers;
ULONG MaximumBuffers;
ULONG MaximumFileSize;
ULONG LogFileMode;
ULONG FlushTimer;
ULONG EnableFlags;
union
{
LONG AgeLimit;
LONG FlushThreshold;
};
ULONG Wow;
LONG Padding_719;
union
{
PVOID LogFileHandle;
ULONGLONG LogFileHandle64;
};
union
{
ULONG NumberOfBuffers;
ULONG InstanceCount;
};
union
{
ULONG FreeBuffers;
ULONG InstanceId;
};
union
{
ULONG EventsLost;
ULONG NumberOfProcessors;
};
ULONG BuffersWritten;
union
{
ULONG LogBuffersLost;
ULONG Flags;
};
ULONG RealTimeBuffersLost;
union
{
PVOID LoggerThreadId;
ULONGLONG LoggerThreadId64;
};
union
{
UNICODE_STRING LogFileName;
STRING64 LogFileName64;
};
union
{
UNICODE_STRING LoggerName;
STRING64 LoggerName64;
};
ULONG RealTimeConsumerCount;
ULONG SpareUlong;
union
{
union
{
PVOID LoggerExtension;
ULONGLONG LoggerExtension64;
};
} DUMMYUNIONNAME10;
} WMI_LOGGER_INFORMATION, * PWMI_LOGGER_INFORMATION;
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemModuleInformation = 11
} SYSTEM_INFORMATION_CLASS;
typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY
{
ULONG Unknow1;
ULONG Unknow2;
ULONG Unknow3;
ULONG Unknow4;
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT NameLength;
USHORT LoadCount;
USHORT ModuleNameOffset;
char ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, * PSYSTEM_MODULE_INFORMATION_ENTRY;
typedef struct _SYSTEM_MODULE_INFORMATION
{
ULONG Count;
SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
}SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;
const GUID CkclSessionGuid = { 0x54dea73a, 0xed1f, 0x42a4, { 0xaf, 0x71, 0x3e, 0x63, 0xd0, 0x56, 0xf1, 0x74 } };
const GUID session_guid = { 0x9E814AAD, 0x3204, 0x11D2, { 0x9A, 0x82, 0x0, 0x60, 0x8, 0xA8, 0x69, 0x39 } };
NTSYSCALLAPI
NTSTATUS
NTAPI
ZwTraceControl(
_In_ ULONG FunctionCode,
_In_reads_bytes_opt_(InBufferLen) PVOID InBuffer,
_In_ ULONG InBufferLen,
_Out_writes_bytes_opt_(OutBufferLen) PVOID OutBuffer,
_In_ ULONG OutBufferLen,
_Out_ PULONG ReturnLength
);
NTSYSCALLAPI NTSTATUS
ZwQuerySystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
NTSTATUS OpenEtwLogger() {
ULONG ret;
PWMI_LOGGER_INFORMATION pWmiLogger = (PWMI_LOGGER_INFORMATION)ExAllocatePool(NonPagedPool , PAGE_SIZE);
memset(pWmiLogger, 0, PAGE_SIZE);
pWmiLogger->BufferSize = sizeof(ULONG);
pWmiLogger->MaximumBuffers = pWmiLogger->MinimumBuffers = 2;
pWmiLogger->Wnode.ClientContext = 3;
pWmiLogger->Wnode.Guid = CkclSessionGuid;
pWmiLogger->Wnode.BufferSize = PAGE_SIZE;
pWmiLogger->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
pWmiLogger->LogFileMode = EVENT_TRACE_BUFFERING_MODE;
RtlInitUnicodeString(&pWmiLogger->LoggerName , L"Circular Kernel Context Logger");
NTSTATUS status = ZwTraceControl(EtwpStartTrace, pWmiLogger , PAGE_SIZE , pWmiLogger , PAGE_SIZE , &ret);
pWmiLogger->EnableFlags = EVENT_TRACE_FLAG_SYSTEMCALL;
status = ZwTraceControl(EtwpUpdateTrace, pWmiLogger, PAGE_SIZE, pWmiLogger, PAGE_SIZE, &ret);
if (!NT_SUCCESS(status)) {
DbgPrint("Etw打开失败\n");
return status;
}
DbgPrint("Open Etw Success->%d\n",status);
return STATUS_SUCCESS;
}
NTSTATUS EndEtwLogger() {
ULONG ret;
PWMI_LOGGER_INFORMATION pWmiLogger = (PWMI_LOGGER_INFORMATION)ExAllocatePool(NonPagedPool, PAGE_SIZE);
memset(pWmiLogger, 0, PAGE_SIZE);
pWmiLogger->BufferSize = sizeof(ULONG);
pWmiLogger->MaximumBuffers = pWmiLogger->MinimumBuffers = 2;
pWmiLogger->Wnode.ClientContext = 3;
pWmiLogger->Wnode.Guid = CkclSessionGuid;
pWmiLogger->Wnode.BufferSize = PAGE_SIZE;
pWmiLogger->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
pWmiLogger->LogFileMode = EVENT_TRACE_BUFFERING_MODE;
RtlInitUnicodeString(&pWmiLogger->LoggerName, L"Circular Kernel Context Logger");
NTSTATUS status = ZwTraceControl(EtwpStopTrace, pWmiLogger, PAGE_SIZE, pWmiLogger, PAGE_SIZE, &ret);
if (!NT_SUCCESS(status)) {
DbgPrint("Etw关闭失败\n");
return status;
}
DbgPrint("End Etw Success->%d\n", status);
return status;
}
ULONG64 GetKernelBase(PULONG dwSize) {
ULONG ret;
PSYSTEM_MODULE_INFORMATION pSystemInfo = (PSYSTEM_MODULE_INFORMATION)ExAllocatePool(NonPagedPool, 1024 * 1024);
if (pSystemInfo == NULL) {
return 0;
}
NTSTATUS status = ZwQuerySystemInformation(SystemModuleInformation, pSystemInfo, 1024 * 1024, &ret);
if (!NT_SUCCESS(status)) {
DbgPrint("模块查询失败\n");
return 0;
}
for (ULONG dwCount = 0; dwCount < pSystemInfo->Count; dwCount++) {
if (!strcmp(pSystemInfo->Module[dwCount].ImageName + pSystemInfo->Module[dwCount].ModuleNameOffset, "ntoskrnl.exe")) {
*dwSize = pSystemInfo->Module[dwCount].Size;
return (ULONG64)(pSystemInfo->Module[dwCount].Base);
}
}
return 0;
}
//0x2c, 0x08, 0x04, 0x38, 0x0c
ULONG64 GetEtwpDebuggerDataAddr() {
ULONG dwSize;
ULONG64 NtoskrnlBase = GetKernelBase(&dwSize);
if (!NtoskrnlBase || !dwSize) {
DbgPrint("模块查询失败\n");
return 0;
}
ULONG64 StartAddress;
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)NtoskrnlBase;
PIMAGE_NT_HEADERS64 pNtHeader = (PIMAGE_NT_HEADERS64)((ULONG64)pDosHeader + pDosHeader->e_lfanew);
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHeader);
for (ULONG i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++) {
if (!strcmp(pSection[i].Name , ".data")) {
StartAddress = pSection[i].VirtualAddress + (ULONG64)pDosHeader;
for (ULONG64 Addr = StartAddress; Addr < StartAddress + pSection[i].Misc.VirtualSize; Addr++) {
if (MmIsAddressValid(Addr)) {
if (*(PUCHAR)(Addr) == 0x2C && *(PUCHAR)(Addr + 0x1) == 0x08 && *(PUCHAR)(Addr + 0x2) == 0x04 && *(PUCHAR)(Addr + 0x3) == 0x38 && *(PUCHAR)(Addr + 0x4) == 0x0C) {
DbgPrint("EtwpDebuggerDataAddr->%p\n" ,Addr-0x2);
return Addr - 0x2;
}
}
}
}
}
return 0;
}
NTSTATUS detour_NtCreateFile(
_Out_ PHANDLE FileHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_opt_ PLARGE_INTEGER AllocationSize,
_In_ ULONG FileAttributes,
_In_ ULONG ShareAccess,
_In_ ULONG CreateDisposition,
_In_ ULONG CreateOptions,
_In_reads_bytes_opt_(EaLength) PVOID EaBuffer,
_In_ ULONG EaLength) {
DbgPrint("NtCreateFile 已被接管\n");
return NtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength);
}
ULONG64 FakeGetCpuClock() {
if (ExGetPreviousMode() == KernelMode) {
return __rdtsc();
}
UNICODE_STRING TargetFuncName = RTL_CONSTANT_STRING(L"NtCreateFile");
ULONG64 TargetFuncAddr = (ULONG64)MmGetSystemRoutineAddress(&TargetFuncName);
ULONG64 SysCallAddr = (ULONG64)__readmsr(IA32_LSTAR_MSR);
PULONG64 Stack_Top = (PULONG64)__readgsqword(0x1A8);
PULONG64 Cut_Stack = (PULONG64)_AddressOfReturnAddress();
ULONG magic_1 = 0x501802ul;
USHORT magic = 0xf33ul;
USHORT Stack_GetMagic;
ULONG Stack_GetMagic_1;
for (; Cut_Stack < Stack_Top; Cut_Stack++) {
Stack_GetMagic = *(PUSHORT)Cut_Stack;
if (Stack_GetMagic != magic) {
continue;
}
Cut_Stack++;
Stack_GetMagic_1 = *(PULONG)Cut_Stack;
if (Stack_GetMagic_1 != magic_1) {
continue;
}
for (; Cut_Stack < Stack_Top; Cut_Stack++) {
if (*Cut_Stack >= (ULONG64)PAGE_ALIGN(SysCallAddr) && *Cut_Stack <= (ULONG64)PAGE_ALIGN(SysCallAddr + PAGE_SIZE * 2)) {
PVOID* SysCallTarget = (PVOID*)&Cut_Stack[0x9];
if ((ULONG64)*SysCallTarget == TargetFuncAddr) {
*SysCallTarget = detour_NtCreateFile;
}
break;
}
}
break;
}
return __rdtsc();
}
/*nt!_WMI_LOGGER_CONTEXT
+0x000 LoggerId : 2
+0x004 BufferSize : 0x1000
+0x008 MaximumEventSize : 0xfb8
+0x00c LoggerMode : 0x2800480
+0x010 AcceptNewEvents : 0n0
+0x014 EventMarker : [2] 0xc0130000
+0x01c ErrorMarker : 0xc00d0000
+0x020 SizeMask : 0xffff
+0x028 GetCpuClock : 0xfffff807`8033d450 int64 nt!EtwpGetCycleCount+0
+0x030 LoggerThread : (null)
*/
BOOLEAN HookEtwGetCpuClock() {
ULONG64 EtwpDebuggerDataAdd = GetEtwpDebuggerDataAddr();
ULONG64 EtwpDebuggerDataSilo = *(PULONG64)(EtwpDebuggerDataAdd + 0x10);
ULONG64 CkclWmiLoggerContext = *(PULONG64)(EtwpDebuggerDataSilo + 0x10);
DbgPrint("CkclWmiLoggerContext Addr->%p\n" , CkclWmiLoggerContext);
PULONG64 GetCpuClockAddr = (PULONG64)(CkclWmiLoggerContext+0x28);
*GetCpuClockAddr = (ULONG64)FakeGetCpuClock;
return TRUE;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject) {
EndEtwLogger();
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject , PUNICODE_STRING Reg_Path) {
pDriverObject->DriverUnload = DriverUnload;
OpenEtwLogger();
HookEtwGetCpuClock();
return STATUS_SUCCESS;
}
在win10 1901测试下效果