• NtAllocateVirtualMemory函数逆向分析


    0x00前言

    windows 10 21h2 系统

    0x01NtAllocateVirtualMemory分析

    NTSTATUS __stdcall NtAllocateVirtualMemory(
            HANDLE ProcessHandle,                   // 用户请求内核分配内存空间
            PVOID *BaseAddress,
            ULONG_PTR ZeroBits,
            PSIZE_T RegionSize,
            ULONG AllocationType,
            ULONG Protect)
    {
      unsigned __int64 v8; // r14
      char PreviousMode; // bl
      __int64 v10; // rcx
      __int64 v11; // rcx
      PVOID v12; // rdi
      __int64 v13; // rsi
      NTSTATUS VirtualMemoryPrepare; // ebx
      unsigned __int8 v16; // [rsp+70h] [rbp-138h]
      unsigned __int64 v17; // [rsp+78h] [rbp-130h] BYREF
      PVOID v18; // [rsp+80h] [rbp-128h] BYREF
      PVOID v19; // [rsp+88h] [rbp-120h]
      ULONG_PTR v20; // [rsp+90h] [rbp-118h]
      PVOID Object[3]; // [rsp+98h] [rbp-110h] BYREF
      __int64 v22[10]; // [rsp+B0h] [rbp-F8h] BYREF
      __int64 v23[16]; // [rsp+100h] [rbp-A8h] BYREF
      int v24; // [rsp+1B0h] [rbp+8h]
      int v25; // [rsp+1C0h] [rbp+18h]
    
      v25 = ZeroBits;
      v24 = (int)ProcessHandle;
      v8 = 0i64;
      v19 = 0i64;
      v20 = 0i64;
      memset(v22, 0, 0x48ui64);
      PreviousMode = KeGetCurrentThread()->PreviousMode;
      v16 = PreviousMode;
      if ( PreviousMode )                           // 看权限模式
      {
        v10 = (__int64)BaseAddress;                 // 地址判断
        if ( (unsigned __int64)BaseAddress >= 0x7FFFFFFF0000i64 )
          v10 = 0x7FFFFFFF0000i64;
        *(_QWORD *)v10 = *(_QWORD *)v10;            // 报错
        v11 = (__int64)RegionSize;
        if ( (unsigned __int64)RegionSize >= 0x7FFFFFFF0000i64 )
          v11 = 0x7FFFFFFF0000i64;
        *(_QWORD *)v11 = *(_QWORD *)v11;            // 报错
      }
      v12 = *BaseAddress;
      v19 = *BaseAddress;
      v13 = *RegionSize;
      v20 = *RegionSize;
      LODWORD(v22[4]) = AllocationType & 0x7F;
      if ( (AllocationType & 0x44000) != 0 )        // 检查是否是有效分配类型
        return 0xC000000D;
      memset(v23, 0, sizeof(v23));
      v18 = 0i64;
      Object[0] = 0i64;
      v17 = 0i64;
      VirtualMemoryPrepare = MiAllocateVirtualMemoryPrepare(
                               v24,                 // ProcessHandle目标进程句柄
                               (int)v12,            // BaseAddress 要分配地址
                               v25,                 // 基址高位零位数量 0忽略
                               v13,                 // 期望大小
                               AllocationType & 0xFFFFFF80,// 分配内存类型
                               Protect,             // 页面属性
                               (__int64)v22,
                               PreviousMode,        // 调用状态
                               0,
                               0,
                               0i64,
                               (__int64)v23,
                               (__int64)Object);
      if ( VirtualMemoryPrepare >= 0 )
      {
        if ( v22[3] )
        {
          if ( v22[3] == -3 )
          {
            v8 = 1i64;
            v17 = 1i64;
          }
          else
          {
            VirtualMemoryPrepare = PsReferencePartitionByHandle(v22[3], 2i64, v16, 1633054029i64, &v17);
            v8 = v17;
            if ( VirtualMemoryPrepare < 0 )
              goto LABEL_13;
          }
        }
        if ( LOBYTE(v22[6]) == 1 && (AllocationType & 0x20400000) != 0x400000 )
        {
          VirtualMemoryPrepare = -1073741811;
    LABEL_21:
          if ( v23[0] )
            ++dword_140C4E6EC;
          else
            ++dword_140C4E6E8;
          goto LABEL_14;
        }
        VirtualMemoryPrepare = MiAllocateVirtualMemory(v23, v8, &v18);
        if ( VirtualMemoryPrepare >= 0 )
        {
          v12 = v18;
          v19 = v18;
          v13 = v23[3];
          v20 = v23[3];
        }
      }
    LABEL_13:
      if ( VirtualMemoryPrepare < 0 )
        goto LABEL_21;
    LABEL_14:
      if ( v8 >= 2 )
        PsDereferencePartition(v8);
      if ( Object[0] )
        ObfDereferenceObjectWithTag(Object[0], 0x6D566D4Du);
      if ( VirtualMemoryPrepare >= 0 )
      {
        *BaseAddress = v12;
        *RegionSize = v13;
      }
      return VirtualMemoryPrepare;
    }

    0x02MiAllocateVirtualMemoryPrepare分析

    __int64 __fastcall MiAllocateVirtualMemoryPrepare(
            ULONG_PTR a1,                           //  ProcessHandle目标进程句柄
            __int64 a2,                             // BaseAddress 要分配地址
            __int64 a3,                             // 基址高位零位数量 0忽略
            unsigned __int64 a4,                    // 期望大小
            unsigned int a5,                        // 分配内存类型
            unsigned int a6,                        // 页面属性
            __int64 a7,
            char a8,                                // 调用状态
            unsigned int a9,                        // 0
            int a10,                                // 0
            __int64 a11,                            // 0
            __int64 a12,
            PVOID *a13)                             // Object
    {
      unsigned __int64 v13; // rsi
      __int64 v14; // rbx
      _QWORD *p_Lock; // rax
      unsigned int v17; // ebp
      __int64 v18; // rcx
      __int64 v19; // rdx
      unsigned int v20; // r10d
      unsigned int v21; // eax
      int v22; // r10d
      int v23; // r14d
      __int64 v24; // rdi
      __int64 v25; // rcx
      unsigned __int64 v26; // r13
      int v27; // r9d
      int v28; // edx
      _QWORD *v29; // r14
      unsigned __int64 v30; // rdx
      __int64 v31; // r8
      unsigned __int64 v32; // rdx
      __int64 v33; // rax
      __int64 v34; // r12
      unsigned __int64 v35; // rdx
      __int64 v36; // r10
      unsigned __int64 v37; // r9
      unsigned __int64 v38; // rcx
      int v39; // r11d
      unsigned int v40; // r8d
      char v41; // al
      __int64 v42; // rax
      unsigned int v43; // ecx
      PVOID *v44; // rax
      __int64 result; // rax
      __int64 v46; // rax
      bool v47; // zf
      bool v48; // zf
      __int64 v49; // rcx
      _QWORD *v50; // [rsp+40h] [rbp-58h]
      PVOID Object; // [rsp+48h] [rbp-50h] BYREF
      __int64 v52; // [rsp+50h] [rbp-48h]
      int v53; // [rsp+A8h] [rbp+10h]
      __int64 v54; // [rsp+B0h] [rbp+18h] BYREF
    
      v54 = a3;
      v13 = a2;
      v14 = a12;
      v52 = a2;
      Object = 0i64;
      p_Lock = &KeGetCurrentThread()->ApcState.Process->Header.Lock;
      v50 = p_Lock;
      *(_QWORD *)(a12 + 96) = p_Lock;
      if ( a1 != -1i64 )                            // 如果不是当前进程句柄 检查句柄是否存在
      {
        v23 = ObpReferenceObjectByHandleWithTag(a1, 8, (__int64)PsProcessType, a8, 0x6D566D4Du, &Object, 0i64, 0i64);
        if ( v23 < 0 )
          goto LABEL_88;                            // 结束 return
        p_Lock = Object;
        v50 = Object;
      }
      v17 = a5;                                     // 分配内存类型
      v18 = a5;
      v19 = a9;
      *(_QWORD *)(v14 + 88) = p_Lock;
      v20 = a6;                                     // 页面属性
      v21 = a6 & 0xFFF807FF;
      *(_QWORD *)(v14 + 32) = a4;
      a6 = v21;
      v53 = v20 & 0x7F800;
      v23 = MiValidateAllocationType(v18, v19, v21);// 内存属性计算
      if ( v23 >= 0 )
      {
        if ( !v22 || (v23 = xHalUnmaskInterrupt(), v23 >= 0) )
        {
          if ( (v17 & 0x1000) != 0 && !v13 )
            v17 |= 0x2000u;                         // MEM_COMMIT为特定的页面区域分配内存中或磁盘的页面文件中的物理存储
          v24 = a7;
          if ( *(_QWORD *)(a7 + 24)
            && (v17 & 0x20400000) != 0x20000000     // 提交大页面 物理页面
            && ((v17 & 0x20400000) != 0x20400000 || (*(_BYTE *)(a7 + 56) & 2) == 0) )
          {
            goto LABEL_73;                          // 结束
          }
          v25 = *(_QWORD *)(a7 + 56);
          if ( (v25 & 0x20) != 0 )
            goto LABEL_73;
          v26 = 0x10000i64;
          v27 = v17 & 0x20400000;                   // MEM_LARGE_PAGES大页面0x20000000
          if ( (v17 & 0x20400000) == 0x20000000 )   // MEM_PHYSICAL 物理页面提交0x00400000
            v26 = 0x200000i64;
          v28 = v25 & 0x1A;
          LODWORD(a12) = v28;
          if ( (v25 & 0x1A) != 0 )
          {
            if ( ((v28 - 1) & v28) != 0 )
              goto LABEL_73;
            if ( (v28 & 2) != 0 )
            {
              v47 = v27 == 0x20400000;
            }
            else
            {
              if ( (v28 & 0x10) != 0 )
              {
                if ( (KeFeatureBits & 0x2000000000i64) == 0 )
                {
                  v23 = 0xC00000BB;
                  goto LABEL_88;
                }
                if ( v27 == 0x400000 )              // MEM_PHYSICAL 为特定的页面区域分配内存中或磁盘的页面文件中的物理存储 0x00400000 
                  goto LABEL_73;
                v26 = 0x40000000i64;
              }
              else if ( (v28 & 8) != 0 )
              {
                v26 = 0x200000i64;
              }
              v47 = v27 == 0x20000000;
            }
            if ( v47 )
              goto LABEL_14;
            if ( v27 != 0x400000 )
              goto LABEL_73;
          }
          else
          {
            if ( (v25 & 4) != 0 )
              goto LABEL_73;
            if ( v27 != 0x400000 )
            {
    LABEL_14:
              if ( ((v17 & 0x2000) == 0 || v13) && (*(_QWORD *)a7 || *(_QWORD *)(a7 + 8) || *(_QWORD *)(a7 + 16)) )
                goto LABEL_73;
              if ( v54 )                            // 0就会忽略
              {
                v23 = MiValidateZeroBits(&v54);     // 验证标志位
                if ( v23 < 0 )
                  goto LABEL_88;
                v29 = v50;
                if ( (v17 & 0x2000) != 0 && !v13 )
                  *(_QWORD *)(v24 + 8) = MiGetUserReservationHighestAddress(v50, v54);
                v27 = v17 & 0x20400000;
                v28 = a12;
              }
              else
              {
                v29 = v50;
              }
              if ( (v17 & 0x40000) != 0 )
              {
                *(_DWORD *)(v14 + 60) |= 0x8000000u;
              }
              else
              {
                if ( (v17 & 0x4000) == 0 )
                  goto LABEL_22;
                if ( *(_QWORD *)v24 || *(_QWORD *)(v24 + 8) || *(_QWORD *)(v24 + 16) )
                  goto LABEL_73;
                *(_DWORD *)(v14 + 60) |= 0x4000000u;
              }
              if ( (v17 & 0x4000) != 0 )
              {
                if ( !v28 && v27 != 0x20000000 )
                  goto LABEL_23;
                goto LABEL_24;
              }
    LABEL_22:
              if ( (v17 & 0x2000) == 0 )
              {
    LABEL_23:
                v26 = 4096i64;
                goto LABEL_24;
              }
              if ( (v17 & 0x40000000) != 0 )
              {
                if ( ((v27 - 0x20000000) & 0xFFBFFFFF) == 0 )
                  goto LABEL_73;
                goto LABEL_23;
              }
    LABEL_24:
              v30 = *(_QWORD *)(v24 + 16);
              if ( v30 )
              {
                if ( v30 < v26
                  || ((v30 - 1) & v30) != 0
                  || v30 >= 0x7FFFFFFF0000i64
                  || (v17 & 0x40000000) != 0 && v30 != 4096 )
                {
                  goto LABEL_73;
                }
              }
              else
              {
                *(_QWORD *)(v24 + 16) = v26;
              }
              if ( !a4 || (v17 & 0x2000) != 0 && ((v27 - 0x20000000) & 0xFFBFFFFF) == 0 && ((v26 - 1) & a4) != 0 )
                goto LABEL_73;
              v31 = 0x7FFFFFFEFFFFi64;
              if ( v13 > 0x7FFFFFFEFFFFi64 || 0x7FFFFFFF0000i64 - v13 < a4 )
                goto LABEL_73;
              v32 = v13 + a4;
              if ( (v17 & 0x2000) == 0 )
              {
                if ( v17 == 0x80000 || v17 == 0x1000000 )
                {
                  v46 = ~(v26 - 1);
                  v13 = v46 & (v26 + v13 - 1);
                  v32 &= v46;
                  if ( v13 >= v32 )
                  {
                    v23 = -1073741800;
                    goto LABEL_88;
                  }
                }
                else
                {
                  v33 = ~(v26 - 1);
                  v13 &= v33;
                  v32 = v33 & (v26 + v32 - 1);
                }
    LABEL_34:
                v34 = v52;
                v35 = v32 - v13;
                if ( v52 )
                  *(_QWORD *)v24 = v13;
                else
                  v13 = *(_QWORD *)v24;
                v36 = *(_QWORD *)(v24 + 16);
                v37 = v13;
                if ( ((v36 - 1) & v13) == 0 )
                {
                  v38 = *(_QWORD *)(v24 + 8);
                  if ( v38 )
                  {
                    if ( v38 <= 0x7FFFFFFEFFFFi64 )
                    {
                      v37 = v13;
                      if ( (((_WORD)v38 + 1) & 0xFFF) == 0 )
                        goto LABEL_41;
                    }
                  }
                  else
                  {
                    if ( (v17 & 0x2000) != 0 && !v34 && (v17 & 0x4000) == 0 )
                    {
                      if ( (unsigned __int64)(v29[187] - 1i64) < 0x7FFFFFFEFFFFi64 )
                        v31 = v29[187] - 1i64;
                      v39 = a12;
                      v38 = v31;
                      *(_QWORD *)(v24 + 8) = v31;
                      if ( v39 && (v39 & 2) == 0 )
                      {
                        if ( (v39 & 8) != 0 )
                        {
                          v49 = -2097152i64;
    LABEL_131:
                          v38 = (v31 & v49) - 1;
                          *(_QWORD *)(v24 + 8) = v38;
                          goto LABEL_42;
                        }
                        if ( (v39 & 0x10) != 0 )
                        {
                          v49 = -1073741824i64;
                          goto LABEL_131;
                        }
                      }
    LABEL_42:
                      if ( v37 < v38 && v38 - v37 + 1 >= v35 && (v17 & 0x7F) == 0 )
                      {
                        v40 = *(_DWORD *)(v24 + 32);
                        if ( v40 <= (unsigned __int16)KeNumberNodes )
                        {
                          v41 = *(_BYTE *)(v24 + 49);
                          if ( v41 != 1 || v39 || (v17 & 0x20400000) == 0x20000000 )
                          {
                            *(_BYTE *)(v14 + 56) = v41;
                            *(_BYTE *)(v14 + 104) = a8;
                            *(_DWORD *)(v14 + 60) |= a9;
                            *(_DWORD *)(v14 + 76) = a10;
                            *(_QWORD *)(v14 + 80) = a11;
                            *(_QWORD *)(v14 + 112) = *(_QWORD *)(v24 + 40);
                            v42 = *(_QWORD *)(v24 + 56);
                            *(_QWORD *)(v14 + 8) = v38;
                            v43 = a6;
                            *(_QWORD *)(v14 + 120) = v42;
                            v44 = a13;
                            *(_DWORD *)(v14 + 44) = v43;
                            *(_DWORD *)(v14 + 48) = v53;
                            *v44 = Object;
                            result = 0i64;
                            *(_QWORD *)v14 = v37;
                            *(_QWORD *)(v14 + 16) = v36;
                            *(_QWORD *)(v14 + 24) = v35;
                            *(_DWORD *)(v14 + 40) = v17 & 0xFFFBBFFF;
                            *(_DWORD *)(v14 + 52) = v40;
                            return result;
                          }
                        }
                      }
                      goto LABEL_73;
                    }
                    if ( v13 + v35 >= v13 )
                    {
                      v38 = v13 + v35 - 1;
                      *(_QWORD *)(v24 + 8) = v38;
                      if ( v38 <= 0x7FFFFFFEFFFFi64 )
                      {
    LABEL_41:
                        v39 = a12;
                        goto LABEL_42;
                      }
                    }
                  }
                }
    LABEL_73:
                v23 = 0xC000000D;
                goto LABEL_88;
              }
              if ( (v17 & 0x40000000) != 0 )
              {
                v48 = (((unsigned __int16)v13 | (unsigned __int16)a4) & 0xFFF) == 0;
              }
              else
              {
                if ( (v17 & 0x4000) == 0 )
                {
                  v13 &= -(__int64)v26;
                  if ( ((v27 - 0x20000000) & 0xFFBFFFFF) != 0 )
                    v32 = (v32 + 4095) & 0xFFFFFFFFFFFFF000ui64;
                  else
                    v32 = v13 + a4;
                  goto LABEL_34;
                }
                v48 = ((a4 | v13) & (v26 - 1)) == 0;
              }
              if ( !v48 )
                goto LABEL_73;
              goto LABEL_34;
            }
          }
          if ( (v25 & 0xFFFFFFFFFFFFFFF0ui64) != 0 )
            goto LABEL_73;
          goto LABEL_14;
        }
      }
    LABEL_88:
      if ( Object )
        ObfDereferenceObjectWithTag(Object, 0x6D566D4Du);// 释放掉
      return (unsigned int)v23;
    }
  • 相关阅读:
    .NET开发中应该遵循的几点建议
    .NET开发中应该遵循的几点建议
    .NET开发中应该遵循的几点建议
    查询CPU占用高的SQL语句的解决方案
    查询CPU占用高的SQL语句的解决方案
    HTTP消息中Header头部信息整理
    HTTP消息中Header头部信息整理
    HTTP消息中Header头部信息整理
    mac搭建本地服务器
    常用的GIT
  • 原文地址:https://www.cnblogs.com/feizianquan/p/16071397.html
Copyright © 2020-2023  润新知