如何正确扩展 CLR 兼容 PE 文件中的 .text 部分

问题描述

我想根据文件对齐或节对齐正确扩展 PE 文件中的 .text 节。

详情:

让我们从头开始。 我有 .net v4.8 项目,其中有几个小类,如

public class A1
{
    public int IntProperty {get;set;}
}
public class A2
{
    public string StringProperty {get;set;}
}

这些类是什么并不重要。 使用 MSBuild v16 编译后,我有一个 PE 文件。 (exe 或 dll 也无关紧要)。 然后我用文件或节对齐扩展 .text 节(我都试过)。 因此,如果编译后的 PE 文件具有 512、1024 或 2048 对齐方式 - 效果很好。 但是当它有 4096 或 8192 字节时 - 它不起作用。 这是代码示例,我是怎么做的:


    BYTE* dos_header_ptr = reinterpret_cast<BYTE*>(dosHeader2);
    IMAGE_NT_HEADERS64* nt_header2 = reinterpret_cast<TNT_HEADERS*>(dos_header_ptr + dosHeader2->e_lfanew);
    const IMAGE_FILE_HEADER* file_header = &nt_header2->FileHeader;
    IMAGE_OPTIONAL_HEADER64* optional_headers2 = &nt_header2->OptionalHeader;

    DWORD file_alignment = optional_headers2->FileAlignment;

    file_alignment = optional_headers2->SectionAlignment;

    std::vector<IMAGE_SECTION_HEADER*> sections = ExtractSections(nt_header2);

    IMAGE_SECTION_HEADER* section_header_text2 = sections[0];
    IMAGE_SECTION_HEADER* section_header_rsrc2 = sections[1];

    file_info* old_file_info = file_info2;
    file_info2 = RelocateBufferWithdisplacement(old_file_info,file_alignment,section_header_text2);

    // Update pointers and VA
    dosHeader2 = reinterpret_cast<IMAGE_DOS_HEADER*>(file_info2->buffer);
    dos_header_ptr = reinterpret_cast<BYTE*>(dosHeader2);
    nt_header2 = reinterpret_cast<IMAGE_NT_HEADERS64*>(dos_header_ptr + dosHeader2->e_lfanew);

    file_header = &nt_header2->FileHeader;

    sections.clear();
    sections = ExtractSections<IMAGE_NT_HEADERS64>(nt_header2);
    
    section_header_text2 = sections[0];
    section_header_rsrc2 = sections[1];

    section_header_text2->SizeOfRawData += file_alignment;
    section_header_text2->Misc.VirtualSize = section_header_text2->SizeOfRawData;

    for(int i=1; i<sections.size(); i++)
        sections[i]->PointerToRawData += file_alignment;

    optional_headers2 = &nt_header2->OptionalHeader;
    optional_headers2->SizeOfCode += file_alignment;

    delete old_file_info;

    FlushToFile(input_params.file_name_output,file_info2);

RelocateBufferWithdisplacement 函数


file_info* RelocateBufferWithdisplacement(file_info* file_info2,DWORD file_alignment,IMAGE_SECTION_HEADER* text_section_header)
{
    // copY BUFFERS
    DWORD new_file_size = file_info2->file_size + file_alignment;
    byte* new_buffer = new byte[new_file_size];

    DWORD first_part_of_file_size = text_section_header->PointerToRawData + text_section_header->SizeOfRawData;
    byte* end_first_part_old = file_info2->buffer + first_part_of_file_size;
    byte* start_free_zone_of_file_ptr_new = new_buffer + first_part_of_file_size;
    byte* second_part_of_file_ptr_new = start_free_zone_of_file_ptr_new + file_alignment;

    std::copy(file_info2->buffer,end_first_part_old,new_buffer);
    std::fill(start_free_zone_of_file_ptr_new,second_part_of_file_ptr_new,0);
    std::copy(end_first_part_old,file_info2->buffer + file_info2->file_size,second_part_of_file_ptr_new);

    return new file_info(new_file_size,new_buffer);
}

ExtractSections 方法


std::vector<IMAGE_SECTION_HEADER*>& ExtractSections(IMAGE_NT_HEADERS64* nt_headers)
{
    std::vector<IMAGE_SECTION_HEADER*>* result = new std::vector<IMAGE_SECTION_HEADER*>();
    for(int i=0; i < nt_headers->FileHeader.NumberOfSections; i++)
        result->push_back(reinterpret_cast<IMAGE_SECTION_HEADER*>(reinterpret_cast<BYTE*>(nt_headers) + sizeof(TNT_HEADERS) + i * sizeof(IMAGE_SECTION_HEADER)));

    return *result;
}

这对 x32/x64 文件的工作方式相同,但现在只考虑简化 x64 版本。 我还注意到: 如果我使用更大的项目(例如最多 30000 行代码),即使是 2048 文件对齐我也做不到。仅适用于 512 和 1024。但如果项目几乎明确 - 只有 8192 失败。 我希望也应该更新一些东西,但我不知道究竟是什么。

只是代码的高级愿景:

enter image description here

那么,我做错了什么?

谢谢。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)