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