-
-
[原创]Windows内核之exe文件section
-
发表于: 2天前 454
-
前言:
本文基于ReactOS 0.4.15源码。
在创建section时,如果创建的是exe文件的section,会调用MmCreateImageSection函数。在这个函数内会执行
StatusExeFmt = ExeFmtpCreateImageSection(FileObject, ImageSectionObject);
所以看这个函数。
NTSTATUS
ExeFmtpCreateImageSection(PFILE_OBJECT FileObject,
PMM_IMAGE_SECTION_OBJECT ImageSectionObject)
{
LARGE_INTEGER Offset;
PVOID FileHeader;
PVOID FileHeaderBuffer;
ULONG FileHeaderSize;
ULONG Flags;
ULONG OldNrSegments;
NTSTATUS Status;
ULONG i;
/*
* Read the beginning of the file (2 pages). Should be enough to contain
* all (or most) of the headers
*/
Offset.QuadPart = 0;
Status = ExeFmtpReadFile (FileObject,
&Offset,
PAGE_SIZE * 2,
&FileHeader,
&FileHeaderBuffer,
&FileHeaderSize);
if (!NT_SUCCESS(Status))
return Status;
if (FileHeaderSize == 0)
{
ExFreePool(FileHeaderBuffer);
return STATUS_UNSUCCESSFUL;
}
/*
* Look for a loader that can handle this executable
*/
for (i = 0; i < RTL_NUMBER_OF(ExeFmtpLoaders); ++ i)
{
Flags = 0;
Status = ExeFmtpLoaders[i](FileHeader,
FileHeaderSize,
FileObject,
ImageSectionObject,
&Flags,
ExeFmtpReadFile,
ExeFmtpAllocateSegments);
if (!NT_SUCCESS(Status))
{
if (ImageSectionObject->Segments)
{
ExFreePool(ImageSectionObject->Segments);
ImageSectionObject->Segments = NULL;
}
}
if (Status != STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
break;
}
ExFreePoolWithTag(FileHeaderBuffer, 'rXmM');
/*
* No loader handled the format
*/
if (Status == STATUS_ROS_EXEFMT_UNKNOWN_FORMAT)
{
Status = STATUS_INVALID_IMAGE_NOT_MZ;
ASSERT(!NT_SUCCESS(Status));
}
if (!NT_SUCCESS(Status))
return Status;
ASSERT(ImageSectionObject->Segments != NULL);
ASSERT(ImageSectionObject->RefCount > 0);
/*
* Some defaults
*/
/* FIXME? are these values platform-dependent? */
if (ImageSectionObject->ImageInformation.MaximumStackSize == 0)
ImageSectionObject->ImageInformation.MaximumStackSize = 0x40000;
if(ImageSectionObject->ImageInformation.CommittedStackSize == 0)
ImageSectionObject->ImageInformation.CommittedStackSize = 0x1000;
if(ImageSectionObject->BasedAddress == NULL)
{
if(ImageSectionObject->ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL)
ImageSectionObject->BasedAddress = (PVOID)0x10000000;
else
ImageSectionObject->BasedAddress = (PVOID)0x00400000;
}
/*
* And now the fun part: fixing the segments
*/
/* Sort them by virtual address */
MmspSortSegments(ImageSectionObject, Flags);
/* Ensure they don't overlap in memory */
if (!MmspCheckSegmentBounds(ImageSectionObject, Flags))
return STATUS_INVALID_IMAGE_FORMAT;
/* Ensure they are aligned */
OldNrSegments = ImageSectionObject->NrSegments;
if (!MmspPageAlignSegments(ImageSectionObject, Flags))
return STATUS_INVALID_IMAGE_FORMAT;
/* Trim them if the alignment phase merged some of them */
if (ImageSectionObject->NrSegments < OldNrSegments)
{
PMM_SECTION_SEGMENT Segments;
SIZE_T SizeOfSegments;
SizeOfSegments = sizeof(MM_SECTION_SEGMENT) * ImageSectionObject->NrSegments;
Segments = ExAllocatePoolWithTag(PagedPool,
SizeOfSegments,
TAG_MM_SECTION_SEGMENT);
if (Segments == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyMemory(Segments, ImageSectionObject->Segments, SizeOfSegments);
ExFreePool(ImageSectionObject->Segments);
ImageSectionObject->Segments = Segments;
}
/* And finish their initialization */
for ( i = 0; i < ImageSectionObject->NrSegments; ++ i )
{
ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock);
ImageSectionObject->Segments[i].ReferenceCount = &ImageSectionObject->RefCount;
ImageSectionObject->Segments[i].Flags = &ImageSectionObject->SegFlags;
MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]);
ImageSectionObject->Segments[i].FileObject = FileObject;
}
ASSERT(ImageSectionObject->RefCount > 0);
ImageSectionObject->FileObject = FileObject;
ASSERT(NT_SUCCESS(Status));
return Status;
}首先调用ExeFmtpReadFile函数读取exe文件的头部,exe头部是一些exe的信息。
然后调用了ExeFmtpLoaders函数,这个函数是PeFmtCreateSection函数。在这个函数中会根据exe文件内容填写ImageSectionObject,这个对象在载入exe文件的section中会被使用,载入exe的函数是MmMapViewOfSection:
NrSegments = ImageSectionObject->NrSegments;
ASSERT(ImageSectionObject->RefCount > 0);
ImageBase = (ULONG_PTR)*BaseAddress;
if (ImageBase == 0)
{
ImageBase = (ULONG_PTR)ImageSectionObject->BasedAddress;
}
ImageSize = 0;
for (i = 0; i < NrSegments; i++)
{
ULONG_PTR MaxExtent;
MaxExtent = (ULONG_PTR)(SectionSegments[i].Image.VirtualAddress +
SectionSegments[i].Length.QuadPart);
ImageSize = max(ImageSize, MaxExtent);
}可见首先会获得exe文件中的segments个数,然后遍历所有segments,计算exe文件的大小,这样就可以在虚拟内存中分配空间。
接下来就是在执行exe文件的过程中发生缺页中断载入exe文件的内容。可以看这篇文章:
赞赏
他的文章
赞赏
雪币:
留言: