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);
}
Ejemplo n.º 2
0
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;
}