MiRelocateImage

VOID __fastcall MiRelocateImage(
        _SEGMENT *Segment,
        _MI_CAPTURED_OPTIONAL_HEADER *OptionalHeader,
        UINT64 ImageBaseOffset,
        _MI_RELOCATION_IMAGE_SPACE RelocationImageType){
  unsigned int v5; 
  unsigned int v8; 
  int v9; 
  __int64 v10; 
  __int64 LoadConfigSize; 
  __int64 v12; 
  _CONTROL_AREA *v13; 
  char v14; 
  unsigned int v15; 
  _MMEXTEND_INFO *ExtendInfo; 
  __int16 v17; 
  unsigned int TotalNumberOfPtes; 
  unsigned int v19; 
  __int64 v20; 
  UINT64 v21; 
  _MI_DYNAMIC_RELOCATIONS *Pool; 
  _MI_DYNAMIC_RELOCATIONS *v23; 
  _MI_DYNAMIC_RELOCATIONS *v24; 
  CHAR *v25; 
  INT64 v26; 
  int v27; 
  VOID *v28; 
  char *v29; 
  __int64 v30; 
  __int64 v31; 
  _QWORD *v32; 
  __int64 v33; 
  unsigned int v34; 
  unsigned int v35; 
  unsigned __int64 v36; 
  unsigned int v37; 
  UINT64 v38; 
  unsigned int v39; 
  unsigned int v40; 
  unsigned int v41; 
  __int64 *v42; 
  _ETHREAD *v43; 
  _MMEXTEND_INFO *v44; 
  __int64 v45; 
  union {_MI_SECTION_IMAGE_INFORMATION *ImageInformation;void *FirstMappedVa;} v46; 
  NTSTATUS v47; 
  unsigned int v48; 
  unsigned int v49; 
  unsigned int v50; 
  unsigned __int64 v51; 
  unsigned __int64 v52; 
  unsigned int v53; 
  unsigned __int16 v54; 
  _WORD *v55; 
  unsigned int v56; 
  __int64 v57; 
  unsigned int v58; 
  _MMPTE *PrototypePte; 
  unsigned int v60; 
  unsigned int i; 
  int v62; 
  unsigned __int64 v63; 
  _MMPFN *v64; 
  __int64 v65; 
  unsigned __int64 v66; 
  _MI_PARTITION *ControlAreaPartition; 
  UINT64 v68; 
  _EX_PUSH_LOCK *p_SegmentLock; 
  _CONTROL_AREA *ControlArea; 
  unsigned int v71; 
  unsigned int v72; 
  unsigned int v73; 
  unsigned int PreviousSystemPagePriority; 
  INT64 v76; 
  _QWORD *v77; 
  unsigned int v78; 
  char *ImageBase; 
  _MMPTE *ImageBasea; 
  _ETHREAD *Thread; 
  int v83; 
  unsigned int v84; 
  _MMEXTEND_INFO *v85; 
  unsigned int v86; 
  _MI_DYNAMIC_RELOCATIONS *v87; 
  unsigned int v89; 
  __int64 Size; 
  size_t Sizea; 
  _IMAGE_BASE_RELOCATION RelocationInfo; 
  VOID *BaseAddress; 
  UINT64 PteOffset[3]; 
  _MMEXTEND_INFO *v95; 
  _MI_IMAGE_SECURITY_REFERENCE *SeImageStub; 
  union {_MI_SECTION_IMAGE_INFORMATION *ImageInformation;void *FirstMappedVa;} v97; 
  unsigned __int64 v98; 
  _MI_SYSTEM_SPACE_IMAGE SystemImageInfo[20]; 
  __int64 v100; 
  unsigned int MakeDiffZero; 

  v5 = ImageBaseOffset;
  memset(SystemImageInfo, 0i64, sizeof(SystemImageInfo));
  RelocationInfo = 0i64;
  v8 = 2;
  v97.ImageInformation = (_MI_SECTION_IMAGE_INFORMATION *)Segment->u2;
  if( !MiLegacyImageArchitecture(v97.ImageInformation->ExportedImageInformation.Machine)
    || (v8 = v9 + 34, (*(_BYTE *)(v10 + 44) & 1) == 0) )
  {
    LoadConfigSize = OptionalHeader->LoadConfigSize;
    RelocationInfo.VirtualAddress = LoadConfigSize;
    v12 = *(unsigned int *)&OptionalHeader->ContainsDebug;
    v73 = *(_DWORD *)&OptionalHeader->ContainsDebug;
    RelocationInfo.SizeOfBlock = v73;
    if( (_DWORD)LoadConfigSize )
    {
      if( !(_DWORD)v12 )
        return;
    }
    else
    {
      if( (_DWORD)v12 )
        return;
      v8 &= ~2u;
    }
    if( (Segment->SegmentFlags.UChar2 & 1) == 0 )
    {
      v13 = Segment->ControlArea;
      PteOffset[2] = (UINT64)v13;
      SeImageStub = v13->u2.SeImageStub;
      v14 = Segment->SegmentFlags.UChar1 & 0x40;
      if( (v5 & 0xFFF) <= (v14 != 0 ? 4092 : 4088) && ((v14 != 0 ? 3 : 7) & v5) == 0 )
      {
        v15 = v5 | 1;
        if( !v14 )
          v15 = v5;
        v71 = v15;
        ExtendInfo = Segment->ExtendInfo;
        v85 = ExtendInfo;
        if( v8 < 0x20
          || RelocationImageType
          || (v17 = *(_WORD *)(v10 + 46), (v17 & 0x40) != 0)
          || MmRegistryState == -1
          || (v17 & 0x1000) != 0 )
        {
          TotalNumberOfPtes = Segment->TotalNumberOfPtes;
          v19 = TotalNumberOfPtes;
          v78 = TotalNumberOfPtes;
          if( (v8 & 2) == 0 )
          {
            v19 = (v15 >> 12) + 1;
            v78 = v19;
          }
          v89 = TotalNumberOfPtes << 12;
          if( (int)v12 + (int)LoadConfigSize <= TotalNumberOfPtes << 12 )
          {
            if( (v8 & 2) != 0 )
            {
              if( (int)v12 + (int)LoadConfigSize <= (unsigned int)LoadConfigSize )
                return;
              v20 = LoadConfigSize;
              if( (_MMEXTEND_INFO *)((char *)ExtendInfo + LoadConfigSize) <= ExtendInfo )
                return;
            }
            else
            {
              v20 = LoadConfigSize;
            }
            if( (v8 & 2) == 0 || (_MMEXTEND_INFO *)((char *)ExtendInfo + v12 + v20) > ExtendInfo )
            {
              Size = 2i64 * v19;
              v21 = Size * 4 + v12 + 112;
              BaseAddress = 0i64;
              ImageBase = 0i64;
              PreviousSystemPagePriority = 0;
              Thread = (_ETHREAD *)KeGetCurrentThread();
              Pool = (_MI_DYNAMIC_RELOCATIONS *)MiAllocatePool(256i64, v21, 0x65526D4Dui64);
              v23 = Pool;
              PteOffset[1] = (UINT64)Pool;
              if( Pool )
              {
                v24 = Pool;
                do
                  v24 += 1024;
                while( v24 < (_MI_DYNAMIC_RELOCATIONS *)((char *)Pool + v21) );
                *((_BYTE *)Pool + 68) = 0;
                *((_QWORD *)Pool + 7) = v78;
                *((_QWORD *)Pool + 3) = 0i64;
                if( (v8 & 2) != 0 )
                {
                  if( MiMapImageInSystemSpace(v13, 3ui64, SystemImageInfo) < 0 )
                  {
                    ExFreePoolWithTag(v23, 0);
                    MiSetDeleteOnClose(v13, 0i64);
                    return;
                  }
                  v25 = *(CHAR **)SystemImageInfo;
                  ImageBase = *(char **)SystemImageInfo;
                  PreviousSystemPagePriority = PsSetSystemPagePriorityThread(Thread, 1ui64);
                  v8 |= 1u;
                  v26 = (INT64)(v23 + 18);
                  if( MiParseImageLoadConfig(
                         (INT64)v13,
                         v25,
                         (unsigned int)(SystemImageInfo[4] << 12),
                         (INT64)OptionalHeader,
                         (INT64)ControlArea,
                         (INT64)(v23 + 18)) < 0 )
                  {
                    ExFreePoolWithTag(v23, 0);
                    goto LABEL_69;
                  }
                }
                else
                {
                  v26 = (INT64)(Pool + 18);
                }
                MiSelectImageBase(
                  (_MI_DYNAMIC_RELOCATIONS *)Segment,
                  (_SEGMENT *)v23,
                  RelocationImageType,
                  MakeDiffZero);
                if( v27 < 0 )
                {
                  MiFreeImageLoadConfig(v26);
                  ExFreePoolWithTag(v23, 0);
                  goto LABEL_69;
                }
                v28 = (VOID *)v26;
                v29 = (char *)BaseAddress;
                v95 = (_MMEXTEND_INFO *)BaseAddress;
                if( MiUpdateCfgSystemWideBitmap(v13, BaseAddress, v28) < 0 )
                {
LABEL_149:
                  MiFreeRelocations(v13, v23);
LABEL_69:
                  if( (v8 & 1) != 0 )
                  {
                    MiUnmapImageInSystemSpace(SystemImageInfo);
                    PsRevertToUserPagePriorityThread(Thread, PreviousSystemPagePriority);
                  }
                  return;
                }
                v23[16] = v71;
                *((_QWORD *)v23 + 5) = v29 - (char *)v85;
                v30 = v100 - (_QWORD)v85;
                if( v100 == -1 )
                  v30 = 0i64;
                *((_QWORD *)v23 + 6) = v30;
                v87 = v23 + 28;
                *(_QWORD *)v23 = v23 + 28;
                memset(v23 + 28, 0i64, Size * 4);
                v32 = v23 + 28;
                v76 = (INT64)&v23[Size + 28];
                *((_QWORD *)v23 + 4) = v76;
                v8 |= 4u;
                if( (v8 & 2) == 0 )
                  goto LABEL_55;
                memmove(&v23[Size + 28], &ImageBase[v20], v73);
                LODWORD(v20) = 0;
                v33 = *((_QWORD *)v23 + 12);
                if( v33 )
                {
                  LODWORD(v20) = SystemImageInfo[4] & 0xFFFFF;
                  while( (_DWORD)v20 )
                  {
                    v20 = (unsigned int)(v20 - 1);
                    if( *(_QWORD *)(v33 + 8 * v20 + 56) )
                      goto LABEL_33;
                  }
                  LODWORD(v20) = 0;
                }
LABEL_33:
                v34 = v73;
                v35 = 0;
                if( v73 )
                {
                  v36 = (unsigned __int64)&v23[Size + 28];
                  while( v34 >= 0xA )
                  {
                    v37 = *(_DWORD *)(v36 + 4);
                    v72 = v37;
                    if( v37 > v34 || (v37 & 1) != 0 || v37 < 8 )
                      goto LABEL_68;
                    v38 = *(unsigned int *)v36;
                    v83 = v38;
                    v39 = v8 & 0xFFFFFFFB;
                    if( (v38 & 0xFFF) == 0 )
                      v39 = v8;
                    v8 = v39;
                    if( (int)v38 + 4096 <= (unsigned int)v38 || (int)v38 + 4096 > v89 || (unsigned int)v38 < v35 )
                      goto LABEL_68;
                    if( v37 == 8 )
                    {
                      v34 -= 8;
                      v8 = v39 & 0xFFFFFFFB;
                    }
                    else
                    {
                      if( (MiFlags & 0x40000) != 0 && (v13->u2.WritableUserReferences & 0xC0000) != 0 )
                      {
                        PteOffset[0] = 0i64;
                        if( (MiOffsetToProtos(v13, v38, PteOffset)->u.LongFlags & 4) != 0 )
                          goto LABEL_68;
                        v37 = v72;
                        LODWORD(v38) = v83;
                        v36 = v76;
                      }
                      v84 = (unsigned int)v38 >> 12;
                      *(_QWORD *)&v23[2 * ((unsigned __int64)(unsigned int)v38 >> 12) + 28] |= v36;
                      v86 = (v38 & 0xFFFFF000) + 4096;
                      Sizea = v34 - v37;
                      if( MiScanRelocationPage(
                             ImageBase,
                             (unsigned int)v38,
                             (v37 - 8) >> 1,
                             (UINT16 *)(v36 + 8),
                             v13,
                             v23) < 0 )
                        goto LABEL_68;
                      v8 |= 0x10u;
                      v40 = v84;
                      if( v84 <= (unsigned int)v20 )
                        v40 = v20;
                      LODWORD(v20) = v40;
                      v34 = Sizea;
                      v37 = v72;
                      v35 = v86;
                      v36 = v76;
                    }
                    v36 += v37;
                    v76 = v36;
                    if( !v34 )
                    {
                      v41 = v73;
                      goto LABEL_52;
                    }
                  }
                  if( v34 != 8 )
                    goto LABEL_68;
                  v41 = v73 - 8;
                }
                else
                {
                  v41 = 0;
                }
LABEL_52:
                MiUnmapImageInSystemSpace(SystemImageInfo);
                PsRevertToUserPagePriorityThread(Thread, PreviousSystemPagePriority);
                LOBYTE(v8) = v8 & 0xFE;
                v42 = (__int64 *)*((_QWORD *)v23 + 2);
                if( !v42 )
                {
LABEL_53:
                  MiLogRelocationFaults(v13, &RelocationInfo, v23);
                  *((_QWORD *)v23 + 7) = (unsigned int)(v20 + 1);
                  if( (v8 & 0x14) == 20 )
                  {
                    v23 = MiCompressRelocations(v23, v41);
                    v32 = v23 + 28;
                    v87 = v23 + 28;
                  }
                  else
                  {
                    v32 = v23 + 28;
                  }
LABEL_55:
                  v32[(unsigned __int64)(unsigned int)v23[16] >> 12] |= 1ui64;
                  if( (v13->u.LongFlags & 0x40000000) != 0 )
                  {
                    v57 = 0i64;
                    v58 = 0;
                    v77 = 0i64;
                    PrototypePte = Segment->PrototypePte;
                    ImageBasea = PrototypePte;
                    v60 = v23[14];
                    if( v78 <= v60 )
                      v60 = v78;
                    for( i = 0; i < v60; v87 += 2 )
                    {
                      if( *v32 != v57 || (LOBYTE(v62) = MiDoesPageRequireRetpolineFixups((INT64)(v23 + 18), i), v62) )
                      {
                        LODWORD(v63) = MI_READ_PTE_LOCK_FREE((INT64)&PrototypePte[i]);
                        v98 = v63;
                        if( (v63 & 0x400) != 0 )
                        {
                          *((_QWORD *)v23 + 13) = 0i64;
                          goto LABEL_68;
                        }
                        v57 = 0i64;
                        if( (v63 & 0x800) != 0 )
                        {
                          v31 = 1i64;
                          if( *(&stru_140C4DB30 + 42) )
                          {
                            if( (v63 & 0x10) != 0 )
                              v63 &= ~0x10ui64;
                            else
                              v63 &= ~*(&stru_140C4DB30 + 42);
                          }
                          v64 = &MmGetPfnDb()[(v63 >> 12) & 0xFFFFFFFFFi64];
                          if( (*(_DWORD *)(&v64->3 + 1) & 0x400i64) != 0 )
                          {
                            LODWORD(v65) = MiGetSubsectionFromPte(v64->OriginalPte.u.Hard.$976DF529DAC3D73085C9E386D94B91E6::$E228DCF3D8940E384DBC5EFCA756D8B6::_bf_0);
                            if( (*(_BYTE *)(v65 + 34) & 2) != 0 )
                              v31 = (unsigned int)v57;
                          }
                          if( (_DWORD)v31 )
                          {
                            MiSetLeafPfnBuddy(v64, 0i64);
                            if( *((_QWORD *)v23 + 13) == v57 )
                              *((_QWORD *)v23 + 13) = v66;
                            else
                              MiSetLeafPfnBuddy(v77, v66);
                            v77 = (_QWORD *)v66;
                            ++v58;
                          }
                        }
                        PrototypePte = ImageBasea;
                      }
                      ++i;
                      v32 = v87 + 2;
                    }
                    ControlAreaPartition = MiGetControlAreaPartition(v13, (_EPROCESS *)v31);
                    v68 = v58;
                    if( !MiChargeCommit(ControlAreaPartition, v58, 0i64) )
                    {
                      *((_QWORD *)v23 + 13) = 0i64;
                      goto LABEL_68;
                    }
                    v43 = Thread;
                    --Thread->Tcb.SpecialApcDisable;
                    p_SegmentLock = &Segment->SegmentLock;
                    ExAcquirePushLockExclusiveEx(&Segment->SegmentLock, 0i64);
                    MiUpdateControlAreaCommitCount((INT64)v13, v68);
                    if( (_InterlockedExchangeAdd64(&Segment->SegmentLock._bf_0, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
                      ExfTryToWakePushLock(p_SegmentLock);
                    KeAbPostRelease(p_SegmentLock);
                    KiLeaveGuardedRegionUnsafe((__int64)Thread);
                    v44 = (_MMEXTEND_INFO *)BaseAddress;
                  }
                  else
                  {
                    v43 = Thread;
                    v44 = v95;
                  }
                  LOBYTE(v8) = v8 | 8;
                  MI_LOCK_RELOCATIONS_EXCLUSIVE(v43, v23);
                  v45 = (__int64)SeImageStub;
                  SeImageStub->DynamicRelocations = v23;
                  Segment->ExtendInfo = v44;
                  v46.ImageInformation = v97.ImageInformation;
                  v97.ImageInformation->ExportedImageInformation.TransferAddress = (char *)v97.ImageInformation->ExportedImageInformation.TransferAddress
                                                                                 + *((_QWORD *)v23 + 5);
                  v13->u2.WritableUserReferences |= 0x400000u;
                  if( (v13->u.LongFlags & 0x800) != 0 )
                    MiSetDeleteOnClose(v13, 0i64);
                  if( (MiFlags & 0x4000) == 0
                    || (v13->u2.WritableUserReferences & 0xC0000) == 0
                    || (qword_140C1D940 ? (v47 = qword_140C1D940(*(_QWORD *)(v45 + 40) & 0xFFFFFFFFFFFFFFF8ui64, v44)) : (v47 = -1073741637),
                        v47 >= 0) )
                  {
                    v47 = 0;
                    v48 = RelocationImageType ? -1 : MmGetSessionIdEx(KeGetCurrentThread()->ApcState.Process);
                    if( MakeDiffZero != 1 || *((_QWORD *)v23 + 12) )
                    {
                      if( (v13->u.LongFlags & 0x40000000) != 0 )
                      {
                        MiWalkEntireImage(v13, 0i64, 8i64, v48);
                        if( MiColdPageSizeSupported() )
                          MiMakeUnusedImageExtentsCold((INT64)v13);
                      }
                      v47 = MiWalkEntireImage(v13, 0i64, 2i64, v48);
                    }
                  }
                  MI_UNLOCK_RELOCATIONS_EXCLUSIVE(v43, v23);
                  if( v47 >= 0 && !MakeDiffZero )
                    v46.ImageInformation->ExportedImageInformation.ImageFlags |= 4u;
                  goto LABEL_68;
                }
                while( 1 )
                {
                  v49 = v20;
                  v50 = *((_DWORD *)v42 + 3);
                  v51 = *(_QWORD *)&v23[2 * ((unsigned __int64)v50 >> 12) + 28];
                  LODWORD(v20) = v50 >> 12;
                  if( v50 >> 12 <= v49 )
                    LODWORD(v20) = v49;
                  if( v51 > 1 )
                  {
                    v52 = v51 & 0xFFFFFFFFFFFFFFFEui64;
                    v53 = *(_DWORD *)(v52 + 4) - 8;
                    v54 = v50 & 0xFFF;
                    v55 = (_WORD *)(v52 + 8);
                    v56 = v53 >> 1;
                    if( v56 )
                      break;
                  }
LABEL_91:
                  v42 = (__int64 *)*v42;
                  if( !v42 )
                    goto LABEL_53;
                }
                while( *v55 < 0x1000u || (unsigned __int16)(*v55 & 0xFFF) >= v54 )
                {
                  ++v55;
                  if( !--v56 )
                    goto LABEL_91;
                }
LABEL_68:
                if( (v8 & 8) != 0 )
                  goto LABEL_69;
                goto LABEL_149;
              }
            }
          }
        }
      }
    }
  }
}

Referenced by:

MiGetSystemAddressForImage