/*************************************************************************/ /* Copyright (c) 2015 dx, http://kaimi.ru */ /* */ /* Permission is hereby granted, free of charge, to any person */ /* obtaining a copy of this software and associated documentation */ /* files (the "Software"), to deal in the Software without */ /* restriction, including without limitation the rights to use, */ /* copy, modify, merge, publish, distribute, sublicense, and/or */ /* sell copies of the Software, and to permit persons to whom the */ /* Software is furnished to do so, subject to the following conditions: */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include #include "pe_properties_generic.h" #include "pe_exception.h" #include "utils.h" namespace pe_bliss { using namespace pe_win; //Constructor template std::auto_ptr pe_properties_generic::duplicate() const { return std::auto_ptr(new pe_properties_generic(*this)); } //Fills properly PE structures template void pe_properties_generic::create_pe(uint32_t section_alignment, uint16_t subsystem) { memset(&nt_headers_, 0, sizeof(nt_headers_)); nt_headers_.Signature = 0x4550; //"PE" nt_headers_.FileHeader.Machine = 0x14C; //i386 nt_headers_.FileHeader.SizeOfOptionalHeader = sizeof(nt_headers_.OptionalHeader); nt_headers_.OptionalHeader.Magic = PEClassType::Id; nt_headers_.OptionalHeader.ImageBase = 0x400000; nt_headers_.OptionalHeader.SectionAlignment = section_alignment; nt_headers_.OptionalHeader.FileAlignment = 0x200; nt_headers_.OptionalHeader.SizeOfHeaders = 1024; nt_headers_.OptionalHeader.Subsystem = subsystem; nt_headers_.OptionalHeader.SizeOfHeapReserve = 0x100000; nt_headers_.OptionalHeader.SizeOfHeapCommit = 0x1000; nt_headers_.OptionalHeader.SizeOfStackReserve = 0x100000; nt_headers_.OptionalHeader.SizeOfStackCommit = 0x1000; nt_headers_.OptionalHeader.NumberOfRvaAndSizes = 0x10; } //Duplicate template pe_properties_generic::~pe_properties_generic() {} //Returns true if directory exists template bool pe_properties_generic::directory_exists(uint32_t id) const { return (nt_headers_.OptionalHeader.NumberOfRvaAndSizes - 1) >= id && nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress; } //Removes directory template void pe_properties_generic::remove_directory(uint32_t id) { if(directory_exists(id)) { nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress = 0; nt_headers_.OptionalHeader.DataDirectory[id].Size = 0; if(id == image_directory_entry_basereloc) { set_characteristics_flags(image_file_relocs_stripped); set_dll_characteristics(get_dll_characteristics() & ~image_dllcharacteristics_dynamic_base); } else if(id == image_directory_entry_export) { clear_characteristics_flags(image_file_dll); } } } //Returns directory RVA template uint32_t pe_properties_generic::get_directory_rva(uint32_t id) const { //Check if directory exists if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id) throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist); return nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress; } //Returns directory size template void pe_properties_generic::set_directory_rva(uint32_t id, uint32_t va) { //Check if directory exists if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id) throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist); nt_headers_.OptionalHeader.DataDirectory[id].VirtualAddress = va; } template void pe_properties_generic::set_directory_size(uint32_t id, uint32_t size) { //Check if directory exists if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id) throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist); nt_headers_.OptionalHeader.DataDirectory[id].Size = size; } //Returns directory size template uint32_t pe_properties_generic::get_directory_size(uint32_t id) const { //Check if directory exists if(nt_headers_.OptionalHeader.NumberOfRvaAndSizes <= id) throw pe_exception("Specified directory does not exist", pe_exception::directory_does_not_exist); return nt_headers_.OptionalHeader.DataDirectory[id].Size; } //Strips only zero DATA_DIRECTORY entries to count = min_count //Returns resulting number of data directories //strip_iat_directory - if true, even not empty IAT directory will be stripped template uint32_t pe_properties_generic::strip_data_directories(uint32_t min_count, bool strip_iat_directory) { int i = nt_headers_.OptionalHeader.NumberOfRvaAndSizes - 1; //Enumerate all data directories from the end for(; i >= 0; i--) { //If directory exists, break if(nt_headers_.OptionalHeader.DataDirectory[i].VirtualAddress && (static_cast(i) != image_directory_entry_iat || !strip_iat_directory)) break; if(i <= static_cast(min_count) - 2) break; } if(i == image_numberof_directory_entries - 1) return image_numberof_directory_entries; //Return new number of data directories return nt_headers_.OptionalHeader.NumberOfRvaAndSizes = i + 1; } //Returns image base for PE32 template uint32_t pe_properties_generic::get_image_base_32() const { return static_cast(nt_headers_.OptionalHeader.ImageBase); } //Returns image base for PE32/PE64 template uint64_t pe_properties_generic::get_image_base_64() const { return static_cast(nt_headers_.OptionalHeader.ImageBase); } //Sets new image base template void pe_properties_generic::set_image_base(uint32_t base) { nt_headers_.OptionalHeader.ImageBase = base; } //Sets new image base template void pe_properties_generic::set_image_base_64(uint64_t base) { nt_headers_.OptionalHeader.ImageBase = static_cast(base); } //Returns image entry point template uint32_t pe_properties_generic::get_ep() const { return nt_headers_.OptionalHeader.AddressOfEntryPoint; } //Sets image entry point template void pe_properties_generic::set_ep(uint32_t new_ep) { nt_headers_.OptionalHeader.AddressOfEntryPoint = new_ep; } //Returns file alignment template uint32_t pe_properties_generic::get_file_alignment() const { return nt_headers_.OptionalHeader.FileAlignment; } //Returns section alignment template uint32_t pe_properties_generic::get_section_alignment() const { return nt_headers_.OptionalHeader.SectionAlignment; } //Sets heap size commit for PE32 template void pe_properties_generic::set_heap_size_commit(uint32_t size) { nt_headers_.OptionalHeader.SizeOfHeapCommit = static_cast(size); } //Sets heap size commit for PE32/PE64 template void pe_properties_generic::set_heap_size_commit(uint64_t size) { nt_headers_.OptionalHeader.SizeOfHeapCommit = static_cast(size); } //Sets heap size reserve for PE32 template void pe_properties_generic::set_heap_size_reserve(uint32_t size) { nt_headers_.OptionalHeader.SizeOfHeapReserve = static_cast(size); } //Sets heap size reserve for PE32/PE64 template void pe_properties_generic::set_heap_size_reserve(uint64_t size) { nt_headers_.OptionalHeader.SizeOfHeapReserve = static_cast(size); } //Sets stack size commit for PE32 template void pe_properties_generic::set_stack_size_commit(uint32_t size) { nt_headers_.OptionalHeader.SizeOfStackCommit = static_cast(size); } //Sets stack size commit for PE32/PE64 template void pe_properties_generic::set_stack_size_commit(uint64_t size) { nt_headers_.OptionalHeader.SizeOfStackCommit = static_cast(size); } //Sets stack size reserve for PE32 template void pe_properties_generic::set_stack_size_reserve(uint32_t size) { nt_headers_.OptionalHeader.SizeOfStackReserve = static_cast(size); } //Sets stack size reserve for PE32/PE64 template void pe_properties_generic::set_stack_size_reserve(uint64_t size) { nt_headers_.OptionalHeader.SizeOfStackReserve = static_cast(size); } //Returns heap size commit for PE32 template uint32_t pe_properties_generic::get_heap_size_commit_32() const { return static_cast(nt_headers_.OptionalHeader.SizeOfHeapCommit); } //Returns heap size commit for PE32/PE64 template uint64_t pe_properties_generic::get_heap_size_commit_64() const { return static_cast(nt_headers_.OptionalHeader.SizeOfHeapCommit); } //Returns heap size reserve for PE32 template uint32_t pe_properties_generic::get_heap_size_reserve_32() const { return static_cast(nt_headers_.OptionalHeader.SizeOfHeapReserve); } //Returns heap size reserve for PE32/PE64 template uint64_t pe_properties_generic::get_heap_size_reserve_64() const { return static_cast(nt_headers_.OptionalHeader.SizeOfHeapReserve); } //Returns stack size commit for PE32 template uint32_t pe_properties_generic::get_stack_size_commit_32() const { return static_cast(nt_headers_.OptionalHeader.SizeOfStackCommit); } //Returns stack size commit for PE32/PE64 template uint64_t pe_properties_generic::get_stack_size_commit_64() const { return static_cast(nt_headers_.OptionalHeader.SizeOfStackCommit); } //Returns stack size reserve for PE32 template uint32_t pe_properties_generic::get_stack_size_reserve_32() const { return static_cast(nt_headers_.OptionalHeader.SizeOfStackReserve); } //Returns stack size reserve for PE32/PE64 template uint64_t pe_properties_generic::get_stack_size_reserve_64() const { return static_cast(nt_headers_.OptionalHeader.SizeOfStackReserve); } //Returns virtual size of image template uint32_t pe_properties_generic::get_size_of_image() const { return nt_headers_.OptionalHeader.SizeOfImage; } //Returns number of RVA and sizes (number of DATA_DIRECTORY entries) template uint32_t pe_properties_generic::get_number_of_rvas_and_sizes() const { return nt_headers_.OptionalHeader.NumberOfRvaAndSizes; } //Sets number of RVA and sizes (number of DATA_DIRECTORY entries) template void pe_properties_generic::set_number_of_rvas_and_sizes(uint32_t number) { nt_headers_.OptionalHeader.NumberOfRvaAndSizes = number; } //Returns PE characteristics template uint16_t pe_properties_generic::get_characteristics() const { return nt_headers_.FileHeader.Characteristics; } //Returns checksum of PE file from header template uint32_t pe_properties_generic::get_checksum() const { return nt_headers_.OptionalHeader.CheckSum; } //Sets checksum of PE file template void pe_properties_generic::set_checksum(uint32_t checksum) { nt_headers_.OptionalHeader.CheckSum = checksum; } //Returns DLL Characteristics template uint16_t pe_properties_generic::get_dll_characteristics() const { return nt_headers_.OptionalHeader.DllCharacteristics; } //Returns timestamp of PE file from header template uint32_t pe_properties_generic::get_time_date_stamp() const { return nt_headers_.FileHeader.TimeDateStamp; } //Sets timestamp of PE file template void pe_properties_generic::set_time_date_stamp(uint32_t timestamp) { nt_headers_.FileHeader.TimeDateStamp = timestamp; } //Sets DLL Characteristics template void pe_properties_generic::set_dll_characteristics(uint16_t characteristics) { nt_headers_.OptionalHeader.DllCharacteristics = characteristics; } //Returns Machine field value of PE file from header template uint16_t pe_properties_generic::get_machine() const { return nt_headers_.FileHeader.Machine; } //Sets Machine field value of PE file template void pe_properties_generic::set_machine(uint16_t machine) { nt_headers_.FileHeader.Machine = machine; } //Sets PE characteristics template void pe_properties_generic::set_characteristics(uint16_t ch) { nt_headers_.FileHeader.Characteristics = ch; } //Returns size of headers template uint32_t pe_properties_generic::get_size_of_headers() const { return nt_headers_.OptionalHeader.SizeOfHeaders; } //Returns subsystem template uint16_t pe_properties_generic::get_subsystem() const { return nt_headers_.OptionalHeader.Subsystem; } //Sets subsystem template void pe_properties_generic::set_subsystem(uint16_t subsystem) { nt_headers_.OptionalHeader.Subsystem = subsystem; } //Returns size of optional header template uint16_t pe_properties_generic::get_size_of_optional_header() const { return nt_headers_.FileHeader.SizeOfOptionalHeader; } //Returns PE signature template uint32_t pe_properties_generic::get_pe_signature() const { return nt_headers_.Signature; } //Returns PE magic value template uint32_t pe_properties_generic::get_magic() const { return nt_headers_.OptionalHeader.Magic; } //Sets required operation system version template void pe_properties_generic::set_os_version(uint16_t major, uint16_t minor) { nt_headers_.OptionalHeader.MinorOperatingSystemVersion = minor; nt_headers_.OptionalHeader.MajorOperatingSystemVersion = major; } //Returns required operation system version (minor word) template uint16_t pe_properties_generic::get_minor_os_version() const { return nt_headers_.OptionalHeader.MinorOperatingSystemVersion; } //Returns required operation system version (major word) template uint16_t pe_properties_generic::get_major_os_version() const { return nt_headers_.OptionalHeader.MajorOperatingSystemVersion; } //Sets required subsystem version template void pe_properties_generic::set_subsystem_version(uint16_t major, uint16_t minor) { nt_headers_.OptionalHeader.MinorSubsystemVersion = minor; nt_headers_.OptionalHeader.MajorSubsystemVersion = major; } //Returns required subsystem version (minor word) template uint16_t pe_properties_generic::get_minor_subsystem_version() const { return nt_headers_.OptionalHeader.MinorSubsystemVersion; } //Returns required subsystem version (major word) template uint16_t pe_properties_generic::get_major_subsystem_version() const { return nt_headers_.OptionalHeader.MajorSubsystemVersion; } //Virtual Address (VA) to Relative Virtual Address (RVA) convertions for PE32 template uint32_t pe_properties_generic::va_to_rva(uint32_t va, bool bound_check) const { if(bound_check && static_cast(va) - nt_headers_.OptionalHeader.ImageBase > pe_utils::max_dword) throw pe_exception("Incorrect address conversion", pe_exception::incorrect_address_conversion); return static_cast(va - nt_headers_.OptionalHeader.ImageBase); } //Virtual Address (VA) to Relative Virtual Address (RVA) convertions for PE32/PE64 template uint32_t pe_properties_generic::va_to_rva(uint64_t va, bool bound_check) const { if(bound_check && va - nt_headers_.OptionalHeader.ImageBase > pe_utils::max_dword) throw pe_exception("Incorrect address conversion", pe_exception::incorrect_address_conversion); return static_cast(va - nt_headers_.OptionalHeader.ImageBase); } //Relative Virtual Address (RVA) to Virtual Address (VA) convertions for PE32 template uint32_t pe_properties_generic::rva_to_va_32(uint32_t rva) const { if(!pe_utils::is_sum_safe(rva, static_cast(nt_headers_.OptionalHeader.ImageBase))) throw pe_exception("Incorrect address conversion", pe_exception::incorrect_address_conversion); return static_cast(rva + nt_headers_.OptionalHeader.ImageBase); } //Relative Virtual Address (RVA) to Virtual Address (VA) convertions for PE32/PE64 template uint64_t pe_properties_generic::rva_to_va_64(uint32_t rva) const { return static_cast(rva) + nt_headers_.OptionalHeader.ImageBase; } //Returns number of sections template uint16_t pe_properties_generic::get_number_of_sections() const { return nt_headers_.FileHeader.NumberOfSections; } //Sets number of sections template void pe_properties_generic::set_number_of_sections(uint16_t number) { nt_headers_.FileHeader.NumberOfSections = number; } //Sets virtual size of image template void pe_properties_generic::set_size_of_image(uint32_t size) { nt_headers_.OptionalHeader.SizeOfImage = size; } //Sets size of headers template void pe_properties_generic::set_size_of_headers(uint32_t size) { nt_headers_.OptionalHeader.SizeOfHeaders = size; } //Sets size of optional headers template void pe_properties_generic::set_size_of_optional_header(uint16_t size) { nt_headers_.FileHeader.SizeOfOptionalHeader = size; } //Returns nt headers data pointer template char* pe_properties_generic::get_nt_headers_ptr() { return reinterpret_cast(&nt_headers_); } //Returns nt headers data pointer template const char* pe_properties_generic::get_nt_headers_ptr() const { return reinterpret_cast(&nt_headers_); } //Returns size of NT header template uint32_t pe_properties_generic::get_sizeof_nt_header() const { return sizeof(typename PEClassType::NtHeaders); } //Returns size of optional headers template uint32_t pe_properties_generic::get_sizeof_opt_headers() const { return sizeof(typename PEClassType::OptHeaders); } //Sets file alignment (no checks) template void pe_properties_generic::set_file_alignment_unchecked(uint32_t alignment) { nt_headers_.OptionalHeader.FileAlignment = alignment; } //Sets base of code template void pe_properties_generic::set_base_of_code(uint32_t base) { nt_headers_.OptionalHeader.BaseOfCode = base; } //Returns base of code template uint32_t pe_properties_generic::get_base_of_code() const { return nt_headers_.OptionalHeader.BaseOfCode; } //Returns needed PE magic for PE or PE+ (from template parameters) template uint32_t pe_properties_generic::get_needed_magic() const { return PEClassType::Id; } //Returns PE type of this image template pe_type pe_properties_generic::get_pe_type() const { return PEClassType::Id == image_nt_optional_hdr32_magic ? pe_type_32 : pe_type_64; } //Two used instantiations for PE32 (PE) and PE64 (PE+) template class pe_properties_generic; template class pe_properties_generic; }