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)(指针类型)目的地; } }
我想从内存加载一个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字节。如果您分配: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为零时
- SizeOfUninitializedData:最终会为每个部分分配8192*2字节,这太多了
- SectionAlignment:最终会为每个节分配4096(0x1000)字节,这是不够的
- 以本节的VirtualSize字段为例
- 使用VirtualAlloc()分配结果大小
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;
}
}