MmCopyVirtualMemory

VOID __fastcall MmCopyVirtualMemory(
        _EPROCESS *FromProcess,
        const VOID *FromAddress,
        _EPROCESS *ToProcess,
        VOID *ToAddress,
        UINT64 BufferSize,
        CHAR PreviousMode,
        UINT64 *NumberOfBytesRead){
  char *v8; 
  unsigned int v9; 
  __int64 v10; 
  UINT64 v11; 
  int v12; 
  ULONG_PTR v13; 
  char NextEnclaveBoundary; 
  int v15; 
  unsigned __int8 v16; 
  UINT64 v17; 
  unsigned __int64 v18; 
  char i; 
  __int64 v20; 
  VOID *v21; 
  int v22; 
  $66B5187701DB455CD8F8862345C5A268 *v23; 
  unsigned __int8 v24; 
  int v25; 
  NTSTATUS v26; 
  VOID *v27; 
  char *v28; 
  int v29; 
  NTSTATUS v30; 
  INT64 v31; 
  INT64 v32; 
  bool v33; 
  INT64 v34; 
  INT64 v35; 
  UINT64 *ReturnedBytesTransferred; 
  UINT64 Priority; 
  int v38; 
  char *Buffer; 
  int v40; 
  UINT64 v41; 
  VOID *EnclaveAddress; 
  char *v43; 
  UINT64 v44; 
  ULONG_PTR Process[2]; 
  int v46; 
  UINT64 *v47; 
  ULONG_PTR v48[2]; 
  UINT64 v49; 
  char *v50; 
  unsigned __int64 v51; 
  VOID *Src; 
  int v53; 
  UINT64 v54; 
  VOID *v55; 
  UINT64 BytesToNextBoundary; 
  UINT64 v57[5]; 
  _ETHREAD *CurrentThread; 
  $66B5187701DB455CD8F8862345C5A268 *v59; 
  __int64 v60; 
  INT64 v61; 
  _KAPC_STATE ApcState; 
  char MemoryDescriptorList[168]; 
  char v64[512]; 

  v43 = (char *)ToAddress;
  *(_QWORD *)v48 = ToProcess;
  v8 = (char *)FromAddress;
  v50 = (char *)FromAddress;
  *(_QWORD *)Process = FromProcess;
  v57[3] = (UINT64)FromProcess;
  v57[1] = (UINT64)FromAddress;
  v57[2] = (UINT64)ToProcess;
  v55 = ToAddress;
  v54 = BufferSize;
  v47 = NumberOfBytesRead;
  memset(&ApcState, 0, sizeof(ApcState));
  memset(MemoryDescriptorList, 0i64, sizeof(MemoryDescriptorList));
  v41 = 0i64;
  if( !BufferSize )
    return;
  *v47 = 0i64;
  v9 = 0;
  v51 = 0i64;
  v10 = *(_QWORD *)Process;
  if( !*(_QWORD *)(*(_QWORD *)Process + 1264i64) )
    v9 = 1;
  Src = v8;
  EnclaveAddress = ToAddress;
  v11 = BufferSize;
  v49 = BufferSize;
  v61 = (INT64)MemoryDescriptorList;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  v38 = 0;
  Buffer = 0i64;
  v57[4] = 0i64;
  v46 = 0;
  BytesToNextBoundary = BufferSize;
  v57[0] = BufferSize;
LABEL_5:
  v12 = ((unsigned __int8)v9 ^ (unsigned __int8)(2 * v9)) & 2 ^ v9;
  if( (*(_BYTE *)(v10 + 992) & 1) != 0 )
    v12 |= 0x40u;
  v13 = v48[0];
  if( (*(_BYTE *)(*(_QWORD *)v48 + 992i64) & 1) != 0 )
    v12 |= 0x80u;
  NextEnclaveBoundary = MiFindNextEnclaveBoundary(v10, &v8[BufferSize - v11], v11, &BytesToNextBoundary);
  v15 = 4 * (NextEnclaveBoundary & 3 | (4 * (MiFindNextEnclaveBoundary(v13, &v43[BufferSize - v11], v11, v57) & 3)));
  v16 = v12 & 0xC3;
  v9 = v12 & 0xFFFFFFC3 | v15;
  if( ((v16 | (unsigned __int8)v15) & 0xC0) != 0 || (v9 & 0xC) != 0 )
    v9 &= ~2u;
  v17 = v11;
  v44 = v11;
  if( BytesToNextBoundary < v11 )
  {
    v17 = BytesToNextBoundary;
    v44 = BytesToNextBoundary;
  }
  if( v57[0] < v17 )
  {
    v17 = v57[0];
    v44 = v57[0];
  }
LABEL_15:
  if( v17 >= 0x200 && (v9 & 2) != 0 )
  {
    v18 = 57344i64;
    v33 = BufferSize <= 0xE000;
    goto LABEL_73;
  }
  v9 &= ~2u;
  if( v51 )
  {
    v18 = v17;
    if( v17 > v51 )
      v18 = v51;
    goto LABEL_20;
  }
  if( v17 > 0x200 )
  {
    v18 = 0x10000i64;
    if( v11 <= 0x10000 )
      v18 = v11;
    do
    {
      Buffer = (char *)MiAllocatePool(256i64, v18, 0x77526D4Dui64);
      if( Buffer )
      {
        v51 = v18;
        goto LABEL_86;
      }
      v18 >>= 1;
    }
    while( v18 > 0x200 );
    Buffer = v64;
    v18 = 512i64;
LABEL_86:
    v33 = v17 <= v18;
LABEL_73:
    if( !v33 )
      goto LABEL_20;
    goto LABEL_19;
  }
  Buffer = v64;
LABEL_19:
  v18 = v17;
LABEL_20:
  for( i = v9; ; i = v9 )
  {
    v10 = *(_QWORD *)Process;
    if( !v17 )
    {
      v8 = v50;
      if( v11 )
        goto LABEL_5;
      if( v51 )
        ExFreePoolWithTag(Buffer, 0);
      *v47 = BufferSize;
      return;
    }
    v20 = v17;
    if( v17 >= v18 )
      v20 = v18;
    v18 = v20;
    v60 = v20;
    KiStackAttachProcess(*(PVOID *)Process, 0i64, &ApcState);
    v21 = Src;
    if( PreviousMode
      && Src == v50
      && ((unsigned __int64)&v50[BufferSize] > 0x7FFFFFFF0000i64 || &v50[BufferSize] < v50) )
    {
      MEMORY[0x7FFFFFFF0000] = 0;
    }
    v22 = i & 2;
    v40 = v22;
    v53 = v22;
    if( (i & 2) != 0 )
    {
      *(_QWORD *)MemoryDescriptorList = 0i64;
      *(_WORD *)&MemoryDescriptorList[8] = 8 * (((v18 + ((unsigned __int16)Src & 0xFFF) + 4095i64) >> 12) + 6);
      *(_WORD *)&MemoryDescriptorList[10] = 0;
      *(_QWORD *)&MemoryDescriptorList[32] = (unsigned __int64)Src & 0xFFFFFFFFFFFFF000ui64;
      *(_DWORD *)&MemoryDescriptorList[44] = (unsigned __int16)Src & 0xFFF;
      *(_DWORD *)&MemoryDescriptorList[40] = v18;
      v22 = i & 2;
    }
    v23 = &CurrentThread->Tcb.116;
    v59 = &CurrentThread->Tcb.116;
    v24 = _bittestandset((signed __int32 *)&CurrentThread->Tcb.116, 5u);
    if( v22 )
    {
      MmProbeAndLockPages((PMDL)MemoryDescriptorList, (unsigned __int8)PreviousMode, IoReadAccess);
      v25 = v38;
    }
    else
    {
      if( (v9 & 0x40) != 0 || (v9 & 0xC) == 8 )
      {
        v26 = VslDebugReadWriteSecureProcess(*(__int64 *)Process, (__int64)v21, (INT64)Buffer, v18, 1u, &v41);
      }
      else
      {
        if( (v9 & 0xC) != 4 )
        {
          memmove(Buffer, v21, v18);
          v25 = v38;
          goto LABEL_40;
        }
        v26 = MiDbgReadWriteEnclave(v21, Buffer, v18, 1ui64, &v41);
      }
      v38 = v26;
      v25 = v26;
    }
LABEL_40:
    if( !v24 )
      v23->_bf_0 &= ~0x20u;
    if( v25 < 0 )
    {
      if( !v40 )
      {
        *v47 = BufferSize - v17;
        goto LABEL_79;
      }
LABEL_87:
      v9 &= ~2u;
      KiUnstackDetachProcess(&ApcState, 0i64);
      v11 = v49;
      goto LABEL_15;
    }
    if( v40 )
    {
      LODWORD(Priority) = -1073741792;
      LODWORD(ReturnedBytesTransferred) = 0;
      v27 = MmMapLockedPagesSpecifyCache(
              (_MDL *)MemoryDescriptorList,
              0,
              MmCached,
              0i64,
              (UINT64)ReturnedBytesTransferred,
              Priority);
      if( !v27 )
      {
        MmUnlockPages((INT64)MemoryDescriptorList, v34, v35);
        goto LABEL_87;
      }
    }
    else
    {
      v27 = Buffer;
    }
    KiUnstackDetachProcess(&ApcState, 0i64);
    KiStackAttachProcess(*(PVOID *)v48, 0i64, &ApcState);
    if( PreviousMode && Src == v50 )
    {
      v28 = v43;
      if( (unsigned __int64)&v43[BufferSize] > 0x7FFFFFFF0000i64 || &v43[BufferSize] < v43 )
        MEMORY[0x7FFFFFFF0000] = 0;
    }
    else
    {
      v28 = v43;
    }
    if( (v9 & 0x80u) != 0 || (v9 & 0x30) == 32 )
    {
      v30 = VslDebugReadWriteSecureProcess(*(__int64 *)v48, (__int64)EnclaveAddress, (INT64)Buffer, v18, 0, &v41);
    }
    else
    {
      if( (v9 & 0x30) != 16 )
      {
        memmove(EnclaveAddress, v27, v18);
        v29 = 0;
        v38 = 0;
        v41 = v18;
        goto LABEL_54;
      }
      v30 = MiDbgReadWriteEnclave(EnclaveAddress, Buffer, v18, 0i64, &v41);
    }
    v38 = v30;
    v29 = v30;
LABEL_54:
    if( v29 == -1073741819 )
      break;
    if( v29 < 0 )
      goto LABEL_79;
    KiUnstackDetachProcess(&ApcState, 0i64);
    if( v40 )
      MmUnlockPages((INT64)MemoryDescriptorList, v31, v32);
    v17 -= v18;
    v44 = v17;
    v11 = v49 - v18;
    v49 -= v18;
    Src = (char *)Src + v18;
    EnclaveAddress = (char *)EnclaveAddress + v18;
  }
  *v47 = (UINT64)EnclaveAddress + v41 - (_QWORD)v28;
LABEL_79:
  KiUnstackDetachProcess(&ApcState, 0i64);
  if( v51 )
    ExFreePoolWithTag(Buffer, 0);
}

Referenced by:

KiTpWriteUmMemory
LpcpCopyRequestData
MiReadWriteVirtualMemory
NtQueryInformationProcess
NtQueryInformationThread
PsQueryProcessCommandLine