From 293f738ffa2421685ce37a29cb0f944d06295625 Mon Sep 17 00:00:00 2001
From: rukaimi <rukaimi@985867f9-ca9c-e1f6-822d-e8a4186388af>
Date: Thu, 27 Sep 2012 20:42:12 +0000
Subject: [PATCH] 1. Added image load config directory rebuilder 2. Fixed
 export directory reader and rebuilder to work correctly with empty export
 directories 3. Added config directory Lock Prefix Table reader 4. Added new
 sample (image load config directory rebuilder) 5. Other minor bugfixes

---
 pe_lib/pe_32_64.cpp                           | 169 ++++++++-
 pe_lib/pe_32_64.h                             |   6 +
 pe_lib/pe_base.cpp                            | 153 +++++++-
 pe_lib/pe_base.h                              |  67 +++-
 pe_lib/pe_exception.h                         |   4 +-
 pe_lib_vc10.sln                               |  14 +
 pe_lib_vc9.sln                                |  14 +
 .../image_config_editor.vcproj                | 351 ++++++++++++++++++
 .../image_config_editor.vcxproj               | 154 ++++++++
 .../image_config_editor.vcxproj.filters       |  27 ++
 samples/image_config_editor/main.cpp          |  78 ++++
 11 files changed, 1027 insertions(+), 10 deletions(-)
 create mode 100644 samples/image_config_editor/image_config_editor.vcproj
 create mode 100644 samples/image_config_editor/image_config_editor.vcxproj
 create mode 100644 samples/image_config_editor/image_config_editor.vcxproj.filters
 create mode 100644 samples/image_config_editor/main.cpp

diff --git a/pe_lib/pe_32_64.cpp b/pe_lib/pe_32_64.cpp
index ed04f53..f74b753 100644
--- a/pe_lib/pe_32_64.cpp
+++ b/pe_lib/pe_32_64.cpp
@@ -1207,7 +1207,7 @@ const pe_base::image_config_info pe<PEClassType>::get_image_config() const
 
 	//Check size of config directory
 	if(config_info.Size != sizeof(config_info))
-		throw pe_exception("Incorrect load config directory", pe_exception::incorrect_config_directory);
+		throw pe_exception("Incorrect (or old) load config directory", pe_exception::incorrect_config_directory);
 
 	//Fill return structure
 	image_config_info ret(config_info);
@@ -1217,10 +1217,175 @@ const pe_base::image_config_info pe<PEClassType>::get_image_config() const
 		|| config_info.SEHandlerTable >= static_cast<typename PEClassType::BaseSize>(-1) - config_info.SEHandlerCount * sizeof(DWORD))
 		throw pe_exception("Incorrect load config directory", pe_exception::incorrect_config_directory);
 
-	//Read SE handler RVA list (if any)
+	//Read sorted SE handler RVA list (if any)
 	for(typename PEClassType::BaseSize i = 0; i != config_info.SEHandlerCount; ++i)
 		ret.add_se_handler_rva(section_data_from_va<DWORD>(config_info.SEHandlerTable + i * sizeof(DWORD)));
 
