From 3540e77243d02f6701f95ae28c61e1519cb34143 Mon Sep 17 00:00:00 2001 From: Catminusminus Date: Mon, 18 Jan 2021 11:16:17 +0900 Subject: [PATCH 1/2] fix IAT reconstruction section_from_offset(original_import_offset) can return the previous section of original import section, so use this->binary_->section_from_offset((*original_import_section)->pointerto_raw_data()) where original_import_section is corresponding to the original import section. To obtain original_import_section after adding the new import section, we introduce PE_SECTION_TYPES::OLD_IMPORT type. This type is just used to mark the original import section. --- include/LIEF/PE/enums.hpp.in | 3 ++- src/PE/Builder.tcc | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/LIEF/PE/enums.hpp.in b/include/LIEF/PE/enums.hpp.in index 3ba5cec3e2..3f58087a9e 100644 --- a/include/LIEF/PE/enums.hpp.in +++ b/include/LIEF/PE/enums.hpp.in @@ -23,7 +23,8 @@ enum class PE_SECTION_TYPES : uint8_t { EXPORT = 7, DEBUG = 8, LOAD_CONFIG = 9, - UNKNOWN = 10 + UNKNOWN = 10, + OLD_IMPORT = 100 }; enum class PE_TYPE : uint16_t { diff --git a/src/PE/Builder.tcc b/src/PE/Builder.tcc index 65d9db7d92..01a6e1f9ce 100644 --- a/src/PE/Builder.tcc +++ b/src/PE/Builder.tcc @@ -168,20 +168,28 @@ void Builder::build_import_table(void) { // Remove 'import' type from the original section if (it_import_section != std::end(this->binary_->sections_)) { (*it_import_section)->remove_type(PE_SECTION_TYPES::IMPORT); + (*it_import_section)->add_type(PE_SECTION_TYPES::OLD_IMPORT); } // As add_section will change DATA_DIRECTORY::IMPORT_TABLE we have to save it before uint32_t offset_imports = this->binary_->rva_to_offset(this->binary_->data_directory(DATA_DIRECTORY::IMPORT_TABLE).RVA()); + auto offset_imports_in_section = offset_imports - this->binary_->section_from_offset(offset_imports).offset(); Section& import_section = this->binary_->add_section(new_import_section, PE_SECTION_TYPES::IMPORT); - // Patch the original IAT with the address of the associated trampoline if (this->patch_imports_) { - Section& original_import = this->binary_->section_from_offset(offset_imports); + auto&& original_import_section = std::find_if( + std::begin(this->binary_->sections_), + std::end(this->binary_->sections_), + [] (const Section* section) { + return section != nullptr and section->is_type(PE_SECTION_TYPES::OLD_IMPORT); + }); + (*original_import_section)->remove_type(PE_SECTION_TYPES::OLD_IMPORT); + auto original_import_offset = (*original_import_section)->pointerto_raw_data(); + Section& original_import = this->binary_->section_from_offset(original_import_offset); std::vector import_content = original_import.content(); - uint32_t roffset_import = offset_imports - original_import.offset(); - pe_import *import_header = reinterpret_cast(import_content.data() + roffset_import); + pe_import *import_header = reinterpret_cast(import_content.data() + offset_imports_in_section); uint32_t jumpOffsetTmp = trampolines_offset; while (import_header->ImportAddressTableRVA != 0) { uint32_t offsetTable = this->binary_->rva_to_offset(import_header->ImportLookupTableRVA) - original_import.pointerto_raw_data(); From 6b03898cf1712da2770201a44932bc0399f38e29 Mon Sep 17 00:00:00 2001 From: Catminusminus Date: Tue, 19 Jan 2021 15:31:04 +0900 Subject: [PATCH 2/2] add a fallback mechanism We use section_from_offset(offset_imports) as the original import section if no section has OLD_IMPORT type. --- src/PE/Builder.tcc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/PE/Builder.tcc b/src/PE/Builder.tcc index 01a6e1f9ce..bf20272438 100644 --- a/src/PE/Builder.tcc +++ b/src/PE/Builder.tcc @@ -184,9 +184,13 @@ void Builder::build_import_table(void) { [] (const Section* section) { return section != nullptr and section->is_type(PE_SECTION_TYPES::OLD_IMPORT); }); - (*original_import_section)->remove_type(PE_SECTION_TYPES::OLD_IMPORT); - auto original_import_offset = (*original_import_section)->pointerto_raw_data(); - Section& original_import = this->binary_->section_from_offset(original_import_offset); + // fallback mechanism + const auto is_found = original_import_section != std::end(this->binary_->sections_); + if (is_found) { + (*original_import_section)->remove_type(PE_SECTION_TYPES::OLD_IMPORT); + } + auto original_import_offset = is_found ? (*original_import_section)->pointerto_raw_data() : 0; + Section& original_import = this->binary_->section_from_offset(is_found ? original_import_offset: offset_imports); std::vector import_content = original_import.content(); pe_import *import_header = reinterpret_cast(import_content.data() + offset_imports_in_section);