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;
}

相关