void check_load_config(const image_config_info& info) { PE_TEST(info.get_security_cookie_va() == 0x41E7F4, "Load Config Values test 1", test_level_normal); PE_TEST(info.get_se_handler_count() == 0x20, "Load Config Values test 2", test_level_critical); PE_TEST(info.get_time_stamp() == 0, "Load Config Values test 3", test_level_normal); PE_TEST(info.get_se_handler_rvas()[1] == 0x731a, "Load Config Values test 4", test_level_normal); }
const image_directory rebuild_image_config_base(pe_base& pe, const image_config_info& info, section& image_config_section, uint32_t offset_from_section_start, bool write_se_handlers, bool write_lock_prefixes, bool save_to_pe_header, bool auto_strip_last_section) { //Check that image_config_section is attached to this PE image if(!pe.section_attached(image_config_section)) throw pe_exception("Image Config section must be attached to PE file", pe_exception::section_is_not_attached); uint32_t alignment = pe_utils::align_up(offset_from_section_start, sizeof(typename PEClassType::BaseSize)) - offset_from_section_start; uint32_t needed_size = sizeof(typename PEClassType::ConfigStruct); //Calculate needed size for Image Config table uint32_t image_config_data_pos = offset_from_section_start + alignment; uint32_t current_pos_of_se_handlers = 0; uint32_t current_pos_of_lock_prefixes = 0; if(write_se_handlers) { current_pos_of_se_handlers = needed_size + image_config_data_pos; needed_size += static_cast<uint32_t>(info.get_se_handler_rvas().size()) * sizeof(uint32_t); //RVAs of SE Handlers } if(write_lock_prefixes) { current_pos_of_lock_prefixes = needed_size + image_config_data_pos; needed_size += static_cast<uint32_t>((info.get_lock_prefix_rvas().size() + 1) * sizeof(typename PEClassType::BaseSize)); //VAs of Lock Prefixes (and ending null element) } //Check if image_config_section is last one. If it's not, check if there's enough place for Image Config data if(&image_config_section != &*(pe.get_image_sections().end() - 1) && (image_config_section.empty() || pe_utils::align_up(image_config_section.get_size_of_raw_data(), pe.get_file_alignment()) < needed_size + image_config_data_pos)) throw pe_exception("Insufficient space for TLS directory", pe_exception::insufficient_space); std::string& raw_data = image_config_section.get_raw_data(); //This will be done only if image_config_section is the last section of image or for section with unaligned raw length of data if(raw_data.length() < needed_size + image_config_data_pos) raw_data.resize(needed_size + image_config_data_pos); //Expand section raw data //Create and fill Image Config structure typename PEClassType::ConfigStruct image_config_section_struct = {0}; image_config_section_struct.Size = sizeof(image_config_section_struct); image_config_section_struct.TimeDateStamp = info.get_time_stamp(); image_config_section_struct.MajorVersion = info.get_major_version(); image_config_section_struct.MinorVersion = info.get_minor_version(); image_config_section_struct.GlobalFlagsClear = info.get_global_flags_clear(); image_config_section_struct.GlobalFlagsSet = info.get_global_flags_set(); image_config_section_struct.CriticalSectionDefaultTimeout = info.get_critical_section_default_timeout(); image_config_section_struct.DeCommitFreeBlockThreshold = static_cast<typename PEClassType::BaseSize>(info.get_decommit_free_block_threshold()); image_config_section_struct.DeCommitTotalFreeThreshold = static_cast<typename PEClassType::BaseSize>(info.get_decommit_total_free_threshold()); image_config_section_struct.MaximumAllocationSize = static_cast<typename PEClassType::BaseSize>(info.get_max_allocation_size()); image_config_section_struct.VirtualMemoryThreshold = static_cast<typename PEClassType::BaseSize>(info.get_virtual_memory_threshold()); image_config_section_struct.ProcessHeapFlags = info.get_process_heap_flags(); image_config_section_struct.ProcessAffinityMask = static_cast<typename PEClassType::BaseSize>(info.get_process_affinity_mask()); image_config_section_struct.CSDVersion = info.get_service_pack_version(); image_config_section_struct.EditList = static_cast<typename PEClassType::BaseSize>(info.get_edit_list_va()); image_config_section_struct.SecurityCookie = static_cast<typename PEClassType::BaseSize>(info.get_security_cookie_va()); image_config_section_struct.SEHandlerCount = static_cast<typename PEClassType::BaseSize>(info.get_se_handler_rvas().size()); if(write_se_handlers) { if(info.get_se_handler_rvas().empty()) { write_se_handlers = false; image_config_section_struct.SEHandlerTable = 0; } else { typename PEClassType::BaseSize va; pe.rva_to_va(pe.rva_from_section_offset(image_config_section, current_pos_of_se_handlers), va); image_config_section_struct.SEHandlerTable = va; } } else { image_config_section_struct.SEHandlerTable = static_cast<typename PEClassType::BaseSize>(info.get_se_handler_table_va()); } if(write_lock_prefixes) { if(info.get_lock_prefix_rvas().empty()) { write_lock_prefixes = false; image_config_section_struct.LockPrefixTable = 0; } else { typename PEClassType::BaseSize va; pe.rva_to_va(pe.rva_from_section_offset(image_config_section, current_pos_of_lock_prefixes), va); image_config_section_struct.LockPrefixTable = va; } } else { image_config_section_struct.LockPrefixTable = static_cast<typename PEClassType::BaseSize>(info.get_lock_prefix_table_va()); } //Write image config section memcpy(&raw_data[image_config_data_pos], &image_config_section_struct, sizeof(image_config_section_struct)); if(write_se_handlers) { //Sort SE Handlers list image_config_info::se_handler_list sorted_list = info.get_se_handler_rvas(); std::sort(sorted_list.begin(), sorted_list.end()); //Write SE Handlers table for(image_config_info::se_handler_list::const_iterator it = sorted_list.begin(); it != sorted_list.end(); ++it) { uint32_t se_handler_rva = *it; memcpy(&raw_data[current_pos_of_se_handlers], &se_handler_rva, sizeof(se_handler_rva)); current_pos_of_se_handlers += sizeof(se_handler_rva); } } if(write_lock_prefixes) { //Write Lock Prefixes VA list for(image_config_info::lock_prefix_rva_list::const_iterator it = info.get_lock_prefix_rvas().begin(); it != info.get_lock_prefix_rvas().end(); ++it) { typename PEClassType::BaseSize lock_prefix_va; pe.rva_to_va(*it, lock_prefix_va); memcpy(&raw_data[current_pos_of_lock_prefixes], &lock_prefix_va, sizeof(lock_prefix_va)); current_pos_of_lock_prefixes += sizeof(lock_prefix_va); } { //Ending null VA typename PEClassType::BaseSize lock_prefix_va = 0; memcpy(&raw_data[current_pos_of_lock_prefixes], &lock_prefix_va, sizeof(lock_prefix_va)); } } //Adjust section raw and virtual sizes pe.recalculate_section_sizes(image_config_section, auto_strip_last_section); image_directory ret(pe.rva_from_section_offset(image_config_section, image_config_data_pos), sizeof(typename PEClassType::ConfigStruct)); //If auto-rewrite of PE headers is required if(save_to_pe_header) { pe.set_directory_rva(image_directory_entry_load_config, ret.get_rva()); pe.set_directory_size(image_directory_entry_load_config, ret.get_size()); } return ret; }