内核上项目【让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;
}

参考资料

火哥五期资料

相关推荐
hu1j32 分钟前
[HTB] 靶机学习(十二)Eureka
学习·安全·web安全·网络安全·云原生·eureka
搞机械的假程序猿38 分钟前
普中51单片机学习笔记-点亮第一个LED
笔记·学习·51单片机
菜鸟‍1 小时前
【论文学习】基于 Transformer 的图像分割模型
深度学习·学习·transformer
Han.miracle3 小时前
Java的多线程——多线程(3)线程安全
java·开发语言·jvm·学习·安全·线程·多线程
d111111111d3 小时前
STM32外设学习--TIM定时器--输入捕获---测频方法。
stm32·单片机·学习
刘恒1234567894 小时前
Windows 10 docker 配置(PHP+Nginx+Mysql)(thinkphp5项目)环境
windows·docker·php
学习_学习_再学习4 小时前
ffmpeg学习记录
学习·ffmpeg
im_AMBER5 小时前
算法笔记 10
笔记·学习·算法·leetcode
苏比的博客7 小时前
Windows MFC添加类,变量,类导向
c++·windows·mfc
qzhqbb7 小时前
神经网络—— 学习与感知器
神经网络·学习