------------恢复内容开始------------
1. 为什么只能扩大最后一个?
节与节之间有相互依存的关系,a 节中的代码可能会使用 b 节、c 节的数据或者说 a 节中代码会跳转到 b 节、c 节。如果把其中某个节
扩大了了,偏移就会改变。
注解:详情参考 Intel 指令编码。
2. 扩大节方法
1. 仿照 windows 加载器载入 PE 文件
内存分配大小:SizeOfImage + 内存对齐(追加数据的字节数)
2. 修改最后一个节的 Section Header
修改 Section Header 的 Misc.VirtualSize 成员以及 SizeOfRawData 成员。
Misc.VirtualSize 要分为两种情况考虑
Misc.VirtualSize = 0 ;则不需要修改
Misc.VirtualSize != 0 ;则 Misc.VirtualSize = 最后一个节的内存大小(对齐后)+ 追加数据的字节数
注解:win10 pe 加载器会使用 Misc.VirtualSize (不为 0)
SizeOfRawData = SizeOfRawData + 文件对齐(追加数据的字节数)
3. 修改 Optional Header 的 SizeOfImage 成员
SizeOfImage = SizeOfImage + 内存对齐(追加数据的字节数)
3. 伪代码
void* expand_section(const void* image, unsigned long expand_size) { if (!is_pe_file(image)) return nullptr; //----------------------------> 对齐 auto expand_size_section_alignment = section_alignment(image, expand_size); //----------------------------> 拷贝原 pe 数据 auto old_sizeof_image = get_sizeof_image(image); auto new_sizeof_image = old_sizeof_image + expand_size_section_alignment; std::unique_ptr<byte[]> new_image(CNew byte[new_sizeof_image]()); if (!new_image) return nullptr; memcpy_s(new_image.get(), new_sizeof_image, image, old_sizeof_image); //----------------------------> 修改 section header auto last_section = get_last_section(new_image.get()); if (last_section->Misc.VirtualSize != 0) { last_section->Misc.VirtualSize = section_alignment(image, last_section->Misc.VirtualSize); last_section->Misc.VirtualSize += expand_size; } // 修改 SizeOfRawData last_section->SizeOfRawData += file_alignment(new_image.get(), expand_size); // 修改 SizeOfImage set_sizeof_image(new_image.get(), new_sizeof_image); //---------------------------->return std::move(new_image); }
------------恢复内容结束------------