Windows 关于将dll节复制到内存 void CopySections(常量无符号字符*数据、PIMAGE\u NT\u头旧头、PMEMORYMODULE) { int i,大小; 无符号字符*codeBase=module->codeBase; 无符号字符*dest; PIMAGE_SECTION_HEADER SECTION=图像_FIRST_SECTION(模块->标题); 对于(i=0;iheaders->FileHeader.NumberOfSections;i++,section++){ 如果(节->SizeOfRawData==0){ //节不包含dll本身中的数据,但可以定义 //未初始化数据 大小=旧标题->可选标题.SectionAlignment; 如果(大小>0){ dest=(无符号字符*)VirtualAlloc(代码基+节->VirtualAddress, 大小, 请记住, 页面(读写); 节->杂项物理地址=(DWORD)(指针类型)目的地; memset(dest,0,size); } //节是空的 继续; } //提交内存块并从dll复制数据 dest=(无符号字符*)VirtualAlloc(代码基+节->VirtualAddress, 章节->SizeOfRawData, 请记住, 页面(读写); memcpy(dest,data+section->PointerToRawData,section->SizeOfRawData); 节->杂项物理地址=(DWORD)(指针类型)目的地; } }

Windows 关于将dll节复制到内存 void CopySections(常量无符号字符*数据、PIMAGE\u NT\u头旧头、PMEMORYMODULE) { int i,大小; 无符号字符*codeBase=module->codeBase; 无符号字符*dest; PIMAGE_SECTION_HEADER SECTION=图像_FIRST_SECTION(模块->标题); 对于(i=0;iheaders->FileHeader.NumberOfSections;i++,section++){ 如果(节->SizeOfRawData==0){ //节不包含dll本身中的数据,但可以定义 //未初始化数据 大小=旧标题->可选标题.SectionAlignment; 如果(大小>0){ dest=(无符号字符*)VirtualAlloc(代码基+节->VirtualAddress, 大小, 请记住, 页面(读写); 节->杂项物理地址=(DWORD)(指针类型)目的地; memset(dest,0,size); } //节是空的 继续; } //提交内存块并从dll复制数据 dest=(无符号字符*)VirtualAlloc(代码基+节->VirtualAddress, 章节->SizeOfRawData, 请记住, 页面(读写); memcpy(dest,data+section->PointerToRawData,section->SizeOfRawData); 节->杂项物理地址=(DWORD)(指针类型)目的地; } },windows,dll,portable-executable,Windows,Dll,Portable Executable,我想从内存加载一个dll文件。上面的代码在中找到 我还发现作者说: “文件中没有数据的部分(如所用变量的数据部分)SizeOfRawData为0,因此您可以使用OptionalHeader的SizeOfFinitializedData或SizeOfOnInitializedData。必须根据可能在节的特征中设置的位标志IMAGE_SCN_CNT_INITIALIZED_数据和IMAGE_SCN_CNT_UNINITIALIZED_数据选择哪一个。” 但我无法理解当SizeOfRawData为零时

我想从内存加载一个dll文件。上面的代码在中找到

我还发现作者说: “文件中没有数据的部分(如所用变量的数据部分)SizeOfRawData为0,因此您可以使用OptionalHeader的SizeOfFinitializedData或SizeOfOnInitializedData。必须根据可能在节的特征中设置的位标志IMAGE_SCN_CNT_INITIALIZED_数据和IMAGE_SCN_CNT_UNINITIALIZED_数据选择哪一个。”

但我无法理解当SizeOfRawData为零时,为什么提交的内存大小是SectionAlignment,既不是SizeFinitializedData,也不是SizeOfUninitializedData

根据尺寸,在以下情况下,FRAWDATA为零:

当节仅包含未初始化的数据时,此字段(SizeOfRawData)应为零

(作为旁注,如果节仅包含初始化为0的初始化数据,则这也是正确的。)

SizeOfInitializedData或SizeOfUninitializedData不能按节使用,因为如果有多个此类节(引用规范),则这些字段是所有初始化节和未初始化节的总和:

SizeFinitializedData:初始化数据节的大小,如果有多个数据节,则为所有此类节的总和

SizeOfUninitializedData:未初始化数据节(BSS)的大小,或 如果存在多个BSS区段,则所有此类区段的总和

因此,如果您有多个已初始化或未初始化的节,那么如果使用(分别)SizeOfInitializedData或SizeOfUninitializedData字段,则最终会为单个节分配更多

它不能是SectionAlignment(通常设置为系统分配粒度),因为如果xection的大小大于分配粒度(通常为4Kibi或4096字节),那么您也将无法为分区分配足够的空间

SectionAlignment:节加载到内存时的对齐方式(以字节为单位)。它必须大于或等于FileAlignment。默认值是体系结构的页面大小

例如,假设您有两个未初始化的数据节(每个节的SizeOfRawData=0),每个节8192字节。如果您分配:

  • SizeOfUninitializedData:最终会为每个部分分配8192*2字节,这太多了

  • SectionAlignment:最终会为每个节分配4096(0x1000)字节,这是不够的

依我看,在您的案例中唯一相关的字段是IMAGE\u SECTION\u HEADER.VirtualSize:

VirtualSize:加载到内存时节的总大小。如果该值大于SizeOfRawData,则该段为零填充。此字段仅对可执行图像有效,对于对象文件应设置为零

请注意,VirtualSize字段不是四舍五入的(它是内存中所需的确切字节数,不考虑页面粒度)

因此,如果您有一个SizeOfRawData=0的节,您应该:

  • 以本节的VirtualSize字段为例
  • 使用VirtualAlloc()分配结果大小
您不必对VirtualSize进行取整,因为VirtualAlloc()将负责分配到页面大小粒度的下一个倍数(如和SYSTEM_INFO.dwPageSize字段所示)

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;
    }
}