From 7863cbeb4a51f526369859a7ed7ed84db00bd0d9 Mon Sep 17 00:00:00 2001 From: rukaimi <rukaimi@985867f9-ca9c-e1f6-822d-e8a4186388af> Date: Sat, 8 Sep 2012 12:00:18 +0000 Subject: [PATCH] Fixed relocation rebuilder bug (auto-alignment added) Changed samples Removed unneeded code Added version --- pe_lib/pe_32_64.cpp | 4 ++-- pe_lib/pe_base.cpp | 26 ++++++++++++++++++++------ pe_lib/pe_structures.h | 4 ---- samples/relocation_adder/main.cpp | 9 +++++---- samples/resource_editor/main.cpp | 6 +++--- 5 files changed, 30 insertions(+), 19 deletions(-) diff --git a/pe_lib/pe_32_64.cpp b/pe_lib/pe_32_64.cpp index f4467a0..94a91d1 100644 --- a/pe_lib/pe_32_64.cpp +++ b/pe_lib/pe_32_64.cpp @@ -675,7 +675,7 @@ const pe_base::image_directory pe<PEClassType>::rebuild_imports(const imported_f std::string& raw_data = import_section.get_raw_data(); - //This will be done only is image_section is latest section of image or for section with unaligned raw length of data + //This will be done only is image_section is the last section of image or for section with unaligned raw length of data if(raw_data.length() < needed_size + import_settings.get_offset_from_section_start()) raw_data.resize(needed_size + import_settings.get_offset_from_section_start()); //Expand section raw data @@ -944,7 +944,7 @@ const pe_base::image_directory pe<PEClassType>::rebuild_tls(const tls_info& info std::string& raw_data = tls_section.get_raw_data(); - //This will be done only is tls_section is latest section of image or for section with unaligned raw length of data + //This will be done only is tls_section is the last section of image or for section with unaligned raw length of data if(raw_data.length() < needed_size + offset_from_section_start) raw_data.resize(needed_size + offset_from_section_start); //Expand section raw data diff --git a/pe_lib/pe_base.cpp b/pe_lib/pe_base.cpp index f800c1f..1b9b78e 100644 --- a/pe_lib/pe_base.cpp +++ b/pe_lib/pe_base.cpp @@ -2107,7 +2107,7 @@ const pe_base::image_directory pe_base::rebuild_exports(const export_info& info, std::string& raw_data = exports_section.get_raw_data(); - //This will be done only is exports_section is latest section of image or for section with unaligned raw length of data + //This will be done only is exports_section is the last section of image or for section with unaligned raw length of data if(raw_data.length() < needed_size + offset_from_section_start) raw_data.resize(needed_size + offset_from_section_start); //Expand section raw data @@ -2615,9 +2615,17 @@ const pe_base::image_directory pe_base::rebuild_relocations(const relocation_tab //sizeof(IMAGE_BASE_RELOCATION) = ending empty relocation table header //sizeof(DWORD) = for DWORD alignment + DWORD current_reloc_data_pos = align_up(offset_from_section_start, sizeof(DWORD)); + DWORD start_reloc_pos = current_reloc_data_pos; + //Enumerate relocation tables for(relocation_table_list::const_iterator it = relocs.begin(); it != relocs.end(); ++it) + { needed_size += static_cast<DWORD>((*it).get_relocations().size() * sizeof(WORD) /* relocations */ + sizeof(IMAGE_BASE_RELOCATION) /* table header */); + //End of each table will be DWORD-aligned + if((start_reloc_pos + needed_size) % sizeof(DWORD)) + needed_size += sizeof(WORD); //Align it with IMAGE_REL_BASED_ABSOLUTE relocation + } //Check if reloc_section is last one. If it's not, check if there's enough place for relocations data if(&reloc_section != &*(sections_.end() - 1) && @@ -2626,12 +2634,10 @@ const pe_base::image_directory pe_base::rebuild_relocations(const relocation_tab std::string& raw_data = reloc_section.get_raw_data(); - //This will be done only is reloc_section is latest section of image or for section with unaligned raw length of data + //This will be done only is reloc_section is the last section of image or for section with unaligned raw length of data if(raw_data.length() < needed_size + offset_from_section_start) raw_data.resize(needed_size + offset_from_section_start); //Expand section raw data - DWORD current_reloc_data_pos = align_up(offset_from_section_start, sizeof(DWORD)); - //Enumerate relocation tables for(relocation_table_list::const_iterator it = relocs.begin(); it != relocs.end(); ++it) { @@ -2640,6 +2646,8 @@ const pe_base::image_directory pe_base::rebuild_relocations(const relocation_tab reloc.VirtualAddress = (*it).get_rva(); const relocation_table::relocation_list& reloc_list = (*it).get_relocations(); reloc.SizeOfBlock = static_cast<DWORD>(sizeof(IMAGE_BASE_RELOCATION) + sizeof(WORD) * reloc_list.size()); + if((reloc_list.size() * sizeof(WORD)) % sizeof(DWORD)) //If we must align end of relocation table + reloc.SizeOfBlock += sizeof(WORD); memcpy(&raw_data[current_reloc_data_pos], &reloc, sizeof(reloc)); current_reloc_data_pos += sizeof(reloc); @@ -2652,6 +2660,12 @@ const pe_base::image_directory pe_base::rebuild_relocations(const relocation_tab memcpy(&raw_data[current_reloc_data_pos], &reloc_value, sizeof(reloc_value)); current_reloc_data_pos += sizeof(reloc_value); } + + if(current_reloc_data_pos % sizeof(DWORD)) //If end of table is not DWORD-aligned + { + memset(&raw_data[current_reloc_data_pos], 0, sizeof(WORD)); //Align it with IMAGE_REL_BASED_ABSOLUTE relocation + current_reloc_data_pos += sizeof(WORD); + } } { @@ -2660,7 +2674,7 @@ const pe_base::image_directory pe_base::rebuild_relocations(const relocation_tab memcpy(&raw_data[current_reloc_data_pos], &reloc, sizeof(reloc)); } - image_directory ret(rva_from_section_offset(reloc_section, offset_from_section_start), needed_size); + image_directory ret(rva_from_section_offset(reloc_section, start_reloc_pos), needed_size); //Adjust section raw and virtual sizes recalculate_section_sizes(reloc_section); @@ -3673,7 +3687,7 @@ const pe_base::image_directory pe_base::rebuild_resources(resource_directory& in std::string& raw_data = resources_section.get_raw_data(); - //This will be done only is resources_section is latest section of image or for section with unaligned raw length of data + //This will be done only is resources_section is the last section of image or for section with unaligned raw length of data if(raw_data.length() < needed_size + offset_from_section_start) raw_data.resize(needed_size + offset_from_section_start); //Expand section raw data diff --git a/pe_lib/pe_structures.h b/pe_lib/pe_structures.h index eb4d9b2..e3fc3cf 100644 --- a/pe_lib/pe_structures.h +++ b/pe_lib/pe_structures.h @@ -3,10 +3,6 @@ #include <Windows.h> #endif -//Macros to align TLS data (not used yet) -#define TLS_ALIGNMENT (2 * sizeof(void *)) -#define TLS_ALIGN(size) (((size) + TLS_ALIGNMENT - 1) & ~(TLS_ALIGNMENT - 1)) - #pragma pack(push, 1) #ifndef _WINNT_ diff --git a/samples/relocation_adder/main.cpp b/samples/relocation_adder/main.cpp index 96cc7f8..9a48324 100644 --- a/samples/relocation_adder/main.cpp +++ b/samples/relocation_adder/main.cpp @@ -25,10 +25,11 @@ int main(int argc, char* argv[]) //Создаем экземпляр PE или PE+ класса с помощью фабрики std::auto_ptr<pe_base> image = pe_factory::create_pe(pe_file); - //Перечислим и получим все полностью записи из таблиц релокаций в PE-файле - //Можно было бы абсолютные записи (ABSOLUTE) и не перечислять, передав в вызов false - //Эти записи все равно не нужны - pe_base::relocation_table_list tables = image->get_relocations(true); + //Перечислим и получим все записи из таблиц релокаций в PE-файле, кроме абсолютных + //Можно было бы включить в список и абсолютные записи (ABSOLUTE), передав в вызов true + //Эти записи не нужны при пересборке релокаций, они используются для выравнивания + //и будут добавлены автоматически пересборщиком + pe_base::relocation_table_list tables = image->get_relocations(); //Создаем новую таблицу релокаций pe_base::relocation_table new_table; diff --git a/samples/resource_editor/main.cpp b/samples/resource_editor/main.cpp index e4d39d9..aa1b601 100644 --- a/samples/resource_editor/main.cpp +++ b/samples/resource_editor/main.cpp @@ -55,7 +55,7 @@ int main(int argc, char* argv[]) return -1; } - //Получим нашу иконку из этой директории: мы знаем, что ее ID=101 и она одна в директории имен, поэтому делаем так + //Получим нашу иконку из этой директории: мы знаем, что ее ID=100 и она одна в директории имен, поэтому делаем так //Получаем ее по нулевому индексу (можно было получить по языку, но это незачем, т.к. она единственная) const pe_resource_viewer::resource_data_info data = res.get_resource_data_by_id(L"CUSTOM", IDR_CUSTOM1); @@ -64,7 +64,7 @@ int main(int argc, char* argv[]) //Помните, что сначала идут именованные ресурсы, а потом ресурсы с идентификаторами, и всё сортируется //Создадим группу иконок с именем MAIN_ICON res.add_icon(data.get_data(), //Данные файла иконки - L"MAIN_ICON", //Имя группы иконок (помните, у нас три картинки внутри иконки, они будут находиться в этой группе + L"MAIN_ICON", //Имя группы иконок (помните, у нас три картинки внутри иконки, они будут находиться в этой группе) 0, //Язык - нам неважен pe_resource_manager::icon_place_after_max_icon_id, //Вариант расположения иконок в существующей группе - нам он неважен, так как мы создаем новую группу data.get_codepage(), //Сохраним исходную Codepage @@ -112,7 +112,7 @@ int main(int argc, char* argv[]) //Осталось переименовать старую секцию ресурсов //Она называется .rsrc - //Переименование необходимо для того, чтобы Windows Explorer смог считать оттуда иконку + //Переименование необходимо для того, чтобы Windows Explorer смог считать из новой секции иконку image->section_from_directory(IMAGE_DIRECTORY_ENTRY_RESOURCE).set_name("oldres"); //Пересоберем ресурсы -- GitLab