void
CopySections(const unsigned char *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module)
{
    int i, size;
    unsigned char *codeBase = module->codeBase;
    unsigned char *dest;
    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
    for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++) {
        if (section->SizeOfRawData == 0) {
            // section doesn't contain data in the dll itself, but may define
            // uninitialized data
            size = old_headers->OptionalHeader.SectionAlignment;
            if (size > 0) {
                dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
                    size,
                    MEM_COMMIT,
                    PAGE_READWRITE);

                section->Misc.PhysicalAddress = (DWORD) (POINTER_TYPE) dest;
                memset(dest, 0, size);
            }

            // section is empty
            continue;
        }

        // commit memory block and copy data from dll
        dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
                            section->SizeOfRawData,
                            MEM_COMMIT,
                            PAGE_READWRITE);
        memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData);
        section->Misc.PhysicalAddress = (DWORD) (POINTER_TYPE) dest;
    }
}

我想从内存中加载一个dll文件,上面的代码可以在http://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory中找到。
我还发现作者说:
“文件中没有数据的节(如用于所用变量的数据节)的sizeofrawdata为0,因此可以使用optionalheader的sizeoffinitializeddata或sizeofuninitializeddata。根据在节特性中设置的位标志image_scn_cnt_initialized_data和image_scn_cnt_uninitialized_data,必须选择哪一个。”
但我不明白sizeofrawdata为零时,提交的内存大小为何是sectionalignment,既不是sizeoffinitializeddata,也不是sizeofuninitializeddata。

最佳答案

根据Microsoft PE and COFF Specificationsizeofrawdata为零,当:
当节仅包含未初始化的数据时,此字段(sizeofrawdata)应为零。
(另一方面,如果节仅包含初始化为0的初始化数据,则此情况也适用。)
SizeOfinitializedData或SizeOfunInitializedData不能按节使用,因为如果有多个此类节(引用规范),则这些字段是所有已初始化节和未初始化节的总和:
sizeOfinitializedData:初始化数据节的大小,如果有多个数据节,则为所有这些节的总和。
sizeofuninitializeddata:未初始化数据节(bss)的大小,或
如果有多个BSS节,则为所有此类节的总和。
因此,如果有多个已初始化或未初始化的节,那么如果分别使用sizeoffinitializeddata或sizeofuninitializeddata字段,则最终会为单个节分配到多个。
它不能是SectionAlignment(通常设置为系统分配粒度),因为如果Xection的大小大于分配粒度(通常为4kibi或4096字节),那么最终也将无法为节分配足够的空间。
节对齐:节加载到内存中时的对齐方式(字节)。它必须大于或等于filealignment。默认值是体系结构的页面大小。
例如,假设有两个未初始化的数据节(每个节的sizeofrawdata=0),每个节8192字节。如果分配:
sizeofuninitializeddata:最后会为每个部分分配8192*2字节,这太多了。
SectionAlignment:最后会为每个部分分配4096(0x1000)字节,这是不够的。
imo,在您的案例中唯一相关的字段是image_section_header.virtualize:
VirtualSize:加载到内存时节的总大小。如果此值大于sizeofrawdata,则该节为零填充。此字段仅对可执行映像有效,对于对象文件应设置为零。
注意,virtualize字段不是四舍五入的(它是内存中所需的确切字节数,不考虑页面粒度)。
因此,如果您有一个sizeofrawdata=0的部分,您应该:
获取本节的virtualize字段
使用virtualAlloc()分配结果大小
您不必对virtualSize进行舍入,因为virtualAlloc()将负责分配到页面大小粒度的下一个倍数(由GetSystemInfo和System_info.dwPageSize字段给出)。

08-05 10:14