NTSTATUS

 

Values are 32 bit and are laid out as follows. The following diagram is independent of endianness; that is, the diagram is shown in host byte order and merely shows the layout of the numbering space.

Any protocol that uses NTSTATUS values on the wire is responsible for stating the order that the bytes are placed on the wire.

Sev (2 bits): Severity. Severity codes are as follows.

 

C (1 bit): Customer. This specifies if the value is customer- or Microsoft-defined. This bit is set for customer-defined values and clear for Microsoft-defined values.<4>

N (1 bit): Reserved. MUST be set to 0 so that it is possible to map an NTSTATUS value to an equivalent HRESULT value, as specified in section 2.1, by setting this bit.

Facility (12 bits): A value that, together with the C bit, indicates the numbering space to use for the Code field.<5>

Code (2 bytes): The remainder of the error code. Vendors SHOULD reuse the values in the following table with their indicated meaning or define their own values with the C bit set. Choosing any other value with the C bit clear runs the risk of a collision in the future.

源代码: filter.cpp 源文件: #include "filter.h" #include "ioctl.h" ///global var wddm_filter_t __gbl_wddm_filter; #define DEV_NAME L"\\Device\\WddmFilterCtrlDevice" #define DOS_NAME L"\\DosDevices\\WddmFilterCtrlDevice" ///// static NTSTATUS create_ctrl_device() { NTSTATUS status = STATUS_SUCCESS; PDEVICE_OBJECT devObj; UNICODE_STRING dev_name; UNICODE_STRING dos_name; RtlInitUnicodeString(&dev_name, DEV_NAME); RtlInitUnicodeString(&dos_name, DOS_NAME); status = IoCreateDevice( wf->driver_object, 0, &dev_name, //dev name FILE_DEVICE_VIDEO, FILE_DEVICE_SECURE_OPEN, FALSE, &devObj); if (!NT_SUCCESS(status)) { DPT("IoCreateDevice err=0x%X\n", status ); return status; } status = IoCreateSymbolicLink(&dos_name, &dev_name); if (!NT_SUCCESS(status)) { DPT("IoCreateSymbolicLink err=0x%X\n", status ); IoDeleteDevice(devObj); return status; } // attach wf->dxgkrnl_nextDevice = IoAttachDeviceToDeviceStack(devObj, wf->dxgkrnl_pdoDevice); if (!wf->dxgkrnl_nextDevice) { DPT("IoAttachDeviceToDeviceStack error.\n"); IoDeleteDevice(devObj); IoDeleteSymbolicLink(&dos_name); return STATUS_NOT_FOUND; } devObj->Flags |= DO_POWER_PAGABLE | DO_BUFFERED_IO | DO_DIRECT_IO; wf->ctrl_devobj = devObj; ///// return status; } NTSTATUS create_wddm_filter_ctrl_device(PDRIVER_OBJECT drvObj ) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING drvPath; UNICODE_STRING drvName; RtlInitUnicodeString(&drvPath, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\SERVICES\\DXGKrnl"); RtlInitUnicodeString(&drvName, L"\\Device\\Dxgkrnl"); // RtlZeroMemory(wf, sizeof(wddm_filter_t)); wf->driver_object = drvObj; KeInitializeSpinLock(&wf->spin_lock); InitializeListHead(&wf->vidpn_if_head); InitializeListHead(&wf->topology_if_head); //����dxgkrnl.sys���� status = ZwLoadDriver(&drvPath); if (!NT_SUCCESS(status)) { if (status != STATUS_IMAGE_ALREADY_LOADED) { DPT("ZwLoadDriver error st=0x%X\n", status ); return status; } } status = IoGetDeviceObjectPointer(&drvName, FILE_ALL_ACCESS, &wf->dxgkrnl_fileobj, &wf->dxgkrnl_pdoDevice); if (!NT_SUCCESS(status)) { DPT("IoGetDeviceObjectPointer Get DxGkrnl err=0x%X\n", status ); return status; } KEVENT evt; IO_STATUS_BLOCK ioStatus; KeInitializeEvent(&evt, NotificationEvent, FALSE); PIRP pIrp = IoBuildDeviceIoControlRequest( IOCTL_VIDEO_DDI_FUNC_REGISTER, //0x23003F , dxgkrnl.sys ����ע�ắ�� wf->dxgkrnl_pdoDevice, NULL, 0, &wf->dxgkrnl_dpiInit, sizeof(PDXGKRNL_DPIINITIALIZE), TRUE, // IRP_MJ_INTERNAL_DEVICE_CONTROL &evt, &ioStatus); if (!pIrp) { DPT("IoBuildDeviceIoControlRequest return NULL.\n"); ObDereferenceObject(wf->dxgkrnl_fileobj); return STATUS_NO_MEMORY; } status = IoCallDriver(wf->dxgkrnl_pdoDevice, pIrp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&evt, Executive, KernelMode, FALSE, NULL); status = ioStatus.Status; } if (!wf->dxgkrnl_dpiInit) {// DPT("Can not Load PDXGKRNL_DPIINITIALIZE function address. st=0x%X\n", status ); ObDereferenceObject(wf->dxgkrnl_fileobj); return STATUS_NOT_FOUND; } ///create filter device status = create_ctrl_device(); if (!NT_SUCCESS(status)) { ObDereferenceObject(wf->dxgkrnl_fileobj); return status; } //// return status; } NTSTATUS log_event(PUNICODE_STRING str) { NTSTATUS status = STATUS_SUCCESS; return status; } filter.h 源文件: #pragma once #include <ntddk.h> #include <wdm.h> #include <ntstrsafe.h> #include <ntddvdeo.h> #include <initguid.h> #include <Dispmprt.h> #include <d3dkmdt.h> //////////////////////////////////////////////////////////// #ifdef DBG #define DPT DbgPrint #else #define DPT // #endif ///����VIDPN�����豸ID�� #define VIDPN_CHILD_UDID 0x667b0099 ///////// ///0x23003F , dxgkrnl.sys ����ע�ắ�� DXGKRNL_DPIINITIALIZE #define IOCTL_VIDEO_DDI_FUNC_REGISTER \ CTL_CODE( FILE_DEVICE_VIDEO, 0xF, METHOD_NEITHER, FILE_ANY_ACCESS ) typedef __checkReturn NTSTATUS DXGKRNL_DPIINITIALIZE( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath, DRIVER_INITIALIZATION_DATA* DriverInitData ); typedef DXGKRNL_DPIINITIALIZE* PDXGKRNL_DPIINITIALIZE; /////// struct vidpn_target_id { LONG num; D3DDDI_VIDEO_PRESENT_TARGET_ID ids[1]; }; struct vidpn_paths_t { LONG num_paths; vidpn_target_id* target_paths[1]; }; struct vidpn_intf_t { LIST_ENTRY list; /// D3DKMDT_HVIDPN hVidPn; DXGK_VIDPN_INTERFACE vidpn_if, mod_vidpn_if; //// D3DKMDT_HVIDPNTOPOLOGY hTopology; DXGK_VIDPNTOPOLOGY_INTERFACE topology_if, mod_topology_if; vidpn_paths_t* paths; //// }; struct wddm_filter_t { PDRIVER_OBJECT driver_object; //// PDEVICE_OBJECT ctrl_devobj; //// PFILE_OBJECT dxgkrnl_fileobj; PDEVICE_OBJECT dxgkrnl_pdoDevice; PDEVICE_OBJECT dxgkrnl_nextDevice; /// PDXGKRNL_DPIINITIALIZE dxgkrnl_dpiInit; /// KSPIN_LOCK spin_lock; KIRQL kirql; LIST_ENTRY vidpn_if_head; LIST_ENTRY topology_if_head; //// DRIVER_INITIALIZATION_DATA orgDpiFunc; //ԭʼ��DRIVER_INITIALIZATION_DATA ULONG vidpn_source_count; ULONG vidpn_target_count; DXGKRNL_INTERFACE DxgkInterface; }; extern wddm_filter_t __gbl_wddm_filter; #define wf (&(__gbl_wddm_filter)) #define wf_lock() KeAcquireSpinLock(&wf->spin_lock, &wf->kirql); #define wf_unlock() KeReleaseSpinLock(&wf->spin_lock, wf->kirql); ////////////////function NTSTATUS create_wddm_filter_ctrl_device(PDRIVER_OBJECT drvObj); inline NTSTATUS call_lower_driver(PIRP irp) { IoSkipCurrentIrpStackLocation(irp); return IoCallDriver(wf->dxgkrnl_nextDevice, irp); } NTSTATUS DpiInitialize( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath, DRIVER_INITIALIZATION_DATA* DriverInitData); NTSTATUS DxgkDdiEnumVidPnCofuncModality(CONST HANDLE hAdapter, CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg); NTSTATUS DxgkDdiIsSupportedVidPn( IN_CONST_HANDLE hAdapter, INOUT_PDXGKARG_ISSUPPORTEDVIDPN pIsSupportedVidPn); NTSTATUS DxgkDdiCommitVidPn( IN_CONST_HANDLE hAdapter, IN_CONST_PDXGKARG_COMMITVIDPN_CONST pCommitVidPn); NTSTATUS DxgkDdiSetVidPnSourceVisibility( IN_CONST_HANDLE hAdapter, IN_CONST_PDXGKARG_SETVIDPNSOURCEVISIBILITY pSetVidPnSourceVisibility); NTSTATUS APIENTRY DxgkDdiSetVidPnSourceAddress( const HANDLE hAdapter, const DXGKARG_SETVIDPNSOURCEADDRESS *pSetVidPnSourceAddress); main.cpp: /// by fanxiushu 2018-08-29 #include "filter.h" static NTSTATUS commonDispatch(PDEVICE_OBJECT devObj, PIRP irp) { PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(irp); switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: break; case IRP_MJ_CLEANUP: break; case IRP_MJ_CLOSE: break; case IRP_MJ_INTERNAL_DEVICE_CONTROL: if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_VIDEO_DDI_FUNC_REGISTER) { ///////�Կ�������DxgkInitialize�����е��� IOCTL��ȡdxgkrnl.sys��ע��ص�����������hook�˴�����ȡ���Կ������ṩ������DDI���� irp->IoStatus.Information = 0; irp->IoStatus.Status = STATUS_SUCCESS; ///�����ǵĻص��������ظ��Կ�����. if (irp->UserBuffer) { /// irp->IoStatus.Information = sizeof(PDXGKRNL_DPIINITIALIZE); *((PDXGKRNL_DPIINITIALIZE*)irp->UserBuffer) = DpiInitialize; } ///// IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; /// } break; } //// return call_lower_driver(irp); } extern "C" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_SUCCESS; for (UCHAR i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i) { DriverObject->MajorFunction[i] = commonDispatch; } status = create_wddm_filter_ctrl_device(DriverObject); /// DriverObject->DriverUnload = NULL; ///������ж�� return status; } miniport.cpp 源文件: #include "filter.h" static NTSTATUS DxgkDdiAddDevice( IN_CONST_PDEVICE_OBJECT PhysicalDeviceObject, OUT PVOID *MiniportDeviceContext) { DPT("Hook: DxgkDdiAddDevice. \n"); return wf->orgDpiFunc.DxgkDdiAddDevice(PhysicalDeviceObject, MiniportDeviceContext); } static NTSTATUS DxgkDdiRemoveDevice(IN PVOID MiniportDeviceContext) { DPT("Hook: DxgkDdiRemoveDevice\n"); return wf->orgDpiFunc.DxgkDdiRemoveDevice(MiniportDeviceContext); } ////HOOK DxgkCbQueryVidPnInterface, �ҹ�DxgkCbQueryVidPnInterface��ص����лص�������������ƭԭʼ������Target Source �� Path ��ѯ. //��ѯ����·�������Ұ���SourceId���� static vidpn_paths_t* enum_all_paths(IN_CONST_D3DKMDT_HVIDPNTOPOLOGY topology_handle, const DXGK_VIDPNTOPOLOGY_INTERFACE* topology_if ) { NTSTATUS status = STATUS_SUCCESS; SIZE_T num = 0; status = topology_if->pfnGetNumPaths(topology_handle, &num); if (num <= 0) { return NULL; } LONG sz = sizeof(vidpn_paths_t) + sizeof(vidpn_target_id*)*wf->vidpn_source_count + wf->vidpn_source_count*( sizeof(vidpn_target_id) + num* sizeof(D3DDDI_VIDEO_PRESENT_TARGET_ID) ); vidpn_paths_t* p = (vidpn_paths_t*)ExAllocatePoolWithTag(NonPagedPool, sz, 'FXSD'); if (!p)return NULL; /// RtlZeroMemory(p, sz); //// p->num_paths = num; CHAR* ptr = (CHAR*)p + sizeof(vidpn_paths_t) + sizeof(vidpn_target_id*)*wf->vidpn_source_count; for (INT i = 0; i < wf->vidpn_source_count; ++i) { p->target_paths[i] = (vidpn_target_id*)( ptr + i* ( sizeof(vidpn_target_id) + num * sizeof(D3DDDI_VIDEO_PRESENT_TARGET_ID) ) ); } ////// CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info; CONST D3DKMDT_VIDPN_PRESENT_PATH *next_path_info; status = topology_if->pfnAcquireFirstPathInfo(topology_handle, &curr_path_info); if (status == STATUS_GRAPHICS_DATASET_IS_EMPTY) { ExFreePool(p); return NULL; } else if (!NT_SUCCESS(status)) { ExFreePool(p); return NULL; } ///// INT t_num = 0; do { /// UINT sid = curr_path_info->VidPnSourceId; UINT did = curr_path_info->VidPnTargetId; if ( sid < (UINT)wf->vidpn_source_count) { /// if (did != VIDPN_CHILD_UDID) {// skip my target path /// LONG n = p->target_paths[sid]->num; p->target_paths[sid]->num++; p->target_paths[sid]->ids[n] = did; /// t_num++; } /// } ///next status = topology_if->pfnAcquireNextPathInfo(topology_handle, curr_path_info, &next_path_info); topology_if->pfnReleasePathInfo(topology_handle, curr_path_info); curr_path_info = next_path_info; if (status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) { /// end curr_path_info = NULL; // DPT("pfnAcquireNextPathInfo no more data.\n"); break; } else if (!NT_SUCCESS(status)) { curr_path_info = NULL; DPT("pfnAcquireNextPathInfo err=0x%X\n", status); break; } //// } while (TRUE); p->num_paths = t_num; /// return p; } NTSTATUS pfnGetNumPaths( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, OUT_PSIZE_T pNumPaths) { NTSTATUS status = STATUS_INVALID_PARAMETER; DXGKDDI_VIDPNTOPOLOGY_GETNUMPATHS ptr_pfnGetNumPaths = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hTopology == hVidPnTopology) { ptr_pfnGetNumPaths = intf->topology_if.pfnGetNumPaths; if (intf->paths && pNumPaths) { *pNumPaths = intf->paths->num_paths; wf_unlock(); DPT("pfnGetNumPaths Cache called num=%d\n", *pNumPaths); return STATUS_SUCCESS; } break; } } wf_unlock(); ///// if (!ptr_pfnGetNumPaths) { return STATUS_INVALID_PARAMETER; } status = ptr_pfnGetNumPaths(hVidPnTopology, pNumPaths); DPT("pfnGetNumPaths called num=%d\n", *pNumPaths ); return status; } NTSTATUS pfnGetNumPathsFromSource( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, IN_CONST_D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, OUT_PSIZE_T pNumPathsFromSource) { NTSTATUS status = STATUS_SUCCESS; DXGKDDI_VIDPNTOPOLOGY_GETNUMPATHSFROMSOURCE ptr_pfnGetNumPathsFromSource = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hTopology == hVidPnTopology) { ptr_pfnGetNumPathsFromSource = intf->topology_if.pfnGetNumPathsFromSource; if (intf->paths && pNumPathsFromSource && VidPnSourceId < wf->vidpn_source_count ) { *pNumPathsFromSource = intf->paths->target_paths[VidPnSourceId]->num; wf_unlock(); DPT("pfnGetNumPathsFromSource Cache called. num=%d\n", *pNumPathsFromSource); return STATUS_SUCCESS; } break; } } wf_unlock(); //// if (!ptr_pfnGetNumPathsFromSource) { return STATUS_INVALID_PARAMETER; } status = ptr_pfnGetNumPathsFromSource(hVidPnTopology, VidPnSourceId, pNumPathsFromSource); DPT("pfnGetNumPathsFromSource called. num=%d\n", *pNumPathsFromSource); return status; } NTSTATUS pfnEnumPathTargetsFromSource( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, IN_CONST_D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, IN_CONST_D3DKMDT_VIDPN_PRESENT_PATH_INDEX VidPnPresentPathIndex, OUT_PD3DDDI_VIDEO_PRESENT_TARGET_ID pVidPnTargetId) { NTSTATUS status = STATUS_SUCCESS; DXGKDDI_VIDPNTOPOLOGY_ENUMPATHTARGETSFROMSOURCE ptr_pfnEnumPathTargetsFromSource = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hTopology == hVidPnTopology) { ptr_pfnEnumPathTargetsFromSource = intf->topology_if.pfnEnumPathTargetsFromSource; if (intf->paths && VidPnSourceId < wf->vidpn_source_count && pVidPnTargetId ) { if (VidPnPresentPathIndex >= intf->paths->target_paths[VidPnSourceId]->num) { wf_unlock(); DPT("VidPnPresentPathIndex >= intf->paths->target_path_num[VidPnSourceId]\n"); return STATUS_INVALID_PARAMETER; } *pVidPnTargetId = intf->paths->target_paths[VidPnSourceId]->ids[VidPnPresentPathIndex]; //// wf_unlock(); DPT("pfnEnumPathTargetsFromSource Cache called sourceId=%d, index=%d, targetid=%d, st=0x%X\n", VidPnSourceId, VidPnPresentPathIndex, *pVidPnTargetId, status); return STATUS_SUCCESS; } break; } } wf_unlock(); ///// if (!ptr_pfnEnumPathTargetsFromSource) { return STATUS_INVALID_PARAMETER; } status = ptr_pfnEnumPathTargetsFromSource(hVidPnTopology, VidPnSourceId, VidPnPresentPathIndex, pVidPnTargetId); DPT("pfnEnumPathTargetsFromSource called sourceId=%d, index=%d, targetid=%d, st=0x%X\n", VidPnSourceId, VidPnPresentPathIndex, *pVidPnTargetId, status ); return status; } static NTSTATUS skip_my_target_path( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, IN_CONST_PD3DKMDT_VIDPN_PRESENT_PATH_CONST pVidPnPresentPathInfo, DEREF_OUT_CONST_PPD3DKMDT_VIDPN_PRESENT_PATH ppNextVidPnPresentPathInfo, DXGKDDI_VIDPNTOPOLOGY_ACQUIRENEXTPATHINFO ptr_pfnAcquireNextPathInfo, DXGKDDI_VIDPNTOPOLOGY_RELEASEPATHINFO ptr_pfnReleasePathInfo) { NTSTATUS status = STATUS_SUCCESS; CONST D3DKMDT_VIDPN_PRESENT_PATH* curr_path = pVidPnPresentPathInfo; do { if (curr_path->VidPnTargetId != VIDPN_CHILD_UDID) {//����Ƿ����ǵ�target ID break; } /////skip my target id status = ptr_pfnAcquireNextPathInfo(hVidPnTopology, curr_path, ppNextVidPnPresentPathInfo ); ptr_pfnReleasePathInfo(hVidPnTopology, curr_path); /// release pathinfo /// if (status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) { break; } else if (!NT_SUCCESS(status)) { break; } curr_path = *ppNextVidPnPresentPathInfo; //// ///// } while (TRUE); /// return status; } static NTSTATUS pfnAcquireFirstPathInfo( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, DEREF_OUT_CONST_PPD3DKMDT_VIDPN_PRESENT_PATH ppFirstVidPnPresentPathInfo) { NTSTATUS status = STATUS_SUCCESS; DXGKDDI_VIDPNTOPOLOGY_ACQUIREFIRSTPATHINFO ptr_pfnAcquireFirstPathInfo = NULL; DXGKDDI_VIDPNTOPOLOGY_ACQUIRENEXTPATHINFO ptr_pfnAcquireNextPathInfo = NULL; DXGKDDI_VIDPNTOPOLOGY_RELEASEPATHINFO ptr_pfnReleasePathInfo = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hTopology == hVidPnTopology) { ptr_pfnAcquireFirstPathInfo = intf->topology_if.pfnAcquireFirstPathInfo; ptr_pfnAcquireNextPathInfo = intf->topology_if.pfnAcquireNextPathInfo; ptr_pfnReleasePathInfo = intf->topology_if.pfnReleasePathInfo; break; } } wf_unlock(); /// if (!ptr_pfnAcquireFirstPathInfo) { DPT("** pfnAcquireFirstPathInfo NULL.\n"); return STATUS_INVALID_PARAMETER; } status = ptr_pfnAcquireFirstPathInfo(hVidPnTopology, ppFirstVidPnPresentPathInfo); if ( NT_SUCCESS(status) && status != STATUS_GRAPHICS_DATASET_IS_EMPTY ) { CONST D3DKMDT_VIDPN_PRESENT_PATH* curr_path = *ppFirstVidPnPresentPathInfo; status = skip_my_target_path(hVidPnTopology, curr_path, ppFirstVidPnPresentPathInfo, ptr_pfnAcquireNextPathInfo, ptr_pfnReleasePathInfo); //// } // DPT("ppFirstVidPnPresentPathInfo called. st=0x%X\n", status ); ///// return status; } static NTSTATUS pfnAcquireNextPathInfo( IN_CONST_D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, IN_CONST_PD3DKMDT_VIDPN_PRESENT_PATH_CONST pVidPnPresentPathInfo, DEREF_OUT_CONST_PPD3DKMDT_VIDPN_PRESENT_PATH ppNextVidPnPresentPathInfo) { NTSTATUS status = STATUS_SUCCESS; DXGKDDI_VIDPNTOPOLOGY_ACQUIRENEXTPATHINFO ptr_pfnAcquireNextPathInfo = NULL; DXGKDDI_VIDPNTOPOLOGY_RELEASEPATHINFO ptr_pfnReleasePathInfo = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hTopology == hVidPnTopology) { ptr_pfnAcquireNextPathInfo = intf->topology_if.pfnAcquireNextPathInfo; ptr_pfnReleasePathInfo = intf->topology_if.pfnReleasePathInfo; break; } } wf_unlock(); ///// if (!ptr_pfnAcquireNextPathInfo) { DPT("** pfnAcquireNextPathInfo NULL.\n"); return STATUS_INVALID_PARAMETER; } status = ptr_pfnAcquireNextPathInfo(hVidPnTopology, pVidPnPresentPathInfo, ppNextVidPnPresentPathInfo ); if (NT_SUCCESS(status) && status != STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET ) { CONST D3DKMDT_VIDPN_PRESENT_PATH* curr_path = *ppNextVidPnPresentPathInfo; status = skip_my_target_path(hVidPnTopology, curr_path, ppNextVidPnPresentPathInfo, ptr_pfnAcquireNextPathInfo, ptr_pfnReleasePathInfo); //// } // DPT("pfnAcquireNextPathInfo called. st=0x%X\n", status ); return status; } static NTSTATUS pfnGetTopology( IN_CONST_D3DKMDT_HVIDPN hVidPn, OUT_PD3DKMDT_HVIDPNTOPOLOGY phVidPnTopology, DEREF_OUT_CONST_PPDXGK_VIDPNTOPOLOGY_INTERFACE ppVidPnTopologyInterface) { NTSTATUS status = STATUS_SUCCESS; DXGKDDI_VIDPN_GETTOPOLOGY ptr_pfnGetTopology = NULL; wf_lock(); for (PLIST_ENTRY entry = wf->vidpn_if_head.Flink; entry != &wf->vidpn_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (hVidPn == intf->hVidPn) { ptr_pfnGetTopology = intf->vidpn_if.pfnGetTopology; break; } } wf_unlock(); if (!ptr_pfnGetTopology) { DPT("pfnGetTopology==NULL.\n"); return STATUS_INVALID_PARAMETER; } status = ptr_pfnGetTopology(hVidPn, phVidPnTopology, ppVidPnTopologyInterface); // DPT("pfnGetTopology called.\n"); if (NT_SUCCESS(status) && ppVidPnTopologyInterface && *ppVidPnTopologyInterface && phVidPnTopology ) { ///���¼��㲻���������Լ���target path��·�� vidpn_paths_t* p = enum_all_paths(*phVidPnTopology, *ppVidPnTopologyInterface); /// //// wf_lock(); /// PLIST_ENTRY entry; BOOLEAN find = FALSE; vidpn_intf_t* intf = NULL; for (entry = wf->topology_if_head.Flink; entry != &wf->topology_if_head; entry = entry->Flink) { vidpn_intf_t* it = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (it->hTopology == *phVidPnTopology) { intf = it; if (intf->paths) { ExFreePool(intf->paths); intf->paths = NULL; }/// break; } } if (!intf) { intf = (vidpn_intf_t*)ExAllocatePoolWithTag(NonPagedPool, sizeof(vidpn_intf_t), 'FXSD'); if (intf) { InsertTailList(&wf->topology_if_head, &intf->list); intf->hTopology = *phVidPnTopology; intf->paths = NULL; ///// } } if (intf) { intf->paths = p; /// intf->topology_if = **ppVidPnTopologyInterface; intf->mod_topology_if = intf->topology_if; *ppVidPnTopologyInterface = &intf->mod_topology_if; /// ///�滻���� intf->mod_topology_if.pfnGetNumPaths = pfnGetNumPaths; intf->mod_topology_if.pfnGetNumPathsFromSource = pfnGetNumPathsFromSource; intf->mod_topology_if.pfnEnumPathTargetsFromSource = pfnEnumPathTargetsFromSource; intf->mod_topology_if.pfnAcquireFirstPathInfo = pfnAcquireFirstPathInfo; intf->mod_topology_if.pfnAcquireNextPathInfo = pfnAcquireNextPathInfo; ///// } //// wf_unlock(); } /// return status; } static NTSTATUS DxgkCbQueryVidPnInterface( IN_CONST_D3DKMDT_HVIDPN hVidPn, IN_CONST_DXGK_VIDPN_INTERFACE_VERSION VidPnInterfaceVersion, DEREF_OUT_CONST_PPDXGK_VIDPN_INTERFACE ppVidPnInterface) { NTSTATUS status = STATUS_SUCCESS; status = wf->DxgkInterface.DxgkCbQueryVidPnInterface(hVidPn, VidPnInterfaceVersion, ppVidPnInterface); /// �滻���Լ��Ļص���������������������Hook Driver��ߵ� Target . if (NT_SUCCESS(status) && ppVidPnInterface && *ppVidPnInterface ) { /// PLIST_ENTRY entry; BOOLEAN find = FALSE; /// wf_lock(); for (entry = wf->vidpn_if_head.Flink; entry != &wf->vidpn_if_head; entry = entry->Flink) { vidpn_intf_t* intf = CONTAINING_RECORD(entry, vidpn_intf_t, list); if (intf->hVidPn == hVidPn) { intf->vidpn_if = *(*ppVidPnInterface); intf->mod_vidpn_if = intf->vidpn_if; intf->mod_vidpn_if.pfnGetTopology = pfnGetTopology; //// *ppVidPnInterface = &intf->mod_vidpn_if; find = TRUE; break; } } if (!find) { vidpn_intf_t* intf = (vidpn_intf_t*)ExAllocatePoolWithTag(NonPagedPool, sizeof(vidpn_intf_t), 'Fxsd'); if (intf) { intf->hVidPn = hVidPn; intf->vidpn_if = *(*ppVidPnInterface); intf->mod_vidpn_if = intf->vidpn_if; intf->mod_vidpn_if.pfnGetTopology = pfnGetTopology; /// *ppVidPnInterface = &intf->mod_vidpn_if; InsertTailList(&wf->vidpn_if_head, &intf->list); //// //// } } wf_unlock(); //// } //// return status; } /////// static NTSTATUS DxgkDdiStartDevice( IN PVOID MiniportDeviceContext, IN PDXGK_START_INFO DxgkStartInfo, IN PDXGKRNL_INTERFACE DxgkInterface, OUT PULONG NumberOfVideoPresentSources, OUT PULONG NumberOfChildren) { NTSTATUS status = STATUS_SUCCESS; ////WDDM1.1 �� WDDM2.3 ÿ�������в�ͬ���壬������WDK7�±��룬���ֻcopy WDDM1.1�IJ��֡� wf->DxgkInterface = *DxgkInterface; /// save interface function,����VIDPN���� ///////�滻ԭ���Ľӿ� DxgkInterface->DxgkCbQueryVidPnInterface = DxgkCbQueryVidPnInterface; ////// status = wf->orgDpiFunc.DxgkDdiStartDevice(MiniportDeviceContext, DxgkStartInfo, DxgkInterface, NumberOfVideoPresentSources, NumberOfChildren); //// DxgkInterface->DxgkCbQueryVidPnInterface = wf->DxgkInterface.DxgkCbQueryVidPnInterface; /// DPT("Hook: DxgkDdiStartDevice status=0x%X.\n", status ); /// if (NT_SUCCESS(status)) { DPT("org: DxgkDdiStartDevice, NumberOfVideoPresentSources=%d, NumberOfChildren=%d\n", *NumberOfVideoPresentSources, *NumberOfChildren); //// �ֱ����� 1������ source �� target wf->vidpn_source_count = *NumberOfVideoPresentSources; // +1; wf->vidpn_target_count = *NumberOfChildren + 1; ////// *NumberOfVideoPresentSources = wf->vidpn_source_count; *NumberOfChildren = wf->vidpn_target_count; //// } //// return status; } static NTSTATUS DxgkDdiStopDevice(IN PVOID MiniportDeviceContext) { DPT("Hook: DxgkDdiStopDevice.\n"); return wf->orgDpiFunc.DxgkDdiStopDevice(MiniportDeviceContext); } static NTSTATUS DxgkDdiQueryChildRelations(IN PVOID pvMiniportDeviceContext, IN OUT PDXGK_CHILD_DESCRIPTOR pChildRelations, IN ULONG ChildRelationsSize) { NTSTATUS status; status = wf->orgDpiFunc.DxgkDdiQueryChildRelations(pvMiniportDeviceContext, pChildRelations, ChildRelationsSize); DPT("Hook: DxgkDdiQueryChildRelations status=0x%X\n", status); //// if (NT_SUCCESS(status)) { //// LONG reqSize = sizeof(DXGK_CHILD_DESCRIPTOR)*wf->vidpn_target_count; if (reqSize > ChildRelationsSize) { return STATUS_BUFFER_TOO_SMALL; } ///// pChildRelations[wf->vidpn_target_count - 1] = pChildRelations[0]; ///�ѵ�һ�����Ƹ����ǵ�target pChildRelations[wf->vidpn_target_count - 1].ChildUid = VIDPN_CHILD_UDID; //�������ǵ�target vidpn��ID pChildRelations[wf->vidpn_target_count - 1].AcpiUid = VIDPN_CHILD_UDID; //// } return status; } static NTSTATUS DxgkDdiQueryChildStatus(IN PVOID MiniportDeviceContext, IN PDXGK_CHILD_STATUS ChildStatus, IN BOOLEAN NonDestructiveOnly) { DPT("Hook: DxgkDdiQueryChildStatus Uid=0x%X\n", ChildStatus->ChildUid); if (ChildStatus->ChildUid == VIDPN_CHILD_UDID) { ChildStatus->HotPlug.Connected = TRUE; /// /// return STATUS_SUCCESS; } //// return wf->orgDpiFunc.DxgkDdiQueryChildStatus(MiniportDeviceContext, ChildStatus, NonDestructiveOnly); } static NTSTATUS DxgkDdiQueryDeviceDescriptor(IN_CONST_PVOID MiniportDeviceContext, IN_ULONG ChildUid, INOUT_PDXGK_DEVICE_DESCRIPTOR DeviceDescriptor) { DPT("Hook: DxgkDdiQueryDeviceDescriptor Uid=0x%X\n", ChildUid); if (ChildUid == VIDPN_CHILD_UDID) { /// return STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA; } //// return wf->orgDpiFunc.DxgkDdiQueryDeviceDescriptor(MiniportDeviceContext, ChildUid, DeviceDescriptor); } ///// NTSTATUS DpiInitialize( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath, DRIVER_INITIALIZATION_DATA* DriverInitData) { NTSTATUS status = STATUS_SUCCESS; static BOOLEAN is_hooked = FALSE; //// UNICODE_STRING vm_str; RtlInitUnicodeString(&vm_str, L"\\Driver\\vm3dmp_loader"); // Vmware 3D UNICODE_STRING igfx_str; RtlInitUnicodeString(&igfx_str, L"\\Driver\\igfx"); // Intel Graphics UNICODE_STRING nv_str; RtlInitUnicodeString(&nv_str, L"\\Driver\\nvlddmkm"); // nvidia Graphics if ( !is_hooked && ( RtlEqualUnicodeString(&vm_str, &DriverObject->DriverName, TRUE) || RtlEqualUnicodeString(&nv_str, &DriverObject->DriverName, TRUE) //vmware��������Կ�����Intel�Կ� ) ) { //����ֻHOOK��һ���Կ� is_hooked = TRUE; /// //���︴����Ҫע�⣺ // DRIVER_INITIALIZATION_DATA�ṹ���壬WDDM1.1 �� WDDM2.3 ÿ�������в�ͬ���壬������WDK7�±��룬���ֻcopy WDDM1.1�IJ��֡� RtlCopyMemory(&wf->orgDpiFunc, DriverInitData, sizeof(DRIVER_INITIALIZATION_DATA)); ////replace some function DriverInitData->DxgkDdiAddDevice = DxgkDdiAddDevice; DriverInitData->DxgkDdiRemoveDevice = DxgkDdiRemoveDevice; DriverInitData->DxgkDdiStartDevice = DxgkDdiStartDevice; DriverInitData->DxgkDdiStopDevice = DxgkDdiStopDevice; DriverInitData->DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations; DriverInitData->DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus; DriverInitData->DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor; DriverInitData->DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality; //// DriverInitData->DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn; DriverInitData->DxgkDdiCommitVidPn = DxgkDdiCommitVidPn; DriverInitData->DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility; DriverInitData->DxgkDdiSetVidPnSourceAddress = DxgkDdiSetVidPnSourceAddress; // DriverInitData->DxgkDdiPresent = DxgkDdiPresent; ///// } ///�滻��ijЩ�����󣬽��ŵ��� dxgkrnl.sys �ص�����ע�� return wf->dxgkrnl_dpiInit(DriverObject, RegistryPath, DriverInitData); } vidpn.cpp 源文件: #include "filter.h" static D3DKMDT_2DREGION Modes[]= { {1024, 768}, {1366, 768}, {1920, 1080}, // {6000, 4000} }; static NTSTATUS add_source_mode(D3DKMDT_HVIDPNSOURCEMODESET source_mode_set_hdl, CONST DXGK_VIDPNSOURCEMODESET_INTERFACE *source_mode_set_if, D3DKMDT_2DREGION* mode) { NTSTATUS status = STATUS_SUCCESS; D3DKMDT_VIDPN_SOURCE_MODE *source_mode; D3DKMDT_GRAPHICS_RENDERING_FORMAT *fmt; status = source_mode_set_if->pfnCreateNewModeInfo(source_mode_set_hdl, &source_mode); if (!NT_SUCCESS(status)) { DPT("** pfnCreateNewModeInfo(Source) err=0x%X\n", status ); return status; } /* Let OS assign the ID, set the type.*/ source_mode->Type = D3DKMDT_RMT_GRAPHICS; /* Initialize the rendering format per our constraints and the current mode. */ fmt = &source_mode->Format.Graphics; fmt->PrimSurfSize.cx = mode->cx; fmt->PrimSurfSize.cy = mode->cy; fmt->VisibleRegionSize.cx = mode->cx; fmt->VisibleRegionSize.cy = mode->cy; fmt->Stride = mode->cx*4 ; // RGBA fmt->PixelFormat = D3DDDIFMT_A8R8G8B8; fmt->ColorBasis = D3DKMDT_CB_SRGB; fmt->PixelValueAccessMode = D3DKMDT_PVAM_DIRECT; status = source_mode_set_if->pfnAddMode(source_mode_set_hdl, source_mode); if (!NT_SUCCESS(status)) { DPT("** pfnAddMode(Source) err=0x%X\n", status ); source_mode_set_if->pfnReleaseModeInfo(source_mode_set_hdl, source_mode); } /// return status; } static NTSTATUS update_source_modes( CONST D3DKMDT_HVIDPN vidpn_hdl, CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info, CONST DXGK_VIDPN_INTERFACE* vidpn_if) { NTSTATUS status = STATUS_SUCCESS; D3DKMDT_HVIDPNSOURCEMODESET source_mode_set_hdl = NULL; CONST DXGK_VIDPNSOURCEMODESET_INTERFACE *source_mode_set_if; CONST D3DKMDT_VIDPN_SOURCE_MODE *src_mode_info = NULL; status = vidpn_if->pfnAcquireSourceModeSet(vidpn_hdl, curr_path_info->VidPnSourceId, &source_mode_set_hdl, &source_mode_set_if); if (!NT_SUCCESS(status)) { DPT("** not pfnAcquireSourceModeSet st=0x%X\n", status ); return status; } //// status = source_mode_set_if->pfnAcquirePinnedModeInfo(source_mode_set_hdl, &src_mode_info); if (!NT_SUCCESS(status)) { vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl); DPT("pfnAcquirePinnedModeInfo(Source) err=0x%X\n", status ); return status; } //// if (src_mode_info != NULL) { source_mode_set_if->pfnReleaseModeInfo(source_mode_set_hdl, src_mode_info); } vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl); source_mode_set_hdl = NULL; /// /// if (status == STATUS_SUCCESS && src_mode_info != NULL) { // pinned mode . /// DPT("Source Mode Pinned Mode: 0x%X -> 0x%X\n", curr_path_info->VidPnSourceId, curr_path_info->VidPnTargetId); return STATUS_SUCCESS;///�Ѿ����ˣ������� } //// status = vidpn_if->pfnCreateNewSourceModeSet(vidpn_hdl, curr_path_info->VidPnSourceId, &source_mode_set_hdl, &source_mode_set_if); if (!NT_SUCCESS(status)) { DPT("** pfnCreateNewSourceModeSet err=0x%X\n", status); return status; } //// for (INT i = 0; i < sizeof(Modes) / sizeof(Modes[0]); ++i) { //// status = add_source_mode(source_mode_set_hdl, source_mode_set_if, &Modes[i]); if (!NT_SUCCESS(status)) { /// vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl); DPT("add_source_mode err=0x%X\n", status); return status; } //// } ////// status = vidpn_if->pfnAssignSourceModeSet(vidpn_hdl, curr_path_info->VidPnSourceId, source_mode_set_hdl); if (!NT_SUCCESS(status)) { DPT("** pfnAssignSourceModeSet err=0x%X\n", status); vidpn_if->pfnReleaseSourceModeSet(vidpn_hdl, source_mode_set_hdl); } //// return status; } //// target static NTSTATUS add_target_mode(D3DKMDT_HVIDPNTARGETMODESET tgt_mode_set_hdl, CONST DXGK_VIDPNTARGETMODESET_INTERFACE *target_mode_set_if, D3DKMDT_2DREGION* mode) { D3DKMDT_VIDPN_TARGET_MODE *target_mode; D3DKMDT_VIDEO_SIGNAL_INFO *signal_info; NTSTATUS status; status = target_mode_set_if->pfnCreateNewModeInfo(tgt_mode_set_hdl, &target_mode); if (!NT_SUCCESS(status)) { DPT("** pfnCreateNewModeInfo(Target) err=0x%X\n", status ); return status; } //// /* Let OS assign the ID, set the preferred mode field.*/ target_mode->Preference = D3DKMDT_MP_PREFERRED; //// #define REFRESH_RATE 60 signal_info = &target_mode->VideoSignalInfo; signal_info->VideoStandard = D3DKMDT_VSS_VESA_DMT;// D3DKMDT_VSS_OTHER; signal_info->TotalSize.cx = mode->cx; signal_info->TotalSize.cy = mode->cy; signal_info->ActiveSize.cx = mode->cx; signal_info->ActiveSize.cy = mode->cy; signal_info->PixelRate = mode->cx * mode->cy * REFRESH_RATE; signal_info->VSyncFreq.Numerator = REFRESH_RATE * 1000; signal_info->VSyncFreq.Denominator = 1000; signal_info->HSyncFreq.Numerator = (UINT)((signal_info->PixelRate / signal_info->TotalSize.cy) * 1000); signal_info->HSyncFreq.Denominator = 1000; signal_info->ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE; status = target_mode_set_if->pfnAddMode(tgt_mode_set_hdl, target_mode); if (!NT_SUCCESS(status)) { DPT("pfnAddMode failed: 0x%x", status); target_mode_set_if->pfnReleaseModeInfo(tgt_mode_set_hdl, target_mode); return status; } return status; } static NTSTATUS update_target_modes( CONST D3DKMDT_HVIDPN vidpn_hdl, CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info, CONST DXGK_VIDPN_INTERFACE* vidpn_if) { NTSTATUS status = STATUS_SUCCESS; D3DKMDT_HVIDPNTARGETMODESET tgt_mode_set_hdl = NULL; CONST DXGK_VIDPNTARGETMODESET_INTERFACE *target_mode_set_if; CONST D3DKMDT_VIDPN_TARGET_MODE *tgt_mode_info = NULL; status = vidpn_if->pfnAcquireTargetModeSet(vidpn_hdl, curr_path_info->VidPnTargetId, &tgt_mode_set_hdl, &target_mode_set_if); if (!NT_SUCCESS(status)) { DPT("** pfnAcquireTargetModeSet err=0x%X\n", status ); return status; } status = target_mode_set_if->pfnAcquirePinnedModeInfo(tgt_mode_set_hdl, &tgt_mode_info); if (!NT_SUCCESS(status)) { vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl); DPT("** pfnAcquirePinnedModeInfo(Source) err=0x%X\n", status ); return status; } //// if (tgt_mode_info) { target_mode_set_if->pfnReleaseModeInfo(tgt_mode_set_hdl, tgt_mode_info); } vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl); tgt_mode_set_hdl = NULL; if (status == STATUS_SUCCESS && tgt_mode_info != NULL) { DPT("Target Mode Pinned Mode: 0x%X -> 0x%X\n", curr_path_info->VidPnSourceId, curr_path_info->VidPnTargetId); return STATUS_SUCCESS;///�Ѿ����ˣ������� /// } ///// status = vidpn_if->pfnCreateNewTargetModeSet(vidpn_hdl, curr_path_info->VidPnTargetId, &tgt_mode_set_hdl, &target_mode_set_if); if (!NT_SUCCESS(status)) { DPT("** pfnCreateNewTargetModeSet err=0x%X\n", status ); return status; } ///add target for (INT i = 0; i < sizeof(Modes) / sizeof(Modes[0]); ++i) { status = add_target_mode(tgt_mode_set_hdl, target_mode_set_if, &Modes[i]); if (!NT_SUCCESS(status)) { /// vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl); DPT("add_target_mode err=0x%X\n", status); return status; } /// } ////// status = vidpn_if->pfnAssignTargetModeSet(vidpn_hdl, curr_path_info->VidPnTargetId, tgt_mode_set_hdl); if (!NT_SUCCESS(status)) { DPT("** pfnAssignTargetModeSet err=0x%x\n", status ); vidpn_if->pfnReleaseTargetModeSet(vidpn_hdl, tgt_mode_set_hdl); return status; } return status; } static NTSTATUS DxgkDdiEnumVidPnCofuncModality_modify(CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST arg) { NTSTATUS status = STATUS_SUCCESS; D3DKMDT_HVIDPN hConstrainingVidPn = arg->hConstrainingVidPn; CONST DXGK_VIDPN_INTERFACE* vidpn_if; status = wf->DxgkInterface.DxgkCbQueryVidPnInterface( hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &vidpn_if); if (!NT_SUCCESS(status)) { return status; } //// D3DKMDT_HVIDPNTOPOLOGY topology_handle = NULL; CONST DXGK_VIDPNTOPOLOGY_INTERFACE* topology_if = NULL; CONST D3DKMDT_VIDPN_PRESENT_PATH *curr_path_info; CONST D3DKMDT_VIDPN_PRESENT_PATH *next_path_info; status = vidpn_if->pfnGetTopology(hConstrainingVidPn, &topology_handle, &topology_if); if (!NT_SUCCESS(status)) { return status; } //// status = topology_if->pfnAcquireFirstPathInfo(topology_handle, &curr_path_info); if (status == STATUS_GRAPHICS_DATASET_IS_EMPTY) { // Empty topology, nothing to do. DPT("pfnAcquireFirstPathInfo: Empty topology.\n"); return STATUS_SUCCESS; } else if (!NT_SUCCESS(status)) { DPT("pfnAcquireFirstPathInfo failed: 0x%x", status); return STATUS_NO_MEMORY; //// } //// do { ////����ÿ��·�� DPT("0x%X --> 0x%X\n", curr_path_info->VidPnSourceId, curr_path_info->VidPnTargetId); if (curr_path_info->VidPnTargetId == VIDPN_CHILD_UDID) {//·��Ŀ���������Լ��� /// if ((arg->EnumPivotType != D3DKMDT_EPT_VIDPNSOURCE) || (arg->EnumPivot.VidPnSourceId != curr_path_info->VidPnSourceId)) { ///// status = update_source_modes(arg->hConstrainingVidPn, curr_path_info, vidpn_if); DPT("update_source_modes st=0x%X\n",status ); if (!NT_SUCCESS(status)) { DPT("** update_source_modes err=0x%X\n", status ); } ////// } ///// if ((arg->EnumPivotType != D3DKMDT_EPT_VIDPNTARGET) || (arg->EnumPivot.VidPnTargetId != curr_path_info->VidPnTargetId)) { status = update_target_modes(arg->hConstrainingVidPn, curr_path_info, vidpn_if); DPT("update_target_modes st=0x%X\n", status); if (!NT_SUCCESS(status)) { DPT("** update_target_modes err=0x%X\n", status); } } //////// } ///next status = topology_if->pfnAcquireNextPathInfo(topology_handle, curr_path_info, &next_path_info); topology_if->pfnReleasePathInfo(topology_handle, curr_path_info); curr_path_info = next_path_info; if (status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET) { /// end curr_path_info = NULL; // DPT("pfnAcquireNextPathInfo no more data.\n"); break; } else if (!NT_SUCCESS(status)) { curr_path_info = NULL; DPT("pfnAcquireNextPathInfo err=0x%X\n", status ); break; } ///// } while (TRUE); return status; } NTSTATUS DxgkDdiEnumVidPnCofuncModality(CONST HANDLE hAdapter, CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg) { NTSTATUS status = STATUS_SUCCESS; DPT("DxgkDdiEnumVidPnCofuncModality: type=%d, 0x%X -> 0x%X, [%d, %d]\n", pEnumCofuncModalityArg->EnumPivotType, pEnumCofuncModalityArg->EnumPivot.VidPnSourceId, pEnumCofuncModalityArg->EnumPivot.VidPnTargetId, wf->vidpn_source_count, wf->vidpn_target_count ); /// DxgkDdiEnumVidPnCofuncModality_modify(pEnumCofuncModalityArg); //// //// status = wf->orgDpiFunc.DxgkDdiEnumVidPnCofuncModality(hAdapter, pEnumCofuncModalityArg); if (!NT_SUCCESS(status)) { DPT("** DxgkDdiEnumVidPnCofuncModality err=0x%X\n", status ); } return status; } NTSTATUS DxgkDdiIsSupportedVidPn( IN_CONST_HANDLE hAdapter, INOUT_PDXGKARG_ISSUPPORTEDVIDPN pIsSupportedVidPn) { NTSTATUS status; status = wf->orgDpiFunc.DxgkDdiIsSupportedVidPn(hAdapter, pIsSupportedVidPn); if (NT_SUCCESS(status)) { DPT("DxgkDdiIsSupportedVidPn handle=%p, supported=%d, \n", pIsSupportedVidPn->hDesiredVidPn, pIsSupportedVidPn->IsVidPnSupported ); } else { DPT("** DxgkDdiIsSupportedVidPn err=0x%X, handle=%p, supported=%d\n", status , pIsSupportedVidPn->hDesiredVidPn, pIsSupportedVidPn->IsVidPnSupported ); } return status; } NTSTATUS DxgkDdiCommitVidPn( IN_CONST_HANDLE hAdapter, IN_CONST_PDXGKARG_COMMITVIDPN_CONST pCommitVidPn) { NTSTATUS status; status = wf->orgDpiFunc.DxgkDdiCommitVidPn(hAdapter, pCommitVidPn ); // if (!NT_SUCCESS(status)) { /// DPT(" DxgkDdiCommitVidPn st=0x%X\n", status ); // } //// return status; } NTSTATUS DxgkDdiSetVidPnSourceVisibility( IN_CONST_HANDLE hAdapter, IN_CONST_PDXGKARG_SETVIDPNSOURCEVISIBILITY pSetVidPnSourceVisibility) { NTSTATUS status; status = wf->orgDpiFunc.DxgkDdiSetVidPnSourceVisibility(hAdapter, pSetVidPnSourceVisibility); DPT(" DxgkDdiSetVidPnSourceVisibility sourceId=0x%X, visible=0x%X, st=0x%X\n", pSetVidPnSourceVisibility->VidPnSourceId, pSetVidPnSourceVisibility->Visible ,status ); return status; } NTSTATUS APIENTRY DxgkDdiSetVidPnSourceAddress( const HANDLE hAdapter, const DXGKARG_SETVIDPNSOURCEADDRESS *pSetVidPnSourceAddress) { NTSTATUS status; status = wf->orgDpiFunc.DxgkDdiSetVidPnSourceAddress(hAdapter, pSetVidPnSourceAddress ); DPT("DxgkDdiSetVidPnSourceAddress sourceId=0x%X, paddr=%llu, st=0x%X\n", pSetVidPnSourceAddress->VidPnSourceId, pSetVidPnSourceAddress->PrimaryAddress.QuadPart, status ); return status; } 修改以上代码,添加虚拟显示器管理代码
最新发布
07-10
#include <ntifs.h> #include <ntddk.h> #include <intrin.h> #include "ptehook.h" #define CR0_WP (1 << 16) #define DRIVER_TAG 'HKOB' #define MAX_G_BIT_RECORDS 128 #define MAX_HOOK_COUNT 64 #define PAGE_ALIGN(va) ((PVOID)((ULONG_PTR)(va) & ~0xFFF)) #define PTE_NX_BIT (1ULL << 63) // 调试打印宏 #define LOG_ERROR(fmt, ...) \ DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] ERROR: " fmt "\n", ##__VA_ARGS__) #define LOG_INFO(fmt, ...) \ DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] INFO: " fmt "\n", ##__VA_ARGS__) #define LOG_TRACE(fmt, ...) \ DbgPrintEx(DPFLTR极IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "[PTE_HOOK] TRACE: " fmt "\n", ##__VA_ARGS__) // 修正的跳板指令结构 #pragma pack(push, 1) typedef struct _JMP_ABS { UINT8 opcode[6]; // FF 25 00 00 00 00 = jmp [rip+0] ULONG64 address; // 目标地址 (紧跟在指令后) } JMP_ABS, * PJMP_ABS; #pragma pack(pop) static_assert(sizeof(JMP_ABS) == 14, "JMP_ABS size must be 14 bytes"); // 声明PsGetProcessImageFileName extern "C" NTSYSAPI CHAR* NTAPI PsGetProcessImageFileName(PEPROCESS Process); // 页表结构定义 typedef struct _PAGE_TABLE { UINT64 LineAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 极; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 ignored_1 : 1; UINT64 page_size : 1; UINT64 ignored_2 : 4; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdpteAddress; UINT64* Pml4Address; BOOLEAN IsLargePage; BOOLEAN Is1GBPage; UINT64 OriginalPte; UINT64 OriginalPde; UINT64 OriginalPdpte; UINT64 OriginalPml4e; HANDLE ProcessId; } PAGE_TABLE, * PPAGE_TABLE; // G位信息记录结构体 typedef struct _G_BIT_INFO { void* AlignAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; BOOLEAN IsLargePage; } G_BIT_INFO, * PG_BIT_INFO; typedef struct _HOOK_INFO { void* OriginalAddress; void* HookAddress; UINT8 OriginalBytes[20]; UINT8 HookBytes[20]; UINT32 HookLength; BOOLEAN IsHooked; HANDLE ProcessId; UINT64 OriginalPteValue; UINT64 HookedPteValue; } HOOK_INFO; class PteHookManager { public: bool fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr); bool fn_remove_hook(HANDLE process_id, void* hook_addr); static PteHookManager* GetInstance(); HOOK_INFO* GetHookInfo() { return m_HookInfo; } char* GetTrampLinePool() { return m_TrampLinePool; } UINT32 GetHookCount() { return m_HookCount; } bool fn_resume_global_bits(void* align_addr); ~PteHookManager(); private: bool WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd); bool SetPageExecution(void* address, bool executable); void fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address); bool fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde); bool fn_isolation_pages(HANDLE process_id, void* ori_addr); bool fn_split_large_pages(void* in_pde, void* out_pde); NTSTATUS get_page_table(UINT64 cr3, PAGE_TABLE& table); void* fn_pa_to_va(UINT64 pa); UINT64 fn_va_to_pa(void* va); __forceinline KIRQL DisableWriteProtection(); __forceinline void EnableWriteProtection(KIRQL oldIrql); void FlushCacheAndTlb(void* address); G_BIT_INFO m_GbitRecords[MAX_G_BIT_RECORDS]; UINT32 m_GbitCount = 0; void* m_PteBase = 0; HOOK_INFO m_HookInfo[MAX_HOOK_COUNT] = { 0 }; UINT32 m_HookCount = 0; char* m_TrampLinePool = nullptr; UINT32 m_PoolUsed = 0; static PteHookManager* m_Instance; }; PteHookManager* PteHookManager::m_Instance = nullptr; // 实现部分 __forceinline KIRQL P极HookManager::DisableWriteProtection() { KIRQL oldIrql = KeRaiseIrqlToDpcLevel(); UINT64 cr0 = __readcr0(); __writecr0(cr0 & ~CR0_WP); // 清除CR0.WP位 _mm_mfence(); return oldIrql; } __forceinline void PteHookManager::EnableWriteProtection(KIRQL oldIrql) { _mm_mfence(); UINT64 cr0 = __readcr0(); __writecr0(cr0 | CR0_WP); // 设置CR0.WP位 KeLowerIrql(oldIrql); } void* PteHookManager::fn_pa_to_va(UINT64 pa) { PHYSICAL_ADDRESS physAddr; physAddr.QuadPart = pa; return MmGetVirtualForPhysical(physAddr); } UINT64 PteHookManager::fn_va_to_pa(void* va) { PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(va); return physAddr.QuadPart; } NTSTATUS PteHookManager::get_page_table(UINT64 cr3_val, PAGE_TABLE& table) { UINT64 va = table.LineAddress; UINT64 pml4e_index = (va >> 39) & 0x1FF; UINT64 pdpte_index = (va >> 30) & 0x1FF; UINT64 pde_index = (va >> 21) & 0x1FF; UINT64 pte_index = (va >> 12) & 0x1FF; // PML4 UINT64 pml4_pa = cr3_val & ~0xFFF; UINT64* pml4_va = (UINT64*)fn_pa_to_va(pml4_pa); if (!pml4_va) return STATUS_INVALID_ADDRESS; table.Pml4Address = &pml4_va[pml4e_index]; table.OriginalPml4e = *table.Pml4Address; if (!(table.OriginalPml4e & 1)) return STATUS_ACCESS_VIOLATION; // PDPTE UINT64 pdpte_pa = table.OriginalPml4e & ~0xFFF; UINT64* pdpte_va = (UINT64*)fn_pa_to_va(pdpte_pa); if (!pdpte_va) return STATUS_INVALID_ADDRESS; table.PdpteAddress = (decltype(table.PdpteAddress))&pdpte_va[pdpte_index]; table.OriginalPdpte = table.PdpteAddress->value; table.Is1GBPage = (table.PdpteAddress->flags.page_size) ? TRUE : FALSE; if (!(table.OriginalPdpte & 1)) return STATUS_ACCESS_VIOLATION; if (table.Is1GBPage) return STATUS_SUCCESS; // PDE UINT64 pde_pa = table.OriginalPdpte & ~0xFFF; UINT64* pde_va = (UINT64*)fn_pa_to_va(pde_pa); if (!pde_va) return STATUS_INVALID_ADDRESS; table.PdeAddress = (decltype(table.PdeAddress))&pde_va[pde_index]; table.OriginalPde = table.PdeAddress->value; table.IsLargePage = (table.PdeAddress->flags.large_page) ? TRUE : FALSE; if (!(table.OriginalPde & 1)) return STATUS_ACCESS_VIOLATION; if (table.IsLargePage) return STATUS_SUCCESS; // PTE UINT64 pte_pa = table.OriginalPde & ~0xFFF; UINT64* pte_va = (UINT64*)fn_pa_to_va(pte_pa); if (!pte_va) return STATUS_INVALID_ADDRESS; table.PteAddress = (decltype(table.PteAddress))&pte_va[pte_index]; table.OriginalPte = table.PteAddress->value; if (!(table.OriginalPte & 1)) return STATUS_ACCESS_VIOLATION; LOG_TRACE("Page Table Info: VA=0x%p, PTE=0x%llX", (void*)table.LineAddress, table.OriginalPte); return STATUS_SUCCESS; } bool PteHookManager::fn_split_large_pages(void* in_pde_ptr, void* out_pde_ptr) { auto in_pde = (decltype(PAGE_TABLE::PdeAddress))in_pde_ptr; auto out_pde = (decltype(PAGE_TABLE::PdeAddress))out_pde_ptr; LOG_INFO("Splitting large page: Input PDE=0x%llx", in_pde->value); PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; auto pt = (decltype(PAGE_TABLE::PteAddress))MmAllocateContiguousMemorySpecifyCache( PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!pt) { LOG_ERROR("Failed to allocate contiguous memory for page splitting"); return false; } UINT64 start_pfn = in_pde->flags.page_frame_number; for (int i = 0; i < 512; i++) { pt[i].value = 0; pt[i].flags.present = 1; pt[i].flags.write = in_pde->flags.write; pt[i].flags.user = in_pde->flags.user; pt[i].flags.write_through = in_pde->flags.write_through; pt[i].flags.cache_disable = in_pde->flags.cache_disable; pt[i].flags.accessed = in_pde->flags.accessed; pt[i].flags.dirty = in_pde->flags.dirty; pt[i].flags.global = 0; pt[i].flags.page_frame_number = start_pfn + i; } out_pde->value = in_pde->value; out_pde->flags.large_page = 0; out_pde->flags.page_frame_number = fn_va_to_pa(pt) >> 12; LOG_INFO("Large page split complete: New PTE table at PA=0x%llx", fn_va_to_pa(pt)); return true; } bool PteHookManager::SetPageExecution(void* address, bool executable) { // 使用页表遍历函数修改NX位 PAGE_TABLE table = { 0 }; table.LineAddress = (UINT64)address; NTSTATUS status = get_page_table(__readcr3(), table); if (!NT_SUCCESS(status)) { LOG_ERROR("Failed to get page table for address 0x%p", address); return false; } KIRQL oldIrql = DisableWriteProtection(); UINT64 oldPte = table.PteAddress->value; UINT64 newPte = oldPte; // 设置或清除NX位 if (executable) { newPte &= ~PTE_NX_BIT; } else { newPte |= PTE_NX_BIT; } table.PteAddress->value = newPte; // 刷新TLB __invlpg(address); _mm_mfence(); EnableWriteProtection(oldIrql); LOG_TRACE("PTE modified for 0x%p: Old=0x%llX, New=0x%llX", address, oldPte, newPte); return true; } bool PteHookManager::fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde_ptr) { PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; LOG_INFO("Isolating page table: CR3=0x%llx, Address=0x%p", cr3_val, replace_align_addr); auto Va4kb = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, Low极, MmNonCached); auto VaPdt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPdpt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!VaPt || !Va4kb || !VaPdt || !VaPdpt) { if (VaPt) MmFreeContiguousMemory(VaPt); if (Va4kb) MmFreeContiguousMemory(Va4kb); if (VaPdt) MmFreeContiguousMemory(VaPdt); if (VaPdpt) MmFreeContiguousMemory(VaPd极); LOG_ERROR("Failed to allocate contiguous memory for isolation"); return false; } PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)replace_align_addr; NTSTATUS status = get_page_table(cr3_val, Table); if (!NT_SUCCESS(status)) { MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); LOG_ERROR("get_page_table failed with status 0x%X", status); return false; } UINT64 pte_index = (Table.LineAddress >> 12) & 0x1FF; UINT64 pde_index = (Table.LineAddress >> 21) & 0x1FF; UINT64 pdpte_index = (Table.LineAddress >> 30) & 0x1FF; UINT64 pml4e_index = (Table.LineAddress >> 39) & 0x1FF; memcpy(Va4kb, replace_align_addr, PAGE_SIZE); if (Table.IsLargePage && split_pde_ptr) { auto split_pde = (decltype(PAGE_TABLE::PdeAddress))split_pde_ptr; memcpy(VaPt, (void*)(split_pde->flags.page_frame_number << 12), PAGE_SIZE); } else { memcpy(VaPt, (void*)(Table.PdeAddress->flags.page_frame_number << 12), PAGE_SIZE); } memcpy(VaPdt, (void*)(Table.PdpteAddress->flags.page_frame_number << 12), PAGE_SIZE); memcpy(VaPdpt, (void*)(Table.Pml4Address[pml4e_index] & ~0xFFF), PAGE_SIZE); auto new_pte = (decltype(PAGE_TABLE::PteAddress))VaPt; new_pte[pte_index].flags.page_frame_number = fn_va_to_pa(Va4kb) >> 12; auto new_pde = (decltype(PAGE_TABLE::PdeAddress))VaPdt; new_pde[pde_index].value = Table.OriginalPde; new_pde[pde_index].flags.large_page = 0; new_pde[pde_index].flags.page_frame_number = fn_va_to_pa(VaPt) >> 12; auto new_pdpte = (decltype(PAGE_TABLE::PdpteAddress))VaPdpt; new_pdpte[pdpte_index].flags.page_frame_number = fn_va_to_pa(VaPdt) >> 12; auto new_pml4 = (UINT64*)fn_pa_to_va(cr3_val & ~0xFFF); new_pml4[pml4e_index] = (new_pml4[pml4e_index] & 0xFFF) | (fn_va_to_pa(VaPdpt) & ~0xFFF); __invlpg(replace_align_addr); LOG_INFO("Page table isolation complete: New PFN=0x%llx", fn_va_to_pa(Va4kb) >> 12); return true; } bool PteHookManager::fn_isolation_pages(HANDLE process_id, void* ori_addr) { PEPROCESS Process; if (!NT_SUCCESS(PsLookupProcessByProcessId(process_id, &Process))) { LOG_ERROR("PsLookupProcessByProcessId failed"); return false; } LOG_INFO("Isolating pages: PID=%d, Address=0x%p", HandleToUlong(process_id), ori_addr); KAPC_STATE ApcState; KeStackAttachProcess(Process, &ApcState); void* AlignAddr = PAGE_ALIGN(ori_addr); PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)AlignAddr; UINT64 target_cr3 = *(UINT64*)((UCHAR*)Process + 0x28); if (!NT_SUCCESS(get_page_table(target_cr3, Table))) { KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); LOG_ERROR("get_page_table failed"); return false; } bool success = false; decltype(PAGE_TABLE::PdeAddress) split_pde = nullptr; if (Table.IsLargePage) { split_pde = (decltype(PAGE_TABLE::PdeAddress))ExAllocatePoolWithTag(NonPagedPool, sizeof(*split_pde), 'pdeS'); if (!split_pde || !fn_split_large_pages(Table.PdeAddress, split_pde)) { if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); LOG_ERROR("Splitting large page failed"); return false; } if (Table.PdeAddress->flags.global) { Table.PdeAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, Table.PdeAddress, nullptr); LOG_INFO("Cleared G-bit for large page PDE: 0x%llx", Table.PdeAddress->value); } } else if (Table.PteAddress && Table.PteAddress->flags.global) { Table.PteAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, nullptr, Table.PteAddress); LOG_INFO("Cleared G-bit for PTE: 0x%llx", Table.PteAddress->value); } success = fn_isolation_pagetable(__readcr3(), AlignAddr, split_pde); if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); if (success) { LOG_INFO("Page isolation successful"); } else { LOG_ERROR("Page isolation failed"); } return success; } bool PteHookManager::WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd) { // 确保8字节对齐 if (reinterpret_cast<ULONG_PTR>(trampoline) & 0x7) { LOG_ERROR("Trampoline address not aligned: 0x%p", trampoline); return false; } // 禁用写保护 KIRQL oldIrql = DisableWriteProtection(); // 直接写入内存 RtlCopyMemory(trampoline, &jmpCmd, sizeof(JMP_ABS)); // 刷新缓存 __invlpg(trampoline); _mm_mfence(); // 恢复写保护 EnableWriteProtection(oldIrql); LOG_TRACE("Trampoline instruction written at 0x%p", trampoline); return true; } void PteHookManager::fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address) { if (m_GbitCount >= MAX_G_BIT_RECORDS) { LOG_ERROR("Max G-bit records reached"); return; } PG_BIT_INFO record = &m_GbitRecords[m_GbitCount++]; record->AlignAddress = align_addr; record->PdeAddress = (decltype(G_BIT_INFO::PdeAddress))pde_address; record->PteAddress = (decltype(G_BIT_INFO::PteAddress))pte_address; record->IsLargePage = (pde_address != nullptr); LOG_TRACE("Added G-bit record: Address=0x%p, PDE=0x%p, PTE=0x%p", align_addr, pde_address, pte_address); } bool PteHookManager::fn_resume_global_bits(void* align_addr) { KIRQL oldIrql = DisableWriteProtection(); bool found = false; LOG_INFO("Restoring G-bits for address: 0x%p", align_addr); for (UINT32 i = 0; i < m_GbitCount; i++) { PG_BIT_INFO record = &m_GbitRecords[i]; if (align_addr && record->AlignAddress != align_addr) continue; if (record->PteAddress) { record->PteAddress->flags.global = 1; __invlpg(record->AlignAddress); LOG_TRACE("Restored G-bit for PTE: 0x%p", record->AlignAddress); } if (record->PdeAddress) { record->PdeAddress->flags.global = 1; if (record->IsLargePage) { __invlpg(record->AlignAddress); } LOG_TRACE("Restored G-bit for PDE: 0x%p", record->AlignAddress); } found = true; if (align_addr) break; } EnableWriteProtection(oldIrql); if (found) { LOG_INFO("G-bits restoration complete"); } else { LOG_ERROR("No matching G-bit record found"); } return found; } bool PteHookManager::fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr) { if (!ori_addr || !hk_addr || !*ori_addr) { LOG_ERROR("Invalid parameters: ori_addr=%p, hk_addr=%p", ori_addr, hk_addr); return false; } // 分配跳板池(如果尚未分配) if (!m_TrampLinePool) { PHYSICAL_ADDRESS LowAddr; LowAddr.QuadPart = 0x100000; PHYSICAL_ADDRESS HighAddr; HighAddr.QuadPart = ~0ull; m_TrampLinePool = (char*)MmAllocateContiguousMemorySpecifyCache( PAGE_SIZE * 8, LowAddr, HighAddr, LowAddr, MmNonCached); if (!m_TrampLinePool) { LOG_ERROR("Failed to allocate trampoline pool"); return false; } // 设置跳板池可执行 if (!SetPageExecution(m_TrampLinePool, true)) { MmFreeContiguousMemory(m_TrampLinePool); m_TrampLinePool = nullptr; LOG_ERROR("Failed to set trampoline pool executable"); return false; } LOG_INFO("Trampoline pool allocated: Address=0x%p, Size=%d bytes", m_TrampLinePool, PAGE_SIZE * 8); } // 计算跳板位置(16字节对齐确保RIP相对寻址) void* trampoline = (void*)((ULONG_PTR)(m_TrampLinePool + m_PoolUsed + 15) & ~15); SIZE_T requiredSize = ((char*)trampoline - m_TrampLinePool) + sizeof(JMP_ABS); // 检查跳板池空间 if (requiredSize > PAGE_SIZE * 8) { LOG_ERROR("Trampoline pool out of space: Used=%d, Required=%d", m_PoolUsed, requiredSize); return false; } // 构造跳转指令 JMP_ABS jmpCmd; memcpy(jmpCmd.opcode, "\xFF\x25\x00\x00\x00\x00", 6); // jmp [rip+0] jmpCmd.address = reinterpret_cast<ULONG64>(hk_addr); LOG_INFO("Constructing jump instruction: Target=0x%p, Trampoline=0x%p", hk_addr, trampoline); // 写入跳板指令 if (!WriteTrampolineInstruction(trampoline, jmpCmd)) { return false; } // 设置目标函数不可执行(触发页错误) if (!SetPageExecution(*ori_addr, false)) { LOG_ERROR("Failed to set target function non-executable"); return false; } // 记录Hook信息 bool hookRecorded = false; for (UINT32 i = 0; i < MAX_HOOK_COUNT; i++) { if (!m_HookInfo[i].IsHooked) { m_HookInfo[i].OriginalAddress = *ori_addr; m_HookInfo[i].HookAddress = trampoline; m_HookInfo[i].ProcessId = process_id; m_HookInfo极i].IsHooked = TRUE; m_HookInfo[i].HookLength = sizeof(JMP_ABS); RtlCopyMemory(m_HookInfo[i].HookBytes, &jmpCmd, sizeof(jmpCmd)); // 保存原始PTE值 PAGE_TABLE table = { 0 }; table.LineAddress = (UINT64)*ori_addr; if (NT_SUCCESS(get_page_table(__readcr3(), table))) { m_HookInfo[i].OriginalPteValue = table.OriginalPte; } m_HookCount++; hookRecorded = true; LOG_INFO("Hook recorded #%d: Original=0x%p, Trampoline=0x%p", i, *ori_addr, trampoline); break; } } if (!hookRecorded) { LOG_ERROR("Exceeded max hook count (%d)", MAX_HOOK_COUNT); return false; } // 更新原始地址为跳板地址 *ori_addr = trampoline; m_PoolUsed = (UINT32)requiredSize; LOG_INFO("Hook installed successfully: Trampoline=0x%p -> Hook=0x%p", trampoline, hk_addr); return true; } bool PteHookManager::fn_remove_hook(HANDLE process_id, void* hook_addr) { LOG_INFO("Removing hook: HookAddr=0x%p", hook_addr); for (UINT32 i = 0; i < m_HookCount; i++) { if (m_HookInfo[i].HookAddress == hook_addr && m_HookInfo[i].IsHooked) { LOG_INFO("Found matching hook: OriginalAddr=0x%p", m_HookInfo[i].OriginalAddress); // 恢复目标函数执行权限 SetPageExecution(m_HookInfo[i].OriginalAddress, true); // 恢复原始PTE值 if (m_HookInfo[i].OriginalPteValue) { PAGE_TABLE table = { 0 }; table.LineAddress = (UINT64)m_HookInfo[i].OriginalAddress; if (NT_SUCCESS(get_page_table(__readcr3(), table))) { KIRQL oldIrql = KeRaiseIrqlToDpcLevel(); table.PteAddress->value = m_HookInfo[i].OriginalPteValue; __invlpg(m_HookInfo[i].OriginalAddress); KeLowerIrql(oldIrql); LOG_TRACE("Restored PTE for 0x%p: 0x%llX", m_HookInfo[i].OriginalAddress, m_HookInfo[i].OriginalPteValue); } } m_HookInfo[i].IsHooked = FALSE; LOG_INFO("Hook removed successfully"); return true; } } LOG_ERROR("No matching hook found"); return false; } PteHookManager::~PteHookManager() { if (m_TrampLinePool) { MmFreeContiguousMemory(m_TrampLinePool); m_TrampLinePool = nullptr; LOG_INFO("Trampoline pool freed"); } } PteHookManager* PteHookManager::GetInstance() { if (!m_Instance) { m_Instance = static_cast<PteHookManager*>( ExAllocatePoolWithTag(NonPagedPool, sizeof(PteHookManager), 'tpHk')); if (m_Instance) { RtlZeroMemory(m_Instance, sizeof(PteHookManager)); LOG_INFO("PTE Hook Manager instance created: 0x%p", m_Instance); } else { LOG_ERROR("Failed to create PTE Hook Manager instance"); } } return m_Instance; } // 全局PTE Hook管理器实例 PteHookManager* g_PteHookManager = nullptr; // 目标进程名称 const char target_process_name[] = "oxygen.exe"; // 辅助函数:检查是否为目标进程 BOOLEAN IsTargetProcess(CHAR* imageName) { CHAR currentName[16]; RtlZeroMemory(currentName, sizeof(currentName)); strncpy(currentName, imageName, sizeof(currentName) - 1); return (_stricmp(currentName, target_process_name) == 0); } // 函数类型定义 typedef NTSTATUS(*fn_ObReferenceObjectByHandleWithTag)( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ); fn_ObReferenceObjectByHandleWithTag g_OriginalObReferenceObjectByHandleWithTag = nullptr; // Hook 函数 NTSTATUS MyObReferenceObjectByHandleWithTag( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ) { PEPROCESS currentProcess = PsGetCurrentProcess(); CHAR* imageName = PsGetProcessImageFileName(currentProcess); LOG_INFO("Hook function called by process: %s", imageName); if (IsTargetProcess(imageName)) { LOG_INFO("Access denied for target process: %s", imageName); return STATUS_ACCESS_DENIED; } return g_OriginalObReferenceObjectByHandleWithTag( Handle, DesiredAccess, ObjectType, AccessMode, Tag, Object, HandleInformation ); } NTSTATUS InstallHook(HANDLE targetProcessId) { UNICODE_STRING funcName; RtlInitUnicodeString(&funcName, L"ObReferenceObjectByHandleWithTag"); g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)MmGetSystemRoutineAddress(&funcName); if (!g_OriginalObReferenceObjectByHandleWithTag) { LOG_ERROR("ObReferenceObjectByHandleWithTag not found"); return STATUS_NOT_FOUND; } LOG_INFO("Target function found: 0x%p", g_OriginalObReferenceObjectByHandleWithTag); void* targetFunc = (void*)g_OriginalObReferenceObjectByHandleWithTag; void* hookFunc = (void*)MyObReferenceObjectByHandleWithTag; if (!g_PteHookManager->fn_pte_inline_hook_bp_pg(targetProcessId, &targetFunc, hookFunc)) { LOG_ERROR("PTE Hook installation failed"); return STATUS_UNSUCCESSFUL; } g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)targetFunc; LOG_INFO("Hook installed successfully. Trampoline: 0x%p", targetFunc); return STATUS_SUCCESS; } // 移除 Hook VOID RemoveHook() { if (g_OriginalObReferenceObjectByHandleWithTag && g_PteHookManager) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), (void*)MyObReferenceObjectByHandleWithTag); } } // 工作线程上下文 typedef struct _HOOK_THREAD_CONTEXT { HANDLE TargetProcessId; } HOOK_THREAD_CONTEXT, * PHOOK_THREAD_CONTEXT; // 工作线程函数 VOID InstallHookWorker(PVOID Context) { PHOOK_THREAD_CONTEXT ctx = (PHOOK_THREAD_CONTEXT)Context; if (ctx) { LOG_INFO("Installing hook for PID: %d", HandleToUlong(ctx->TargetProcessId)); InstallHook(ctx->TargetProcessId); ExFreePoolWithTag(ctx, 'CtxH'); } PsTerminateSystemThread(STATUS_SUCCESS); } // 进程创建回调 - 修正后的签名 VOID ProcessNotifyCallback( _In_ PEPROCESS Process, _In_ HANDLE ProcessId, _In_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo ) { if (CreateInfo != NULL) { // 进程创建 CHAR* imageName = PsGetProcessImageFileName(Process); if (IsTargetProcess(imageName)) { LOG_INFO("Target process created: %s (PID: %d)", imageName, HandleToUlong(ProcessId)); // 创建工作线程上下文 PHOOK_THREAD_CONTEXT ctx = (PHOOK_THREAD_CONTEXT)ExAllocatePoolWithTag(NonPagedPool, sizeof(HOOK_THREAD_CONTEXT), 'CtxH'); if (ctx) { ctx->TargetProcessId = ProcessId; HANDLE threadHandle; NTSTATUS status = PsCreateSystemThread( &threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, InstallHookWorker, ctx ); if (NT_SUCCESS(status)) { ZwClose(threadHandle); LOG_INFO("Worker thread created for hook installation"); } else { ExFreePoolWithTag(ctx, 'CtxH'); LOG_ERROR("Failed to create worker thread: 0x%X", status); } } else { LOG_ERROR("Failed to allocate thread context"); } } } } // 驱动卸载函数 VOID DriverUnload(PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); LOG_INFO("Driver unloading..."); // 移除进程通知回调 PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, TRUE); // 移除Hook RemoveHook(); // 清理PTE Hook资源 if (g_PteHookManager) { LOG_INFO("Cleaning up PTE Hook Manager"); // 恢复所有被修改的G位 g_PteHookManager->fn_resume_global_bits(nullptr); // 移除所有活动的Hook HOOK_INFO* hookInfo = g_PteHookManager->GetHookInfo(); UINT32 hookCount = g_PteHookManager->GetHookCount(); for (UINT32 i = 0; i < hookCount; i++) { if (hookInfo[i].IsHooked) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), hookInfo[i].HookAddress); } } // 释放管理器实例 ExFreePoolWithTag(g_PteHookManager, 'tpHk'); g_PteHookManager = nullptr; } LOG_INFO("Driver unloaded successfully"); } extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath); LOG_INFO("Driver loading..."); DriverObject->DriverUnload = DriverUnload; g_PteHookManager = PteHookManager::GetInstance(); if (!g_PteHookManager) { LOG_ERROR("Failed to initialize PteHookManager"); return STATUS_INSUFFICIENT_RESOURCES; } NTSTATUS status = PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, FALSE); if (!NT_SUCCESS(status)) { LOG_ERROR("Failed to register process callback: 0x%X", status); return status; } LOG_INFO("Driver loaded successfully"); return STATUS_SUCCESS; } 严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息 错误(活动) E0020 未定义标识符 "极" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 51 错误(活动) E0276 后面有“::”的名称一定是类名或命名空间名 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 203 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 276 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 349 错误(活动) E0020 未定义标识符 "Low极" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 360 错误(活动) E0020 未定义标识符 "VaPd极" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 368 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 508 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 524 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 541 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 549 错误(活动) E0020 未定义标识符 "m_HookInfo极i" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 636 错误(活动) E0065 应输入“;” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 636 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 687 错误 C2065 “极”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 51 错误 C2653 “P极HookManager”: 不是类或命名空间名称 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 203 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 276 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 349 错误 C2065 “Low极”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 360 错误 C3536 “VaPt”: 初始化之前无法使用 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 364 错误 C2664 “void MmFreeContiguousMemory(PVOID)”: 无法将参数 1 从“int”转换为“PVOID” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 365 错误 C2065 “VaPd极”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 368 错误 C2664 “void MmFreeContiguousMemory(PVOID)”: 无法将参数 1 从“int”转换为“PVOID” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 377 错误 C2664 “void *memcpy(void *,const void *,size_t)”: 无法将参数 1 从“int”转换为“void *” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 394 错误 C2664 “void *memcpy(void *,const void *,size_t)”: 无法将参数 1 从“int”转换为“void *” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 397 错误 C2664 “UINT64 PteHookManager::fn_va_to_pa(void *)”: 无法将参数 1 从“int”转换为“void *” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 409 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 508 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 524 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 541 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 549 错误 C2065 “m_HookInfo极i”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 636 错误 C2143 语法错误: 缺少“;”(在“]”的前面) obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 636 错误 C2059 语法错误:“]” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 636 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 687
06-26
#include <ntifs.h> #include <ntddk.h> #include <intrin.h> #include "ptehook.h" #define CR0_WP (1 << 16) #define _WIN32_WINNT 0x0601 #define NTOS_MODE_USER void HexDump(const void* data, size_t size); typedef INT(*LDE_DISASM)(PVOID address, INT bits); typedef unsigned long DWORD; typedef unsigned __int64 ULONG64; // 使用WDK标准类型 typedef unsigned char BYTE; typedef LONG NTSTATUS; // 修正的跳板指令结构 #pragma pack(push, 1) typedef struct _JMP_ABS { BYTE opcode[6]; // FF 25 00 00 00 00 = jmp [rip+0] ULONG64 address; // 目标地址 (紧跟在指令后) } JMP_ABS, * PJMP_ABS; #pragma pack(pop) static_assert(sizeof(JMP_ABS) == 14, "JMP_ABS size must be 14 bytes"); LDE_DISASM lde_disasm; // 初始化引擎 VOID lde_init() { lde_disasm = (LDE_DISASM)ExAllocatePool(NonPagedPool, 12800); memcpy(lde_disasm, szShellCode, 12800); } // 得到完整指令长度,避免截断 ULONG GetFullPatchSize(PUCHAR Address) { ULONG LenCount = 0, Len = 0; // 至少需要14字节 while (LenCount <= 14) { Len = lde_disasm(Address, 64); Address = Address + Len; LenCount = LenCount + Len; } return LenCount; } #define PROCESS_NAME_LENGTH 16 #define DRIVER_TAG 'HKOB' EXTERN_C char* PsGetProcessImageFileName(PEPROCESS process); char target_process_name[] = "oxygen.exe"; typedef NTSTATUS(*fn_ObReferenceObjectByHandleWithTag)( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ); fn_ObReferenceObjectByHandleWithTag g_OriginalObReferenceObjectByHandleWithTag = NULL; // PTE Hook Framework #define MAX_G_BIT_RECORDS 128 #define MAX_HOOK_COUNT 64 #define PAGE_ALIGN(va) ((PVOID)((ULONG_PTR)(va) & ~0xFFF)) #define PDPTE_PS_BIT (1 << 7) #define PDE_PS_BIT (1 << 7) #define PTE_NX_BIT (1ULL << 63) #define CACHE_WB (6ULL << 3) // 页表结构定义 typedef struct _PAGE_TABLE { UINT64 LineAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 ignored_1 : 1; UINT64 page_size : 1; UINT64 ignored_2 : 4; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdpteAddress; UINT64* Pml4Address; BOOLEAN IsLargePage; BOOLEAN Is1GBPage; UINT64 OriginalPte; UINT64 OriginalPde; UINT64 OriginalPdpte; UINT64 OriginalPml4e; HANDLE ProcessId; } PAGE_TABLE, * PPAGE_TABLE; // G位信息记录结构体 typedef struct _G_BIT_INFO { void* AlignAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; BOOLEAN IsLargePage; } G_BIT_INFO, * PG_BIT_INFO; typedef struct _HOOK_INFO { void* OriginalAddress; void* HookAddress; UINT8 OriginalBytes[20]; UINT8 HookBytes[20]; UINT32 HookLength; BOOLEAN IsHooked; HANDLE ProcessId; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*HookedPte; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*HookedPde; } HOOK_INFO; class PteHookManager { public: bool fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr); bool fn_remove_hook(HANDLE process_id, void* hook_addr); static PteHookManager* GetInstance(); HOOK_INFO* GetHookInfo() { return m_HookInfo; } char* GetTrampLinePool() { return m_TrampLinePool; } UINT32 GetHookCount() { return m_HookCount; } bool fn_resume_global_bits(void* align_addr); ~PteHookManager(); // 添加析构函数声明 private: bool WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd); void fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address); bool fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde); bool fn_isolation_pages(HANDLE process_id, void* ori_addr); bool fn_split_large_pages(void* in_pde, void* out_pde); NTSTATUS get_page_table(UINT64 cr3, PAGE_TABLE& table); void* fn_pa_to_va(UINT64 pa); UINT64 fn_va_to_pa(void* va); __forceinline KIRQL DisableWriteProtection(); __forceinline void EnableWriteProtection(KIRQL oldIrql); void logger(const char* info, bool is_err, LONG err_code = 0); void PrintPageTableInfo(const PAGE_TABLE& table); void PrintHookInfo(const HOOK_INFO& hookInfo); void PrintGBitInfo(const G_BIT_INFO& gbitInfo); static constexpr SIZE_T MAX_HOOKS = 256; // 根据需求调整 G_BIT_INFO m_GbitRecords[MAX_G_BIT_RECORDS]; UINT32 m_GbitCount = 0; void* m_PteBase = 0; HOOK_INFO m_HookInfo[MAX_HOOK_COUNT] = { 0 }; DWORD m_HookCount = 0; char* m_TrampLinePool = nullptr; // 合并为一个声明 UINT32 m_PoolUsed = 0; static PteHookManager* m_Instance; }; PteHookManager* PteHookManager::m_Instance = nullptr; // 实现部分 __forceinline KIRQL PteHookManager::DisableWriteProtection() { KIRQL oldIrql = KeRaiseIrqlToDpcLevel(); UINT64 cr0 = __readcr0(); __writecr0(cr0 & ~0x10000); // 清除CR0.WP位 _mm_mfence(); return oldIrql; } __forceinline void PteHookManager::EnableWriteProtection(KIRQL oldIrql) { _mm_mfence(); UINT64 cr0 = __readcr0(); __writecr0(cr0 | 0x10000); // 设置CR0.WP位 KeLowerIrql(oldIrql); } void PteHookManager::logger(const char* info, bool is_err, LONG err_code) { if (is_err) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] ERROR: %s (0x%X)\n", info, err_code); } else { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] INFO: %s\n", info); } } void PteHookManager::PrintPageTableInfo(const PAGE_TABLE& table) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Page Table Info for VA: 0x%p\n", (void*)table.LineAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PML4E: 0x%llx (Address: 0x%p)\n", table.OriginalPml4e, table.Pml4Address); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDPTE: 0x%llx (Address: 0x%p), Is1GBPage: %d\n", table.OriginalPdpte, table.PdpteAddress, table.Is1GBPage); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDE: 0x%llx (Address: 0x%p), IsLargePage: %d\n", table.OriginalPde, table.PdeAddress, table.IsLargePage); if (!table.IsLargePage && !table.Is1GBPage) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PTE: 0x%llx (Address: 0x%p)\n", table.OriginalPte, table.PteAddress); } } void PteHookManager::PrintHookInfo(const HOOK_INFO& hookInfo) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook Info:\n"); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Original Address: 0x%p\n", hookInfo.OriginalAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Address: 0x%p\n", hookInfo.HookAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Length: %d\n", hookInfo.HookLength); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Is Hooked: %d\n", hookInfo.IsHooked); // 打印原始字节 DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Original Bytes: "); for (UINT32 i = 0; i < sizeof(hookInfo.OriginalBytes); i++) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", hookInfo.OriginalBytes[i]); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); // 打印Hook字节 DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Hook Bytes: "); for (UINT32 i = 0; i < sizeof(hookInfo.HookBytes); i++) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", hookInfo.HookBytes[i]); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); } void PteHookManager::PrintGBitInfo(const G_BIT_INFO& gbitInfo) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] G-Bit Info:\n"); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " Align Address: 0x%p\n", gbitInfo.AlignAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " IsLargePage: %d\n", gbitInfo.IsLargePage); if (gbitInfo.PdeAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PDE: 0x%llx (Address: 0x%p)\n", gbitInfo.PdeAddress->value, gbitInfo.PdeAddress); } if (gbitInfo.PteAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, " PTE: 0x%llx (Address: 0x%p)\n", gbitInfo.PteAddress->value, gbitInfo.PteAddress); } } void* PteHookManager::fn_pa_to_va(UINT64 pa) { PHYSICAL_ADDRESS physAddr; physAddr.QuadPart = pa; return MmGetVirtualForPhysical(physAddr); } UINT64 PteHookManager::fn_va_to_pa(void* va) { PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(va); return physAddr.QuadPart; } NTSTATUS PteHookManager::get_page_table(UINT64 cr3_val, PAGE_TABLE& table) { UINT64 va = table.LineAddress; UINT64 pml4e_index = (va >> 39) & 0x1FF; UINT64 pdpte_index = (va >> 30) & 0x1FF; UINT64 pde_index = (va >> 21) & 0x1FF; UINT64 pte_index = (va >> 12) & 0x1FF; // PML4 UINT64 pml4_pa = cr3_val & ~0xFFF; UINT64* pml4_va = (UINT64*)fn_pa_to_va(pml4_pa); if (!pml4_va) return STATUS_INVALID_ADDRESS; table.Pml4Address = &pml4_va[pml4e_index]; table.OriginalPml4e = *table.Pml4Address; if (!(table.OriginalPml4e & 1)) return STATUS_ACCESS_VIOLATION; // PDPTE UINT64 pdpte_pa = table.OriginalPml4e & ~0xFFF; UINT64* pdpte_va = (UINT64*)fn_pa_to_va(pdpte_pa); if (!pdpte_va) return STATUS_INVALID_ADDRESS; table.PdpteAddress = (decltype(table.PdpteAddress))&pdpte_va[pdpte_index]; table.OriginalPdpte = table.PdpteAddress->value; table.Is1GBPage = (table.PdpteAddress->flags.page_size) ? TRUE : FALSE; if (!(table.OriginalPdpte & 1)) return STATUS_ACCESS_VIOLATION; if (table.Is1GBPage) return STATUS_SUCCESS; // PDE UINT64 pde_pa = table.OriginalPdpte & ~0xFFF; UINT64* pde_va = (UINT64*)fn_pa_to_va(pde_pa); if (!pde_va) return STATUS_INVALID_ADDRESS; table.PdeAddress = (decltype(table.PdeAddress))&pde_va[pde_index]; table.OriginalPde = table.PdeAddress->value; table.IsLargePage = (table.PdeAddress->flags.large_page) ? TRUE : FALSE; if (!(table.OriginalPde & 1)) return STATUS_ACCESS_VIOLATION; if (table.IsLargePage) return STATUS_SUCCESS; // PTE UINT64 pte_pa = table.OriginalPde & ~0xFFF; UINT64* pte_va = (UINT64*)fn_pa_to_va(pte_pa); if (!pte_va) return STATUS_INVALID_ADDRESS; table.PteAddress = (decltype(table.PteAddress))&pte_va[pte_index]; table.OriginalPte = table.PteAddress->value; if (!(table.OriginalPte & 1)) return STATUS_ACCESS_VIOLATION; // 打印页表信息 PrintPageTableInfo(table); return STATUS_SUCCESS; } bool PteHookManager::fn_split_large_pages(void* in_pde_ptr, void* out_pde_ptr) { auto in_pde = (decltype(PAGE_TABLE::PdeAddress))in_pde_ptr; auto out_pde = (decltype(PAGE_TABLE::PdeAddress))out_pde_ptr; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 正在拆分大页: 输入PDE=0x%llx, 输出PDE=0x%p\n", in_pde->value, out_pde); PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; auto pt = (decltype(PAGE_TABLE::PteAddress))MmAllocateContiguousMemorySpecifyCache( PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!pt) { logger("分配连续内存失败 (用于拆分大页)", true); return false; } UINT64 start_pfn = in_pde->flags.page_frame_number; for (int i = 0; i < 512; i++) { pt[i].value = 0; pt[i].flags.present = 1; pt[i].flags.write = in_pde->flags.write; pt[i].flags.user = in_pde->flags.user; pt[i].flags.write_through = in_pde->flags.write_through; pt[i].flags.cache_disable = in_pde->flags.cache_disable; pt[i].flags.accessed = in_pde->flags.accessed; pt[i].flags.dirty = in_pde->flags.dirty; pt[i].flags.global = 0; pt[i].flags.page_frame_number = start_pfn + i; } out_pde->value = in_pde->value; out_pde->flags.large_page = 0; out_pde->flags.page_frame_number = fn_va_to_pa(pt) >> 12; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 大页拆分完成: 新PTE表物理地址=0x%llx\n", fn_va_to_pa(pt)); return true; } bool PteHookManager::fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde_ptr) { PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始隔离页表: CR3=0x%llx, 地址=0x%p\n", cr3_val, replace_align_addr); auto Va4kb = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPdt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPdpt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!VaPt || !Va4kb || !VaPdt || !VaPdpt) { if (VaPt) MmFreeContiguousMemory(VaPt); if (Va4kb) MmFreeContiguousMemory(Va4kb); if (VaPdt) MmFreeContiguousMemory(VaPdt); if (VaPdpt) MmFreeContiguousMemory(VaPdpt); logger("分配连续内存失败 (用于隔离页表)", true); return false; } PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)replace_align_addr; NTSTATUS status = get_page_table(cr3_val, Table); if (!NT_SUCCESS(status)) { MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); logger("获取页表信息失败", true, status); return false; } UINT64 pte_index = (Table.LineAddress >> 12) & 0x1FF; UINT64 pde_index = (Table.LineAddress >> 21) & 0x1FF; UINT64 pdpte_index = (Table.LineAddress >> 30) & 0x1FF; UINT64 pml4e_index = (Table.LineAddress >> 39) & 0x1FF; memcpy(Va4kb, replace_align_addr, PAGE_SIZE); if (Table.IsLargePage && split_pde_ptr) { auto split_pde = (decltype(PAGE_TABLE::PdeAddress))split_pde_ptr; memcpy(VaPt, (void*)(split_pde->flags.page_frame_number << 12), PAGE_SIZE); } else { memcpy(VaPt, (void*)(Table.PdeAddress->flags.page_frame_number << 12), PAGE_SIZE); } memcpy(VaPdt, (void*)(Table.PdpteAddress->flags.page_frame_number << 12), PAGE_SIZE); memcpy(VaPdpt, (void*)(Table.Pml4Address[pml4e_index] & ~0xFFF), PAGE_SIZE); auto new_pte = (decltype(PAGE_TABLE::PteAddress))VaPt; new_pte[pte_index].flags.page_frame_number = fn_va_to_pa(Va4kb) >> 12; auto new_pde = (decltype(PAGE_TABLE::PdeAddress))VaPdt; new_pde[pde_index].value = Table.OriginalPde; new_pde[pde_index].flags.large_page = 0; new_pde[pde_index].flags.page_frame_number = fn_va_to_pa(VaPt) >> 12; auto new_pdpte = (decltype(PAGE_TABLE::PdpteAddress))VaPdpt; new_pdpte[pdpte_index].flags.page_frame_number = fn_va_to_pa(VaPdt) >> 12; auto new_pml4 = (UINT64*)fn_pa_to_va(cr3_val & ~0xFFF); new_pml4[pml4e_index] = (new_pml4[pml4e_index] & 0xFFF) | (fn_va_to_pa(VaPdpt) & ~0xFFF); __invlpg(replace_align_addr); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页表隔离完成: 新PFN=0x%llx\n", fn_va_to_pa(Va4kb) >> 12); return true; } bool PteHookManager::fn_isolation_pages(HANDLE process_id, void* ori_addr) { PEPROCESS Process; if (!NT_SUCCESS(PsLookupProcessByProcessId(process_id, &Process))) { logger("查找进程失败", true); return false; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始隔离页面: PID=%d, 地址=0x%p\n", (ULONG)(ULONG_PTR)process_id, ori_addr); KAPC_STATE ApcState; KeStackAttachProcess(Process, &ApcState); void* AlignAddr = PAGE_ALIGN(ori_addr); PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)AlignAddr; UINT64 target_cr3 = *(UINT64*)((UCHAR*)Process + 0x28); if (!NT_SUCCESS(get_page_table(target_cr3, Table))) { KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); logger("获取目标进程页表失败", true); return false; } bool success = false; decltype(PAGE_TABLE::PdeAddress) split_pde = nullptr; if (Table.IsLargePage) { split_pde = (decltype(PAGE_TABLE::PdeAddress))ExAllocatePoolWithTag(NonPagedPool, sizeof(*split_pde), 'pdeS'); if (!split_pde || !fn_split_large_pages(Table.PdeAddress, split_pde)) { if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); logger("拆分大页失败", true); return false; } if (Table.PdeAddress->flags.global) { Table.PdeAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, Table.PdeAddress, nullptr); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 清除大页G位: PDE=0x%llx\n", Table.PdeAddress->value); } } else if (Table.PteAddress && Table.PteAddress->flags.global) { Table.PteAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, nullptr, Table.PteAddress); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 清除PTE G位: PTE=0x%llx\n", Table.PteAddress->value); success = fn_isolation_pagetable(__readcr3(), AlignAddr, split_pde); if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页表状态: IsLargePage=%d, Is1GBPage=%d\n", Table.IsLargePage, Table.Is1GBPage); if (Table.PteAddress) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] PTE 值: 0x%llx (G位=%d)\n", Table.PteAddress->value, Table.PteAddress->flags.global); } KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); if (success) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 页面隔离成功\n"); } else { logger("页面隔离失败", true); } return success; } KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); return true; } bool PteHookManager::WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd) { // 1. 确保8字节对齐 if (reinterpret_cast<ULONG_PTR>(trampoline) & 0x7) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 跳板地址未对齐 (0x%p)\n", trampoline); return false; } // 2. 禁用写保护 KIRQL oldIrql = DisableWriteProtection(); // 3. 直接写入内存 RtlCopyMemory(trampoline, &jmpCmd, sizeof(JMP_ABS)); // 4. 刷新缓存 __invlpg(trampoline); _mm_mfence(); // 5. 恢复写保护 EnableWriteProtection(oldIrql); // 6. 验证写入 BYTE buffer[sizeof(JMP_ABS)]; RtlCopyMemory(buffer, trampoline, sizeof(buffer)); if (memcmp(buffer, &jmpCmd, sizeof(jmpCmd)) != 0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 验证失败! 内存内容:\n"); HexDump(buffer, sizeof(buffer)); return false; } // 7. 反汇编验证 DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 跳板指令: jmp [rip+0] -> 0x%016llX\n", jmpCmd.address); return true; } // 辅助函数:十六进制转储 void HexDump(const void* data, size_t size) { const BYTE* bytes = static_cast<const BYTE*>(data); for (size_t i = 0; i < size; ++i) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%02X ", bytes[i]); if ((i + 1) % 16 == 0) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "\n"); } bool PteHookManager::fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr) { if (!ori_addr || !hk_addr || !*ori_addr) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 无效参数 (ori_addr=%p, hk_addr=%p)\n", ori_addr, hk_addr); return false; } // 分配跳板池(如果尚未分配) if (!m_TrampLinePool) { PHYSICAL_ADDRESS LowAddr = { LowAddr.QuadPart = 0x100000 }; PHYSICAL_ADDRESS HighAddr = { HighAddr.QuadPart = ~0ull }; m_TrampLinePool = (char*)MmAllocateContiguousMemorySpecifyCache( PAGE_SIZE * 8, LowAddr, HighAddr, LowAddr, MmNonCached); if (!m_TrampLinePool) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 无法分配跳板池内存\n"); return false; } // 设置内存保护属性 PMDL pMdl = IoAllocateMdl(m_TrampLinePool, PAGE_SIZE * 8, FALSE, FALSE, NULL); if (pMdl) { MmBuildMdlForNonPagedPool(pMdl); MmProtectMdlSystemAddress(pMdl, PAGE_EXECUTE_READWRITE); IoFreeMdl(pMdl); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 跳板池分配成功: 地址=0x%p, 大小=%d字节\n", m_TrampLinePool, PAGE_SIZE * 8); } // 计算跳板位置(8字节对齐) void* trampoline = (void*)((ULONG_PTR)(m_TrampLinePool + m_PoolUsed + 7) & ~7) ; SIZE_T requiredSize = ((char*)trampoline - m_TrampLinePool) + sizeof(JMP_ABS); // 构造正确的跳转指令 JMP_ABS jmpCmd = {}; memcpy(jmpCmd.opcode, "\xFF\x25\x00\x00\x00\x00", 6); // jmp [rip+0] jmpCmd.address = reinterpret_cast<ULONG64>(hk_addr); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 构造跳转指令:\n" " 目标地址: 0x%p\n" " 跳板位置: 0x%p\n" " 指令格式: FF 25 00 00 00 00 + 8字节地址\n", hk_addr, trampoline); // 写入跳板指令 if (!WriteTrampolineInstruction(trampoline, jmpCmd)) { return false; } // 记录Hook信息 bool hookRecorded = false; for (UINT32 i = 0; i < MAX_HOOK_COUNT; i++) { if (!m_HookInfo[i].IsHooked) { m_HookInfo[i].OriginalAddress = *ori_addr; m_HookInfo[i].HookAddress = trampoline; m_HookInfo[i].ProcessId = process_id; m_HookInfo[i].IsHooked = TRUE; RtlCopyMemory(m_HookInfo[i].HookBytes, &jmpCmd, sizeof(jmpCmd)); m_HookInfo[i].HookLength = sizeof(JMP_ABS); m_HookCount++; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook记录 #%d: 原始地址=0x%p, 跳板=0x%p\n", i, *ori_addr, trampoline); hookRecorded = true; break; } } if (!hookRecorded) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 错误: 超过最大Hook数量限制 (%d)\n", MAX_HOOK_COUNT); return false; } // 更新原始地址为跳板地址 *ori_addr = trampoline; m_PoolUsed = (UINT32)requiredSize; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook安装成功! 跳板指令:\n" " jmp [rip+0] -> 0x%p\n", hk_addr); return true; } // 析构函数清理资源 PteHookManager::~PteHookManager() { if (m_TrampLinePool) { MmFreeContiguousMemory(m_TrampLinePool); m_TrampLinePool = nullptr; } } bool PteHookManager::fn_remove_hook(HANDLE process_id, void* hook_addr) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 尝试移除Hook: Hook地址=0x%p\n", hook_addr); for (UINT32 i = 0; i < m_HookCount; i++) { if (m_HookInfo[i].HookAddress == hook_addr && m_HookInfo[i].IsHooked) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 找到匹配的Hook: 原始地址=0x%p\n", m_HookInfo[i].OriginalAddress); KIRQL oldIrql = DisableWriteProtection(); memcpy(m_HookInfo[i].OriginalAddress, m_HookInfo[i].OriginalBytes, sizeof(m_HookInfo[i].OriginalBytes)); EnableWriteProtection(oldIrql); m_HookInfo[i].IsHooked = FALSE; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] Hook已成功移除\n"); return true; } } logger("未找到匹配的Hook", true); return false; } void PteHookManager::fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address) { if (m_GbitCount >= MAX_G_BIT_RECORDS) { logger("达到最大G位记录数量限制", true); return; } PG_BIT_INFO record = &m_GbitRecords[m_GbitCount++]; record->AlignAddress = align_addr; record->PdeAddress = (decltype(G_BIT_INFO::PdeAddress))pde_address; record->PteAddress = (decltype(G_BIT_INFO::PteAddress))pte_address; record->IsLargePage = (pde_address && ((decltype(PAGE_TABLE::PdeAddress))pde_address)->flags.large_page); // 打印G位信息 PrintGBitInfo(*record); } bool PteHookManager::fn_resume_global_bits(void* align_addr) { KIRQL oldIrql = DisableWriteProtection(); bool found = false; DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] 开始恢复G位: 对齐地址=0x%p\n", align_addr); for (UINT32 i = 0; i < m_GbitCount; i++) { PG_BIT_INFO record = &m_GbitRecords[i]; if (align_addr && record->AlignAddress != align_addr) continue; if (record->PteAddress) { record->PteAddress->flags.global = 1; __invlpg(record->AlignAddress); DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, " 恢复PTE G位: PTE=0x%llx, 地址=0x%p\n", record->PteAddress->value, record->AlignAddress); } if (record->PdeAddress) { record->PdeAddress->flags.global = 1; if (record->IsLargePage) { __invlpg(record->AlignAddress); } DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, " 恢复PDE G位: PDE=0x%llx, 地址=0x%p, 大页=%d\n", record->PdeAddress->value, record->AlignAddress, record->IsLargePage); } found = true; if (align_addr) break; } EnableWriteProtection(oldIrql); if (found) { DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] G位恢复完成\n"); } else { logger("未找到匹配的G位记录", true); } return found; } PteHookManager* PteHookManager::GetInstance() { if (!m_Instance) { m_Instance = static_cast<PteHookManager*>( ExAllocatePoolWithTag(NonPagedPool, sizeof(PteHookManager), 'tpHk')); if (m_Instance) { RtlZeroMemory(m_Instance, sizeof(PteHookManager)); DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_INFO_LEVEL, "[PTE_HOOK] PTE Hook管理器实例已创建: 地址=0x%p\n", m_Instance); } else { DbgPrintEx(DPFLTR_ERROR_LEVEL, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] 创建PTE Hook管理器实例失败\n"); } } return m_Instance; } // 全局PTE Hook管理器实例 PteHookManager* g_PteHookManager = nullptr; // 辅助函数:检查是否为目标进程 BOOLEAN IsTargetProcess(CHAR* imageName) { CHAR currentName[16]; // 复制到本地缓冲区并确保 NULL 终止 RtlCopyMemory(currentName, imageName, 16); currentName[15] = '\0'; // 确保终止 // 修剪尾部空格 for (int i = 15; i >= 0; i--) { if (currentName[i] == ' ') currentName[i] = '\0'; else if (currentName[i] != '\0') break; } return (strcmp(currentName, target_process_name) == 0); } // Hook 函数 NTSTATUS MyObReferenceObjectByHandleWithTag( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ) { __debugbreak(); // 强制中断,确认是否执行到这里 PEPROCESS currentProcess = PsGetCurrentProcess(); CHAR* imageName = PsGetProcessImageFileName(currentProcess); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[!] [HookFunction] 进入 Hook 函数! 当前进程: %s\n", imageName); if (IsTargetProcess(imageName)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[!] [HookFunction] 拒绝访问目标进程 PID=%d\n", HandleToULong(PsGetCurrentProcessId())); return STATUS_ACCESS_DENIED; } return g_OriginalObReferenceObjectByHandleWithTag( Handle, DesiredAccess, ObjectType, AccessMode, Tag, Object, HandleInformation ); } NTSTATUS InstallHook() { UNICODE_STRING funcName; RtlInitUnicodeString(&funcName, L"ObReferenceObjectByHandleWithTag"); g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)MmGetSystemRoutineAddress(&funcName); if (!g_OriginalObReferenceObjectByHandleWithTag) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [InstallHook] 找不到 ObReferenceObjectByHandleWithTag\n"); return STATUS_NOT_FOUND; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [InstallHook] 找到目标函数地址: %p\n", g_OriginalObReferenceObjectByHandleWithTag); void* targetFunc = (void*)g_OriginalObReferenceObjectByHandleWithTag; void* hookFunc = (void*)MyObReferenceObjectByHandleWithTag; HANDLE currentProcessId = PsGetCurrentProcessId(); if (!g_PteHookManager->fn_pte_inline_hook_bp_pg(currentProcessId, &targetFunc, hookFunc)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [InstallHook] PTE Hook 安装失败\n"); return STATUS_UNSUCCESSFUL; } g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)targetFunc; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [InstallHook] Hook 成功安装. 跳板地址: %p\n", targetFunc); return STATUS_SUCCESS; } // 移除 Hook VOID RemoveHook() { if (g_OriginalObReferenceObjectByHandleWithTag && g_PteHookManager) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), (void*)MyObReferenceObjectByHandleWithTag); } } // 工作线程函数 VOID InstallHookWorker(PVOID Context) { UNREFERENCED_PARAMETER(Context); DbgPrint("[+] Worker thread started for hook installation\n"); InstallHook(); PsTerminateSystemThread(STATUS_SUCCESS); } // 进程创建回调 VOID ProcessNotifyCallback( _In_ HANDLE ParentId, _In_ HANDLE ProcessId, _In_ BOOLEAN Create ) { UNREFERENCED_PARAMETER(ParentId); if (Create) { PEPROCESS process = NULL; if (NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &process))) { CHAR* imageName = PsGetProcessImageFileName(process); CHAR currentName[16]; RtlCopyMemory(currentName, imageName, 16); currentName[15] = '\0'; for (int i = 15; i >= 0; i--) { if (currentName[i] == ' ') currentName[i] = '\0'; else if (currentName[i] != '\0') break; } if (strcmp(currentName, target_process_name) == 0) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [ProcessNotifyCallback] 目标进程 %s 创建 (PID: %d)\n", currentName, HandleToULong(ProcessId)); HANDLE threadHandle; NTSTATUS status = PsCreateSystemThread( &threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, InstallHookWorker, NULL ); if (NT_SUCCESS(status)) { ZwClose(threadHandle); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [ProcessNotifyCallback] 工作线程已创建\n"); } else { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [ProcessNotifyCallback] 创建线程失败: 0x%X\n", status); } } ObDereferenceObject(process); } } } // 驱动卸载函数 VOID DriverUnload(PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); DbgPrint("[+] Driver unloading...\n"); // 移除进程通知回调 PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)ProcessNotifyCallback, TRUE); // 移除Hook RemoveHook(); // 清理PTE Hook资源 if (g_PteHookManager) { DbgPrint("[PTE_HOOK] Cleaning up PTE...\n"); // 恢复所有被修改的G位 g_PteHookManager->fn_resume_global_bits(nullptr); // 移除所有活动的Hook HOOK_INFO* hookInfo = g_PteHookManager->GetHookInfo(); UINT32 hookCount = g_PteHookManager->GetHookCount(); for (UINT32 i = 0; i < hookCount; i++) { if (hookInfo[i].IsHooked) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), hookInfo[i].HookAddress); } } // 释放跳板池内存 char* trampLinePool = g_PteHookManager->GetTrampLinePool(); if (trampLinePool) { ExFreePoolWithTag(trampLinePool, 'JmpP'); } // 释放管理器实例 ExFreePoolWithTag(g_PteHookManager, 'tpHk'); g_PteHookManager = nullptr; } DbgPrint("[+] Driver unloaded successfully\n"); } extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [DriverEntry] 驱动加载开始\n"); DriverObject->DriverUnload = DriverUnload; g_PteHookManager = PteHookManager::GetInstance(); if (!g_PteHookManager) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [DriverEntry] 初始化 PteHookManager 失败\n"); return STATUS_INSUFFICIENT_RESOURCES; } NTSTATUS status = PsSetCreateProcessNotifyRoutineEx((PCREATE_PROCESS_NOTIFY_ROUTINE_EX)ProcessNotifyCallback, FALSE); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] [DriverEntry] 注册进程通知失败 (0x%X)\n", status); return status; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[+] [DriverEntry] 驱动加载成功\n"); return STATUS_SUCCESS; } 将整个代码修改正确
06-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值