1. 程式人生 > 其它 >NtAllocateVirtualMemory函式逆向分析

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