+	if(config_info.LockPrefixTable)
+	{
+		//Read Lock Prefix VA list (if any)
+		unsigned long current = 0;
+		while(true)
+		{
+			typename PEClassType::BaseSize lock_prefix_va = section_data_from_va<typename PEClassType::BaseSize>(config_info.LockPrefixTable + current * sizeof(typename PEClassType::BaseSize));
+			if(!lock_prefix_va)
+				break;
+
+			ret.add_lock_prefix_rva(va_to_rva(lock_prefix_va));
+
+			++current;
+		}
+	}
+
+	return ret;
+}
+
+//Image config directory rebuilder
+//auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped
+//If write_se_handlers = true, SE Handlers list will be written just after image config directory structure
+//If write_lock_prefixes = true, Lock Prefixes address list will be written just after image config directory structure
+template<typename PEClassType>
+const pe_base::image_directory pe<PEClassType>::rebuild_image_config(const image_config_info& info, section& image_config_section, DWORD 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(!section_attached(image_config_section))
+		throw pe_exception("Image Config section must be attached to PE file", pe_exception::section_is_not_attached);
+	
+	DWORD alignment = align_up(offset_from_section_start, sizeof(typename PEClassType::BaseSize)) - offset_from_section_start;
+
+	DWORD needed_size = sizeof(typename PEClassType::ConfigStruct) + alignment; //Calculate needed size for Image Config table
+
+	DWORD current_pos_of_se_handlers = 0;
+	DWORD current_pos_of_lock_prefixes = 0;
+	
+	if(write_se_handlers)
+	{
+		current_pos_of_se_handlers = needed_size + offset_from_section_start;
+		needed_size += static_cast<DWORD>(info.get_se_handler_rvas().size()) * sizeof(DWORD); //RVAs of SE Handlers
+	}
+	
+	if(write_lock_prefixes)
+	{
+		current_pos_of_lock_prefixes = needed_size + offset_from_section_start;
+		needed_size += static_cast<DWORD>((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 != &*(sections_.end() - 1) && 
+		(image_config_section.empty() || align_up(image_config_section.get_size_of_raw_data(), get_file_alignment()) < needed_size + offset_from_section_start))
+		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 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
+
+	DWORD image_config_data_pos = offset_from_section_start + alignment;
+
+	//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
+		{
+			rva_to_va(rva_from_section_offset(image_config_section, current_pos_of_se_handlers), image_config_section_struct.SEHandlerTable);
+		}
+	}
+	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
+		{
+			rva_to_va(rva_from_section_offset(image_config_section, current_pos_of_lock_prefixes), image_config_section_struct.LockPrefixTable);
+		}
+	}
+	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)
+		{
+			DWORD 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;
+			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
+	recalculate_section_sizes(image_config_section, auto_strip_last_section);
+
+	image_directory ret(rva_from_section_offset(image_config_section, image_config_data_pos), sizeof(PEClassType::ConfigStruct));
+
+	//If auto-rewrite of PE headers is required
+	if(save_to_pe_header)
+	{
+		set_directory_rva(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, ret.get_rva());
+		set_directory_size(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, ret.get_size());
+	}
+
 	return ret;
 }
 
diff --git a/pe_lib/pe_32_64.h b/pe_lib/pe_32_64.h
index 782bcfa..f548775 100644
--- a/pe_lib/pe_32_64.h
+++ b/pe_lib/pe_32_64.h
@@ -199,6 +199,12 @@ public: //IMAGE CONFIG
 	//Returns image config info
 	//If image does not have config info, throws an exception
 	virtual const image_config_info get_image_config() const;
+	
+	//Image config directory rebuilder
+	//auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped
+	//If write_se_handlers = true, SE Handlers list will be written just after image config directory structure
+	//If write_lock_prefixes = true, Lock Prefixes address list will be written just after image config directory structure
+	virtual const image_directory rebuild_image_config(const image_config_info& info, section& image_config_section, DWORD offset_from_section_start = 0, bool write_se_handlers = true, bool write_lock_prefixes = true, bool save_to_pe_header = true, bool auto_strip_last_section = true);
 
 public: //RELOCATIONS
 	//Recalculates image base with the help of relocation tables
