论坛首页 开源情报交流区 阅读主题

[原创]Windows内核之载入exe文件

459 浏览 0 回复
#1 楼主 2026-06-01 21:08:58
前言:本文基于ReactOS 0.4.15源码。
在创建进程时会载入exe文件,分两步进行,首先是将可执行映像映射到用户空间,这一步可以理解为对虚拟内存地址的规划。在实际执行exe文件时会触发缺页中断,此时才会读取exe文件的内容,本文介绍的就是缺页中断的处理。
缺页中断的处理函数是MmNotPresentFaultSectionView,来看看这个函数。    Entry = MmGetPageEntrySectionSegment(Segment, &Offset);

    if (Entry == 0)
         * If the entry is zero, then we need to load the page.
        if ((Offset.QuadPart >= (LONGLONG)PAGE_ROUND_UP(Segment->RawLength.QuadPart)) && (MemoryArea->VadNode.u.VadFlags.VadType == VadImageMap))
            /* We are beyond the data which is on file. Just get a new page. */
            MI_SET_USAGE(MI_USAGE_SECTION);
            if (Process) MI_SET_PROCESS2(Process->ImageFileName);
            if (!Process) MI_SET_PROCESS2("Kernel Section");
            Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
            if (!NT_SUCCESS(Status))
                MmUnlockSectionSegment(Segment);
                return STATUS_NO_MEMORY;
            MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SSE(Page << PAGE_SHIFT, 1));
            MmUnlockSectionSegment(Segment);

            Status = MmCreateVirtualMapping(Process, PAddress, Attributes, Page);
            if (!NT_SUCCESS(Status))
                DPRINT1("Unable to create virtual mapping\n");
                KeBugCheck(MEMORY_MANAGEMENT);
            ASSERT(MmIsPagePresent(Process, PAddress));
            if (Process)
                MmInsertRmap(Page, Process, Address);

            DPRINT("Address 0x%p\n", Address);
            return STATUS_SUCCESS;

        MmUnlockSectionSegment(Segment);
        MmUnlockAddressSpace(AddressSpace);

        /* The data must be paged in. Lock the file, so that the VDL doesn't get updated behind us. */
        FsRtlAcquireFileExclusive(Segment->FileObject);

        PFSRTL_COMMON_FCB_HEADER FcbHeader = Segment->FileObject->FsContext;

        Status = MmMakeSegmentResident(Segment, Offset.QuadPart, PAGE_SIZE, &FcbHeader->ValidDataLength, FALSE);

        FsRtlReleaseFile(Segment->FileObject);

        /* Lock address space again */
        MmLockAddressSpace(AddressSpace);
        if (!NT_SUCCESS(Status))
            if (Status == STATUS_NO_MEMORY)
                return Status;
            /* Damn */
            DPRINT1("Failed to page data in!\n");
            return STATUS_IN_PAGE_ERROR;

        /* Everything went fine. Restart the operation */
        return STATUS_MM_RESTART_OPERATION;
    }首先调用MmGetPageEntrySectionSegment,此时返回的Entry为空,所以会进入if语句,此时会执行Mm函数MakeSegmentResident,这个函数内会读取exe文件的内容。之后返回STATUS_MM_RESTART_OPERATION,这会导致MmNotPresentFaultSectionView被再次调用,不过此时执行的路径就和第一次不同了。/* We already have a page on this section offset. Map it into the process address space. */
        Page = PFN_FROM_SSE(Entry);

        Status = MmCreateVirtualMapping(Process,


...(已截断)

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-290864.htm

暂无回复,快来抢沙发吧!

请登录后参与讨论

立即登录 注册账号