内核上项目【让ntoskrnl.exe保护程序】

文章目录

简介

如题让ntoskrnl.exe保护我们的程序,乍眼一看好像挺强,实际操作主要是借用了一下ntoskrnl.exe中的jump ecx指令,在注册回调的时候第一个参数就是ecx,所以直接将回调函数注册成ntoskrnl.exe的jump ecx,真正的回调函数放到参数即可

代码

ExportFunc.h

c 复制代码
#pragma once
#include <ntifs.h>

typedef struct _KLDR_DATA_TABLE_ENTRY {
	LIST_ENTRY InLoadOrderLinks;
	PVOID ExceptionTable;
	ULONG ExceptionTableSize;
	// ULONG padding on IA64
	PVOID GpValue;
	PVOID NonPagedDebugInfo;
	PVOID DllBase;
	PVOID EntryPoint;
	ULONG SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	ULONG Flags;
	USHORT LoadCount;
	USHORT __Unused5;
	PVOID SectionPointer;
	ULONG CheckSum;
	// ULONG padding on IA64
	PVOID LoadedImports;
	PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, * PKLDR_DATA_TABLE_ENTRY;

EXTERN_C void* NTAPI PsGetProcessWow64Process(PEPROCESS Process);

EXTERN_C PVOID NTAPI PsGetProcessPeb(PEPROCESS Process);

NTKERNELAPI NTSTATUS ObReferenceObjectByName(
	__in PUNICODE_STRING ObjectName,
	__in ULONG Attributes,
	__in_opt PACCESS_STATE AccessState,
	__in_opt ACCESS_MASK DesiredAccess,
	__in POBJECT_TYPE ObjectType,
	__in KPROCESSOR_MODE AccessMode,
	__inout_opt PVOID ParseContext,
	__out PVOID* Object
);

NTSTATUS MmCopyVirtualMemory(
	IN PEPROCESS FromProcess,
	IN CONST VOID* FromAddress,
	IN PEPROCESS ToProcess,
	OUT PVOID ToAddress,
	IN SIZE_T BufferSize,
	IN KPROCESSOR_MODE PreviousMode,
	OUT PSIZE_T NumberOfBytesCopied
);

Search.h

c 复制代码
#pragma once
#include <ntifs.h>


typedef enum _SYSTEM_INFORMATION_CLASS {
	SystemBasicInformation,
	SystemProcessorInformation,             // obsolete...delete
	SystemPerformanceInformation,
	SystemTimeOfDayInformation,
	SystemPathInformation,
	SystemProcessInformation,
	SystemCallCountInformation,
	SystemDeviceInformation,
	SystemProcessorPerformanceInformation,
	SystemFlagsInformation,
	SystemCallTimeInformation,
	SystemModuleInformation,
	SystemLocksInformation,
	SystemStackTraceInformation,
	SystemPagedPoolInformation,
	SystemNonPagedPoolInformation,
	SystemHandleInformation,
	SystemObjectInformation,
	SystemPageFileInformation,
	SystemVdmInstemulInformation,
	SystemVdmBopInformation,
	SystemFileCacheInformation,
	SystemPoolTagInformation,
	SystemInterruptInformation,
	SystemDpcBehaviorInformation,
	SystemFullMemoryInformation,
	SystemLoadGdiDriverInformation,
	SystemUnloadGdiDriverInformation,
	SystemTimeAdjustmentInformation,
	SystemSummaryMemoryInformation,
	SystemMirrorMemoryInformation,
	SystemPerformanceTraceInformation,
	SystemObsolete0,
	SystemExceptionInformation,
	SystemCrashDumpStateInformation,
	SystemKernelDebuggerInformation,
	SystemContextSwitchInformation,
	SystemRegistryQuotaInformation,
	SystemExtendServiceTableInformation,
	SystemPrioritySeperation,
	SystemVerifierAddDriverInformation,
	SystemVerifierRemoveDriverInformation,
	SystemProcessorIdleInformation,
	SystemLegacyDriverInformation,
	SystemCurrentTimeZoneInformation,
	SystemLookasideInformation,
	SystemTimeSlipNotification,
	SystemSessionCreate,
	SystemSessionDetach,
	SystemSessionInformation,
	SystemRangeStartInformation,
	SystemVerifierInformation,
	SystemVerifierThunkExtend,
	SystemSessionProcessInformation,
	SystemLoadGdiDriverInSystemSpace,
	SystemNumaProcessorMap,
	SystemPrefetcherInformation,
	SystemExtendedProcessInformation,
	SystemRecommendedSharedDataAlignment,
	SystemComPlusPackage,
	SystemNumaAvailableMemory,
	SystemProcessorPowerInformation,
	SystemEmulationBasicInformation,
	SystemEmulationProcessorInformation,
	SystemExtendedHandleInformation,
	SystemLostDelayedWriteInformation,
	SystemBigPoolInformation,
	SystemSessionPoolTagInformation,
	SystemSessionMappedViewInformation,
	SystemHotpatchInformation,
	SystemObjectSecurityMode,
	SystemWatchdogTimerHandler,
	SystemWatchdogTimerInformation,
	SystemLogicalProcessorInformation,
	SystemWow64SharedInformation,
	SystemRegisterFirmwareTableInformationHandler,
	SystemFirmwareTableInformation,
	SystemModuleInformationEx,
	SystemVerifierTriageInformation,
	SystemSuperfetchInformation,
	SystemMemoryListInformation,
	SystemFileCacheInformationEx,
	MaxSystemInfoClass  // MaxSystemInfoClass should always be the last enum
} SYSTEM_INFORMATION_CLASS;

typedef struct _RTL_PROCESS_MODULE_INFORMATION {
	HANDLE Section;                 // Not filled in
	PVOID MappedBase;
	PVOID ImageBase;
	ULONG ImageSize;
	ULONG Flags;
	USHORT LoadOrderIndex;
	USHORT InitOrderIndex;
	USHORT LoadCount;
	USHORT OffsetToFileName;
	UCHAR  FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;

typedef struct _RTL_PROCESS_MODULES {
	ULONG NumberOfModules;
	RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;


NTSTATUS NTAPI ZwQuerySystemInformation(
	__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
	__out_bcount_opt(SystemInformationLength) PVOID SystemInformation,
	__in ULONG SystemInformationLength,
	__out_opt PULONG ReturnLength
);



typedef struct _FindCode
{
	UCHAR code[0x200];
	ULONG len;
	int offset;
	ULONG lastAddressOffset;
}FindCode, * PFindCode;


void initFindCodeStruct(PFindCode findCode, PCHAR code, ULONG_PTR offset, ULONG_PTR lastAddrOffset);

ULONG_PTR findAddressByCode(ULONG_PTR beginAddr, ULONG_PTR endAddr, PFindCode  findCode, ULONG numbers);

ULONG_PTR QuerySysModule(char* MoudleName, _Out_opt_ ULONG_PTR* module);

ULONG_PTR searchNtCode(char* code, int offset);

ULONG_PTR searchCode(char* moduleName, char* segmentName, char* code, int offset);

driver.c

c 复制代码
#include <ntifs.h>
#include"Search.h"

PVOID g_RegistrationHandle = NULL;
NTSYSCALLAPI PCHAR PsGetProcessImageFileName(IN PEPROCESS pProcess);


typedef struct _LDR_DATA_TABLE_ENTRY64
{
    LIST_ENTRY64    InLoadOrderLinks;
    LIST_ENTRY64    InMemoryOrderLinks;
    LIST_ENTRY64    InInitializationOrderLinks;
    PVOID            DllBase;
    PVOID            EntryPoint;
    ULONG            SizeOfImage;
    UNICODE_STRING    FullDllName;
    UNICODE_STRING     BaseDllName;
    ULONG            Flags;
    USHORT            LoadCount;
    USHORT            TlsIndex;
    PVOID            SectionPointer;
    ULONG            CheckSum;
    PVOID            LoadedImports;
    PVOID            EntryPointActivationContext;
    PVOID            PatchInformation;
    LIST_ENTRY64    ForwarderLinks;
    LIST_ENTRY64    ServiceTagLinks;
    LIST_ENTRY64    StaticLinks;
    PVOID            ContextInformation;
    ULONG64            OriginalBase;
    LARGE_INTEGER    LoadTime;
} LDR_DATA_TABLE_ENTRY64, * PLDR_DATA_TABLE_ENTRY64;

OB_PREOP_CALLBACK_STATUS PreOperationCallback(_In_ PVOID RegistrationContext,
    _Inout_ POB_PRE_OPERATION_INFORMATION PreInfo)
{
    //获取操作目标进程
    PEPROCESS process = (PEPROCESS)PreInfo->Object;

    if (PreInfo->ObjectType == *PsThreadType) {
        process = IoThreadToProcess((PETHREAD)PreInfo->Object);
    }
    if (PreInfo->ObjectType == *PsProcessType) {
        process = (PEPROCESS)PreInfo->Object;
    }
    //获取进程名
    PUCHAR processName = PsGetProcessImageFileName(process);
    PUCHAR SelfprocessName = PsGetProcessImageFileName(IoGetCurrentProcess());

    //自身非保护进程,但是目标确是受保护的进程
    if (_stricmp((char*)SelfprocessName, "Notepad.exe") != 0 && _stricmp((char*)processName, "Notepad.exe")==0) {
        //防止自身句柄被打开
        PreInfo->Parameters->CreateHandleInformation.DesiredAccess = 0;
        PreInfo->Parameters->CreateHandleInformation.OriginalDesiredAccess = 0;
        
        return OB_PREOP_SUCCESS;
    }
 
    return OB_PREOP_SUCCESS;
}

NTSTATUS DriverUnload(
    _In_ PDRIVER_OBJECT DriverObject
)
{
    if(g_RegistrationHandle) ObUnRegisterCallbacks(g_RegistrationHandle);
    
    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(
    _In_ PDRIVER_OBJECT DriverObject,
    _In_ PUNICODE_STRING RegistryPath
)
{
    NTSTATUS status = STATUS_SUCCESS;

    OB_OPERATION_REGISTRATION obOperationRegistrations;
    obOperationRegistrations.ObjectType = PsProcessType;
    obOperationRegistrations.Operations |= OB_OPERATION_HANDLE_CREATE;
    obOperationRegistrations.Operations |= OB_OPERATION_HANDLE_DUPLICATE;
    obOperationRegistrations.PreOperation = PreOperationCallback;
    obOperationRegistrations.PostOperation = NULL;

    ULONG64 jmpRcx = searchCode("ntoskrnl.exe", ".text", "FFE1", 0);

    OB_CALLBACK_REGISTRATION obCallbackRegistration = { 0 };
    UNICODE_STRING altitude = { 0 };
    RtlInitUnicodeString(&altitude, L"1000");
    obCallbackRegistration.Version = ObGetFilterVersion();
    obCallbackRegistration.OperationRegistrationCount = 1;
    obCallbackRegistration.RegistrationContext = jmpRcx;
    obCallbackRegistration.Altitude = altitude;
    obCallbackRegistration.OperationRegistration = &obOperationRegistrations;
    
    PLDR_DATA_TABLE_ENTRY64 ldrDataTable;
    ldrDataTable = (PLDR_DATA_TABLE_ENTRY64)DriverObject->DriverSection;
    ldrDataTable->Flags |= 0x20;  //过MmVerifyCallbackFunction,以保证ObRegisterCallbacks可以注册上回调

    NTSTATUS status2 = ObRegisterCallbacks(&obCallbackRegistration, &g_RegistrationHandle);
    
    DriverObject->DriverUnload = DriverUnload;
    
    return status;
}

Search.c

c 复制代码
#include "Search.h"
#include <ntimage.h>
#include "ExportFunc.h"

UCHAR charToHex(UCHAR* ch)
{
	unsigned char temps[2] = { 0 };
	for (int i = 0; i < 2; i++)
	{
		if (ch[i] >= '0' && ch[i] <= '9')
		{
			temps[i] = (ch[i] - '0');
		}
		else if (ch[i] >= 'A' && ch[i] <= 'F')
		{
			temps[i] = (ch[i] - 'A') + 0xA;
		}
		else if (ch[i] >= 'a' && ch[i] <= 'f')
		{
			temps[i] = (ch[i] - 'a') + 0xA;
		}
	}
	return ((temps[0] << 4) & 0xf0) | (temps[1] & 0xf);
}



void initFindCodeStruct(PFindCode findCode, PCHAR code, ULONG_PTR offset, ULONG_PTR lastAddrOffset)
{

	memset(findCode, 0, sizeof(FindCode));

	findCode->lastAddressOffset = lastAddrOffset;
	findCode->offset = offset;

	PCHAR pTemp = code;
	ULONG_PTR i = 0;
	for (i = 0; *pTemp != '\0'; i++)
	{
		if (*pTemp == '*' || *pTemp == '?')
		{
			findCode->code[i] = *pTemp;
			pTemp++;
			continue;
		}

		findCode->code[i] = charToHex(pTemp);
		pTemp += 2;

	}

	findCode->len = i;
}


ULONG_PTR findAddressByCode(ULONG_PTR beginAddr, ULONG_PTR endAddr, PFindCode  findCode, ULONG numbers)
{
	ULONG64 j = 0;
	LARGE_INTEGER rtna = { 0 };

	for (ULONG_PTR i = beginAddr; i <= endAddr; i++)
	{
		if (!MmIsAddressValid((PVOID)i))
		{
			i = i & (~0xfff) + PAGE_SIZE - 1;
			continue;
		}



		for (j = 0; j < numbers; j++)
		{
			FindCode  fc = findCode[j];
			ULONG_PTR tempAddress = i;

			UCHAR* code = (UCHAR*)(tempAddress + fc.offset);
			BOOLEAN isFlags = FALSE;

			for (ULONG_PTR k = 0; k < fc.len; k++)
			{
				if (!MmIsAddressValid((PVOID)(code + k)))
				{
					isFlags = TRUE;
					break;
				}

				if (fc.code[k] == '*' || fc.code[k] == '?') continue;

				if (code[k] != fc.code[k])
				{
					isFlags = TRUE;
					break;
				}
			}

			if (isFlags) break;

		}

		//找到了
		if (j == numbers)
		{
			rtna.QuadPart = i;
			rtna.LowPart += findCode[0].lastAddressOffset;
			break;
		}

	}

	return rtna.QuadPart;
}

char* CharToUper(char* wstr, BOOLEAN isAllocateMemory)
{
	char* ret = NULL;

	if (isAllocateMemory)
	{
		int len = strlen(wstr) + 2;
		ret = ExAllocatePool(PagedPool, len);
		memset(ret, 0, len);
		memcpy(ret, wstr, len - 2);
	}
	else
	{
		ret = wstr;
	}

	_strupr(ret);

	return ret;
}

//返回值为模块的大小
ULONG_PTR QuerySysModule(char* MoudleName, _Out_opt_ ULONG_PTR* module)
{
	RTL_PROCESS_MODULES info;
	ULONG retPro = NULL;
	ULONG_PTR moduleSize = 0;



	NTSTATUS ststas = ZwQuerySystemInformation(SystemModuleInformation, &info, sizeof(info), &retPro);
	char* moduleUper = CharToUper(MoudleName, TRUE);

	if (ststas == STATUS_INFO_LENGTH_MISMATCH)
	{
		//申请长度
		ULONG len = retPro + sizeof(RTL_PROCESS_MODULES);
		PRTL_PROCESS_MODULES mem = (PRTL_PROCESS_MODULES)ExAllocatePool(PagedPool, len);
		memset(mem, 0, len);
		ststas = ZwQuerySystemInformation(SystemModuleInformation, mem, len, &retPro);

		if (!NT_SUCCESS(ststas))
		{
			ExFreePool(moduleUper);
			ExFreePool(mem);
			return 0;
		}

		//开始查询

		if (strstr(MoudleName, "ntkrnlpa.exe") || strstr(MoudleName, "ntoskrnl.exe"))
		{
			PRTL_PROCESS_MODULE_INFORMATION ModuleInfo = &(mem->Modules[0]);
			*module = ModuleInfo->ImageBase;
			moduleSize = ModuleInfo->ImageSize;
		}
		else
		{
			for (int i = 0; i < mem->NumberOfModules; i++)
			{
				PRTL_PROCESS_MODULE_INFORMATION processModule = &mem->Modules[i];
				CharToUper(processModule->FullPathName, FALSE);
				if (strstr(processModule->FullPathName, moduleUper))
				{
					if (module)
					{
						*module = processModule->ImageBase;

					}

					moduleSize = processModule->ImageSize;

					break;
				}

			}
		}




		ExFreePool(mem);
	}


	ExFreePool(moduleUper);
	return moduleSize;
}


ULONG_PTR searchNtCode(char* code, int offset)
{
	FindCode fs[1] = { 0 };
	initFindCodeStruct(&fs[0], code, 0, offset);


	SIZE_T moduleBase = 0;
	ULONG size = QuerySysModule("ntoskrnl.exe", &moduleBase);


	ULONG_PTR func = findAddressByCode(moduleBase, size + moduleBase, fs, 1);

	return func;
}

ULONG_PTR searchCode(char* moduleName, char* segmentName, char* code, int offset)
{
	FindCode fs[1] = { 0 };
	initFindCodeStruct(&fs[0], code, 0, offset);
	SIZE_T moduleBase = 0;
	ULONG size = QuerySysModule(moduleName, &moduleBase);

	if (!moduleBase)
	{
		return 0;
	}


	PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)moduleBase;

	PIMAGE_NT_HEADERS pNts = (PIMAGE_NT_HEADERS)((PUCHAR)moduleBase + pDos->e_lfanew);

	PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNts);

	PIMAGE_SECTION_HEADER pTemp = NULL;

	for (int i = 0; i < pNts->FileHeader.NumberOfSections; i++)
	{
		char bufName[9] = { 0 };
		memcpy(bufName, pSection->Name, 8);
		if (_stricmp(bufName, segmentName) == 0)
		{
			pTemp = pSection;
			break;
		}
		pSection++;
	}

	if (pTemp)
	{
		moduleBase = pSection->VirtualAddress + moduleBase;
		size = pSection->SizeOfRawData;
	}

	PVOID mem = ExAllocatePool(NonPagedPool, size);
	SIZE_T retSize = 0;
	MmCopyVirtualMemory(IoGetCurrentProcess(), moduleBase, IoGetCurrentProcess(), mem, size, KernelMode, &retSize);

	ULONG_PTR func = findAddressByCode(moduleBase, size + moduleBase, fs, 1);
	ExFreePool(mem);
	return func;
}

参考资料

火哥五期资料

相关推荐
李游Leo17 分钟前
HarmonyOS 7 + ArkUI + Adaptive Layout 学习笔记:折叠屏多形态布局适配与窗口状态响应机制【鸿蒙心迹】
笔记·学习·harmonyos
kyrie_sakura36 分钟前
大模型学习6 -- 深度学习 1 概述和PyTorch
pytorch·深度学习·学习
额额额对了1 小时前
嵌入式 ADC 从入门到实战:基于 i.MX6ULL 的裸机驱动开发
驱动开发·嵌入式硬件·arm
Code Man1 小时前
实现 Android 字符设备驱动
android·驱动开发·lineageos
sukalot1 小时前
Windows 驱动实例分析系列:libwdi 驱动分析 - examples 篇(四)
windows·驱动开发
传奇开心果编程1 小时前
【Flutter入门练中学】第3课:滚动与列表
android·学习·flutter·ui·ios
WangWei_CM1 小时前
Windows 会话、Session 0 与进程 Token 隔离身份
windows
李游Leo1 小时前
HarmonyOS 7 + ArkTS + Image Kit 学习笔记:图像超分处理链路与 PixelMap 数据流实践【鸿蒙心迹】
笔记·学习·harmonyos
波力海苔夹心脆6751 小时前
C# 海康威视摄像头二次开发入门:HCNetSDK 登录、实时预览、云台控制、录像与抓图(WinForms 实战)
开发语言·windows·经验分享·tcp/ip·c#
李游Leo2 小时前
HarmonyOS 7 + ArkTS + NAPI 学习笔记:Native 模块桥接、CMake 构建与跨语言调用实践【鸿蒙心迹】
笔记·学习·harmonyos