diff --git a/pe_lib/pe_base.cpp b/pe_lib/pe_base.cpp
index 619f4b6..4bc41c5 100644
--- a/pe_lib/pe_base.cpp
+++ b/pe_lib/pe_base.cpp
@@ -452,6 +452,9 @@ void pe_base::prepare_section(section& s)
 //Adds section to image
 pe_base::section& pe_base::add_section(section s)
 {
+	if(sections_.size() >= maximum_number_of_sections)
+		throw pe_exception("Maximum number of sections has been reached", pe_exception::no_more_sections_can_be_added);
+
 	//Prepare section before adding it
 	prepare_section(s);
 
@@ -476,7 +479,7 @@ pe_base::section& pe_base::add_section(section s)
 	//Add section to the end of section list
 	sections_.push_back(s);
 	//Set number of sections in PE header
-	set_number_of_sections(sections_.size());
+	set_number_of_sections(static_cast<WORD>(sections_.size()));
 	//Recalculate virtual size of image
 	set_size_of_image(get_size_of_image() + s.virtual_size_aligned_);
 	//Return last section
@@ -1871,8 +1874,11 @@ const std::vector<pe_base::exported_function> pe_base::get_exported_functions(ex
 			info->set_timestamp(exports.TimeDateStamp);
 		}
 
+		if(!exports.NumberOfFunctions)
+			return ret;
+
 		//Check IMAGE_EXPORT_DIRECTORY fields
-		if(!exports.NumberOfFunctions || exports.NumberOfNames > exports.NumberOfFunctions)
+		if(exports.NumberOfNames > exports.NumberOfFunctions)
 			throw pe_exception("Incorrect export directory", pe_exception::incorrect_export_directory);
 
 		//Check some export directory fields
@@ -2044,10 +2050,6 @@ const pe_base::image_directory pe_base::rebuild_exports(const export_info& info,
 	//Check that exports_section is attached to this PE image
 	if(!section_attached(exports_section))
 		throw pe_exception("Exports section must be attached to PE file", pe_exception::section_is_not_attached);
-	
-	//Check if we're exporting something
-	if(exports.empty())
-		throw pe_exception("Exports list is empty", pe_exception::exports_list_is_empty);
 
 	//Needed space for strings
 	DWORD needed_size_for_strings = static_cast<DWORD>(info.get_name().length() + 1);
@@ -2055,6 +2057,9 @@ const pe_base::image_directory pe_base::rebuild_exports(const export_info& info,
 	DWORD max_ordinal = 0; //Maximum ordinal number
 	DWORD ordinal_base = static_cast<DWORD>(-1); //Minimum ordinal value
 	
+	if(exports.empty())
+		ordinal_base = info.get_ordinal_base();
+
 	DWORD needed_size_for_function_names = 0; //Needed space for function name strings
 	DWORD needed_size_for_function_forwards = 0; //Needed space for function forwards names
 	
@@ -3007,6 +3012,12 @@ const pe_base::image_config_info::se_handler_list& pe_base::image_config_info::g
 	return se_handlers_;
 }
 
+//Returns Lock Prefix RVA list
+const pe_base::image_config_info::lock_prefix_rva_list& pe_base::image_config_info::get_lock_prefix_rvas() const
+{
+	return lock_prefixes_;
+}
+
 //Adds SE Handler RVA to list
 void pe_base::image_config_info::add_se_handler_rva(DWORD rva)
 {
@@ -3019,6 +3030,136 @@ void pe_base::image_config_info::clear_se_handler_list()
 	se_handlers_.clear();
 }
 
+//Adds Lock Prefix RVA to list
+void pe_base::image_config_info::add_lock_prefix_rva(DWORD rva)
+{
+	lock_prefixes_.push_back(rva);
+}
+
+//Clears Lock Prefix list
+void pe_base::image_config_info::clear_lock_prefix_list()
+{
+	lock_prefixes_.clear();
+}
+
+//Sets the date and time stamp value
+void pe_base::image_config_info::set_time_stamp(DWORD time_stamp)
+{
+	time_stamp_ = time_stamp;
+}
+
+//Sets major version number
+void pe_base::image_config_info::set_major_version(WORD major_version)
+{
+	major_version_ = major_version;
+}
+
+//Sets minor version number
+void pe_base::image_config_info::set_minor_version(WORD minor_version)
+{
+	minor_version_ = minor_version;
+}
+
+//Sets clear global flags
+void pe_base::image_config_info::set_global_flags_clear(DWORD global_flags_clear)
+{
+	global_flags_clear_ = global_flags_clear;
+}
+
+//Sets set global flags
+void pe_base::image_config_info::set_global_flags_set(DWORD global_flags_set)
+{
+	global_flags_set_ = global_flags_set;
+}
+
+//Sets critical section default timeout
+void pe_base::image_config_info::set_critical_section_default_timeout(DWORD critical_section_default_timeout)
+{
+	critical_section_default_timeout_ = critical_section_default_timeout;
+}
+
+//Sets the size of the minimum block that
+//must be freed before it is freed (de-committed), in bytes
+void pe_base::image_config_info::set_decommit_free_block_threshold(ULONGLONG decommit_free_block_threshold)
+{
+	decommit_free_block_threshold_ = decommit_free_block_threshold;
+}
+
+//Sets the size of the minimum total memory
+//that must be freed in the process heap before it is freed (de-committed), in bytes
+void pe_base::image_config_info::set_decommit_total_free_threshold(ULONGLONG decommit_total_free_threshold)
+{
+	decommit_total_free_threshold_ = decommit_total_free_threshold;
+}
+
+//Sets VA of a list of addresses where the LOCK prefix is used
+//If you rebuild this list, VA will be re-assigned automatically
+void pe_base::image_config_info::set_lock_prefix_table_va(ULONGLONG lock_prefix_table_va)
+{
+	lock_prefix_table_va_ = lock_prefix_table_va;
+}
+
+//Sets the maximum allocation size, in bytes
+void pe_base::image_config_info::set_max_allocation_size(ULONGLONG max_allocation_size)
+{
+	max_allocation_size_ = max_allocation_size;
+}
+
+//Sets the maximum block size that can be allocated from heap segments, in bytes
+void pe_base::image_config_info::set_virtual_memory_threshold(ULONGLONG virtual_memory_threshold)
+{
+	virtual_memory_threshold_ = virtual_memory_threshold;
+}
+
+//Sets process affinity mask
+void pe_base::image_config_info::set_process_affinity_mask(ULONGLONG process_affinity_mask)
+{
+	process_affinity_mask_ = process_affinity_mask;
+}
+
+//Sets process heap flags
+void pe_base::image_config_info::set_process_heap_flags(DWORD process_heap_flags)
+{
+	process_heap_flags_ = process_heap_flags;
+}
+
+//Sets service pack version (CSDVersion)
+void pe_base::image_config_info::set_service_pack_version(WORD service_pack_version)
+{
+	service_pack_version_ = service_pack_version;
+}
+
+//Sets VA of edit list (reserved by system)
+void pe_base::image_config_info::set_edit_list_va(ULONGLONG edit_list_va)
+{
+	edit_list_va_ = edit_list_va;
+}
+
+//Sets a pointer to a cookie that is used by Visual C++ or GS implementation
+void pe_base::image_config_info::set_security_cookie_va(ULONGLONG security_cookie_va)
+{
+	security_cookie_va_ = security_cookie_va;
+}
+
+//Sets VA of the sorted table of RVAs of each valid, unique handler in the image
+//If you rebuild this list, VA will be re-assigned automatically
+void pe_base::image_config_info::set_se_handler_table_va(ULONGLONG se_handler_table_va)
+{
+	se_handler_table_va_ = se_handler_table_va;
+}
+
+//Returns SE Handler RVA list
+pe_base::image_config_info::se_handler_list& pe_base::image_config_info::get_se_handler_rvas()
+{
+	return se_handlers_;
+}
+
+//Returns Lock Prefix RVA list
+pe_base::image_config_info::lock_prefix_rva_list& pe_base::image_config_info::get_lock_prefix_rvas()
+{
+	return lock_prefixes_;
+}
+
 //BOUND IMPORT
 //Default constructor
 pe_base::bound_import_ref::bound_import_ref()
diff --git a/pe_lib/pe_base.h b/pe_lib/pe_base.h
index 3e9baa1..047d138 100644
--- a/pe_lib/pe_base.h
+++ b/pe_lib/pe_base.h
@@ -12,12 +12,13 @@
 
 //Please don't remove this information from header
 //PE Library (c) DX 2011 - 2012, http://kaimi.ru
-//Version: 0.1.7
+//Version: 0.1.8
 //Free to use, modify and distribute
 
 // == more important ==
 //TODO: relocations that take more than one element (seems to be not possible in Windows PE, but anyway)
 //TODO: create sample-based tests
+//TODO: create PE/PE+ image (without PE-file)
 //== less important ==
 //TODO: delay import directory
 //TODO: write message tables
@@ -1090,6 +1091,7 @@ public: //IMAGE CONFIG
 	{
 	public:
 		typedef std::vector<DWORD> se_handler_list;
+		typedef std::vector<DWORD> lock_prefix_rva_list;
 
 	public:
 		//Default constructor
@@ -1139,12 +1141,67 @@ public: //IMAGE CONFIG
 
 		//Returns SE Handler RVA list
 		const se_handler_list& get_se_handler_rvas() const;
+		
+		//Returns Lock Prefix RVA list
+		const lock_prefix_rva_list& get_lock_prefix_rvas() const;
 
 	public: //These functions do not change everything inside image, they are used by PE class
+		//Also you can use these functions to rebuild image config directory
+
 		//Adds SE Handler RVA to list
 		void add_se_handler_rva(DWORD rva);
 		//Clears SE Handler list
 		void clear_se_handler_list();
+		
+		//Adds Lock Prefix RVA to list
+		void add_lock_prefix_rva(DWORD rva);
+		//Clears Lock Prefix list
+		void clear_lock_prefix_list();
+		
+		//Sets the date and time stamp value
+		void set_time_stamp(DWORD time_stamp);
+		//Sets major version number
+		void set_major_version(WORD major_version);
+		//Sets minor version number
+		void set_minor_version(WORD minor_version);
+		//Sets clear global flags
+		void set_global_flags_clear(DWORD global_flags_clear);
+		//Sets set global flags
+		void set_global_flags_set(DWORD global_flags_set);
+		//Sets critical section default timeout
+		void set_critical_section_default_timeout(DWORD critical_section_default_timeout);
+		//Sets the size of the minimum block that
+		//must be freed before it is freed (de-committed), in bytes
+		void set_decommit_free_block_threshold(ULONGLONG decommit_free_block_threshold);
+		//Sets the size of the minimum total memory
+		//that must be freed in the process heap before it is freed (de-committed), in bytes
+		void set_decommit_total_free_threshold(ULONGLONG decommit_total_free_threshold);
+		//Sets VA of a list of addresses where the LOCK prefix is used
+		//If you rebuild this list, VA will be re-assigned automatically
+		void set_lock_prefix_table_va(ULONGLONG lock_prefix_table_va);
+		//Sets the maximum allocation size, in bytes
+		void set_max_allocation_size(ULONGLONG max_allocation_size);
+		//Sets the maximum block size that can be allocated from heap segments, in bytes
+		void set_virtual_memory_threshold(ULONGLONG virtual_memory_threshold);
+		//Sets process affinity mask
+		void set_process_affinity_mask(ULONGLONG process_affinity_mask);
+		//Sets process heap flags
+		void set_process_heap_flags(DWORD process_heap_flags);
+		//Sets service pack version (CSDVersion)
+		void set_service_pack_version(WORD service_pack_version);
+		//Sets VA of edit list (reserved by system)
+		void set_edit_list_va(ULONGLONG edit_list_va);
+		//Sets a pointer to a cookie that is used by Visual C++ or GS implementation
+		void set_security_cookie_va(ULONGLONG security_cookie_va);
+		//Sets VA of the sorted table of RVAs of each valid, unique handler in the image
+		//If you rebuild this list, VA will be re-assigned automatically
+		void set_se_handler_table_va(ULONGLONG se_handler_table_va);
+
+		//Returns SE Handler RVA list
+		se_handler_list& get_se_handler_rvas();
+
+		//Returns Lock Prefix RVA list
+		lock_prefix_rva_list& get_lock_prefix_rvas();
 
 	private:
 		DWORD time_stamp_;
@@ -1164,6 +1221,7 @@ public: //IMAGE CONFIG
 		ULONGLONG se_handler_count_;
 
 		se_handler_list se_handlers_;
+		lock_prefix_rva_list lock_prefixes_;
 	};
 
 	//Returns image config info
@@ -1171,6 +1229,13 @@ public: //IMAGE CONFIG
 	virtual const image_config_info get_image_config() const = 0;
 
 
+	//Image config directory rebuilder
+	//auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped
+	//If write_se_handlers = true, SE Handlers list will be written just after image config directory structure
+	//If write_lock_prefixes = true, Lock Prefixes address list will be written just after image config directory structure
+	virtual const image_directory rebuild_image_config(const image_config_info& info, section& image_config_section, DWORD offset_from_section_start = 0, bool write_se_handlers = true, bool write_lock_prefixes = true, bool save_to_pe_header = true, bool auto_strip_last_section = true) = 0;
+
+
 public: //BOUND IMPORT
 	//Structure representing bound import reference
 	struct bound_import_ref
diff --git a/pe_lib/pe_exception.h b/pe_lib/pe_exception.h
index 7b05071..9d6587e 100644
--- a/pe_lib/pe_exception.h
+++ b/pe_lib/pe_exception.h
@@ -76,7 +76,9 @@ public:
 		duplicate_exported_function_name,
 		duplicate_exported_function_name_ordinal,
 
-		version_info_string_does_not_exist
+		version_info_string_does_not_exist,
+
+		no_more_sections_can_be_added
 	};
 
 public:
diff --git a/pe_lib_vc10.sln b/pe_lib_vc10.sln
index 23cfe04..b8be2d7 100644
--- a/pe_lib_vc10.sln
+++ b/pe_lib_vc10.sln
@@ -134,6 +134,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "resource_editor", "samples\
 		{1461F543-D1FA-4E4C-B6D7-0F879F566035} = {1461F543-D1FA-4E4C-B6D7-0F879F566035}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "image_config_editor", "samples\image_config_editor\image_config_editor.vcxproj", "{48B99169-44E6-41E5-A681-78243B885E86}"
+	ProjectSection(ProjectDependencies) = postProject
+		{1461F543-D1FA-4E4C-B6D7-0F879F566035} = {1461F543-D1FA-4E4C-B6D7-0F879F566035}
+	EndProjectSection
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -350,6 +355,14 @@ Global
 		{B88455A6-C93A-4F17-93A5-FC84B70F9CFE}.Release|Win32.Build.0 = Release|Win32
 		{B88455A6-C93A-4F17-93A5-FC84B70F9CFE}.Release|x64.ActiveCfg = Release|x64
 		{B88455A6-C93A-4F17-93A5-FC84B70F9CFE}.Release|x64.Build.0 = Release|x64
+		{48B99169-44E6-41E5-A681-78243B885E86}.Debug|Win32.ActiveCfg = Debug|Win32
+		{48B99169-44E6-41E5-A681-78243B885E86}.Debug|Win32.Build.0 = Debug|Win32
+		{48B99169-44E6-41E5-A681-78243B885E86}.Debug|x64.ActiveCfg = Debug|x64
+		{48B99169-44E6-41E5-A681-78243B885E86}.Debug|x64.Build.0 = Debug|x64
+		{48B99169-44E6-41E5-A681-78243B885E86}.Release|Win32.ActiveCfg = Release|Win32
+		{48B99169-44E6-41E5-A681-78243B885E86}.Release|Win32.Build.0 = Release|Win32
+		{48B99169-44E6-41E5-A681-78243B885E86}.Release|x64.ActiveCfg = Release|x64
+		{48B99169-44E6-41E5-A681-78243B885E86}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -381,5 +394,6 @@ Global
 		{7375047B-90D7-4564-BA84-7E5C638C7CCE} = {53A03406-AEFB-4ABA-8DD1-5AE9B8DFB036}
 		{ABA9C7BF-D145-4066-8E0D-41C190BB5C0A} = {53A03406-AEFB-4ABA-8DD1-5AE9B8DFB036}
 		{B88455A6-C93A-4F17-93A5-FC84B70F9CFE} = {53A03406-AEFB-4ABA-8DD1-5AE9B8DFB036}
+		{48B99169-44E6-41E5-A681-78243B885E86} = {53A03406-AEFB-4ABA-8DD1-5AE9B8DFB036}
 	EndGlobalSection
 EndGlobal
diff --git a/pe_lib_vc9.sln b/pe_lib_vc9.sln
index e012e3d..334f53d 100644
--- a/pe_lib_vc9.sln
+++ b/pe_lib_vc9.sln
@@ -134,6 +134,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tls_reader", "samples\tls_r
 		{4B658F8F-1722-4EEA-880C-A4A64DCA9F2C} = {4B658F8F-1722-4EEA-880C-A4A64DCA9F2C}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "image_config_editor", "samples\image_config_editor\image_config_editor.vcproj", "{22788F46-AB6B-4278-B1C0-ED220AE85F4A}"
+	ProjectSection(ProjectDependencies) = postProject
+		{4B658F8F-1722-4EEA-880C-A4A64DCA9F2C} = {4B658F8F-1722-4EEA-880C-A4A64DCA9F2C}
+	EndProjectSection
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -350,6 +355,14 @@ Global
 		{BA36739B-F101-4C91-928D-678AB9521A22}.Release|Win32.Build.0 = Release|Win32
 		{BA36739B-F101-4C91-928D-678AB9521A22}.Release|x64.ActiveCfg = Release|x64
 		{BA36739B-F101-4C91-928D-678AB9521A22}.Release|x64.Build.0 = Release|x64
+		{22788F46-AB6B-4278-B1C0-ED220AE85F4A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{22788F46-AB6B-4278-B1C0-ED220AE85F4A}.Debug|Win32.Build.0 = Debug|Win32
+		{22788F46-AB6B-4278-B1C0-ED220AE85F4A}.Debug|x64.ActiveCfg = Debug|x64
+		{22788F46-AB6B-4278-B1C0-ED220AE85F4A}.Debug|x64.Build.0 = Debug|x64
+		{22788F46-AB6B-4278-B1C0-ED220AE85F4A}.Release|Win32.ActiveCfg = Release|Win32
+		{22788F46-AB6B-4278-B1C0-ED220AE85F4A}.Release|Win32.Build.0 = Release|Win32
+		{22788F46-AB6B-4278-B1C0-ED220AE85F4A}.Release|x64.ActiveCfg = Release|x64
+		{22788F46-AB6B-4278-B1C0-ED220AE85F4A}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -381,5 +394,6 @@ Global
 		{B0D287DB-451D-4005-9CE3-185D7602F0B7} = {0CF51D6D-1F80-4D2C-95BE-566641BD1F71}
 		{C3B58F69-FA5D-4E9E-8E21-F6C5EBAC22ED} = {0CF51D6D-1F80-4D2C-95BE-566641BD1F71}
 		{781B56DF-15CE-4CBA-A008-0403029E558A} = {0CF51D6D-1F80-4D2C-95BE-566641BD1F71}
+		{22788F46-AB6B-4278-B1C0-ED220AE85F4A} = {0CF51D6D-1F80-4D2C-95BE-566641BD1F71}
 	EndGlobalSection
 EndGlobal
diff --git a/samples/image_config_editor/image_config_editor.vcproj b/samples/image_config_editor/image_config_editor.vcproj
new file mode 100644
index 0000000..398fd64
--- /dev/null
+++ b/samples/image_config_editor/image_config_editor.vcproj
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9,00"
+	Name="image_config_editor"
+	ProjectGUID="{22788F46-AB6B-4278-B1C0-ED220AE85F4A}"
+	RootNamespace="image_config_editor"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../pe_lib/;../"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="../../pe_lib/;../"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../pe_lib/;../"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="../../pe_lib/;../"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\main.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\lib.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/samples/image_config_editor/image_config_editor.vcxproj b/samples/image_config_editor/image_config_editor.vcxproj
new file mode 100644
index 0000000..fb83c0c
--- /dev/null
+++ b/samples/image_config_editor/image_config_editor.vcxproj
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{48B99169-44E6-41E5-A681-78243B885E86}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>image_config_editor</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>../../pe_lib/;../</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>../../pe_lib/;../</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>../../pe_lib/;../</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>../../pe_lib/;../</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="main.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\lib.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/samples/image_config_editor/image_config_editor.vcxproj.filters b/samples/image_config_editor/image_config_editor.vcxproj.filters
new file mode 100644
index 0000000..ef90d25
--- /dev/null
+++ b/samples/image_config_editor/image_config_editor.vcxproj.filters
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="main.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\lib.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/samples/image_config_editor/main.cpp b/samples/image_config_editor/main.cpp
new file mode 100644
index 0000000..a2c19c8
--- /dev/null
+++ b/samples/image_config_editor/main.cpp
@@ -0,0 +1,78 @@
+#include <iostream>
+#include <fstream>
+#include <pe_factory.h>
+#include "lib.h"
+
+//Пример, показывающий, как пересобрать директорию Load Config у PE-файла
+int main(int argc, char* argv[])
+{
+	if(argc != 2)
+	{
+		std::cout << "Usage: image_config_editor.exe PE_FILE" << std::endl;
+		return 0;
+	}
+
+	//Открываем файл
+	std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary);
+	if(!pe_file)
+	{
+		std::cout << "Cannot open " << argv[1] << std::endl;
+		return -1;
+	}
+
+	try
+	{
+		//Создаем экземпляр PE или PE+ класса с помощью фабрики
+		std::auto_ptr<pe_base> image = pe_factory::create_pe(pe_file);
+
+		//Получим информацию о директории Load Config
+		pe_base::image_config_info info = image->get_image_config();
+
+		//Но пересоберем эту директорию, расположив ее в новой секции
+		pe_base::section load_config;
+		load_config.get_raw_data().resize(1); //Мы не можем добавлять пустые секции, поэтому пусть у нее будет начальный размер данных 1
+		load_config.set_name("load_cfg"); //Имя секции
+		load_config.readable(true).writeable(true); //Доступна на чтение и запись
+		pe_base::section& attached_section = image->add_section(load_config); //Добавим секцию и получим ссылку на добавленную секцию с просчитанными размерами
+
+		//Если у файла была таблица SE Handler'ов
+		if(info.get_se_handler_table_va())
+			info.add_se_handler_rva(0x7777); //Добавим новый SE Handler в таблицу (просто для теста)
+
+		//Если у файла не существовало таблицы Lock-префиксов, добавим ее
+		//(также для теста)
+		if(!info.get_lock_prefix_table_va())
+			info.add_lock_prefix_rva(0x9999);
+
+		//Пересобираем директорию Image Load Config, пересобираем таблицу Lock-префиксов, если она имелась, а также
+		//таблицу SE Handler'ов, если она есть
+		image->rebuild_image_config(info, attached_section, 1);
+
+		//Создаем новый PE-файл
+		std::string base_file_name(argv[1]);
+		std::string::size_type slash_pos;
+		if((slash_pos = base_file_name.find_last_of("/\\")) != std::string::npos)
+			base_file_name = base_file_name.substr(slash_pos + 1);
+
+		base_file_name = "new_" + base_file_name;
+		std::ofstream new_pe_file(base_file_name.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
+		if(!new_pe_file)
+		{
+			std::cout << "Cannot create " << base_file_name << std::endl;
+			return -1;
+		}
+
+		//Пересобираем PE-файл
+		image->rebuild_pe(new_pe_file);
+
+		std::cout << "PE was rebuilt and saved to " << base_file_name << std::endl;
+	}
+	catch(const pe_exception& e)
+	{
+		//Если возникла ошибка
+		std::cout << "Error: " << e.what() << std::endl;
+		return -1;
+	}
+
+	return 0;
+}
-- 
GitLab