virtualx-engine/drivers/pe_bliss/pe_imports.cpp
masoud bh 24f3f43457 Add icon to exe file in windows export
add version_info and icon sections in "export to windows platform".
add version_info and icon to godot exe file (editor & template exe).
fix an problem in image class.
change all default icons to android export icon (a little more rounded).
create an python script for convert file to cpp byte array for use in
'splash.h'.
2015-11-09 02:23:58 +03:30

756 lines
28 KiB
C++

#include <string.h>
#include "pe_imports.h"
#include "pe_properties_generic.h"
namespace pe_bliss
{
using namespace pe_win;
//IMPORTS
//Default constructor
//If set_to_pe_headers = true, IMAGE_DIRECTORY_ENTRY_IMPORT entry will be reset
//to new value after import rebuilding
//If auto_zero_directory_entry_iat = true, IMAGE_DIRECTORY_ENTRY_IAT will be set to zero
//IMAGE_DIRECTORY_ENTRY_IAT is used by loader to temporarily make section, where IMAGE_DIRECTORY_ENTRY_IAT RVA points, writeable
//to be able to modify IAT thunks
import_rebuilder_settings::import_rebuilder_settings(bool set_to_pe_headers, bool auto_zero_directory_entry_iat)
:offset_from_section_start_(0),
build_original_iat_(true),
save_iat_and_original_iat_rvas_(true),
fill_missing_original_iats_(false),
set_to_pe_headers_(set_to_pe_headers),
zero_directory_entry_iat_(auto_zero_directory_entry_iat),
rewrite_iat_and_original_iat_contents_(false),
auto_strip_last_section_(true)
{}
//Returns offset from section start where import directory data will be placed
uint32_t import_rebuilder_settings::get_offset_from_section_start() const
{
return offset_from_section_start_;
}
//Returns true if Original import address table (IAT) will be rebuilt
bool import_rebuilder_settings::build_original_iat() const
{
return build_original_iat_;
}
//Returns true if Original import address and import address tables will not be rebuilt,
//works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero
bool import_rebuilder_settings::save_iat_and_original_iat_rvas() const
{
return save_iat_and_original_iat_rvas_;
}
//Returns true if Original import address and import address tables contents will be rewritten
//works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero
//and save_iat_and_original_iat_rvas is true
bool import_rebuilder_settings::rewrite_iat_and_original_iat_contents() const
{
return rewrite_iat_and_original_iat_contents_;
}
//Returns true if original missing IATs will be rebuilt
//(only if IATs are saved)
bool import_rebuilder_settings::fill_missing_original_iats() const
{
return fill_missing_original_iats_;
}
//Returns true if PE headers should be updated automatically after rebuilding of imports
bool import_rebuilder_settings::auto_set_to_pe_headers() const
{
return set_to_pe_headers_;
}
//Returns true if IMAGE_DIRECTORY_ENTRY_IAT must be zeroed, works only if auto_set_to_pe_headers = true
bool import_rebuilder_settings::zero_directory_entry_iat() const
{
return zero_directory_entry_iat_;
}
//Returns true if the last section should be stripped automatically, if imports are inside it
bool import_rebuilder_settings::auto_strip_last_section_enabled() const
{
return auto_strip_last_section_;
}
//Sets offset from section start where import directory data will be placed
void import_rebuilder_settings::set_offset_from_section_start(uint32_t offset)
{
offset_from_section_start_ = offset;
}
//Sets if Original import address table (IAT) will be rebuilt
void import_rebuilder_settings::build_original_iat(bool enable)
{
build_original_iat_ = enable;
}
//Sets if Original import address and import address tables will not be rebuilt,
//works only if import descriptor IAT (and orig.IAT, if present) RVAs are not zero
void import_rebuilder_settings::save_iat_and_original_iat_rvas(bool enable, bool enable_rewrite_iat_and_original_iat_contents)
{
save_iat_and_original_iat_rvas_ = enable;
if(save_iat_and_original_iat_rvas_)
rewrite_iat_and_original_iat_contents_ = enable_rewrite_iat_and_original_iat_contents;
else
rewrite_iat_and_original_iat_contents_ = false;
}
//Sets if original missing IATs will be rebuilt
//(only if IATs are saved)
void import_rebuilder_settings::fill_missing_original_iats(bool enable)
{
fill_missing_original_iats_ = enable;
}
//Sets if PE headers should be updated automatically after rebuilding of imports
void import_rebuilder_settings::auto_set_to_pe_headers(bool enable)
{
set_to_pe_headers_ = enable;
}
//Sets if IMAGE_DIRECTORY_ENTRY_IAT must be zeroed, works only if auto_set_to_pe_headers = true
void import_rebuilder_settings::zero_directory_entry_iat(bool enable)
{
zero_directory_entry_iat_ = enable;
}
//Sets if the last section should be stripped automatically, if imports are inside it, default true
void import_rebuilder_settings::enable_auto_strip_last_section(bool enable)
{
auto_strip_last_section_ = enable;
}
//Default constructor
imported_function::imported_function()
:hint_(0), ordinal_(0), iat_va_(0)
{}
//Returns name of function
const std::string& imported_function::get_name() const
{
return name_;
}
//Returns true if imported function has name (and hint)
bool imported_function::has_name() const
{
return !name_.empty();
}
//Returns hint
uint16_t imported_function::get_hint() const
{
return hint_;
}
//Returns ordinal of function
uint16_t imported_function::get_ordinal() const
{
return ordinal_;
}
//Returns IAT entry VA (usable if image has both IAT and original IAT and is bound)
uint64_t imported_function::get_iat_va() const
{
return iat_va_;
}
//Sets name of function
void imported_function::set_name(const std::string& name)
{
name_ = name;
}
//Sets hint
void imported_function::set_hint(uint16_t hint)
{
hint_ = hint;
}
//Sets ordinal
void imported_function::set_ordinal(uint16_t ordinal)
{
ordinal_ = ordinal;
}
//Sets IAT entry VA (usable if image has both IAT and original IAT and is bound)
void imported_function::set_iat_va(uint64_t va)
{
iat_va_ = va;
}
//Default constructor
import_library::import_library()
:rva_to_iat_(0), rva_to_original_iat_(0), timestamp_(0)
{}
//Returns name of library
const std::string& import_library::get_name() const
{
return name_;
}
//Returns RVA to Import Address Table (IAT)
uint32_t import_library::get_rva_to_iat() const
{
return rva_to_iat_;
}
//Returns RVA to Original Import Address Table (Original IAT)
uint32_t import_library::get_rva_to_original_iat() const
{
return rva_to_original_iat_;
}
//Returns timestamp
uint32_t import_library::get_timestamp() const
{
return timestamp_;
}
//Sets name of library
void import_library::set_name(const std::string& name)
{
name_ = name;
}
//Sets RVA to Import Address Table (IAT)
void import_library::set_rva_to_iat(uint32_t rva_to_iat)
{
rva_to_iat_ = rva_to_iat;
}
//Sets RVA to Original Import Address Table (Original IAT)
void import_library::set_rva_to_original_iat(uint32_t rva_to_original_iat)
{
rva_to_original_iat_ = rva_to_original_iat;
}
//Sets timestamp
void import_library::set_timestamp(uint32_t timestamp)
{
timestamp_ = timestamp;
}
//Returns imported functions list
const import_library::imported_list& import_library::get_imported_functions() const
{
return imports_;
}
//Adds imported function
void import_library::add_import(const imported_function& func)
{
imports_.push_back(func);
}
//Clears imported functions list
void import_library::clear_imports()
{
imports_.clear();
}
const imported_functions_list get_imported_functions(const pe_base& pe)
{
return (pe.get_pe_type() == pe_type_32 ?
get_imported_functions_base<pe_types_class_32>(pe)
: get_imported_functions_base<pe_types_class_64>(pe));
}
const image_directory rebuild_imports(pe_base& pe, const imported_functions_list& imports, section& import_section, const import_rebuilder_settings& import_settings)
{
return (pe.get_pe_type() == pe_type_32 ?
rebuild_imports_base<pe_types_class_32>(pe, imports, import_section, import_settings)
: rebuild_imports_base<pe_types_class_64>(pe, imports, import_section, import_settings));
}
//Returns imported functions list with related libraries info
template<typename PEClassType>
const imported_functions_list get_imported_functions_base(const pe_base& pe)
{
imported_functions_list ret;
//If image has no imports, return empty array
if(!pe.has_imports())
return ret;
unsigned long current_descriptor_pos = pe.get_directory_rva(image_directory_entry_import);
//Get first IMAGE_IMPORT_DESCRIPTOR
image_import_descriptor import_descriptor = pe.section_data_from_rva<image_import_descriptor>(current_descriptor_pos, section_data_virtual, true);
//Iterate them until we reach zero-element
//We don't need to check correctness of this, because exception will be thrown
//inside of loop if we go outsize of section
while(import_descriptor.Name)
{
//Get imported library information
import_library lib;
unsigned long max_name_length;
//Get byte count that we have for library name
if((max_name_length = pe.section_data_length_from_rva(import_descriptor.Name, import_descriptor.Name, section_data_virtual, true)) < 2)
throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
//Get DLL name pointer
const char* dll_name = pe.section_data_from_rva(import_descriptor.Name, section_data_virtual, true);
//Check for null-termination
if(!pe_utils::is_null_terminated(dll_name, max_name_length))
throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
//Set library name
lib.set_name(dll_name);
//Set library timestamp
lib.set_timestamp(import_descriptor.TimeDateStamp);
//Set library RVA to IAT and original IAT
lib.set_rva_to_iat(import_descriptor.FirstThunk);
lib.set_rva_to_original_iat(import_descriptor.OriginalFirstThunk);
//Get RVA to IAT (it must be filled by loader when loading PE)
uint32_t current_thunk_rva = import_descriptor.FirstThunk;
typename PEClassType::BaseSize import_address_table = pe.section_data_from_rva<typename PEClassType::BaseSize>(current_thunk_rva, section_data_virtual, true);
//Get RVA to original IAT (lookup table), which must handle imported functions names
//Some linkers leave this pointer zero-filled
//Such image is valid, but it is not possible to restore imported functions names
//afted image was loaded, because IAT becomes the only one table
//containing both function names and function RVAs after loading
uint32_t current_original_thunk_rva = import_descriptor.OriginalFirstThunk;
typename PEClassType::BaseSize import_lookup_table = current_original_thunk_rva == 0 ? import_address_table : pe.section_data_from_rva<typename PEClassType::BaseSize>(current_original_thunk_rva, section_data_virtual, true);
if(current_original_thunk_rva == 0)
current_original_thunk_rva = current_thunk_rva;
//List all imported functions for current DLL
if(import_lookup_table != 0 && import_address_table != 0)
{
while(true)
{
//Imported function description
imported_function func;
//Get VA from IAT
typename PEClassType::BaseSize address = pe.section_data_from_rva<typename PEClassType::BaseSize>(current_thunk_rva, section_data_virtual, true);
//Move pointer
current_thunk_rva += sizeof(typename PEClassType::BaseSize);
//Jump to next DLL if we finished with this one
if(!address)
break;
func.set_iat_va(address);
//Get VA from original IAT
typename PEClassType::BaseSize lookup = pe.section_data_from_rva<typename PEClassType::BaseSize>(current_original_thunk_rva, section_data_virtual, true);
//Move pointer
current_original_thunk_rva += sizeof(typename PEClassType::BaseSize);
//Check if function is imported by ordinal
if((lookup & PEClassType::ImportSnapFlag) != 0)
{
//Set function ordinal
func.set_ordinal(static_cast<uint16_t>(lookup & 0xffff));
}
else
{
//Get byte count that we have for function name
if(lookup > static_cast<uint32_t>(-1) - sizeof(uint16_t))
throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
//Get maximum available length of function name
if((max_name_length = pe.section_data_length_from_rva(static_cast<uint32_t>(lookup + sizeof(uint16_t)), static_cast<uint32_t>(lookup + sizeof(uint16_t)), section_data_virtual, true)) < 2)
throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
//Get imported function name
const char* func_name = pe.section_data_from_rva(static_cast<uint32_t>(lookup + sizeof(uint16_t)), section_data_virtual, true);
//Check for null-termination
if(!pe_utils::is_null_terminated(func_name, max_name_length))
throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
//HINT in import table is ORDINAL in export table
uint16_t hint = pe.section_data_from_rva<uint16_t>(static_cast<uint32_t>(lookup), section_data_virtual, true);
//Save hint and name
func.set_name(func_name);
func.set_hint(hint);
}
//Add function to list
lib.add_import(func);
}
}
//Check possible overflow
if(!pe_utils::is_sum_safe(current_descriptor_pos, sizeof(image_import_descriptor)))
throw pe_exception("Incorrect import directory", pe_exception::incorrect_import_directory);
//Go to next library
current_descriptor_pos += sizeof(image_import_descriptor);
import_descriptor = pe.section_data_from_rva<image_import_descriptor>(current_descriptor_pos, section_data_virtual, true);
//Save import information
ret.push_back(lib);
}
//Return resulting list
return ret;
}
//Simple import directory rebuilder
//You can get all image imports with get_imported_functions() function
//You can use returned value to, for example, add new imported library with some functions
//to the end of list of imported libraries
//To keep PE file working, rebuild its imports with save_iat_and_original_iat_rvas = true (default)
//Don't add new imported functions to existing imported library entries, because this can cause
//rewriting of some used memory (or other IAT/orig.IAT fields) by system loader
//The safest way is just adding import libraries with functions to the end of imported_functions_list array
template<typename PEClassType>
const image_directory rebuild_imports_base(pe_base& pe, const imported_functions_list& imports, section& import_section, const import_rebuilder_settings& import_settings)
{
//Check that import_section is attached to this PE image
if(!pe.section_attached(import_section))
throw pe_exception("Import section must be attached to PE file", pe_exception::section_is_not_attached);
uint32_t needed_size = 0; //Calculate needed size for import structures and strings
uint32_t needed_size_for_strings = 0; //Calculate needed size for import strings (library and function names and hints)
uint32_t size_of_iat = 0; //Size of IAT structures
needed_size += static_cast<uint32_t>((1 /* ending null descriptor */ + imports.size()) * sizeof(image_import_descriptor));
//Enumerate imported functions
for(imported_functions_list::const_iterator it = imports.begin(); it != imports.end(); ++it)
{
needed_size_for_strings += static_cast<uint32_t>((*it).get_name().length() + 1 /* nullbyte */);
const import_library::imported_list& funcs = (*it).get_imported_functions();
//IMAGE_THUNK_DATA
size_of_iat += static_cast<uint32_t>(sizeof(typename PEClassType::BaseSize) * (1 /*ending null */ + funcs.size()));
//Enumerate all imported functions in library
for(import_library::imported_list::const_iterator f = funcs.begin(); f != funcs.end(); ++f)
{
if((*f).has_name())
needed_size_for_strings += static_cast<uint32_t>((*f).get_name().length() + 1 /* nullbyte */ + sizeof(uint16_t) /* hint */);
}
}
if(import_settings.build_original_iat() || import_settings.fill_missing_original_iats())
needed_size += size_of_iat * 2; //We'll have two similar-sized IATs if we're building original IAT
else
needed_size += size_of_iat;
needed_size += sizeof(typename PEClassType::BaseSize); //Maximum align for IAT and original IAT
//Total needed size for import structures and strings
needed_size += needed_size_for_strings;
//Check if import_section is last one. If it's not, check if there's enough place for import data
if(&import_section != &*(pe.get_image_sections().end() - 1) &&
(import_section.empty() || pe_utils::align_up(import_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + import_settings.get_offset_from_section_start()))
throw pe_exception("Insufficient space for import directory", pe_exception::insufficient_space);
std::string& raw_data = import_section.get_raw_data();
//This will be done only if 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
uint32_t current_string_pointer = import_settings.get_offset_from_section_start();/* we will paste structures after strings */
//Position for IAT
uint32_t current_pos_for_iat = pe_utils::align_up(static_cast<uint32_t>(needed_size_for_strings + import_settings.get_offset_from_section_start() + (1 + imports.size()) * sizeof(image_import_descriptor)), sizeof(typename PEClassType::BaseSize));
//Position for original IAT
uint32_t current_pos_for_original_iat = current_pos_for_iat + size_of_iat;
//Position for import descriptors
uint32_t current_pos_for_descriptors = needed_size_for_strings + import_settings.get_offset_from_section_start();
//Build imports
for(imported_functions_list::const_iterator it = imports.begin(); it != imports.end(); ++it)
{
//Create import descriptor
image_import_descriptor descr;
memset(&descr, 0, sizeof(descr));
descr.TimeDateStamp = (*it).get_timestamp(); //Restore timestamp
descr.Name = pe.rva_from_section_offset(import_section, current_string_pointer); //Library name RVA
//If we should save IAT for current import descriptor
bool save_iats_for_this_descriptor = import_settings.save_iat_and_original_iat_rvas() && (*it).get_rva_to_iat() != 0;
//If we should write original IAT
bool write_original_iat = (!save_iats_for_this_descriptor && import_settings.build_original_iat()) || import_settings.fill_missing_original_iats();
//If we should rewrite saved original IAT for current import descriptor (without changing its position)
bool rewrite_saved_original_iat = save_iats_for_this_descriptor && import_settings.rewrite_iat_and_original_iat_contents() && import_settings.build_original_iat();
//If we should rewrite saved IAT for current import descriptor (without changing its position)
bool rewrite_saved_iat = save_iats_for_this_descriptor && import_settings.rewrite_iat_and_original_iat_contents() && (*it).get_rva_to_iat() != 0;
//Helper values if we're rewriting existing IAT or orig.IAT
uint32_t original_first_thunk = 0;
uint32_t first_thunk = 0;
if(save_iats_for_this_descriptor)
{
//If there's no original IAT and we're asked to rebuild missing original IATs
if(!(*it).get_rva_to_original_iat() && import_settings.fill_missing_original_iats())
descr.OriginalFirstThunk = import_settings.build_original_iat() ? pe.rva_from_section_offset(import_section, current_pos_for_original_iat) : 0;
else
descr.OriginalFirstThunk = import_settings.build_original_iat() ? (*it).get_rva_to_original_iat() : 0;
descr.FirstThunk = (*it).get_rva_to_iat();
original_first_thunk = descr.OriginalFirstThunk;
first_thunk = descr.FirstThunk;
if(rewrite_saved_original_iat)
{
if((*it).get_rva_to_original_iat())
write_original_iat = true;
else
rewrite_saved_original_iat = false;
}
if(rewrite_saved_iat)
save_iats_for_this_descriptor = false;
}
else
{
//We are creating new IAT and original IAT (if needed)
descr.OriginalFirstThunk = import_settings.build_original_iat() ? pe.rva_from_section_offset(import_section, current_pos_for_original_iat) : 0;
descr.FirstThunk = pe.rva_from_section_offset(import_section, current_pos_for_iat);
}
//Save import descriptor
memcpy(&raw_data[current_pos_for_descriptors], &descr, sizeof(descr));
current_pos_for_descriptors += sizeof(descr);
//Save library name
memcpy(&raw_data[current_string_pointer], (*it).get_name().c_str(), (*it).get_name().length() + 1 /* nullbyte */);
current_string_pointer += static_cast<uint32_t>((*it).get_name().length() + 1 /* nullbyte */);
//List all imported functions
const import_library::imported_list& funcs = (*it).get_imported_functions();
for(import_library::imported_list::const_iterator f = funcs.begin(); f != funcs.end(); ++f)
{
if((*f).has_name()) //If function is imported by name
{
//Get RVA of IMAGE_IMPORT_BY_NAME
typename PEClassType::BaseSize rva_of_named_import = pe.rva_from_section_offset(import_section, current_string_pointer);
if(!save_iats_for_this_descriptor)
{
if(write_original_iat)
{
//We're creating original IATs - so we can write to IAT saved VA (because IMAGE_IMPORT_BY_NAME will be read
//by PE loader from original IAT)
typename PEClassType::BaseSize iat_value = static_cast<typename PEClassType::BaseSize>((*f).get_iat_va());
if(rewrite_saved_iat)
{
if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(iat_value))
throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space);
memcpy(pe.section_data_from_rva(first_thunk, true), &iat_value, sizeof(iat_value));
first_thunk += sizeof(iat_value);
}
else
{
memcpy(&raw_data[current_pos_for_iat], &iat_value, sizeof(iat_value));
current_pos_for_iat += sizeof(rva_of_named_import);
}
}
else
{
//Else - write to IAT RVA of IMAGE_IMPORT_BY_NAME
if(rewrite_saved_iat)
{
if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(rva_of_named_import))
throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space);
memcpy(pe.section_data_from_rva(first_thunk, true), &rva_of_named_import, sizeof(rva_of_named_import));
first_thunk += sizeof(rva_of_named_import);
}
else
{
memcpy(&raw_data[current_pos_for_iat], &rva_of_named_import, sizeof(rva_of_named_import));
current_pos_for_iat += sizeof(rva_of_named_import);
}
}
}
if(write_original_iat)
{
if(rewrite_saved_original_iat)
{
if(pe.section_data_length_from_rva(original_first_thunk, original_first_thunk, section_data_raw, true) <= sizeof(rva_of_named_import))
throw pe_exception("Insufficient space inside initial original IAT", pe_exception::insufficient_space);
memcpy(pe.section_data_from_rva(original_first_thunk, true), &rva_of_named_import, sizeof(rva_of_named_import));
original_first_thunk += sizeof(rva_of_named_import);
}
else
{
//We're creating original IATs
memcpy(&raw_data[current_pos_for_original_iat], &rva_of_named_import, sizeof(rva_of_named_import));
current_pos_for_original_iat += sizeof(rva_of_named_import);
}
}
//Write IMAGE_IMPORT_BY_NAME (WORD hint + string function name)
uint16_t hint = (*f).get_hint();
memcpy(&raw_data[current_string_pointer], &hint, sizeof(hint));
memcpy(&raw_data[current_string_pointer + sizeof(uint16_t)], (*f).get_name().c_str(), (*f).get_name().length() + 1 /* nullbyte */);
current_string_pointer += static_cast<uint32_t>((*f).get_name().length() + 1 /* nullbyte */ + sizeof(uint16_t) /* hint */);
}
else //Function is imported by ordinal
{
uint16_t ordinal = (*f).get_ordinal();
typename PEClassType::BaseSize thunk_value = ordinal;
thunk_value |= PEClassType::ImportSnapFlag; //Imported by ordinal
if(!save_iats_for_this_descriptor)
{
if(write_original_iat)
{
//We're creating original IATs - so we can wtire to IAT saved VA (because ordinal will be read
//by PE loader from original IAT)
typename PEClassType::BaseSize iat_value = static_cast<typename PEClassType::BaseSize>((*f).get_iat_va());
if(rewrite_saved_iat)
{
if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(iat_value))
throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space);
memcpy(pe.section_data_from_rva(first_thunk, true), &iat_value, sizeof(iat_value));
first_thunk += sizeof(iat_value);
}
else
{
memcpy(&raw_data[current_pos_for_iat], &iat_value, sizeof(iat_value));
current_pos_for_iat += sizeof(thunk_value);
}
}
else
{
//Else - write ordinal to IAT
if(rewrite_saved_iat)
{
if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(thunk_value))
throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space);
memcpy(pe.section_data_from_rva(first_thunk, true), &thunk_value, sizeof(thunk_value));
first_thunk += sizeof(thunk_value);
}
else
{
memcpy(&raw_data[current_pos_for_iat], &thunk_value, sizeof(thunk_value));
}
}
}
//We're writing ordinal to original IAT slot
if(write_original_iat)
{
if(rewrite_saved_original_iat)
{
if(pe.section_data_length_from_rva(original_first_thunk, original_first_thunk, section_data_raw, true) <= sizeof(thunk_value))
throw pe_exception("Insufficient space inside initial original IAT", pe_exception::insufficient_space);
memcpy(pe.section_data_from_rva(original_first_thunk, true), &thunk_value, sizeof(thunk_value));
original_first_thunk += sizeof(thunk_value);
}
else
{
memcpy(&raw_data[current_pos_for_original_iat], &thunk_value, sizeof(thunk_value));
current_pos_for_original_iat += sizeof(thunk_value);
}
}
}
}
if(!save_iats_for_this_descriptor)
{
//Ending null thunks
typename PEClassType::BaseSize thunk_value = 0;
if(rewrite_saved_iat)
{
if(pe.section_data_length_from_rva(first_thunk, first_thunk, section_data_raw, true) <= sizeof(thunk_value))
throw pe_exception("Insufficient space inside initial IAT", pe_exception::insufficient_space);
memcpy(pe.section_data_from_rva(first_thunk, true), &thunk_value, sizeof(thunk_value));
first_thunk += sizeof(thunk_value);
}
else
{
memcpy(&raw_data[current_pos_for_iat], &thunk_value, sizeof(thunk_value));
current_pos_for_iat += sizeof(thunk_value);
}
}
if(write_original_iat)
{
//Ending null thunks
typename PEClassType::BaseSize thunk_value = 0;
if(rewrite_saved_original_iat)
{
if(pe.section_data_length_from_rva(original_first_thunk, original_first_thunk, section_data_raw, true) <= sizeof(thunk_value))
throw pe_exception("Insufficient space inside initial original IAT", pe_exception::insufficient_space);
memcpy(pe.section_data_from_rva(original_first_thunk, true), &thunk_value, sizeof(thunk_value));
original_first_thunk += sizeof(thunk_value);
}
else
{
memcpy(&raw_data[current_pos_for_original_iat], &thunk_value, sizeof(thunk_value));
current_pos_for_original_iat += sizeof(thunk_value);
}
}
}
{
//Null ending descriptor
image_import_descriptor descr;
memset(&descr, 0, sizeof(descr));
memcpy(&raw_data[current_pos_for_descriptors], &descr, sizeof(descr));
}
//Strip data a little, if we saved some place
//We're allocating more space than needed, if present original IAT and IAT are saved
raw_data.resize(current_pos_for_original_iat);
//Adjust section raw and virtual sizes
pe.recalculate_section_sizes(import_section, import_settings.auto_strip_last_section_enabled());
//Return information about rebuilt import directory
image_directory ret(pe.rva_from_section_offset(import_section, import_settings.get_offset_from_section_start() + needed_size_for_strings), needed_size - needed_size_for_strings);
//If auto-rewrite of PE headers is required
if(import_settings.auto_set_to_pe_headers())
{
pe.set_directory_rva(image_directory_entry_import, ret.get_rva());
pe.set_directory_size(image_directory_entry_import, ret.get_size());
//If we are requested to zero IMAGE_DIRECTORY_ENTRY_IAT also
if(import_settings.zero_directory_entry_iat())
{
pe.set_directory_rva(image_directory_entry_iat, 0);
pe.set_directory_size(image_directory_entry_iat, 0);
}
}
return ret;
}
}