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