文章目录
简介
如题让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;
}
参考资料
火哥五期资料