├── .gitignore ├── README.md └── src ├── CMakeLists.txt ├── config.cmake ├── pe_lib ├── CMakeLists.txt ├── entropy.cpp ├── entropy.h ├── file_version_info.cpp ├── file_version_info.h ├── message_table.cpp ├── message_table.h ├── pe_base.cpp ├── pe_base.h ├── pe_bliss.h ├── pe_bliss_resources.h ├── pe_bound_import.cpp ├── pe_bound_import.h ├── pe_checksum.cpp ├── pe_checksum.h ├── pe_debug.cpp ├── pe_debug.h ├── pe_directory.cpp ├── pe_directory.h ├── pe_dotnet.cpp ├── pe_dotnet.h ├── pe_exception.cpp ├── pe_exception.h ├── pe_exception_directory.cpp ├── pe_exception_directory.h ├── pe_exports.cpp ├── pe_exports.h ├── pe_factory.cpp ├── pe_factory.h ├── pe_imports.cpp ├── pe_imports.h ├── pe_load_config.cpp ├── pe_load_config.h ├── pe_properties.cpp ├── pe_properties.h ├── pe_properties_generic.cpp ├── pe_properties_generic.h ├── pe_rebuilder.cpp ├── pe_rebuilder.h ├── pe_relocations.cpp ├── pe_relocations.h ├── pe_resource_manager.cpp ├── pe_resource_manager.h ├── pe_resource_viewer.cpp ├── pe_resource_viewer.h ├── pe_resources.cpp ├── pe_resources.h ├── pe_rich_data.cpp ├── pe_rich_data.h ├── pe_section.cpp ├── pe_section.h ├── pe_structures.h ├── pe_tls.cpp ├── pe_tls.h ├── readme.txt ├── resource_bitmap_reader.cpp ├── resource_bitmap_reader.h ├── resource_bitmap_writer.cpp ├── resource_bitmap_writer.h ├── resource_cursor_icon_reader.cpp ├── resource_cursor_icon_reader.h ├── resource_cursor_icon_writer.cpp ├── resource_cursor_icon_writer.h ├── resource_data_info.cpp ├── resource_data_info.h ├── resource_internal.h ├── resource_message_list_reader.cpp ├── resource_message_list_reader.h ├── resource_string_table_reader.cpp ├── resource_string_table_reader.h ├── resource_version_info_reader.cpp ├── resource_version_info_reader.h ├── resource_version_info_writer.cpp ├── resource_version_info_writer.h ├── stdint_defs.h ├── utils.cpp ├── utils.h ├── version_info_editor.cpp ├── version_info_editor.h ├── version_info_types.h ├── version_info_viewer.cpp └── version_info_viewer.h ├── samples ├── CMakeLists.txt ├── address_convertions │ ├── CMakeLists.txt │ └── main.cpp ├── basic_dotnet_viewer │ ├── CMakeLists.txt │ └── main.cpp ├── basic_info_viewer │ ├── CMakeLists.txt │ └── main.cpp ├── bound_import_reader │ ├── CMakeLists.txt │ └── main.cpp ├── debug_info_reader │ ├── CMakeLists.txt │ └── main.cpp ├── entropy_calculator │ ├── CMakeLists.txt │ └── main.cpp ├── exception_dir_reader │ ├── CMakeLists.txt │ └── main.cpp ├── export_adder │ ├── CMakeLists.txt │ └── main.cpp ├── exports_reader │ ├── CMakeLists.txt │ └── main.cpp ├── full_pe_rebuilder │ ├── CMakeLists.txt │ └── main.cpp ├── image_config_editor │ ├── CMakeLists.txt │ └── main.cpp ├── import_adder │ ├── CMakeLists.txt │ └── main.cpp ├── imports_reader │ ├── CMakeLists.txt │ └── main.cpp ├── pe_config_reader │ ├── CMakeLists.txt │ └── main.cpp ├── pe_realigner │ ├── CMakeLists.txt │ └── main.cpp ├── pe_rebaser │ ├── CMakeLists.txt │ └── main.cpp ├── pe_sections_reader │ ├── CMakeLists.txt │ └── main.cpp ├── pe_stripper │ ├── CMakeLists.txt │ └── main.cpp ├── relocation_adder │ ├── CMakeLists.txt │ └── main.cpp ├── relocations_reader │ ├── CMakeLists.txt │ └── main.cpp ├── resource_editor │ ├── CMakeLists.txt │ ├── main.cpp │ ├── resource.h │ ├── resource.rc │ └── wxwin.ico ├── resource_viewer │ ├── CMakeLists.txt │ └── main.cpp ├── rich_overlay_stub_reader │ ├── CMakeLists.txt │ └── main.cpp ├── section_adder │ ├── CMakeLists.txt │ └── main.cpp ├── sections_and_addresses │ ├── CMakeLists.txt │ └── main.cpp ├── tls_editor │ ├── CMakeLists.txt │ └── main.cpp └── tls_reader │ ├── CMakeLists.txt │ └── main.cpp └── tests ├── CMakeLists.txt ├── pe_files ├── TestApp.exe ├── bound32.exe ├── bound64.exe ├── debug_test.exe ├── image32.exe ├── image64.exe ├── message_table_resource.exe ├── test_dll_32.dll └── test_dll_64.dll ├── test.h ├── test_bound_import ├── CMakeLists.txt └── main.cpp ├── test_checksum ├── CMakeLists.txt └── main.cpp ├── test_debug ├── CMakeLists.txt └── main.cpp ├── test_dotnet ├── CMakeLists.txt └── main.cpp ├── test_entropy ├── CMakeLists.txt └── main.cpp ├── test_exception_directory ├── CMakeLists.txt └── main.cpp ├── test_exports ├── CMakeLists.txt └── main.cpp ├── test_imports ├── CMakeLists.txt └── main.cpp ├── test_load_config ├── CMakeLists.txt └── main.cpp ├── test_relocations ├── CMakeLists.txt └── main.cpp ├── test_resource_bitmap ├── CMakeLists.txt └── main.cpp ├── test_resource_icon_cursor ├── CMakeLists.txt └── main.cpp ├── test_resource_manager ├── CMakeLists.txt └── main.cpp ├── test_resource_message_table ├── CMakeLists.txt └── main.cpp ├── test_resource_string_table ├── CMakeLists.txt └── main.cpp ├── test_resource_version_info ├── CMakeLists.txt └── main.cpp ├── test_resource_viewer ├── CMakeLists.txt └── main.cpp ├── test_resources ├── CMakeLists.txt └── main.cpp ├── test_rich_data ├── CMakeLists.txt └── main.cpp ├── test_runner ├── CMakeLists.txt └── main.cpp ├── test_tls ├── CMakeLists.txt └── main.cpp ├── tests_basic ├── CMakeLists.txt └── main.cpp └── tests_utils ├── CMakeLists.txt └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | /obj/ 2 | /lib/ 3 | /bin/ 4 | /build-* 5 | CMakeLists.txt.user 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PE Bliss # 2 | 3 | ### Cross-Platform Portable Executable C++ Library ### 4 | 5 | Compatible with Windows and Linux (tested on MSVC++ 2008, 2010, GCC 4.4 on Linux). Currently tested on little-endian systems only and might not support big-endian ones. 6 | 7 | Library has many usage samples and is well unit-tested. 8 | 9 | _Library is free to use in both commertial and non-commertial projects. You can also modify and redistribute it. If you are using it, please, do not forget to specify the name or other copyright of PE Bliss somewhere in the description of your project._ 10 | 11 | 12 | 13 | --- 14 | 15 | 16 | **A huge update is coming soon!** Possible new features of the future update: 17 | 18 | * more high-level classes and functions to work with PE resources; 19 | 20 | * high-level .NET PE parsing (metadata tables, signatures, resources); 21 | 22 | * C++/CLI wrapper, which allows .NET developers to use the library in C# or VB.NET projects; 23 | 24 | * more samples and tests; 25 | 26 | * bugfixes. 27 | 28 | 29 | 30 | --- 31 | 32 | 33 | **Current version: 1.0.0** 34 | 35 | ### Summary ### 36 | 37 | [+] Read 32- and 64-bit PE files (PE, PE+) for Windows, work similar with both formats 38 | 39 | [+] Create PE/PE+ binaries from scratch 40 | 41 | [+] Rebuild 32- and 64-bit PE files 42 | 43 | [+] Work with directories and headers 44 | 45 | [+] Convert addresses 46 | 47 | [+] Read and write PE sections 48 | 49 | [+] Read and write imports 50 | 51 | [+] Read and write exports (forwarders supported) 52 | 53 | [+] Read and write relocations 54 | 55 | [+] Read and write resources 56 | 57 | [+] Read and write TLS (including callbacks and raw data) 58 | 59 | [+] Read and write image config (including SE Handlers and Lock Prefix addresses) 60 | 61 | [+] Read basic .NET information 62 | 63 | [+] Read and write bound imports 64 | 65 | [+] Read exception directory (PE+ only) 66 | 67 | [+] Read debug directory and extended debug information 68 | 69 | [+] Calculate entropy 70 | 71 | [+] Change file alignment 72 | 73 | [+] Change base address 74 | 75 | [+] Work with DOS Stub and Rich overlay 76 | 77 | [+] High-level resource reading: bitmaps, icons, cursors, version info, string and message tables 78 | 79 | [+] High-level resource editing: bitmaps, icons, cursors, version info 80 | 81 | 82 | 83 | Library doesn't use WinAPI and doesn't execute PE files, so it's safe to use it with suspicious binaries. 84 | 85 | 86 | 87 | --- 88 | 89 | [Author's blog](http://kaimi.ru/) 90 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | #common properties 4 | 5 | project(pe_lib_root) 6 | 7 | if (NOT CMAKE_BUILD_TYPE) 8 | set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build, options are: Debug Release" FORCE) 9 | endif () 10 | 11 | set(ROOT "${CMAKE_CURRENT_SOURCE_DIR}/..") 12 | set(OBJ_DIR "${ROOT}/obj/${CMAKE_BUILD_TYPE}") 13 | set(LIB_DIR "${ROOT}/lib/${CMAKE_BUILD_TYPE}") 14 | set(BIN_DIR "${ROOT}/bin/${CMAKE_BUILD_TYPE}") 15 | 16 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${LIB_DIR}") 17 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${LIB_DIR}") 18 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BIN_DIR}") 19 | 20 | set(COMPONENTS pe_lib tests samples) 21 | 22 | enable_testing() 23 | 24 | foreach (COMPONENT ${COMPONENTS}) 25 | add_subdirectory(${COMPONENT}) 26 | endforeach () 27 | -------------------------------------------------------------------------------- /src/config.cmake: -------------------------------------------------------------------------------- 1 | project(${PROJECT}) 2 | 3 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 4 | set(CMAKE_COMPILER_IS_CLANGXX 1) 5 | endif () 6 | 7 | if(MSVC) 8 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /WX") 9 | elseif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX) 10 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Werror -fstrict-aliasing -pedantic-errors -pedantic -Wno-deprecated-declarations") 11 | endif() 12 | 13 | if(NOT DEFINED HEADERS) 14 | file(GLOB HEADERS ${${PROJECT}_SOURCE_DIR}/*.h) 15 | endif () 16 | 17 | if(NOT DEFINED SOURCES) 18 | file(GLOB SOURCES ${${PROJECT}_SOURCE_DIR}/*.cpp) 19 | endif () 20 | 21 | source_group("Header Files" FILES ${HEADERS}) 22 | source_group("Source Files" FILES ${SOURCES}) 23 | 24 | -------------------------------------------------------------------------------- /src/pe_lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT pe_lib) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_library(${PROJECT} STATIC ${HEADERS} ${SOURCES}) 8 | -------------------------------------------------------------------------------- /src/pe_lib/entropy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "entropy.h" 3 | #include "utils.h" 4 | 5 | namespace pe_bliss 6 | { 7 | //Calculates entropy for PE image section 8 | double entropy_calculator::calculate_entropy(const section& s) 9 | { 10 | if(s.get_raw_data().empty()) //Don't count entropy for empty sections 11 | throw pe_exception("Section is empty", pe_exception::section_is_empty); 12 | 13 | return calculate_entropy(s.get_raw_data().data(), s.get_raw_data().length()); 14 | } 15 | 16 | //Calculates entropy for istream (from current position of stream) 17 | double entropy_calculator::calculate_entropy(std::istream& file) 18 | { 19 | uint32_t byte_count[256] = {0}; //Byte count for each of 255 bytes 20 | 21 | if(file.bad()) 22 | throw pe_exception("Stream is bad", pe_exception::stream_is_bad); 23 | 24 | std::streamoff pos = file.tellg(); 25 | 26 | std::streamoff length = pe_utils::get_file_size(file); 27 | length -= file.tellg(); 28 | 29 | if(!length) //Don't calculate entropy for empty buffers 30 | throw pe_exception("Data length is zero", pe_exception::data_is_empty); 31 | 32 | //Count bytes 33 | for(std::streamoff i = 0; i != length; ++i) 34 | ++byte_count[static_cast(file.get())]; 35 | 36 | file.seekg(pos); 37 | 38 | return calculate_entropy(byte_count, length); 39 | } 40 | 41 | //Calculates entropy for data block 42 | double entropy_calculator::calculate_entropy(const char* data, size_t length) 43 | { 44 | uint32_t byte_count[256] = {0}; //Byte count for each of 255 bytes 45 | 46 | if(!length) //Don't calculate entropy for empty buffers 47 | throw pe_exception("Data length is zero", pe_exception::data_is_empty); 48 | 49 | //Count bytes 50 | for(size_t i = 0; i != length; ++i) 51 | ++byte_count[static_cast(data[i])]; 52 | 53 | return calculate_entropy(byte_count, length); 54 | } 55 | 56 | //Calculates entropy for this PE file (only section data) 57 | double entropy_calculator::calculate_entropy(const pe_base& pe) 58 | { 59 | uint32_t byte_count[256] = {0}; //Byte count for each of 255 bytes 60 | 61 | size_t total_data_length = 0; 62 | 63 | //Count bytes for each section 64 | for(section_list::const_iterator it = pe.get_image_sections().begin(); it != pe.get_image_sections().end(); ++it) 65 | { 66 | const std::string& data = (*it).get_raw_data(); 67 | size_t length = data.length(); 68 | total_data_length += length; 69 | for(size_t i = 0; i != length; ++i) 70 | ++byte_count[static_cast(data[i])]; 71 | } 72 | 73 | return calculate_entropy(byte_count, total_data_length); 74 | } 75 | 76 | //Calculates entropy from bytes count 77 | double entropy_calculator::calculate_entropy(const uint32_t byte_count[256], std::streamoff total_length) 78 | { 79 | double entropy = 0.; //Entropy result value 80 | //Calculate entropy 81 | for(uint32_t i = 0; i < 256; ++i) 82 | { 83 | double temp = static_cast(byte_count[i]) / total_length; 84 | if(temp > 0.) 85 | entropy += std::abs(temp * (std::log(temp) * pe_utils::log_2)); 86 | } 87 | 88 | return entropy; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/pe_lib/entropy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "pe_base.h" 4 | 5 | namespace pe_bliss 6 | { 7 | class entropy_calculator 8 | { 9 | public: 10 | //Calculates entropy for PE image section 11 | static double calculate_entropy(const section& s); 12 | 13 | //Calculates entropy for istream (from current position of stream) 14 | static double calculate_entropy(std::istream& file); 15 | 16 | //Calculates entropy for data block 17 | static double calculate_entropy(const char* data, size_t length); 18 | 19 | //Calculates entropy for this PE file (only section data) 20 | static double calculate_entropy(const pe_base& pe); 21 | 22 | private: 23 | entropy_calculator(); 24 | entropy_calculator(const entropy_calculator&); 25 | entropy_calculator& operator=(const entropy_calculator&); 26 | 27 | //Calculates entropy from bytes count 28 | static double calculate_entropy(const uint32_t byte_count[256], std::streamoff total_length); 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /src/pe_lib/message_table.cpp: -------------------------------------------------------------------------------- 1 | #include "message_table.h" 2 | #include "utils.h" 3 | 4 | namespace pe_bliss 5 | { 6 | //Default constructor 7 | message_table_item::message_table_item() 8 | :unicode_(false) 9 | {} 10 | 11 | //Constructor from ANSI string 12 | message_table_item::message_table_item(const std::string& str) 13 | :unicode_(false), ansi_str_(str) 14 | { 15 | pe_utils::strip_nullbytes(ansi_str_); 16 | } 17 | 18 | //Constructor from UNICODE string 19 | message_table_item::message_table_item(const std::wstring& str) 20 | :unicode_(true), unicode_str_(str) 21 | { 22 | pe_utils::strip_nullbytes(unicode_str_); 23 | } 24 | 25 | //Returns true if contained string is unicode 26 | bool message_table_item::is_unicode() const 27 | { 28 | return unicode_; 29 | } 30 | 31 | //Returns ANSI string 32 | const std::string& message_table_item::get_ansi_string() const 33 | { 34 | return ansi_str_; 35 | } 36 | 37 | //Returns UNICODE string 38 | const std::wstring& message_table_item::get_unicode_string() const 39 | { 40 | return unicode_str_; 41 | } 42 | 43 | //Sets ANSI string (clears UNICODE one) 44 | void message_table_item::set_string(const std::string& str) 45 | { 46 | ansi_str_ = str; 47 | pe_utils::strip_nullbytes(ansi_str_); 48 | unicode_str_.clear(); 49 | unicode_ = false; 50 | } 51 | 52 | //Sets UNICODE string (clears ANSI one) 53 | void message_table_item::set_string(const std::wstring& str) 54 | { 55 | unicode_str_ = str; 56 | pe_utils::strip_nullbytes(unicode_str_); 57 | ansi_str_.clear(); 58 | unicode_ = true; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/pe_lib/message_table.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "stdint_defs.h" 5 | 6 | namespace pe_bliss 7 | { 8 | //Structure representing message table string 9 | class message_table_item 10 | { 11 | public: 12 | //Default constructor 13 | message_table_item(); 14 | //Constructors from ANSI and UNICODE strings 15 | explicit message_table_item(const std::string& str); 16 | explicit message_table_item(const std::wstring& str); 17 | 18 | //Returns true if string is UNICODE 19 | bool is_unicode() const; 20 | //Returns ANSI string 21 | const std::string& get_ansi_string() const; 22 | //Returns UNICODE string 23 | const std::wstring& get_unicode_string() const; 24 | 25 | public: 26 | //Sets ANSI or UNICODE string 27 | void set_string(const std::string& str); 28 | void set_string(const std::wstring& str); 29 | 30 | private: 31 | bool unicode_; 32 | std::string ansi_str_; 33 | std::wstring unicode_str_; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /src/pe_lib/pe_bliss.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pe_base.h" 3 | #include "pe_rebuilder.h" 4 | #include "pe_factory.h" 5 | #include "pe_bound_import.h" 6 | #include "pe_debug.h" 7 | #include "pe_dotnet.h" 8 | #include "pe_exception_directory.h" 9 | #include "pe_exports.h" 10 | #include "pe_imports.h" 11 | #include "pe_load_config.h" 12 | #include "pe_relocations.h" 13 | #include "pe_resources.h" 14 | #include "pe_rich_data.h" 15 | #include "pe_tls.h" 16 | #include "pe_properties_generic.h" 17 | #include "pe_checksum.h" 18 | #include "entropy.h" 19 | -------------------------------------------------------------------------------- /src/pe_lib/pe_bliss_resources.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "file_version_info.h" 3 | #include "message_table.h" 4 | #include "pe_resource_manager.h" 5 | #include "pe_resource_viewer.h" 6 | #include "version_info_editor.h" 7 | #include "version_info_viewer.h" 8 | #include "resource_bitmap_reader.h" 9 | #include "resource_bitmap_writer.h" 10 | #include "resource_cursor_icon_reader.h" 11 | #include "resource_cursor_icon_writer.h" 12 | #include "resource_version_info_reader.h" 13 | #include "resource_version_info_writer.h" 14 | #include "resource_string_table_reader.h" 15 | #include "resource_message_list_reader.h" 16 | -------------------------------------------------------------------------------- /src/pe_lib/pe_bound_import.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "pe_structures.h" 5 | #include "pe_base.h" 6 | #include "pe_directory.h" 7 | 8 | namespace pe_bliss 9 | { 10 | //Class representing bound import reference 11 | class bound_import_ref 12 | { 13 | public: 14 | //Default constructor 15 | bound_import_ref(); 16 | //Constructor from data 17 | bound_import_ref(const std::string& module_name, uint32_t timestamp); 18 | 19 | //Returns imported module name 20 | const std::string& get_module_name() const; 21 | //Returns bound import date and time stamp 22 | uint32_t get_timestamp() const; 23 | 24 | public: //Setters 25 | //Sets module name 26 | void set_module_name(const std::string& module_name); 27 | //Sets timestamp 28 | void set_timestamp(uint32_t timestamp); 29 | 30 | private: 31 | std::string module_name_; //Imported module name 32 | uint32_t timestamp_; //Bound import timestamp 33 | }; 34 | 35 | //Class representing image bound import information 36 | class bound_import 37 | { 38 | public: 39 | typedef std::vector ref_list; 40 | 41 | public: 42 | //Default constructor 43 | bound_import(); 44 | //Constructor from data 45 | bound_import(const std::string& module_name, uint32_t timestamp); 46 | 47 | //Returns imported module name 48 | const std::string& get_module_name() const; 49 | //Returns bound import date and time stamp 50 | uint32_t get_timestamp() const; 51 | 52 | //Returns bound references cound 53 | size_t get_module_ref_count() const; 54 | //Returns module references 55 | const ref_list& get_module_ref_list() const; 56 | 57 | public: //Setters 58 | //Sets module name 59 | void set_module_name(const std::string& module_name); 60 | //Sets timestamp 61 | void set_timestamp(uint32_t timestamp); 62 | 63 | //Adds module reference 64 | void add_module_ref(const bound_import_ref& ref); 65 | //Clears module references list 66 | void clear_module_refs(); 67 | //Returns module references 68 | ref_list& get_module_ref_list(); 69 | 70 | private: 71 | std::string module_name_; //Imported module name 72 | uint32_t timestamp_; //Bound import timestamp 73 | ref_list refs_; //Module references list 74 | }; 75 | 76 | typedef std::vector bound_import_module_list; 77 | 78 | //Returns bound import information 79 | const bound_import_module_list get_bound_import_module_list(const pe_base& pe);//Export directory rebuilder 80 | 81 | //imports - bound imported modules list 82 | //imports_section - section where export directory will be placed (must be attached to PE image) 83 | //offset_from_section_start - offset from imports_section raw data start 84 | //save_to_pe_headers - if true, new bound import directory information will be saved to PE image headers 85 | //auto_strip_last_section - if true and bound imports are placed in the last section, it will be automatically stripped 86 | const image_directory rebuild_bound_imports(pe_base& pe, const bound_import_module_list& imports, section& imports_section, uint32_t offset_from_section_start = 0, bool save_to_pe_header = true, bool auto_strip_last_section = true); 87 | } 88 | -------------------------------------------------------------------------------- /src/pe_lib/pe_checksum.cpp: -------------------------------------------------------------------------------- 1 | #include "pe_checksum.h" 2 | #include "pe_structures.h" 3 | #include "pe_base.h" 4 | 5 | namespace pe_bliss 6 | { 7 | using namespace pe_win; 8 | 9 | //Calculate checksum of image 10 | uint32_t calculate_checksum(std::istream& file) 11 | { 12 | //Save istream state 13 | std::ios_base::iostate state = file.exceptions(); 14 | std::streamoff old_offset = file.tellg(); 15 | 16 | //Checksum value 17 | uint64_t checksum = 0; 18 | 19 | try 20 | { 21 | image_dos_header header; 22 | 23 | file.exceptions(std::ios::goodbit); 24 | 25 | //Read DOS header 26 | pe_base::read_dos_header(file, header); 27 | 28 | //Calculate PE checksum 29 | file.seekg(0); 30 | uint64_t top = 0xFFFFFFFF; 31 | top++; 32 | 33 | //"CheckSum" field position in optional PE headers - it's always 64 for PE and PE+ 34 | static const uint32_t checksum_pos_in_optional_headers = 64; 35 | //Calculate real PE headers "CheckSum" field position 36 | //Sum is safe here 37 | int64_t pe_checksum_pos = header.e_lfanew + sizeof(image_file_header) + sizeof(uint32_t) + checksum_pos_in_optional_headers; 38 | 39 | //Calculate checksum for each byte of file 40 | std::streamoff filesize = pe_utils::get_file_size(file); 41 | for(int64_t i = 0; i < filesize; i += 4) 42 | { 43 | uint32_t dw = 0; 44 | 45 | //Read DWORD from file 46 | file.read(reinterpret_cast(&dw), sizeof(dw)); 47 | //Skip "CheckSum" DWORD 48 | if(i == pe_checksum_pos) 49 | continue; 50 | 51 | //Calculate checksum 52 | checksum = (checksum & 0xffffffff) + dw + (checksum >> 32); 53 | if(checksum > top) 54 | checksum = (checksum & 0xffffffff) + (checksum >> 32); 55 | } 56 | 57 | //Finish checksum 58 | checksum = (checksum & 0xffff) + (checksum >> 16); 59 | checksum = (checksum) + (checksum >> 16); 60 | checksum = checksum & 0xffff; 61 | 62 | checksum += static_cast(filesize); 63 | } 64 | catch(const std::exception&) 65 | { 66 | //If something went wrong, restore istream state 67 | file.exceptions(state); 68 | file.seekg(old_offset); 69 | file.clear(); 70 | //Rethrow 71 | throw; 72 | } 73 | 74 | //Restore istream state 75 | file.exceptions(state); 76 | file.seekg(old_offset); 77 | file.clear(); 78 | 79 | //Return checksum 80 | return static_cast(checksum); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/pe_lib/pe_checksum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "stdint_defs.h" 4 | 5 | namespace pe_bliss 6 | { 7 | //Calculate checksum of image (performs no checks on PE structures) 8 | uint32_t calculate_checksum(std::istream& file); 9 | } 10 | -------------------------------------------------------------------------------- /src/pe_lib/pe_directory.cpp: -------------------------------------------------------------------------------- 1 | #include "pe_directory.h" 2 | 3 | namespace pe_bliss 4 | { 5 | //Default constructor 6 | image_directory::image_directory() 7 | :rva_(0), size_(0) 8 | {} 9 | 10 | //Constructor from data 11 | image_directory::image_directory(uint32_t rva, uint32_t size) 12 | :rva_(rva), size_(size) 13 | {} 14 | 15 | //Returns RVA 16 | uint32_t image_directory::get_rva() const 17 | { 18 | return rva_; 19 | } 20 | 21 | //Returns size 22 | uint32_t image_directory::get_size() const 23 | { 24 | return size_; 25 | } 26 | 27 | //Sets RVA 28 | void image_directory::set_rva(uint32_t rva) 29 | { 30 | rva_ = rva; 31 | } 32 | 33 | //Sets size 34 | void image_directory::set_size(uint32_t size) 35 | { 36 | size_ = size; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/pe_lib/pe_directory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdint_defs.h" 3 | 4 | namespace pe_bliss 5 | { 6 | //Class representing image directory data 7 | class image_directory 8 | { 9 | public: 10 | //Default constructor 11 | image_directory(); 12 | //Constructor from data 13 | image_directory(uint32_t rva, uint32_t size); 14 | 15 | //Returns RVA 16 | uint32_t get_rva() const; 17 | //Returns size 18 | uint32_t get_size() const; 19 | 20 | //Sets RVA 21 | void set_rva(uint32_t rva); 22 | //Sets size 23 | void set_size(uint32_t size); 24 | 25 | private: 26 | uint32_t rva_; 27 | uint32_t size_; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /src/pe_lib/pe_dotnet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pe_structures.h" 3 | #include "pe_base.h" 4 | 5 | namespace pe_bliss 6 | { 7 | //Class representing basic .NET header information 8 | class basic_dotnet_info 9 | { 10 | public: 11 | //Default constructor 12 | basic_dotnet_info(); 13 | //Constructor from data 14 | explicit basic_dotnet_info(const pe_win::image_cor20_header& header); 15 | 16 | //Returns major runtime version 17 | uint16_t get_major_runtime_version() const; 18 | //Returns minor runtime version 19 | uint16_t get_minor_runtime_version() const; 20 | 21 | //Returns RVA of metadata (symbol table and startup information) 22 | uint32_t get_rva_of_metadata() const; 23 | //Returns size of metadata (symbol table and startup information) 24 | uint32_t get_size_of_metadata() const; 25 | 26 | //Returns flags 27 | uint32_t get_flags() const; 28 | 29 | //Returns true if entry point is native 30 | bool is_native_entry_point() const; 31 | //Returns true if 32 bit required 32 | bool is_32bit_required() const; 33 | //Returns true if image is IL library 34 | bool is_il_library() const; 35 | //Returns true if image uses IL only 36 | bool is_il_only() const; 37 | 38 | //Returns entry point RVA (if entry point is native) 39 | //Returns entry point managed token (if entry point is managed) 40 | uint32_t get_entry_point_rva_or_token() const; 41 | 42 | //Returns RVA of managed resources 43 | uint32_t get_rva_of_resources() const; 44 | //Returns size of managed resources 45 | uint32_t get_size_of_resources() const; 46 | //Returns RVA of strong name signature 47 | uint32_t get_rva_of_strong_name_signature() const; 48 | //Returns size of strong name signature 49 | uint32_t get_size_of_strong_name_signature() const; 50 | //Returns RVA of code manager table 51 | uint32_t get_rva_of_code_manager_table() const; 52 | //Returns size of code manager table 53 | uint32_t get_size_of_code_manager_table() const; 54 | //Returns RVA of VTable fixups 55 | uint32_t get_rva_of_vtable_fixups() const; 56 | //Returns size of VTable fixups 57 | uint32_t get_size_of_vtable_fixups() const; 58 | //Returns RVA of export address table jumps 59 | uint32_t get_rva_of_export_address_table_jumps() const; 60 | //Returns size of export address table jumps 61 | uint32_t get_size_of_export_address_table_jumps() const; 62 | //Returns RVA of managed native header 63 | //(precompiled header info, usually set to zero, for internal use) 64 | uint32_t get_rva_of_managed_native_header() const; 65 | //Returns size of managed native header 66 | //(precompiled header info, usually set to zero, for internal use) 67 | uint32_t get_size_of_managed_native_header() const; 68 | 69 | private: 70 | pe_win::image_cor20_header header_; 71 | }; 72 | 73 | //Returns basic .NET information 74 | //If image is not native, throws an exception 75 | const basic_dotnet_info get_basic_dotnet_info(const pe_base& pe); 76 | } 77 | -------------------------------------------------------------------------------- /src/pe_lib/pe_exception.cpp: -------------------------------------------------------------------------------- 1 | #include "pe_exception.h" 2 | 3 | namespace pe_bliss 4 | { 5 | //PE exception class constructors 6 | pe_exception::pe_exception(const char* text, exception_id id) 7 | :std::runtime_error(text), id_(id) 8 | {} 9 | 10 | pe_exception::pe_exception(const std::string& text, exception_id id) 11 | :std::runtime_error(text), id_(id) 12 | {} 13 | 14 | //Returns exception ID 15 | pe_exception::exception_id pe_exception::get_id() const 16 | { 17 | return id_; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/pe_lib/pe_exception.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace pe_bliss 6 | { 7 | //PE exception class 8 | class pe_exception : public std::runtime_error 9 | { 10 | public: 11 | //Exception IDs 12 | enum exception_id 13 | { 14 | unknown_error, 15 | bad_pe_file, 16 | bad_dos_header, 17 | image_nt_headers_not_found, 18 | error_reading_image_nt_headers, 19 | error_reading_data_directories, 20 | error_reading_file, 21 | pe_signature_incorrect, 22 | incorrect_number_of_rva_and_sizes, 23 | error_changing_section_virtual_size, 24 | section_number_incorrect, 25 | section_table_incorrect, 26 | incorrect_section_alignment, 27 | incorrect_file_alignment, 28 | incorrect_size_of_image, 29 | incorrect_size_of_headers, 30 | image_section_headers_not_found, 31 | zero_section_sizes, 32 | section_incorrect_addr_or_size, 33 | section_not_found, 34 | image_section_data_not_found, 35 | no_section_found, 36 | image_section_table_incorrect, 37 | directory_does_not_exist, 38 | rva_not_exists, 39 | error_reading_section_header, 40 | error_reading_overlay, 41 | incorrect_address_conversion, 42 | 43 | incorrect_export_directory, 44 | incorrect_import_directory, 45 | incorrect_relocation_directory, 46 | incorrect_tls_directory, 47 | incorrect_config_directory, 48 | incorrect_bound_import_directory, 49 | incorrect_resource_directory, 50 | incorrect_exception_directory, 51 | incorrect_debug_directory, 52 | 53 | resource_directory_entry_error, 54 | resource_directory_entry_not_found, 55 | resource_data_entry_not_found, 56 | resource_incorrect_bitmap, 57 | resource_incorrect_icon, 58 | resource_incorrect_cursor, 59 | resource_incorrect_string_table, 60 | resource_string_not_found, 61 | resource_incorrect_message_table, 62 | resource_incorrect_version_info, 63 | 64 | advanced_debug_information_request_error, 65 | image_does_not_have_managed_code, 66 | 67 | section_is_empty, 68 | data_is_empty, 69 | stream_is_bad, 70 | 71 | section_is_not_attached, 72 | insufficient_space, 73 | 74 | cannot_rebase_relocations, 75 | 76 | exports_list_is_empty, 77 | duplicate_exported_function_ordinal, 78 | duplicate_exported_function_name, 79 | 80 | version_info_string_does_not_exist, 81 | 82 | no_more_sections_can_be_added, 83 | 84 | no_icon_group_found, 85 | no_cursor_group_found, 86 | 87 | encoding_convertion_error, 88 | 89 | error_expanding_section, 90 | 91 | cannot_rebuild_image 92 | }; 93 | 94 | public: 95 | //Class constructors 96 | explicit pe_exception(const char* text, exception_id id = unknown_error); 97 | explicit pe_exception(const std::string& text, exception_id id = unknown_error); 98 | 99 | //Returns exception ID from exception_id enumeration 100 | exception_id get_id() const; 101 | 102 | //Destructor 103 | virtual ~pe_exception() throw() 104 | {} 105 | 106 | private: 107 | exception_id id_; 108 | }; 109 | } 110 | -------------------------------------------------------------------------------- /src/pe_lib/pe_exception_directory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "pe_structures.h" 4 | #include "pe_base.h" 5 | 6 | namespace pe_bliss 7 | { 8 | //Class representing exception directory entry 9 | class exception_entry 10 | { 11 | public: 12 | //Default constructor 13 | exception_entry(); 14 | //Constructor from data 15 | exception_entry(const pe_win::image_runtime_function_entry& entry, const pe_win::unwind_info& unwind_info); 16 | 17 | //Returns starting address of function, affected by exception unwinding 18 | uint32_t get_begin_address() const; 19 | //Returns ending address of function, affected by exception unwinding 20 | uint32_t get_end_address() const; 21 | //Returns unwind info address 22 | uint32_t get_unwind_info_address() const; 23 | 24 | //Returns UNWIND_INFO structure version 25 | uint8_t get_unwind_info_version() const; 26 | 27 | //Returns unwind info flags 28 | uint8_t get_flags() const; 29 | //The function has an exception handler that should be called 30 | //when looking for functions that need to examine exceptions 31 | bool has_exception_handler() const; 32 | //The function has a termination handler that should be called 33 | //when unwinding an exception 34 | bool has_termination_handler() const; 35 | //The unwind info structure is not the primary one for the procedure 36 | bool is_chaininfo() const; 37 | 38 | //Returns size of function prolog 39 | uint8_t get_size_of_prolog() const; 40 | 41 | //Returns number of unwind slots 42 | uint8_t get_number_of_unwind_slots() const; 43 | 44 | //If the function uses frame pointer 45 | bool uses_frame_pointer() const; 46 | //Number of the nonvolatile register used as the frame pointer, 47 | //using the same encoding for the operation info field of UNWIND_CODE nodes 48 | uint8_t get_frame_pointer_register_number() const; 49 | //The scaled offset from RSP that is applied to the FP reg when it is established. 50 | //The actual FP reg is set to RSP + 16 * this number, allowing offsets from 0 to 240 51 | uint8_t get_scaled_rsp_offset() const; 52 | 53 | private: 54 | uint32_t begin_address_, end_address_, unwind_info_address_; 55 | uint8_t unwind_info_version_; 56 | uint8_t flags_; 57 | uint8_t size_of_prolog_; 58 | uint8_t count_of_codes_; 59 | uint8_t frame_register_, frame_offset_; 60 | }; 61 | 62 | typedef std::vector exception_entry_list; 63 | 64 | //Returns exception directory data (exists on PE+ only) 65 | //Unwind opcodes are not listed, because their format and list are subject to change 66 | const exception_entry_list get_exception_directory_data(const pe_base& pe); 67 | } 68 | -------------------------------------------------------------------------------- /src/pe_lib/pe_factory.cpp: -------------------------------------------------------------------------------- 1 | #include "pe_factory.h" 2 | #include "pe_properties_generic.h" 3 | 4 | namespace pe_bliss 5 | { 6 | pe_base pe_factory::create_pe(std::istream& file, bool is_file_from_mem, bool read_debug_raw_data) 7 | { 8 | return pe_base::get_pe_type(file) == pe_type_32 9 | ? pe_base(file, pe_properties_32(), is_file_from_mem, read_debug_raw_data) 10 | : pe_base(file, pe_properties_64(), is_file_from_mem, read_debug_raw_data); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/pe_lib/pe_factory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "pe_base.h" 5 | 6 | namespace pe_bliss 7 | { 8 | class pe_factory 9 | { 10 | public: 11 | //Creates pe_base class instance from PE or PE+ istream 12 | //If read_bound_import_raw_data, raw bound import data will be read (used to get bound import info) 13 | //If read_debug_raw_data, raw debug data will be read (used to get image debug info) 14 | static pe_base create_pe(std::istream& file, bool is_file_from_mem = false, bool read_debug_raw_data = true); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /src/pe_lib/pe_properties.cpp: -------------------------------------------------------------------------------- 1 | #include "pe_properties.h" 2 | 3 | namespace pe_bliss 4 | { 5 | //Destructor 6 | pe_properties::~pe_properties() 7 | {} 8 | 9 | //Clears PE characteristics flag 10 | void pe_properties::clear_characteristics_flags(uint16_t flags) 11 | { 12 | set_characteristics(get_characteristics() & ~flags); 13 | } 14 | 15 | //Sets PE characteristics flag 16 | void pe_properties::set_characteristics_flags(uint16_t flags) 17 | { 18 | set_characteristics(get_characteristics() | flags); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/pe_lib/pe_rebuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace pe_bliss 5 | { 6 | class pe_base; 7 | //Rebuilds PE image, writes resulting image to ostream "out". If strip_dos_header == true, DOS header will be stripped a little 8 | //If change_size_of_headers == true, SizeOfHeaders will be recalculated automatically 9 | //If save_bound_import == true, existing bound import directory will be saved correctly (because some compilers and bind.exe put it to PE headers) 10 | void rebuild_pe(pe_base& pe, std::ostream& out, bool strip_dos_header = false, bool change_size_of_headers = true, bool save_bound_import = true); 11 | } 12 | -------------------------------------------------------------------------------- /src/pe_lib/pe_relocations.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "pe_structures.h" 4 | #include "pe_base.h" 5 | #include "pe_directory.h" 6 | 7 | namespace pe_bliss 8 | { 9 | //Class representing relocation entry 10 | //RVA of relocation is not actually RVA, but 11 | //(real RVA) - (RVA of table) 12 | class relocation_entry 13 | { 14 | public: 15 | //Default constructor 16 | relocation_entry(); 17 | //Constructor from relocation item (WORD) 18 | explicit relocation_entry(uint16_t relocation_value); 19 | //Constructor from relative rva and relocation type 20 | relocation_entry(uint16_t rrva, uint16_t type); 21 | 22 | //Returns RVA of relocation (actually, relative RVA from relocation table RVA) 23 | uint16_t get_rva() const; 24 | //Returns type of relocation 25 | uint16_t get_type() const; 26 | 27 | //Returns relocation item (rrva + type) 28 | uint16_t get_item() const; 29 | 30 | public: //Setters do not change everything inside image, they are used by PE class 31 | //You can also use them to rebuild relocations using rebuild_relocations() 32 | 33 | //Sets RVA of relocation (actually, relative RVA from relocation table RVA) 34 | void set_rva(uint16_t rva); 35 | //Sets type of relocation 36 | void set_type(uint16_t type); 37 | 38 | //Sets relocation item (rrva + type) 39 | void set_item(uint16_t item); 40 | 41 | private: 42 | uint16_t rva_; 43 | uint16_t type_; 44 | }; 45 | 46 | //Class representing relocation table 47 | class relocation_table 48 | { 49 | public: 50 | typedef std::vector relocation_list; 51 | 52 | public: 53 | //Default constructor 54 | relocation_table(); 55 | //Constructor from RVA of relocation table 56 | explicit relocation_table(uint32_t rva); 57 | 58 | //Returns relocation list 59 | const relocation_list& get_relocations() const; 60 | //Returns RVA of block 61 | uint32_t get_rva() const; 62 | 63 | public: //These functions do not change everything inside image, they are used by PE class 64 | //You can also use them to rebuild relocations using rebuild_relocations() 65 | 66 | //Adds relocation to table 67 | void add_relocation(const relocation_entry& entry); 68 | //Returns changeable relocation list 69 | relocation_list& get_relocations(); 70 | //Sets RVA of block 71 | void set_rva(uint32_t rva); 72 | 73 | private: 74 | uint32_t rva_; 75 | relocation_list relocations_; 76 | }; 77 | 78 | typedef std::vector relocation_table_list; 79 | 80 | //Get relocation list of pe file, supports one-word sized relocations only 81 | //If list_absolute_entries = true, IMAGE_REL_BASED_ABSOLUTE will be listed 82 | const relocation_table_list get_relocations(const pe_base& pe, bool list_absolute_entries = false); 83 | 84 | //Simple relocations rebuilder 85 | //To keep PE file working, don't remove any of existing relocations in 86 | //relocation_table_list returned by a call to get_relocations() function 87 | //auto_strip_last_section - if true and relocations are placed in the last section, it will be automatically stripped 88 | //offset_from_section_start - offset from the beginning of reloc_section, where relocations data will be situated 89 | //If save_to_pe_header is true, PE header will be modified automatically 90 | const image_directory rebuild_relocations(pe_base& pe, const relocation_table_list& relocs, section& reloc_section, uint32_t offset_from_section_start = 0, bool save_to_pe_header = true, bool auto_strip_last_section = true); 91 | 92 | //Recalculates image base with the help of relocation tables 93 | //Recalculates VAs of DWORDS/QWORDS in image according to relocations 94 | //Notice: if you move some critical structures like TLS, image relocations will not fix new 95 | //positions of TLS VAs. Instead, some bytes that now doesn't belong to TLS will be fixed. 96 | //It is recommended to rebase image in the very beginning and move all structures afterwards. 97 | void rebase_image(pe_base& pe, const relocation_table_list& tables, uint64_t new_base); 98 | 99 | template 100 | void rebase_image_base(pe_base& pe, const relocation_table_list& tables, uint64_t new_base); 101 | } 102 | -------------------------------------------------------------------------------- /src/pe_lib/pe_rich_data.cpp: -------------------------------------------------------------------------------- 1 | #include "pe_rich_data.h" 2 | 3 | namespace pe_bliss 4 | { 5 | //STUB OVERLAY 6 | //Default constructor 7 | rich_data::rich_data() 8 | :number_(0), version_(0), times_(0) 9 | {} 10 | 11 | //Who knows, what these fields mean... 12 | uint32_t rich_data::get_number() const 13 | { 14 | return number_; 15 | } 16 | 17 | uint32_t rich_data::get_version() const 18 | { 19 | return version_; 20 | } 21 | 22 | uint32_t rich_data::get_times() const 23 | { 24 | return times_; 25 | } 26 | 27 | void rich_data::set_number(uint32_t number) 28 | { 29 | number_ = number; 30 | } 31 | 32 | void rich_data::set_version(uint32_t version) 33 | { 34 | version_ = version; 35 | } 36 | 37 | void rich_data::set_times(uint32_t times) 38 | { 39 | times_ = times; 40 | } 41 | 42 | //Returns MSVC rich data 43 | const rich_data_list get_rich_data(const pe_base& pe) 44 | { 45 | //Returned value 46 | rich_data_list ret; 47 | 48 | const std::string& rich_overlay = pe.get_stub_overlay(); 49 | 50 | //If there's no rich overlay, return empty vector 51 | if(rich_overlay.size() < sizeof(uint32_t)) 52 | return ret; 53 | 54 | //True if rich data was found 55 | bool found = false; 56 | 57 | //Rich overlay ID ("Rich" word) 58 | static const uint32_t rich_overlay_id = 0x68636952; 59 | 60 | //Search for rich data overlay ID 61 | const char* begin = &rich_overlay[0]; 62 | const char* end = begin + rich_overlay.length(); 63 | for(; begin != end; ++begin) 64 | { 65 | if(*reinterpret_cast(begin) == rich_overlay_id) 66 | { 67 | found = true; //We've found it! 68 | break; 69 | } 70 | } 71 | 72 | //If we found it 73 | if(found) 74 | { 75 | //Check remaining length 76 | if(static_cast(end - begin) < sizeof(uint32_t)) 77 | return ret; 78 | 79 | //The XOR key is after "Rich" word, we should get it 80 | uint32_t xorkey = *reinterpret_cast(begin + sizeof(uint32_t)); 81 | 82 | //True if rich data was found 83 | found = false; 84 | 85 | //Second search for signature "DanS" 86 | begin = &rich_overlay[0]; 87 | for(; begin != end; ++begin) 88 | { 89 | if((*reinterpret_cast(begin) ^ xorkey) == 0x536e6144) //"DanS" 90 | { 91 | found = true; 92 | break; 93 | } 94 | } 95 | 96 | //If second signature is found 97 | if(found) 98 | { 99 | begin += sizeof(uint32_t) * 3; 100 | //List all rich data structures 101 | while(begin < end) 102 | { 103 | begin += sizeof(uint32_t); 104 | if(begin >= end) 105 | break; 106 | 107 | //Check for rich overlay data end ("Rich" word reached) 108 | if(*reinterpret_cast(begin) == rich_overlay_id) 109 | break; 110 | 111 | //Create rich_data structure 112 | rich_data data; 113 | data.set_number((*reinterpret_cast(begin) ^ xorkey) >> 16); 114 | data.set_version((*reinterpret_cast(begin) ^ xorkey) & 0xFFFF); 115 | 116 | begin += sizeof(uint32_t); 117 | if(begin >= end) 118 | break; 119 | 120 | data.set_times(*reinterpret_cast(begin) ^ xorkey); 121 | 122 | //Save rich data structure 123 | ret.push_back(data); 124 | } 125 | } 126 | } 127 | 128 | //Return rich data structures list 129 | return ret; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/pe_lib/pe_rich_data.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "pe_structures.h" 4 | #include "pe_base.h" 5 | 6 | namespace pe_bliss 7 | { 8 | //Rich data overlay class of Microsoft Visual Studio 9 | class rich_data 10 | { 11 | public: 12 | //Default constructor 13 | rich_data(); 14 | 15 | public: //Getters 16 | //Who knows, what these fields mean... 17 | uint32_t get_number() const; 18 | uint32_t get_version() const; 19 | uint32_t get_times() const; 20 | 21 | public: //Setters, used by PE library only 22 | void set_number(uint32_t number); 23 | void set_version(uint32_t version); 24 | void set_times(uint32_t times); 25 | 26 | private: 27 | uint32_t number_; 28 | uint32_t version_; 29 | uint32_t times_; 30 | }; 31 | 32 | //Rich data list typedef 33 | typedef std::vector rich_data_list; 34 | 35 | //Returns a vector with rich data (stub overlay) 36 | const rich_data_list get_rich_data(const pe_base& pe); 37 | } 38 | -------------------------------------------------------------------------------- /src/pe_lib/pe_tls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "pe_base.h" 5 | #include "pe_directory.h" 6 | 7 | namespace pe_bliss 8 | { 9 | //Class representing TLS info 10 | //We use "DWORD" type to represent RVAs, because RVA is 11 | //always 32bit even in PE+ 12 | class tls_info 13 | { 14 | public: 15 | typedef std::vector tls_callback_list; 16 | 17 | public: 18 | //Default constructor 19 | tls_info(); 20 | 21 | //Returns start RVA of TLS raw data 22 | uint32_t get_raw_data_start_rva() const; 23 | //Returns end RVA of TLS raw data 24 | uint32_t get_raw_data_end_rva() const; 25 | //Returns TLS index RVA 26 | uint32_t get_index_rva() const; 27 | //Returns TLS callbacks RVA 28 | uint32_t get_callbacks_rva() const; 29 | //Returns size of zero fill 30 | uint32_t get_size_of_zero_fill() const; 31 | //Returns characteristics 32 | uint32_t get_characteristics() const; 33 | //Returns raw TLS data 34 | const std::string& get_raw_data() const; 35 | //Returns TLS callbacks addresses 36 | const tls_callback_list& get_tls_callbacks() const; 37 | 38 | public: //These functions do not change everything inside image, they are used by PE class 39 | //You can also use them to rebuild TLS directory 40 | 41 | //Sets start RVA of TLS raw data 42 | void set_raw_data_start_rva(uint32_t rva); 43 | //Sets end RVA of TLS raw data 44 | void set_raw_data_end_rva(uint32_t rva); 45 | //Sets TLS index RVA 46 | void set_index_rva(uint32_t rva); 47 | //Sets TLS callbacks RVA 48 | void set_callbacks_rva(uint32_t rva); 49 | //Sets size of zero fill 50 | void set_size_of_zero_fill(uint32_t size); 51 | //Sets characteristics 52 | void set_characteristics(uint32_t characteristics); 53 | //Sets raw TLS data 54 | void set_raw_data(const std::string& data); 55 | //Returns TLS callbacks addresses 56 | tls_callback_list& get_tls_callbacks(); 57 | //Adds TLS callback 58 | void add_tls_callback(uint32_t rva); 59 | //Clears TLS callbacks list 60 | void clear_tls_callbacks(); 61 | //Recalculates end address of raw TLS data 62 | void recalc_raw_data_end_rva(); 63 | 64 | private: 65 | uint32_t start_rva_, end_rva_, index_rva_, callbacks_rva_; 66 | uint32_t size_of_zero_fill_, characteristics_; 67 | 68 | //Raw TLS data 69 | std::string raw_data_; 70 | 71 | //TLS callback RVAs 72 | tls_callback_list callbacks_; 73 | }; 74 | 75 | //Represents type of expanding of TLS section containing raw data 76 | //(Works only if you are writing TLS raw data to tls_section and it is the last one in the PE image on the moment of TLS rebuild) 77 | enum tls_data_expand_type 78 | { 79 | tls_data_expand_raw, //If there is not enough raw space for raw TLS data, it can be expanded 80 | tls_data_expand_virtual //If there is not enough virtual place for raw TLS data, it can be expanded 81 | }; 82 | 83 | 84 | //Get TLS info 85 | //If image does not have TLS, throws an exception 86 | const tls_info get_tls_info(const pe_base& pe); 87 | 88 | template 89 | const tls_info get_tls_info_base(const pe_base& pe); 90 | 91 | //Rebuilder of TLS structures 92 | //If write_tls_callbacks = true, TLS callbacks VAs will be written to their place 93 | //If write_tls_data = true, TLS data will be written to its place 94 | //If you have chosen to rewrite raw data, only (EndAddressOfRawData - StartAddressOfRawData) bytes will be written, not the full length of string 95 | //representing raw data content 96 | //auto_strip_last_section - if true and TLS are placed in the last section, it will be automatically stripped 97 | const image_directory rebuild_tls(pe_base& pe, const tls_info& info, section& tls_section, uint32_t offset_from_section_start = 0, bool write_tls_callbacks = true, bool write_tls_data = true, tls_data_expand_type expand = tls_data_expand_raw, bool save_to_pe_header = true, bool auto_strip_last_section = true); 98 | 99 | template 100 | const image_directory rebuild_tls_base(pe_base& pe, const tls_info& info, section& tls_section, uint32_t offset_from_section_start = 0, bool write_tls_callbacks = true, bool write_tls_data = true, tls_data_expand_type expand = tls_data_expand_raw, bool save_to_pe_header = true, bool auto_strip_last_section = true); 101 | } 102 | -------------------------------------------------------------------------------- /src/pe_lib/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/pe_lib/readme.txt -------------------------------------------------------------------------------- /src/pe_lib/resource_bitmap_reader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "resource_bitmap_reader.h" 3 | #include "pe_resource_viewer.h" 4 | #include "pe_structures.h" 5 | 6 | namespace pe_bliss 7 | { 8 | using namespace pe_win; 9 | 10 | resource_bitmap_reader::resource_bitmap_reader(const pe_resource_viewer& res) 11 | :res_(res) 12 | {} 13 | 14 | //Returns bitmap data by name and index in language directory (instead of language) (minimum checks of format correctness) 15 | const std::string resource_bitmap_reader::get_bitmap_by_name(const std::wstring& name, uint32_t index) const 16 | { 17 | return create_bitmap(res_.get_resource_data_by_name(pe_resource_viewer::resource_bitmap, name, index).get_data()); 18 | } 19 | 20 | //Returns bitmap data by name and language (minimum checks of format correctness) 21 | const std::string resource_bitmap_reader::get_bitmap_by_name(uint32_t language, const std::wstring& name) const 22 | { 23 | return create_bitmap(res_.get_resource_data_by_name(language, pe_resource_viewer::resource_bitmap, name).get_data()); 24 | } 25 | 26 | //Returns bitmap data by ID and language (minimum checks of format correctness) 27 | const std::string resource_bitmap_reader::get_bitmap_by_id_lang(uint32_t language, uint32_t id) const 28 | { 29 | return create_bitmap(res_.get_resource_data_by_id(language, pe_resource_viewer::resource_bitmap, id).get_data()); 30 | } 31 | 32 | //Returns bitmap data by ID and index in language directory (instead of language) (minimum checks of format correctness) 33 | const std::string resource_bitmap_reader::get_bitmap_by_id(uint32_t id, uint32_t index) const 34 | { 35 | return create_bitmap(res_.get_resource_data_by_id(pe_resource_viewer::resource_bitmap, id, index).get_data()); 36 | } 37 | 38 | //Helper function of creating bitmap header 39 | const std::string resource_bitmap_reader::create_bitmap(const std::string& resource_data) 40 | { 41 | //Create bitmap file header 42 | bitmapfileheader header = {0}; 43 | header.bfType = 0x4d42; //Signature "BM" 44 | header.bfOffBits = sizeof(bitmapfileheader) + sizeof(bitmapinfoheader); //Offset to bitmap bits 45 | header.bfSize = static_cast(sizeof(bitmapfileheader) + resource_data.length()); //Size of bitmap 46 | 47 | //Check size of resource data 48 | if(resource_data.length() < sizeof(bitmapinfoheader)) 49 | throw pe_exception("Incorrect resource bitmap", pe_exception::resource_incorrect_bitmap); 50 | 51 | { 52 | //Get bitmap info header 53 | const bitmapinfoheader* info = reinterpret_cast(resource_data.data()); 54 | 55 | //If color table is present, skip it 56 | if(info->biClrUsed != 0) 57 | header.bfOffBits += 4 * info->biClrUsed; //Add this size to offset to bitmap bits 58 | else if(info->biBitCount <= 8) 59 | header.bfOffBits += 4 * static_cast(std::pow(2.f, info->biBitCount)); //Add this size to offset to bitmap bits 60 | } 61 | 62 | //Return final bitmap data 63 | return std::string(reinterpret_cast(&header), sizeof(bitmapfileheader)) + resource_data; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/pe_lib/resource_bitmap_reader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "stdint_defs.h" 4 | 5 | namespace pe_bliss 6 | { 7 | class pe_resource_viewer; 8 | 9 | class resource_bitmap_reader 10 | { 11 | public: 12 | resource_bitmap_reader(const pe_resource_viewer& res); 13 | 14 | //Returns bitmap data by name and language (minimum checks of format correctness) 15 | const std::string get_bitmap_by_name(uint32_t language, const std::wstring& name) const; 16 | //Returns bitmap data by name and index in language directory (instead of language) (minimum checks of format correctness) 17 | const std::string get_bitmap_by_name(const std::wstring& name, uint32_t index = 0) const; 18 | //Returns bitmap data by ID and language (minimum checks of format correctness) 19 | const std::string get_bitmap_by_id_lang(uint32_t language, uint32_t id) const; 20 | //Returns bitmap data by ID and index in language directory (instead of language) (minimum checks of format correctness) 21 | const std::string get_bitmap_by_id(uint32_t id, uint32_t index = 0) const; 22 | 23 | private: 24 | //Helper function of creating bitmap header 25 | static const std::string create_bitmap(const std::string& resource_data); 26 | 27 | const pe_resource_viewer& res_; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /src/pe_lib/resource_bitmap_writer.cpp: -------------------------------------------------------------------------------- 1 | #include "resource_bitmap_writer.h" 2 | #include "pe_resource_manager.h" 3 | #include "pe_structures.h" 4 | 5 | namespace pe_bliss 6 | { 7 | using namespace pe_win; 8 | 9 | resource_bitmap_writer::resource_bitmap_writer(pe_resource_manager& res) 10 | :res_(res) 11 | {} 12 | 13 | //Adds bitmap from bitmap file data. If bitmap already exists, replaces it 14 | //timestamp will be used for directories that will be added 15 | void resource_bitmap_writer::add_bitmap(const std::string& bitmap_file, uint32_t id, uint32_t language, uint32_t codepage, uint32_t timestamp) 16 | { 17 | //Check bitmap data a little 18 | if(bitmap_file.length() < sizeof(bitmapfileheader)) 19 | throw pe_exception("Incorrect resource bitmap", pe_exception::resource_incorrect_bitmap); 20 | 21 | resource_directory_entry new_entry; 22 | new_entry.set_id(id); 23 | 24 | //Add bitmap 25 | res_.add_resource(bitmap_file.substr(sizeof(bitmapfileheader)), pe_resource_viewer::resource_bitmap, new_entry, resource_directory::entry_finder(id), language, codepage, timestamp); 26 | } 27 | 28 | //Adds bitmap from bitmap file data. If bitmap already exists, replaces it 29 | //timestamp will be used for directories that will be added 30 | void resource_bitmap_writer::add_bitmap(const std::string& bitmap_file, const std::wstring& name, uint32_t language, uint32_t codepage, uint32_t timestamp) 31 | { 32 | //Check bitmap data a little 33 | if(bitmap_file.length() < sizeof(bitmapfileheader)) 34 | throw pe_exception("Incorrect resource bitmap", pe_exception::resource_incorrect_bitmap); 35 | 36 | resource_directory_entry new_entry; 37 | new_entry.set_name(name); 38 | 39 | //Add bitmap 40 | res_.add_resource(bitmap_file.substr(sizeof(bitmapfileheader)), pe_resource_viewer::resource_bitmap, new_entry, resource_directory::entry_finder(name), language, codepage, timestamp); 41 | } 42 | 43 | //Removes bitmap by name/ID and language 44 | bool resource_bitmap_writer::remove_bitmap(const std::wstring& name, uint32_t language) 45 | { 46 | return res_.remove_resource(pe_resource_viewer::resource_bitmap, name, language); 47 | } 48 | 49 | //Removes bitmap by name/ID and language 50 | bool resource_bitmap_writer::remove_bitmap(uint32_t id, uint32_t language) 51 | { 52 | return res_.remove_resource(pe_resource_viewer::resource_bitmap, id, language); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/pe_lib/resource_bitmap_writer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "stdint_defs.h" 4 | 5 | namespace pe_bliss 6 | { 7 | class pe_resource_manager; 8 | 9 | class resource_bitmap_writer 10 | { 11 | public: 12 | resource_bitmap_writer(pe_resource_manager& res); 13 | 14 | //Adds bitmap from bitmap file data. If bitmap already exists, replaces it 15 | //timestamp will be used for directories that will be added 16 | void add_bitmap(const std::string& bitmap_file, uint32_t id, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0); 17 | void add_bitmap(const std::string& bitmap_file, const std::wstring& name, uint32_t language, uint32_t codepage = 0, uint32_t timestamp = 0); 18 | 19 | //Removes bitmap by name/ID and language 20 | bool remove_bitmap(const std::wstring& name, uint32_t language); 21 | bool remove_bitmap(uint32_t id, uint32_t language); 22 | 23 | private: 24 | pe_resource_manager& res_; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /src/pe_lib/resource_cursor_icon_reader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "stdint_defs.h" 4 | 5 | namespace pe_bliss 6 | { 7 | class pe_resource_viewer; 8 | 9 | class resource_cursor_icon_reader 10 | { 11 | public: 12 | resource_cursor_icon_reader(const pe_resource_viewer& res); 13 | 14 | //Returns single icon data by ID and language (minimum checks of format correctness) 15 | const std::string get_single_icon_by_id_lang(uint32_t language, uint32_t id) const; 16 | //Returns single icon data by ID and index in language directory (instead of language) (minimum checks of format correctness) 17 | const std::string get_single_icon_by_id(uint32_t id, uint32_t index = 0) const; 18 | 19 | //Returns icon data of group of icons by name and language (minimum checks of format correctness) 20 | const std::string get_icon_by_name(uint32_t language, const std::wstring& icon_group_name) const; 21 | //Returns icon data of group of icons by name and index in language directory (instead of language) (minimum checks of format correctness) 22 | const std::string get_icon_by_name(const std::wstring& icon_group_name, uint32_t index = 0) const; 23 | //Returns icon data of group of icons by ID and language (minimum checks of format correctness) 24 | const std::string get_icon_by_id_lang(uint32_t language, uint32_t icon_group_id) const; 25 | //Returns icon data of group of icons by ID and index in language directory (instead of language) (minimum checks of format correctness) 26 | const std::string get_icon_by_id(uint32_t icon_group_id, uint32_t index = 0) const; 27 | 28 | //Returns single cursor data by ID and language (minimum checks of format correctness) 29 | const std::string get_single_cursor_by_id_lang(uint32_t language, uint32_t id) const; 30 | //Returns single cursor data by ID and index in language directory (instead of language) (minimum checks of format correctness) 31 | const std::string get_single_cursor_by_id(uint32_t id, uint32_t index = 0) const; 32 | 33 | //Returns cursor data by name and language (minimum checks of format correctness) 34 | const std::string get_cursor_by_name(uint32_t language, const std::wstring& cursor_group_name) const; 35 | //Returns cursor data by name and index in language directory (instead of language) (minimum checks of format correctness) 36 | const std::string get_cursor_by_name(const std::wstring& cursor_group_name, uint32_t index = 0) const; 37 | //Returns cursor data by ID and language (minimum checks of format correctness) 38 | const std::string get_cursor_by_id_lang(uint32_t language, uint32_t cursor_group_id) const; 39 | //Returns cursor data by ID and index in language directory (instead of language) (minimum checks of format correctness) 40 | const std::string get_cursor_by_id(uint32_t cursor_group_id, uint32_t index = 0) const; 41 | 42 | private: 43 | const pe_resource_viewer& res_; 44 | 45 | //Helper function of creating icon headers from ICON_GROUP resource data 46 | //Returns icon count 47 | static uint16_t format_icon_headers(std::string& ico_data, const std::string& resource_data); 48 | 49 | //Helper function of creating cursor headers from CURSOR_GROUP resource data 50 | //Returns cursor count 51 | uint16_t format_cursor_headers(std::string& cur_data, const std::string& resource_data, uint32_t language, uint32_t index = 0xFFFFFFFF) const; 52 | 53 | //Looks up icon group by icon id and returns full icon headers if found 54 | const std::string lookup_icon_group_data_by_icon(uint32_t icon_id, uint32_t language) const; 55 | //Checks for icon presence inside icon group, fills icon headers if found 56 | static bool check_icon_presence(const std::string& icon_group_resource_data, uint32_t icon_id, std::string& ico_data); 57 | 58 | //Looks up cursor group by cursor id and returns full cursor headers if found 59 | const std::string lookup_cursor_group_data_by_cursor(uint32_t cursor_id, uint32_t language, const std::string& raw_cursor_data) const; 60 | //Checks for cursor presence inside cursor group, fills cursor headers if found 61 | static bool check_cursor_presence(const std::string& icon_group_resource_data, uint32_t cursor_id, std::string& cur_header_data, const std::string& raw_cursor_data); 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /src/pe_lib/resource_cursor_icon_writer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "stdint_defs.h" 5 | #include "pe_resource_manager.h" 6 | 7 | namespace pe_bliss 8 | { 9 | class pe_resource_manager; 10 | 11 | class resource_cursor_icon_writer 12 | { 13 | public: 14 | //Determines, how new icon(s) or cursor(s) will be placed 15 | enum icon_place_mode 16 | { 17 | icon_place_after_max_icon_id, //Icon(s) will be placed after all existing 18 | icon_place_free_ids //New icon(s) will take all free IDs between existing icons 19 | }; 20 | 21 | public: 22 | resource_cursor_icon_writer(pe_resource_manager& res); 23 | 24 | //Removes icon group and all its icons by name/ID and language 25 | bool remove_icon_group(const std::wstring& icon_group_name, uint32_t language); 26 | bool remove_icon_group(uint32_t icon_group_id, uint32_t language); 27 | 28 | //Adds icon(s) from icon file data 29 | //timestamp will be used for directories that will be added 30 | //If icon group with name "icon_group_name" or ID "icon_group_id" already exists, it will be appended with new icon(s) 31 | //(Codepage of icon group and icons will not be changed in this case) 32 | //icon_place_mode determines, how new icon(s) will be placed 33 | void add_icon(const std::string& icon_file, 34 | const std::wstring& icon_group_name, 35 | uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id, 36 | uint32_t codepage = 0, uint32_t timestamp = 0); 37 | 38 | void add_icon(const std::string& icon_file, 39 | uint32_t icon_group_id, 40 | uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id, 41 | uint32_t codepage = 0, uint32_t timestamp = 0); 42 | 43 | //Removes cursor group and all its cursors by name/ID and language 44 | bool remove_cursor_group(const std::wstring& cursor_group_name, uint32_t language); 45 | bool remove_cursor_group(uint32_t cursor_group_id, uint32_t language); 46 | 47 | //Adds cursor(s) from cursor file data 48 | //timestamp will be used for directories that will be added 49 | //If cursor group with name "cursor_group_name" or ID "cursor_group_id" already exists, it will be appended with new cursor(s) 50 | //(Codepage of cursor group and cursors will not be changed in this case) 51 | //icon_place_mode determines, how new cursor(s) will be placed 52 | void add_cursor(const std::string& cursor_file, const std::wstring& cursor_group_name, uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id, uint32_t codepage = 0, uint32_t timestamp = 0); 53 | void add_cursor(const std::string& cursor_file, uint32_t cursor_group_id, uint32_t language, icon_place_mode mode = icon_place_after_max_icon_id, uint32_t codepage = 0, uint32_t timestamp = 0); 54 | 55 | private: 56 | pe_resource_manager& res_; 57 | 58 | //Add icon helper 59 | void add_icon(const std::string& icon_file, const resource_data_info* group_icon_info /* or zero */, resource_directory_entry& new_icon_group_entry, const resource_directory::entry_finder& finder, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp); 60 | 61 | //Remove icon group helper 62 | void remove_icons_from_icon_group(const std::string& icon_group_data, uint32_t language); 63 | 64 | //Add cursor helper 65 | void add_cursor(const std::string& cursor_file, const resource_data_info* group_cursor_info /* or zero */, resource_directory_entry& new_cursor_group_entry, const resource_directory::entry_finder& finder, uint32_t language, icon_place_mode mode, uint32_t codepage, uint32_t timestamp); 66 | 67 | //Remove cursor group helper 68 | void remove_cursors_from_cursor_group(const std::string& cursor_group_data, uint32_t language); 69 | 70 | //Returns free icon or cursor ID list depending on icon_place_mode 71 | const std::vector get_icon_or_cursor_free_id_list(pe_resource_manager::resource_type type, icon_place_mode mode, uint32_t count); 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /src/pe_lib/resource_data_info.cpp: -------------------------------------------------------------------------------- 1 | #include "resource_data_info.h" 2 | #include "pe_resource_viewer.h" 3 | 4 | namespace pe_bliss 5 | { 6 | //Default constructor 7 | resource_data_info::resource_data_info(const std::string& data, uint32_t codepage) 8 | :data_(data), codepage_(codepage) 9 | {} 10 | 11 | //Constructor from data 12 | resource_data_info::resource_data_info(const resource_data_entry& data) 13 | :data_(data.get_data()), codepage_(data.get_codepage()) 14 | {} 15 | 16 | //Returns resource data 17 | const std::string& resource_data_info::get_data() const 18 | { 19 | return data_; 20 | } 21 | 22 | //Returns resource codepage 23 | uint32_t resource_data_info::get_codepage() const 24 | { 25 | return codepage_; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/pe_lib/resource_data_info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "stdint_defs.h" 4 | 5 | namespace pe_bliss 6 | { 7 | class resource_data_entry; 8 | 9 | //Class representing resource data 10 | class resource_data_info 11 | { 12 | public: 13 | //Constructor from data 14 | resource_data_info(const std::string& data, uint32_t codepage); 15 | //Constructor from data 16 | explicit resource_data_info(const resource_data_entry& data); 17 | 18 | //Returns resource data 19 | const std::string& get_data() const; 20 | //Returns resource codepage 21 | uint32_t get_codepage() const; 22 | 23 | private: 24 | std::string data_; 25 | uint32_t codepage_; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/pe_lib/resource_internal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define U16TEXT(t) reinterpret_cast( t ) 4 | 5 | #define StringFileInfo U16TEXT("S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0") 6 | #define SizeofStringFileInfo sizeof("S\0t\0r\0i\0n\0g\0F\0i\0l\0e\0I\0n\0f\0o\0\0") 7 | #define VarFileInfo U16TEXT("V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0") 8 | #define Translation U16TEXT("T\0r\0a\0n\0s\0l\0a\0t\0i\0o\0n\0\0") 9 | 10 | #define VarFileInfoAligned U16TEXT("V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0\0") 11 | #define TranslationAligned U16TEXT("T\0r\0a\0n\0s\0l\0a\0t\0i\0o\0n\0\0\0\0") 12 | #define SizeofVarFileInfoAligned sizeof("V\0a\0r\0F\0i\0l\0e\0I\0n\0f\0o\0\0\0\0") 13 | #define SizeofTranslationAligned sizeof("T\0r\0a\0n\0s\0l\0a\0t\0i\0o\0n\0\0\0\0") 14 | -------------------------------------------------------------------------------- /src/pe_lib/resource_message_list_reader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "message_table.h" 3 | 4 | namespace pe_bliss 5 | { 6 | class pe_resource_viewer; 7 | 8 | //ID; message_table_item 9 | typedef std::map resource_message_list; 10 | 11 | class resource_message_list_reader 12 | { 13 | public: 14 | resource_message_list_reader(const pe_resource_viewer& res); 15 | 16 | //Returns message table data by ID and language 17 | const resource_message_list get_message_table_by_id_lang(uint32_t language, uint32_t id) const; 18 | //Returns message table data by ID and index in language directory (instead of language) 19 | const resource_message_list get_message_table_by_id(uint32_t id, uint32_t index = 0) const; 20 | 21 | //Helper function of parsing message list table 22 | //resource_data - raw message table resource data 23 | static const resource_message_list parse_message_list(const std::string& resource_data); 24 | 25 | private: 26 | const pe_resource_viewer& res_; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /src/pe_lib/resource_string_table_reader.cpp: -------------------------------------------------------------------------------- 1 | #include "resource_string_table_reader.h" 2 | #include "pe_resource_viewer.h" 3 | 4 | namespace pe_bliss 5 | { 6 | resource_string_table_reader::resource_string_table_reader(const pe_resource_viewer& res) 7 | :res_(res) 8 | {} 9 | 10 | //Returns string table data by ID and index in language directory (instead of language) 11 | const resource_string_list resource_string_table_reader::get_string_table_by_id(uint32_t id, uint32_t index) const 12 | { 13 | return parse_string_list(id, res_.get_resource_data_by_id(pe_resource_viewer::resource_string, id, index).get_data()); 14 | } 15 | 16 | //Returns string table data by ID and language 17 | const resource_string_list resource_string_table_reader::get_string_table_by_id_lang(uint32_t language, uint32_t id) const 18 | { 19 | return parse_string_list(id, res_.get_resource_data_by_id(language, pe_resource_viewer::resource_string, id).get_data()); 20 | } 21 | 22 | //Helper function of parsing string list table 23 | const resource_string_list resource_string_table_reader::parse_string_list(uint32_t id, const std::string& resource_data) 24 | { 25 | resource_string_list ret; 26 | 27 | //16 is maximum count of strings in a string table 28 | static const uint32_t max_string_list_entries = 16; 29 | uint32_t passed_bytes = 0; 30 | for(uint32_t i = 0; i != max_string_list_entries; ++i) 31 | { 32 | //Check resource data length 33 | if(resource_data.length() < sizeof(uint16_t) + passed_bytes) 34 | throw pe_exception("Incorrect resource string table", pe_exception::resource_incorrect_string_table); 35 | 36 | //Get string length - the first WORD 37 | uint16_t string_length = *reinterpret_cast(resource_data.data() + passed_bytes); 38 | passed_bytes += sizeof(uint16_t); //WORD containing string length 39 | 40 | //Check resource data length again 41 | if(resource_data.length() < string_length + passed_bytes) 42 | throw pe_exception("Incorrect resource string table", pe_exception::resource_incorrect_string_table); 43 | 44 | if(string_length) 45 | { 46 | //Create and save string (UNICODE) 47 | #ifdef PE_BLISS_WINDOWS 48 | ret.insert( 49 | std::make_pair(static_cast(((id - 1) << 4) + i), //ID of string is calculated such way 50 | std::wstring(reinterpret_cast(resource_data.data() + passed_bytes), string_length))); 51 | #else 52 | ret.insert( 53 | std::make_pair(static_cast(((id - 1) << 4) + i), //ID of string is calculated such way 54 | pe_utils::from_ucs2(u16string(reinterpret_cast(resource_data.data() + passed_bytes), string_length)))); 55 | #endif 56 | } 57 | 58 | //Go to next string 59 | passed_bytes += string_length * 2; 60 | } 61 | 62 | return ret; 63 | } 64 | 65 | //Returns string from string table by ID and language 66 | const std::wstring resource_string_table_reader::get_string_by_id_lang(uint32_t language, uint16_t id) const 67 | { 68 | //List strings by string table id and language 69 | const resource_string_list strings(get_string_table_by_id_lang(language, (id >> 4) + 1)); 70 | resource_string_list::const_iterator it = strings.find(id); //Find string by id 71 | if(it == strings.end()) 72 | throw pe_exception("Resource string not found", pe_exception::resource_string_not_found); 73 | 74 | return (*it).second; 75 | } 76 | 77 | //Returns string from string table by ID and index in language directory (instead of language) 78 | const std::wstring resource_string_table_reader::get_string_by_id(uint16_t id, uint32_t index) const 79 | { 80 | //List strings by string table id and index 81 | const resource_string_list strings(get_string_table_by_id((id >> 4) + 1, index)); 82 | resource_string_list::const_iterator it = strings.find(id); //Find string by id 83 | if(it == strings.end()) 84 | throw pe_exception("Resource string not found", pe_exception::resource_string_not_found); 85 | 86 | return (*it).second; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/pe_lib/resource_string_table_reader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "stdint_defs.h" 5 | 6 | namespace pe_bliss 7 | { 8 | class pe_resource_viewer; 9 | 10 | //ID; string 11 | typedef std::map resource_string_list; 12 | 13 | class resource_string_table_reader 14 | { 15 | public: 16 | resource_string_table_reader(const pe_resource_viewer& res); 17 | 18 | public: 19 | //Returns string table data by ID and language 20 | const resource_string_list get_string_table_by_id_lang(uint32_t language, uint32_t id) const; 21 | //Returns string table data by ID and index in language directory (instead of language) 22 | const resource_string_list get_string_table_by_id(uint32_t id, uint32_t index = 0) const; 23 | //Returns string from string table by ID and language 24 | const std::wstring get_string_by_id_lang(uint32_t language, uint16_t id) const; 25 | //Returns string from string table by ID and index in language directory (instead of language) 26 | const std::wstring get_string_by_id(uint16_t id, uint32_t index = 0) const; 27 | 28 | private: 29 | const pe_resource_viewer& res_; 30 | 31 | //Helper function of parsing string list table 32 | //Id of resource is needed to calculate string IDs correctly 33 | //resource_data is raw string table resource data 34 | static const resource_string_list parse_string_list(uint32_t id, const std::string& resource_data); 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/pe_lib/resource_version_info_reader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "file_version_info.h" 4 | #include "pe_structures.h" 5 | #include "version_info_types.h" 6 | 7 | namespace pe_bliss 8 | { 9 | class pe_resource_viewer; 10 | 11 | class resource_version_info_reader 12 | { 13 | public: //VERSION INFO 14 | resource_version_info_reader(const pe_resource_viewer& res); 15 | 16 | //Returns full version information: 17 | //file_version_info: versions and file info 18 | //lang_lang_string_values_map: map of version info strings with encodings with encodings 19 | //translation_values_map: map of translations 20 | const file_version_info get_version_info(lang_string_values_map& string_values, translation_values_map& translations, uint32_t index = 0) const; 21 | const file_version_info get_version_info_by_lang(lang_string_values_map& string_values, translation_values_map& translations, uint32_t language) const; 22 | 23 | public: 24 | //L"VS_VERSION_INFO" key of root version info block 25 | static const u16string version_info_key; 26 | 27 | private: 28 | const pe_resource_viewer& res_; 29 | 30 | //VERSION INFO helpers 31 | //Returns aligned version block value position 32 | static uint32_t get_version_block_value_pos(uint32_t base_pos, const unicode16_t* key); 33 | 34 | //Returns aligned version block first child position 35 | static uint32_t get_version_block_first_child_pos(uint32_t base_pos, uint32_t value_length, const unicode16_t* key); 36 | 37 | //Returns full version information: 38 | //file_version_info: versions and file info 39 | //lang_string_values_map: map of version info strings with encodings 40 | //translation_values_map: map of translations 41 | const file_version_info get_version_info(lang_string_values_map& string_values, translation_values_map& translations, const std::string& resource_data) const; 42 | 43 | //Throws an exception (id = resource_incorrect_version_info) 44 | static void throw_incorrect_version_info(); 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /src/pe_lib/resource_version_info_writer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "version_info_types.h" 3 | #include "file_version_info.h" 4 | 5 | namespace pe_bliss 6 | { 7 | class pe_resource_manager; 8 | 9 | class resource_version_info_writer 10 | { 11 | public: 12 | resource_version_info_writer(pe_resource_manager& res); 13 | 14 | //Sets/replaces full version information: 15 | //file_version_info: versions and file info 16 | //lang_string_values_map: map of version info strings with encodings 17 | //translation_values_map: map of translations 18 | void set_version_info(const file_version_info& file_info, 19 | const lang_string_values_map& string_values, 20 | const translation_values_map& translations, 21 | uint32_t language, 22 | uint32_t codepage = 0, 23 | uint32_t timestamp = 0); 24 | 25 | //Removes version info by language (ID = 1) 26 | bool remove_version_info(uint32_t language); 27 | 28 | private: 29 | pe_resource_manager& res_; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/pe_lib/stdint_defs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #if defined(_MSC_VER) && _MSC_VER < 1600 3 | namespace pe_bliss 4 | { 5 | //stdint.h definitions for MSVC 2008 and earlier, as 6 | //it doesn't have them 7 | typedef signed char int8_t; 8 | typedef short int16_t; 9 | typedef int int32_t; 10 | 11 | typedef unsigned char uint8_t; 12 | typedef unsigned short uint16_t; 13 | typedef unsigned int uint32_t; 14 | 15 | typedef long long int64_t; 16 | typedef unsigned long long uint64_t; 17 | } 18 | #else 19 | #include 20 | #endif 21 | -------------------------------------------------------------------------------- /src/pe_lib/utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utils.h" 3 | #include "pe_exception.h" 4 | 5 | #ifndef PE_BLISS_WINDOWS 6 | #include 7 | #endif 8 | 9 | namespace pe_bliss 10 | { 11 | const double pe_utils::log_2 = 1.44269504088896340736; //instead of using M_LOG2E 12 | 13 | //Returns stream size 14 | std::streamoff pe_utils::get_file_size(std::istream& file) 15 | { 16 | //Get old istream offset 17 | std::streamoff old_offset = file.tellg(); 18 | file.seekg(0, std::ios::end); 19 | std::streamoff filesize = file.tellg(); 20 | //Set old istream offset 21 | file.seekg(old_offset); 22 | return filesize; 23 | } 24 | 25 | #ifndef PE_BLISS_WINDOWS 26 | const u16string pe_utils::to_ucs2(const std::wstring& str) 27 | { 28 | u16string ret; 29 | if(str.empty()) 30 | return ret; 31 | 32 | ret.resize(str.length()); 33 | 34 | iconv_t conv = iconv_open("UCS-2", "WCHAR_T"); 35 | if(conv == reinterpret_cast(-1)) 36 | throw pe_exception("Error opening iconv", pe_exception::encoding_convertion_error); 37 | 38 | size_t inbytesleft = str.length() * sizeof(wchar_t); 39 | size_t outbytesleft = ret.length() * sizeof(unicode16_t); 40 | const wchar_t* in_pos = str.c_str(); 41 | unicode16_t* out_pos = &ret[0]; 42 | 43 | size_t result = iconv(conv, const_cast(reinterpret_cast(&in_pos)), &inbytesleft, reinterpret_cast(&out_pos), &outbytesleft); 44 | iconv_close(conv); 45 | 46 | if(result == static_cast(-1)) 47 | throw pe_exception("Iconv error", pe_exception::encoding_convertion_error); 48 | 49 | return ret; 50 | } 51 | 52 | const std::wstring pe_utils::from_ucs2(const u16string& str) 53 | { 54 | std::wstring ret; 55 | if(str.empty()) 56 | return ret; 57 | 58 | ret.resize(str.length()); 59 | 60 | iconv_t conv = iconv_open("WCHAR_T", "UCS-2"); 61 | if(conv == reinterpret_cast(-1)) 62 | throw pe_exception("Error opening iconv", pe_exception::encoding_convertion_error); 63 | 64 | size_t inbytesleft = str.length() * sizeof(unicode16_t); 65 | size_t outbytesleft = ret.length() * sizeof(wchar_t); 66 | const unicode16_t* in_pos = str.c_str(); 67 | wchar_t* out_pos = &ret[0]; 68 | 69 | size_t result = iconv(conv, const_cast(reinterpret_cast(&in_pos)), &inbytesleft, reinterpret_cast(&out_pos), &outbytesleft); 70 | iconv_close(conv); 71 | 72 | if(result == static_cast(-1)) 73 | throw pe_exception("Iconv error", pe_exception::encoding_convertion_error); 74 | 75 | return ret; 76 | } 77 | #endif 78 | 79 | bool operator==(const pe_win::guid& guid1, const pe_win::guid& guid2) 80 | { 81 | return guid1.Data1 == guid2.Data1 82 | && guid1.Data2 == guid2.Data2 83 | && guid1.Data3 == guid2.Data3 84 | && !memcmp(guid1.Data4, guid2.Data4, sizeof(guid1.Data4)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/pe_lib/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "stdint_defs.h" 5 | #include "pe_structures.h" 6 | 7 | namespace pe_bliss 8 | { 9 | class pe_utils 10 | { 11 | public: 12 | //Returns true if string "data" with maximum length "raw_length" is null-terminated 13 | template 14 | static bool is_null_terminated(const T* data, size_t raw_length) 15 | { 16 | raw_length /= sizeof(T); 17 | for(size_t l = 0; l < raw_length; l++) 18 | { 19 | if(data[l] == static_cast(L'\0')) 20 | return true; 21 | } 22 | 23 | return false; 24 | } 25 | 26 | //Helper template function to strip nullbytes in the end of string 27 | template 28 | static void strip_nullbytes(std::basic_string& str) 29 | { 30 | while(!str.empty() && !*(str.end() - 1)) 31 | str.erase(str.length() - 1); 32 | } 33 | 34 | //Helper function to determine if number is power of 2 35 | template 36 | static inline bool is_power_of_2(T x) 37 | { 38 | return !(x & (x - 1)); 39 | } 40 | 41 | //Helper function to align number down 42 | template 43 | static inline T align_down(T x, uint32_t align) 44 | { 45 | return x & ~(static_cast(align) - 1); 46 | } 47 | 48 | //Helper function to align number up 49 | template 50 | static inline T align_up(T x, uint32_t align) 51 | { 52 | return (x & static_cast(align - 1)) ? align_down(x, align) + static_cast(align) : x; 53 | } 54 | 55 | //Returns true if sum of two unsigned integers is safe (no overflow occurs) 56 | static inline bool is_sum_safe(uint32_t a, uint32_t b) 57 | { 58 | return a <= static_cast(-1) - b; 59 | } 60 | 61 | //Two gigabytes value in bytes 62 | static const uint32_t two_gb = 0x80000000; 63 | static const uint32_t max_dword = 0xFFFFFFFF; 64 | static const uint32_t max_word = 0x0000FFFF; 65 | static const double log_2; //instead of using M_LOG2E 66 | 67 | //Returns stream size 68 | static std::streamoff get_file_size(std::istream& file); 69 | 70 | #ifndef PE_BLISS_WINDOWS 71 | public: 72 | static const u16string to_ucs2(const std::wstring& str); 73 | static const std::wstring from_ucs2(const u16string& str); 74 | #endif 75 | 76 | private: 77 | pe_utils(); 78 | pe_utils(pe_utils&); 79 | pe_utils& operator=(const pe_utils&); 80 | }; 81 | 82 | //Windows GUID comparison 83 | bool operator==(const pe_win::guid& guid1, const pe_win::guid& guid2); 84 | } 85 | -------------------------------------------------------------------------------- /src/pe_lib/version_info_editor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "version_info_types.h" 3 | #include "version_info_viewer.h" 4 | 5 | namespace pe_bliss 6 | { 7 | //Helper class to read and edit version information 8 | //lang_string_values_map: map of version info strings with encodings 9 | //translation_values_map: map of translations 10 | class version_info_editor : public version_info_viewer 11 | { 12 | public: 13 | //Default constructor 14 | //strings - version info strings with charsets 15 | //translations - version info translations map 16 | version_info_editor(lang_string_values_map& strings, translation_values_map& translations); 17 | 18 | //Below functions have parameter translation 19 | //If it's empty, the default language translation will be taken 20 | //If there's no default language translation, the first one will be taken 21 | 22 | //Sets company name 23 | void set_company_name(const std::wstring& value, const std::wstring& translation = std::wstring()); 24 | //Sets file description 25 | void set_file_description(const std::wstring& value, const std::wstring& translation = std::wstring()); 26 | //Sets file version 27 | void set_file_version(const std::wstring& value, const std::wstring& translation = std::wstring()); 28 | //Sets internal file name 29 | void set_internal_name(const std::wstring& value, const std::wstring& translation = std::wstring()); 30 | //Sets legal copyright 31 | void set_legal_copyright(const std::wstring& value, const std::wstring& translation = std::wstring()); 32 | //Sets original file name 33 | void set_original_filename(const std::wstring& value, const std::wstring& translation = std::wstring()); 34 | //Sets product name 35 | void set_product_name(const std::wstring& value, const std::wstring& translation = std::wstring()); 36 | //Sets product version 37 | void set_product_version(const std::wstring& value, const std::wstring& translation = std::wstring()); 38 | 39 | //Sets version info property value 40 | //property_name - property name 41 | //value - property value 42 | //If translation does not exist, it will be added to strings and translations lists 43 | //If property does not exist, it will be added 44 | void set_property(const std::wstring& property_name, const std::wstring& value, const std::wstring& translation = std::wstring()); 45 | 46 | //Adds translation to translation list 47 | void add_translation(const std::wstring& translation); 48 | void add_translation(uint16_t language_id, uint16_t codepage_id); 49 | 50 | //Removes translation from translations and strings lists 51 | void remove_translation(const std::wstring& translation); 52 | void remove_translation(uint16_t language_id, uint16_t codepage_id); 53 | 54 | private: 55 | lang_string_values_map& strings_edit_; 56 | translation_values_map& translations_edit_; 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /src/pe_lib/version_info_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "stdint_defs.h" 5 | 6 | namespace pe_bliss 7 | { 8 | //Typedef for version info functions: Name - Value 9 | typedef std::map string_values_map; 10 | //Typedef for version info functions: Language string - String Values Map 11 | //Language String consists of LangID and CharsetID 12 | //E.g. 041904b0 for Russian UNICODE, 040004b0 for Process Default Language UNICODE 13 | typedef std::map lang_string_values_map; 14 | 15 | //Typedef for version info functions: Language - Character Set 16 | typedef std::multimap translation_values_map; 17 | } 18 | -------------------------------------------------------------------------------- /src/pe_lib/version_info_viewer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "pe_resource_viewer.h" 6 | #include "pe_structures.h" 7 | #include "version_info_types.h" 8 | 9 | namespace pe_bliss 10 | { 11 | //Helper class to read version information 12 | //lang_string_values_map: map of version info strings with encodings 13 | //translation_values_map: map of translations 14 | class version_info_viewer 15 | { 16 | public: 17 | //Useful typedefs 18 | typedef std::pair translation_pair; 19 | typedef std::vector translation_list; 20 | 21 | public: 22 | //Default constructor 23 | //strings - version info strings with charsets 24 | //translations - version info translations map 25 | version_info_viewer(const lang_string_values_map& strings, const translation_values_map& translations); 26 | 27 | //Below functions have parameter translation 28 | //If it's empty, the default language translation will be taken 29 | //If there's no default language translation, the first one will be taken 30 | 31 | //Returns company name 32 | const std::wstring get_company_name(const std::wstring& translation = std::wstring()) const; 33 | //Returns file description 34 | const std::wstring get_file_description(const std::wstring& translation = std::wstring()) const; 35 | //Returns file version 36 | const std::wstring get_file_version(const std::wstring& translation = std::wstring()) const; 37 | //Returns internal file name 38 | const std::wstring get_internal_name(const std::wstring& translation = std::wstring()) const; 39 | //Returns legal copyright 40 | const std::wstring get_legal_copyright(const std::wstring& translation = std::wstring()) const; 41 | //Returns original file name 42 | const std::wstring get_original_filename(const std::wstring& translation = std::wstring()) const; 43 | //Returns product name 44 | const std::wstring get_product_name(const std::wstring& translation = std::wstring()) const; 45 | //Returns product version 46 | const std::wstring get_product_version(const std::wstring& translation = std::wstring()) const; 47 | 48 | //Returns list of translations in string representation 49 | const translation_list get_translation_list() const; 50 | 51 | //Returns version info property value 52 | //property_name - required property name 53 | //If throw_if_absent = true, will throw exception if property does not exist 54 | //If throw_if_absent = false, will return empty string if property does not exist 55 | const std::wstring get_property(const std::wstring& property_name, const std::wstring& translation = std::wstring(), bool throw_if_absent = false) const; 56 | 57 | //Converts translation HEX-string to pair of language ID and codepage ID 58 | static const translation_pair translation_from_string(const std::wstring& translation); 59 | 60 | public: 61 | //Default process language, UNICODE 62 | static const std::wstring default_language_translation; 63 | 64 | private: 65 | const lang_string_values_map& strings_; 66 | const translation_values_map& translations_; 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /src/samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(COMPONENTS address_convertions bound_import_reader entropy_calculator exports_reader import_adder pe_realigner pe_stripper resource_editor section_adder tls_reader basic_dotnet_viewer exception_dir_reader full_pe_rebuilder imports_reader pe_rebaser relocation_adder resource_viewer sections_and_addresses basic_info_viewer debug_info_reader export_adder image_config_editor pe_config_reader pe_sections_reader relocations_reader rich_overlay_stub_reader tls_editor) 4 | 5 | foreach (COMPONENT ${COMPONENTS}) 6 | add_subdirectory(${COMPONENT}) 7 | endforeach () 8 | 9 | -------------------------------------------------------------------------------- /src/samples/address_convertions/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT address_convertions) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/address_convertions/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как конвертировать адреса для PE-файла 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: address_convertions.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Получаем список секций 30 | std::cout << "Reading PE sections..." << std::hex << std::showbase << std::endl << std::endl; 31 | const section_list sections = image.get_image_sections(); 32 | 33 | //Перечисляем секции и выводим информацию о них 34 | for(section_list::const_iterator it = sections.begin(); it != sections.end(); ++it) 35 | { 36 | const section& s = *it; //Секция 37 | std::cout << "Section [" << s.get_name() << "]" << std::endl //Имя секции 38 | << " -> RVA: " << s.get_virtual_address() << std::endl //Виртуальный адрес (RVA) 39 | << " -> VA: " << image.rva_to_va_64(s.get_virtual_address()) << std::endl //Виртуальный адрес (VA) 40 | << " -> File offset: " << image.rva_to_file_offset(s.get_virtual_address()) //Файловое смещение секции, вычисленное из ее RVA 41 | << std::endl << std::endl; 42 | } 43 | } 44 | catch(const pe_exception& e) 45 | { 46 | //Если возникла ошибка 47 | std::cout << "Error: " << e.what() << std::endl; 48 | return -1; 49 | } 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /src/samples/basic_dotnet_viewer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT basic_dotnet_viewer) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/basic_dotnet_viewer/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как получить базовую информацию о .NET PE-файле 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: basic_dotnet_viewer.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Если образ не .NET, выходим 30 | if(!image.is_dotnet()) 31 | { 32 | std::cout << "Image is not .NET" << std::endl; 33 | return 0; 34 | } 35 | 36 | std::cout << "Reading basic dotnet info..." << std::hex << std::showbase << std::endl << std::endl; 37 | 38 | //Получаем .NET-заголовок PE-файла 39 | const basic_dotnet_info info(get_basic_dotnet_info(image)); 40 | 41 | //Выводим некоторую информацию 42 | std::cout << "Major runtime version: " << info.get_major_runtime_version() << std::endl //Версия рантайма 43 | << "Minor runtime version: " << info.get_minor_runtime_version() << std::endl 44 | << "Flags: " << info.get_flags() << std::endl //Флаги 45 | << "RVA of resources: " << info.get_rva_of_resources() << std::endl //RVA ресурсов 46 | << "RVA of metadata: " << info.get_rva_of_metadata() << std::endl //RVA метаданных 47 | << "Size of resources: " << info.get_size_of_resources() << std::endl //Размер ресурсов 48 | << "Size of metadata: " << info.get_size_of_metadata() << std::endl; //Размер метаданных 49 | 50 | //Определим точку входа .NET 51 | if(info.is_native_entry_point()) 52 | std::cout << "Entry point RVA: "; 53 | else 54 | std::cout << "Entry point token: "; 55 | 56 | std::cout << info.get_entry_point_rva_or_token() << std::endl; 57 | } 58 | catch(const pe_exception& e) 59 | { 60 | //Если возникла ошибка 61 | std::cout << "Error: " << e.what() << std::endl; 62 | return -1; 63 | } 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /src/samples/basic_info_viewer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT basic_info_viewer) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/basic_info_viewer/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как получить базовую информацию о PE-файле 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: basic_info_viewer.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Фабрика автоматически получает тип PE-файла и создает экземпляр нужного класса, 30 | //но можно получить тип PE-файла и вручную, воспользовавшись одной из перегрузок функции get_pe_type 31 | //Здесь мы просто выведем уже известный тип PE-файла: 32 | std::cout << "PE file type: " << (image.get_pe_type() == pe_type_32 ? "PE32 (PE)" : "PE64 (PE+)") << std::endl; 33 | 34 | //Вычислим контрольную сумму PE-файла 35 | std::cout << "Calculated checksum: "<< std::hex << std::showbase << calculate_checksum(pe_file) << std::endl; 36 | //Выведем контрольную сумму из заголовка файла (для не-драйверов она обычно равна 0) 37 | std::cout << "Stored checksum: " << image.get_checksum() << std::endl; 38 | 39 | //Выведем характеристики PE-файла 40 | std::cout << "Characteristics: " << image.get_characteristics() << std::endl; 41 | 42 | //Выведем адрес точки входа 43 | std::cout << "Entry point: " << image.get_ep() << std::endl; 44 | 45 | //Выведем выравнивание 46 | std::cout << "File alignment: " << image.get_file_alignment() << std::endl; 47 | std::cout << "Section alignment: " << image.get_section_alignment() << std::endl; 48 | 49 | //Выведем базу образа в 64-битном виде (универсально для PE и PE+) 50 | std::cout << "Image base: " << image.get_image_base_64() << std::endl; 51 | 52 | //Выведем подсистему 53 | std::cout << "Subsystem: " << image.get_subsystem() << std::endl; 54 | std::cout << "Is console: " << (image.is_console() ? "YES" : "NO") << std::endl; 55 | std::cout << "Is windows GUI: " << (image.is_gui() ? "YES" : "NO") << std::endl; 56 | 57 | //Выведем, какие директории есть у файла 58 | std::cout << "Has bound import: " << (image.has_bound_import() ? "YES" : "NO") << std::endl; 59 | std::cout << "Has config: " << (image.has_config() ? "YES" : "NO") << std::endl; 60 | std::cout << "Has debug: " << (image.has_debug() ? "YES" : "NO") << std::endl; 61 | std::cout << "Has delay import: " << (image.has_delay_import() ? "YES" : "NO") << std::endl; 62 | std::cout << "Has exception directory: " << (image.has_exception_directory() ? "YES" : "NO") << std::endl; 63 | std::cout << "Has exports: " << (image.has_exports() ? "YES" : "NO") << std::endl; 64 | std::cout << "Has imports: " << (image.has_imports() ? "YES" : "NO") << std::endl; 65 | std::cout << "Has reloc: " << (image.has_reloc() ? "YES" : "NO") << std::endl; 66 | std::cout << "Has resources: " << (image.has_resources() ? "YES" : "NO") << std::endl; 67 | std::cout << "Has security: " << (image.has_security() ? "YES" : "NO") << std::endl; 68 | std::cout << "Has tls: " << (image.has_tls() ? "YES" : "NO") << std::endl; 69 | std::cout << "Is .NET: " << (image.is_dotnet() ? "YES" : "NO") << std::endl; 70 | } 71 | catch(const pe_exception& e) 72 | { 73 | //Если возникла ошибка 74 | std::cout << "Error: " << e.what() << std::endl; 75 | return -1; 76 | } 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /src/samples/bound_import_reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT bound_import_reader) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/bound_import_reader/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как считать и получить информацию о привязанном импорте PE-файла 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: bound_import_reader.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Проверим, есть ли привязанный импорт у PE-файла 30 | if(!image.has_bound_import()) 31 | { 32 | std::cout << "Image has no bound import" << std::endl; 33 | return 0; 34 | } 35 | 36 | std::cout << "Reading PE bound import..." << std::hex << std::showbase << std::endl << std::endl; 37 | 38 | //Получаем информацию о привязанном импорте 39 | const bound_import_module_list modules(get_bound_import_module_list(image)); 40 | 41 | //Выведем импортируемые модули и форварды 42 | for(bound_import_module_list::const_iterator it = modules.begin(); it != modules.end(); ++it) 43 | { 44 | const bound_import& import = *it; //Импортируемая библиотека 45 | std::cout << "Module: " << import.get_module_name() << std::endl //Имя модуля 46 | << "Timestamp: " << import.get_timestamp() << std::endl; //Временная метка 47 | 48 | //Перечислим форварды для модуля - модули, на которые ссылается этот: 49 | const bound_import::ref_list& refs = import.get_module_ref_list(); 50 | for(bound_import::ref_list::const_iterator ref_it = refs.begin(); ref_it != refs.end(); ++ref_it) 51 | { 52 | std::cout << " -> Module: " << (*ref_it).get_module_name() << std::endl //Имя модуля, на который ссылается родительский модуль 53 | << " -> Timestamp: " << (*ref_it).get_timestamp() << std::endl; //Временная метка 54 | } 55 | } 56 | } 57 | catch(const pe_exception& e) 58 | { 59 | //Если возникла ошибка 60 | std::cout << "Error: " << e.what() << std::endl; 61 | return -1; 62 | } 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /src/samples/debug_info_reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT debug_info_reader) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/entropy_calculator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT entropy_calculator) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/entropy_calculator/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как посчитать энтропию файла и секций PE 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: entropy_calculator.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | 25 | try 26 | { 27 | //Считаем энтропию файла 28 | std::cout << "File entropy: " << entropy_calculator::calculate_entropy(pe_file) << std::endl; 29 | 30 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 31 | pe_base image(pe_factory::create_pe(pe_file)); 32 | 33 | std::cout << "Sections entropy: " << entropy_calculator::calculate_entropy(image) << std::endl; //Считаем энтропию всех секций 34 | 35 | //Перечисляем секции и считаем их энтропию по отдельности 36 | const section_list sections = image.get_image_sections(); 37 | for(section_list::const_iterator it = sections.begin(); it != sections.end(); ++it) 38 | { 39 | if(!(*it).empty()) //Если секция не пуста - посчитаем ее энтропию 40 | std::cout << "Section [" << (*it).get_name() << "] entropy: " << entropy_calculator::calculate_entropy(*it) << std::endl; 41 | } 42 | } 43 | catch(const pe_exception& e) 44 | { 45 | //Если возникла ошибка 46 | std::cout << "Error: " << e.what() << std::endl; 47 | return -1; 48 | } 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /src/samples/exception_dir_reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT exception_dir_reader) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/exception_dir_reader/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как считать и получить информацию о директории исключений 8 | //Она существует только для 64-разрядных PE-файлов (PE+) 9 | int main(int argc, char* argv[]) 10 | { 11 | if(argc != 2) 12 | { 13 | std::cout << "Usage: exception_dir_reader.exe PE_FILE" << std::endl; 14 | return 0; 15 | } 16 | 17 | //Открываем файл 18 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 19 | if(!pe_file) 20 | { 21 | std::cout << "Cannot open " << argv[1] << std::endl; 22 | return -1; 23 | } 24 | 25 | try 26 | { 27 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 28 | pe_base image(pe_factory::create_pe(pe_file)); 29 | 30 | //Проверим, есть ли директория информации об исключениях у PE-файла 31 | if(!image.has_exception_directory()) 32 | { 33 | std::cout << "Image has no exception directory" << std::endl; 34 | return 0; 35 | } 36 | 37 | std::cout << "Reading exception directory..." << std::hex << std::showbase << std::endl << std::endl; 38 | 39 | //Получаем информацию из exception directory 40 | const exception_entry_list info(get_exception_directory_data(image)); 41 | 42 | //Выведем записи из exception directory 43 | //Подробное описание всех этих структур есть в MSDN 44 | for(exception_entry_list::const_iterator it = info.begin(); it != info.end(); ++it) 45 | { 46 | const exception_entry& entry = *it; //Запись из таблицы 47 | 48 | //Выведем информацию 49 | std::cout << "Addresses: [" << entry.get_begin_address() << ":" << entry.get_end_address() << "]:" << std::endl 50 | << "Flags: " << static_cast(entry.get_flags()) << std::endl 51 | << "Frame pointer register number: " << static_cast(entry.get_frame_pointer_register_number()) << std::endl 52 | << "Number of unwind slots: " << static_cast(entry.get_number_of_unwind_slots()) << std::endl 53 | << "Scaled RSP offset: " << static_cast(entry.get_scaled_rsp_offset()) << std::endl 54 | << "Size of prolog: " << static_cast(entry.get_size_of_prolog()) << std::endl 55 | << "Unwind info address: " << entry.get_unwind_info_address() << std::endl 56 | << "Unwind info version: " << static_cast(entry.get_unwind_info_version()) << std::endl 57 | << std::endl; 58 | } 59 | } 60 | catch(const pe_exception& e) 61 | { 62 | //Если возникла ошибка 63 | std::cout << "Error: " << e.what() << std::endl; 64 | return -1; 65 | } 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /src/samples/export_adder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT export_adder) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/export_adder/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как добавить новый экспорт в таблицу экспорта PE-файла 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: export_adder.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Получим список экспортируемых функций и информацию об экспорте 30 | export_info info; 31 | exported_functions_list exports; 32 | 33 | //Если экспортов у файла нет, этот вызов бросит исключение, но это не значит, что мы 34 | //не можем создать таблицу экспортов с нуля 35 | try 36 | { 37 | exports = get_exported_functions(image, info); 38 | } 39 | catch(const pe_exception&) 40 | { 41 | //Нет таблицы экспортов, или она кривая 42 | //Создадим информацию об экспортах вручную 43 | info.set_name("MySuperLib.dll"); 44 | info.set_ordinal_base(5); 45 | } 46 | 47 | //Создаем новую экспортируемую функцию 48 | exported_function func; 49 | func.set_name("SuperKernelCall"); //Имя экспортируемой функции 50 | func.set_rva(0x123); //Относительный адрес точки входа экспортируемой функции (некорректный, чисто для примера) 51 | 52 | //Необходимо вычислить ординал функции, которую мы добавляем, чтобы не было повторных 53 | //Для этого есть вспомогательная функция 54 | func.set_ordinal(get_export_ordinal_limits(exports).second + 1); //Сделаем наш ординал = максимальный ординал среди существующих экспортов + 1 55 | exports.push_back(func); //Добавим функцию к экспортам 56 | 57 | //Можно редактировать и существующие экспорты 58 | //или изменить информацию об экспортах (info) 59 | //Но мы просто пересоберем таблицу экспортов 60 | //Она будет иметь больший размер, чем до нашего редактирования, 61 | //поэтому запишем ее в новую секцию, чтобы все поместилось 62 | //(мы не можем расширять существующие секции, если только секция не в самом конце файла) 63 | section new_exports; 64 | new_exports.get_raw_data().resize(1); //Мы не можем добавлять пустые секции, поэтому пусть у нее будет начальный размер данных 1 65 | new_exports.set_name("new_exp"); //Имя секции 66 | new_exports.readable(true); //Доступна на чтение 67 | section& attached_section = image.add_section(new_exports); //Добавим секцию и получим ссылку на добавленную секцию с просчитанными размерами 68 | 69 | rebuild_exports(image, info, exports, attached_section); //Пересобираем экспорты, расположив их с начала новой секции и записав новые данные таблиц экспорта в PE-заголовок 70 | 71 | //Создаем новый PE-файл 72 | std::string base_file_name(argv[1]); 73 | std::string::size_type slash_pos; 74 | if((slash_pos = base_file_name.find_last_of("/\\")) != std::string::npos) 75 | base_file_name = base_file_name.substr(slash_pos + 1); 76 | 77 | base_file_name = "new_" + base_file_name; 78 | std::ofstream new_pe_file(base_file_name.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); 79 | if(!new_pe_file) 80 | { 81 | std::cout << "Cannot create " << base_file_name << std::endl; 82 | return -1; 83 | } 84 | 85 | //Пересобираем PE-файл 86 | rebuild_pe(image, new_pe_file); 87 | 88 | std::cout << "PE was rebuilt and saved to " << base_file_name << std::endl; 89 | } 90 | catch(const pe_exception& e) 91 | { 92 | //Если возникла ошибка 93 | std::cout << "Error: " << e.what() << std::endl; 94 | return -1; 95 | } 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /src/samples/exports_reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT exports_reader) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/exports_reader/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как считать и получить информацию об экспортах PE или PE+ файла 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: exports_reader.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Проверим, есть ли экспорты у PE-файла 30 | if(!image.has_exports()) 31 | { 32 | std::cout << "Image has no exports" << std::endl; 33 | return 0; 34 | } 35 | 36 | std::cout << "Reading PE exports..." << std::hex << std::showbase << std::endl << std::endl; 37 | 38 | //Получаем полную информацию об экспортах и список экспортируемых функций 39 | export_info info; 40 | const exported_functions_list exports = get_exported_functions(image, info); 41 | 42 | //Выведем некоторую информацию об экспорте: 43 | std::cout << "Export info" << std::endl 44 | << "Library name: " << info.get_name() << std::endl //Имя библиотеки 45 | << "Timestamp: " << info.get_timestamp() << std::endl //Временная метка 46 | << "Ordinal base: " << info.get_ordinal_base() << std::endl //База ординалов 47 | << std::endl; 48 | 49 | //Перечисляем секции и выводим информацию о них 50 | for(exported_functions_list::const_iterator it = exports.begin(); it != exports.end(); ++it) 51 | { 52 | const exported_function& func = *it; //Экспортируемая функция 53 | std::cout << "[+] "; 54 | if(func.has_name()) //Если функция имеет имя, выведем его и ординал имени 55 | std::cout << func.get_name() << ", name ordinal: " << func.get_name_ordinal() << " "; 56 | 57 | //Ординал функции 58 | std::cout << "ORD: " << func.get_ordinal(); 59 | 60 | //Если функция - форвард (переадресация в другую DLL), выведем имя форварда 61 | if(func.is_forwarded()) 62 | std::cout << std::endl << " -> " << func.get_forwarded_name(); 63 | 64 | std::cout << std::endl; 65 | } 66 | } 67 | catch(const pe_exception& e) 68 | { 69 | //Если возникла ошибка 70 | std::cout << "Error: " << e.what() << std::endl; 71 | return -1; 72 | } 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /src/samples/full_pe_rebuilder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT full_pe_rebuilder) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/full_pe_rebuilder/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace pe_bliss; 7 | 8 | //Пример, показывающий, как с нуля создать PE-файл 9 | int main(int argc, char* argv[]) 10 | { 11 | if(argc != 2) 12 | { 13 | std::cout << "Usage: full_pe_rebuilder.exe PE_FILE" << std::endl; 14 | return 0; 15 | } 16 | 17 | //Открываем файл 18 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 19 | if(!pe_file) 20 | { 21 | std::cout << "Cannot open " << argv[1] << std::endl; 22 | return -1; 23 | } 24 | 25 | try 26 | { 27 | //Новый образ, который мы создадим из открытого с нуля 28 | std::unique_ptr new_image; 29 | 30 | { 31 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 32 | pe_base image(pe_factory::create_pe(pe_file)); 33 | 34 | //Создаем новый пустой образ 35 | new_image.reset(image.get_pe_type() == pe_type_32 36 | ? static_cast(new pe_base(pe_properties_32(), image.get_section_alignment())) 37 | : static_cast(new pe_base(pe_properties_64(), image.get_section_alignment()))); 38 | 39 | //Копируем важные параметры старого образа в новый 40 | new_image->set_characteristics(image.get_characteristics()); 41 | new_image->set_dll_characteristics(image.get_dll_characteristics()); 42 | new_image->set_file_alignment(image.get_file_alignment()); 43 | new_image->set_heap_size_commit(image.get_heap_size_commit_64()); 44 | new_image->set_heap_size_reserve(image.get_heap_size_reserve_64()); 45 | new_image->set_stack_size_commit(image.get_stack_size_commit_64()); 46 | new_image->set_stack_size_reserve(image.get_stack_size_reserve_64()); 47 | new_image->set_image_base_64(image.get_image_base_64()); 48 | new_image->set_ep(image.get_ep()); 49 | new_image->set_number_of_rvas_and_sizes(new_image->get_number_of_rvas_and_sizes()); 50 | new_image->set_subsystem(image.get_subsystem()); 51 | 52 | //Копируем все существующие директории 53 | for(uint32_t i = 0; i < image.get_number_of_rvas_and_sizes(); ++i) 54 | { 55 | new_image->set_directory_rva(i, image.get_directory_rva(i)); 56 | new_image->set_directory_size(i, image.get_directory_size(i)); 57 | } 58 | 59 | //Копируем данные секций 60 | { 61 | const section_list& pe_sections = image.get_image_sections(); 62 | for(section_list::const_iterator it = pe_sections.begin(); it != pe_sections.end(); ++it) 63 | new_image->set_section_virtual_size(new_image->add_section(*it), (*it).get_virtual_size()); 64 | } 65 | } 66 | 67 | 68 | //Просчитаем контрольную сумму нового PE-файла 69 | //и сохраним ее (для примера) 70 | { 71 | std::stringstream temp_pe(std::ios::out | std::ios::in | std::ios::binary); 72 | rebuild_pe(*new_image, temp_pe); 73 | new_image->set_checksum(calculate_checksum(temp_pe)); 74 | } 75 | 76 | 77 | //Создаем новый PE-файл 78 | std::string base_file_name(argv[1]); 79 | std::string::size_type slash_pos; 80 | if((slash_pos = base_file_name.find_last_of("/\\")) != std::string::npos) 81 | base_file_name = base_file_name.substr(slash_pos + 1); 82 | 83 | base_file_name = "new_" + base_file_name; 84 | std::ofstream new_pe_file(base_file_name.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); 85 | if(!new_pe_file) 86 | { 87 | std::cout << "Cannot create " << base_file_name << std::endl; 88 | return -1; 89 | } 90 | 91 | new_image->set_stub_overlay("alalalalala alalalala!!! alalalala alalalalalala!!!!!!"); 92 | 93 | //Пересобираем PE-файл из нового обраща 94 | rebuild_pe(*new_image, new_pe_file); 95 | 96 | std::cout << "PE was rebuilt and saved to " << base_file_name << std::endl; 97 | } 98 | catch(const pe_exception& e) 99 | { 100 | //Если возникла ошибка 101 | std::cout << "Error: " << e.what() << std::endl; 102 | return -1; 103 | } 104 | 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /src/samples/image_config_editor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT image_config_editor) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/image_config_editor/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как пересобрать директорию Load Config у PE-файла 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: image_config_editor.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Получим информацию о директории Load Config 30 | image_config_info info(get_image_config(image)); 31 | 32 | //Но пересоберем эту директорию, расположив ее в новой секции 33 | section load_config; 34 | load_config.get_raw_data().resize(1); //Мы не можем добавлять пустые секции, поэтому пусть у нее будет начальный размер данных 1 35 | load_config.set_name("load_cfg"); //Имя секции 36 | load_config.readable(true).writeable(true); //Доступна на чтение и запись 37 | section& attached_section = image.add_section(load_config); //Добавим секцию и получим ссылку на добавленную секцию с просчитанными размерами 38 | 39 | //Если у файла была таблица SE Handler'ов 40 | if(info.get_se_handler_table_va()) 41 | info.add_se_handler_rva(0x7777); //Добавим новый SE Handler в таблицу (просто для теста) 42 | 43 | //Если у файла не существовало таблицы Lock-префиксов, добавим ее 44 | //(также для теста) 45 | if(!info.get_lock_prefix_table_va()) 46 | info.add_lock_prefix_rva(0x9999); 47 | 48 | //Пересобираем директорию Image Load Config, пересобираем таблицу Lock-префиксов, если она имелась, а также 49 | //таблицу SE Handler'ов, если она есть 50 | rebuild_image_config(image, info, attached_section, 1); 51 | 52 | //Создаем новый PE-файл 53 | std::string base_file_name(argv[1]); 54 | std::string::size_type slash_pos; 55 | if((slash_pos = base_file_name.find_last_of("/\\")) != std::string::npos) 56 | base_file_name = base_file_name.substr(slash_pos + 1); 57 | 58 | base_file_name = "new_" + base_file_name; 59 | std::ofstream new_pe_file(base_file_name.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); 60 | if(!new_pe_file) 61 | { 62 | std::cout << "Cannot create " << base_file_name << std::endl; 63 | return -1; 64 | } 65 | 66 | //Пересобираем PE-файл 67 | rebuild_pe(image, new_pe_file); 68 | 69 | std::cout << "PE was rebuilt and saved to " << base_file_name << std::endl; 70 | } 71 | catch(const pe_exception& e) 72 | { 73 | //Если возникла ошибка 74 | std::cout << "Error: " << e.what() << std::endl; 75 | return -1; 76 | } 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /src/samples/import_adder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT import_adder) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/import_adder/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как добавить новый импорт в таблицу импорта PE-файла 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: import_adder.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Получим список импортируемых библиотек и функций 30 | imported_functions_list imports(get_imported_functions(image)); 31 | 32 | //Создадим новую библиотеку, из которой будем импортировать функции 33 | import_library new_lib; 34 | new_lib.set_name("kaimi_dx.dll"); //Пусть это будет kaimi_dx.dll 35 | 36 | //Добавим к ней пару импортов функций 37 | imported_function func; 38 | func.set_name("Tralala"); //Один импорт - по имени Tralala 39 | func.set_iat_va(0x1); //Запишем ненулевой абсолютный адрес в import address table 40 | 41 | imported_function func2; 42 | func2.set_ordinal(5); //Другой импорт - по ординалу 5 43 | func2.set_iat_va(0x2); //Запишем ненулевой абсолютный адрес в import address table 44 | 45 | //Мы указали некорректное содержимое (0x1 и 0x2) для ячеек, в которые будут записаны адреса импортируемых функций 46 | //Это не имеет значения в общем случае, потому что эти значения всегда переписываются загрузчиком 47 | //Эти адреса важны только в том случае, если exe-файл имеет привязанный импорт 48 | 49 | //Добавим импорты 50 | new_lib.add_import(func); 51 | new_lib.add_import(func2); 52 | imports.push_back(new_lib); //Добавим импортированную библиотеку к импортам 53 | 54 | //Можно редактировать и существующие импорты 55 | 56 | //Но мы просто пересоберем таблицу импортов 57 | //Она будет иметь больший размер, чем до нашего редактирования, 58 | //поэтому запишем ее в новую секцию, чтобы все поместилось 59 | //(мы не можем расширять существующие секции, если только секция не в самом конце файла) 60 | section new_imports; 61 | new_imports.get_raw_data().resize(1); //Мы не можем добавлять пустые секции, поэтому пусть у нее будет начальный размер данных 1 62 | new_imports.set_name("new_imp"); //Имя секции 63 | new_imports.readable(true).writeable(true); //Доступна на чтение и запись 64 | section& attached_section = image.add_section(new_imports); //Добавим секцию и получим ссылку на добавленную секцию с просчитанными размерами 65 | 66 | //Структура, отвечающая за настройки пересборщика импортов 67 | import_rebuilder_settings settings(true, false); //Модифицируем заголовок PE и не очищаем поле IMAGE_DIRECTORY_ENTRY_IAT 68 | rebuild_imports(image, imports, attached_section, settings); //Пересобираем импорты 69 | 70 | //Создаем новый PE-файл 71 | std::string base_file_name(argv[1]); 72 | std::string::size_type slash_pos; 73 | if((slash_pos = base_file_name.find_last_of("/\\")) != std::string::npos) 74 | base_file_name = base_file_name.substr(slash_pos + 1); 75 | 76 | base_file_name = "new_" + base_file_name; 77 | std::ofstream new_pe_file(base_file_name.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); 78 | if(!new_pe_file) 79 | { 80 | std::cout << "Cannot create " << base_file_name << std::endl; 81 | return -1; 82 | } 83 | 84 | //Пересобираем PE-файл 85 | rebuild_pe(image, new_pe_file); 86 | 87 | std::cout << "PE was rebuilt and saved to " << base_file_name << std::endl; 88 | } 89 | catch(const pe_exception& e) 90 | { 91 | //Если возникла ошибка 92 | std::cout << "Error: " << e.what() << std::endl; 93 | return -1; 94 | } 95 | 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /src/samples/imports_reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT imports_reader) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/imports_reader/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как считать и получить информацию об импортах PE или PE+ файла 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: imports_reader.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Проверим, есть ли импорты у файла 30 | if(!image.has_imports()) 31 | { 32 | std::cout << "Image has no imports" << std::endl; 33 | return 0; 34 | } 35 | 36 | std::cout << "Reading PE imports..." << std::hex << std::showbase << std::endl << std::endl; 37 | 38 | //Получаем список импортируемых библиотек с функциями 39 | const imported_functions_list imports = get_imported_functions(image); 40 | 41 | //Перечисляем импортированные библиотеки и выводим информацию о них 42 | for(imported_functions_list::const_iterator it = imports.begin(); it != imports.end(); ++it) 43 | { 44 | const import_library& lib = *it; //Импортируемая библиотека 45 | std::cout << "Library [" << lib.get_name() << "]" << std::endl //Имя 46 | << "Timestamp: " << lib.get_timestamp() << std::endl //Временная метка 47 | << "RVA to IAT: " << lib.get_rva_to_iat() << std::endl //Относительный адрес к import address table 48 | << "========" << std::endl; 49 | 50 | //Перечисляем импортированные функции для библиотеки 51 | const import_library::imported_list& functions = lib.get_imported_functions(); 52 | for(import_library::imported_list::const_iterator func_it = functions.begin(); func_it != functions.end(); ++func_it) 53 | { 54 | const imported_function& func = *func_it; //Импортированная функция 55 | std::cout << "[+] "; 56 | if(func.has_name()) //Если функция имеет имя - выведем его 57 | std::cout << func.get_name(); 58 | else 59 | std::cout << "#" << func.get_ordinal(); //Иначе она импортирована по ординалу 60 | 61 | //Хинт 62 | std::cout << " hint: " << func.get_hint() << std::endl; 63 | } 64 | 65 | std::cout << std::endl; 66 | } 67 | } 68 | catch(const pe_exception& e) 69 | { 70 | //Если возникла ошибка 71 | std::cout << "Error: " << e.what() << std::endl; 72 | return -1; 73 | } 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /src/samples/pe_config_reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT pe_config_reader) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/pe_config_reader/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как считать и получить информацию о Image Config (конфигурация исполняемого файла) PE или PE+ 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: pe_config_reader.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | std::cout << "Reading PE image config info..." << std::hex << std::showbase << std::endl << std::endl; 30 | 31 | //Получаем конфигурацию 32 | const image_config_info info(get_image_config(image)); 33 | 34 | //Выводим данные конфигурации 35 | //Подробнее о полях - в MSDN 36 | std::cout << "Critical section default timeout: " << info.get_critical_section_default_timeout() << std::endl 37 | << "Decommit free block threshold: " << info.get_decommit_free_block_threshold() << std::endl 38 | << "Decommit total free threshold: " << info.get_decommit_total_free_threshold() << std::endl 39 | << "Global flags clear: " << info.get_global_flags_clear() << std::endl 40 | << "Global flags set: " << info.get_global_flags_set() << std::endl 41 | << "VA of lock table prefix: " << info.get_lock_prefix_table_va() << std::endl 42 | << "Max allocation size: " << info.get_max_allocation_size() << std::endl 43 | << "Process affinity mask: " << info.get_process_affinity_mask() << std::endl 44 | << "Process heap flags: " << info.get_process_heap_flags() << std::endl 45 | << "Security cookie VA: " << info.get_security_cookie_va() << std::endl 46 | << "CSDVersion: " << info.get_service_pack_version() << std::endl 47 | << "Timestamp: " << info.get_time_stamp() << std::endl 48 | << "Virtual memory threshold: " << info.get_virtual_memory_threshold() << std::endl 49 | << std::endl; 50 | 51 | //Выведем адреса SE-хендлеров 52 | const image_config_info::se_handler_list& se_handlers = info.get_se_handler_rvas(); 53 | for(image_config_info::se_handler_list::const_iterator it = se_handlers.begin(); it != se_handlers.end(); ++it) 54 | std::cout << "SE Handler: " << (*it) << std::endl; 55 | } 56 | catch(const pe_exception& e) 57 | { 58 | //Если возникла ошибка 59 | std::cout << "Error: " << e.what() << std::endl; 60 | return -1; 61 | } 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /src/samples/pe_realigner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT pe_realigner) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/pe_realigner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как изменить файловое выравнивание PE-файлов 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: pe_realigner.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Выведем темущий file alignment 30 | std::cout << "File alignment: " << image.get_file_alignment() << std::endl; 31 | 32 | //Предложим выбрать новое выравнивание 33 | unsigned int new_alignment_index = static_cast(-1); 34 | 35 | while(new_alignment_index > 3) 36 | { 37 | if(std::cin.fail()) 38 | { 39 | //На случай, если пользователь ввел что-то некорректное 40 | std::cin.clear(); 41 | std::cin.ignore(static_cast(-1), '\n'); 42 | } 43 | 44 | std::cout << "Choose new file alignment" << std::endl; 45 | std::cout << "(0 = 512, 1 = 1024, 2 = 2048, 3 = 4096): "; 46 | std::cin >> new_alignment_index; 47 | } 48 | 49 | unsigned int available_aligns[] = {512, 1024, 2048, 4096}; 50 | 51 | //Изменим выравнивание на то, которое указал пользователь 52 | image.realign_file(available_aligns[new_alignment_index]); 53 | 54 | //Создаем новый PE-файл 55 | std::string base_file_name(argv[1]); 56 | std::string::size_type slash_pos; 57 | if((slash_pos = base_file_name.find_last_of("/\\")) != std::string::npos) 58 | base_file_name = base_file_name.substr(slash_pos + 1); 59 | 60 | base_file_name = "new_" + base_file_name; 61 | std::ofstream new_pe_file(base_file_name.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); 62 | if(!new_pe_file) 63 | { 64 | std::cout << "Cannot create " << base_file_name << std::endl; 65 | return -1; 66 | } 67 | 68 | //Пересобираем PE-файл 69 | rebuild_pe(image, new_pe_file); 70 | 71 | std::cout << "PE was rebuilt and saved to " << base_file_name << std::endl; 72 | } 73 | catch(const pe_exception& e) 74 | { 75 | //Если возникла ошибка 76 | std::cout << "Error: " << e.what() << std::endl; 77 | return -1; 78 | } 79 | 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /src/samples/pe_rebaser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT pe_rebaser) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/pe_rebaser/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как изменить базовый адрес загрузки PE-файла при условии наличия релокаций 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: pe_rebaser.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Проверим, есть ли релокации у образа 30 | if(!image.has_reloc()) 31 | { 32 | std::cout << "Image has no relocations, rebase is not possible" << std::endl; 33 | return 0; 34 | } 35 | 36 | //Получим значение базового адреса загрузки образа (64-бита, универсально для PE и PE+) 37 | uint64_t base = image.get_image_base_64(); 38 | base += 0x100000; //Изменим базовый адрес загрузки 39 | 40 | //Произведем пересчет необходимых адресов 41 | rebase_image(image, get_relocations(image), base); 42 | 43 | //Создаем новый PE-файл 44 | std::string base_file_name(argv[1]); 45 | std::string::size_type slash_pos; 46 | if((slash_pos = base_file_name.find_last_of("/\\")) != std::string::npos) 47 | base_file_name = base_file_name.substr(slash_pos + 1); 48 | 49 | base_file_name = "new_" + base_file_name; 50 | std::ofstream new_pe_file(base_file_name.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); 51 | if(!new_pe_file) 52 | { 53 | std::cout << "Cannot create " << base_file_name << std::endl; 54 | return -1; 55 | } 56 | 57 | //Пересобираем PE-файл 58 | rebuild_pe(image, new_pe_file); 59 | 60 | std::cout << "PE was rebuilt and saved to " << base_file_name << std::endl; 61 | } 62 | catch(const pe_exception& e) 63 | { 64 | //Если возникла ошибка 65 | std::cout << "Error: " << e.what() << std::endl; 66 | return -1; 67 | } 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /src/samples/pe_sections_reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT pe_sections_reader) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/pe_sections_reader/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как считать и получить информацию о секциях PE или PE+ файла 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: pe_sections_reader.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Получаем список секций 30 | std::cout << "Reading PE sections..." << std::hex << std::showbase << std::endl << std::endl; 31 | const section_list sections(image.get_image_sections()); 32 | 33 | //Перечисляем секции и выводим информацию о них 34 | for(section_list::const_iterator it = sections.begin(); it != sections.end(); ++it) 35 | { 36 | const section& s = *it; //Секция 37 | std::cout << "Section [" << s.get_name() << "]" << std::endl //Имя секции 38 | << "Characteristics: " << s.get_characteristics() << std::endl //Характеристики 39 | << "Size of raw data: " << s.get_size_of_raw_data() << std::endl //Размер данных в файле 40 | << "Virtual address: " << s.get_virtual_address() << std::endl //Виртуальный адрес 41 | << "Virtual size: " << s.get_virtual_size() << std::endl //Виртуальный размер 42 | << std::endl; 43 | } 44 | } 45 | catch(const pe_exception& e) 46 | { 47 | //Если возникла ошибка 48 | std::cout << "Error: " << e.what() << std::endl; 49 | return -1; 50 | } 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /src/samples/pe_stripper/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT pe_stripper) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/pe_stripper/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как вырезать ненужные данные из PE-файла и пересобрать его 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: pe_stripper.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Удалим DOS stub и rich overlay 30 | image.strip_stub_overlay(); 31 | 32 | //Удалим ненужные DATA_DIRECTORY (нулевые) 33 | //Очень малое количество линкеров умеют это делать 34 | image.strip_data_directories(0); 35 | 36 | //Создаем новый PE-файл 37 | std::string base_file_name(argv[1]); 38 | std::string::size_type slash_pos; 39 | if((slash_pos = base_file_name.find_last_of("/\\")) != std::string::npos) 40 | base_file_name = base_file_name.substr(slash_pos + 1); 41 | 42 | base_file_name = "new_" + base_file_name; 43 | std::ofstream new_pe_file(base_file_name.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); 44 | if(!new_pe_file) 45 | { 46 | std::cout << "Cannot create " << base_file_name << std::endl; 47 | return -1; 48 | } 49 | 50 | //Пересобираем PE-файл с опцией сжатия DOS-header 51 | //Уменьшения размера это не дает, но упаковывает NT-заголовки в DOS-заголовок 52 | //При пересборке автоматически убираются ненужные нулевые байты в самом конце образа, 53 | //в результате чего размер образа становится немного меньше 54 | rebuild_pe(image, new_pe_file, true); 55 | 56 | std::cout << "PE was rebuilt and saved to " << base_file_name << std::endl; 57 | } 58 | catch(const pe_exception& e) 59 | { 60 | //Если возникла ошибка 61 | std::cout << "Error: " << e.what() << std::endl; 62 | return -1; 63 | } 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /src/samples/relocation_adder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT relocation_adder) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/relocation_adder/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как добавить новую релокацию в таблицы релокаций PE-файла 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: relocation_adder.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Перечислим и получим все записи из таблиц релокаций в PE-файле, кроме абсолютных 30 | //Можно было бы включить в список и абсолютные записи (ABSOLUTE), передав в вызов true 31 | //Эти записи не нужны при пересборке релокаций, они используются для выравнивания 32 | //и будут добавлены автоматически пересборщиком 33 | relocation_table_list tables(get_relocations(image)); 34 | 35 | //Создаем новую таблицу релокаций 36 | relocation_table new_table; 37 | new_table.set_rva(0x5678); //Относительный адрес релокаций в таблице - он некорректен, для примера, поэтому получившийся PE скорее всего не загрузится 38 | //Добавим в таблицу новую релокацию 39 | new_table.add_relocation(relocation_entry(10, 3)); //Тип 3 - HIGHLOW-релокация, RRVA = 10, т.е. RVA = 0x5678 + 10 40 | //Добавляем таблицу 41 | tables.push_back(new_table); 42 | 43 | //Можно редактировать и существующие релокации, но делать этого не стоит, так как файл не загрузится, если что-то в них поменять 44 | //Если их удалить у EXE-файла полностью, то все будет нормально, у DLL этого делать не стоит 45 | //Мы просто пересоберем релокации 46 | //Они будет иметь больший размер, чем до нашего редактирования, 47 | //поэтому запишем их в новую секцию, чтобы все поместилось 48 | //(мы не можем расширять существующие секции, если только секция не в самом конце файла) 49 | section new_relocs; 50 | new_relocs.get_raw_data().resize(1); //Мы не можем добавлять пустые секции, поэтому пусть у нее будет начальный размер данных 1 51 | new_relocs.set_name("new_rel"); //Имя секции 52 | new_relocs.readable(true); //Доступна на чтение 53 | section& attached_section = image.add_section(new_relocs); //Добавим секцию и получим ссылку на добавленную секцию с просчитанными размерами 54 | 55 | rebuild_relocations(image, tables, attached_section); //Пересобираем экспорты, расположив их с начала новой секции и записав новые данные таблиц релокаций в PE-заголовок 56 | 57 | //Создаем новый PE-файл 58 | std::string base_file_name(argv[1]); 59 | std::string::size_type slash_pos; 60 | if((slash_pos = base_file_name.find_last_of("/\\")) != std::string::npos) 61 | base_file_name = base_file_name.substr(slash_pos + 1); 62 | 63 | base_file_name = "new_" + base_file_name; 64 | std::ofstream new_pe_file(base_file_name.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); 65 | if(!new_pe_file) 66 | { 67 | std::cout << "Cannot create " << base_file_name << std::endl; 68 | return -1; 69 | } 70 | 71 | //Пересобираем PE-файл 72 | rebuild_pe(image, new_pe_file); 73 | 74 | std::cout << "PE was rebuilt and saved to " << base_file_name << std::endl; 75 | } 76 | catch(const pe_exception& e) 77 | { 78 | //Если возникла ошибка 79 | std::cout << "Error: " << e.what() << std::endl; 80 | return -1; 81 | } 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /src/samples/relocations_reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT relocations_reader) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/relocations_reader/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как считать и получить информацию о релокациях PE или PE+ файла 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: relocations_reader.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Проверим, есть ли релокации у файла 30 | if(!image.has_reloc()) 31 | { 32 | std::cout << "Image has no relocations" << std::endl; 33 | return 0; 34 | } 35 | 36 | std::cout << "Reading PE relocations..." << std::hex << std::showbase << std::endl << std::endl; 37 | 38 | //Получаем список таблиц релокаций 39 | const relocation_table_list tables(get_relocations(image)); 40 | 41 | //Перечисляем таблицы релокаций и выводим информацию о них 42 | for(relocation_table_list::const_iterator it = tables.begin(); it != tables.end(); ++it) 43 | { 44 | const relocation_table& table = *it; //Таблица релокаций 45 | std::cout << "RVA [" << table.get_rva() << "]" << std::endl //Относительный адрес 46 | << "==========" 47 | << std::endl; 48 | 49 | //Перечислим все релокации 50 | const relocation_table::relocation_list& relocs = table.get_relocations(); 51 | for(relocation_table::relocation_list::const_iterator reloc_it = relocs.begin(); reloc_it != relocs.end(); ++reloc_it) 52 | { 53 | std::cout << "[+] " << (*reloc_it).get_item() << std::endl; 54 | } 55 | 56 | std::cout << std::endl; 57 | } 58 | } 59 | catch(const pe_exception& e) 60 | { 61 | //Если возникла ошибка 62 | std::cout << "Error: " << e.what() << std::endl; 63 | return -1; 64 | } 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /src/samples/resource_editor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT resource_editor) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/resource_editor/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by resource.rc 4 | // 5 | #define IDR_CUSTOM1 100 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 101 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /src/samples/resource_editor/resource.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/samples/resource_editor/resource.rc -------------------------------------------------------------------------------- /src/samples/resource_editor/wxwin.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/samples/resource_editor/wxwin.ico -------------------------------------------------------------------------------- /src/samples/resource_viewer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT resource_viewer) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/rich_overlay_stub_reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT rich_overlay_stub_reader) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/rich_overlay_stub_reader/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как получить информацию о стабе PE-файла и rich overlay, который добавляет при компиляции MS Visual Studio 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: rich_overlay_stub_reader.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Выведем длину DOS stub'а 30 | std::cout << "Image stub length: " << image.get_stub_overlay().length() << std::endl << std::endl; 31 | 32 | //Перечисляем все RICH-записи 33 | rich_data_list data = get_rich_data(image); 34 | for(rich_data_list::const_iterator it = data.begin(); it != data.end(); ++it) 35 | { 36 | //Выводим информацию о записи 37 | std::cout << "Number: " << (*it).get_number() << std::endl 38 | << "Times: " << (*it).get_times() << std::endl 39 | << "Version: " << (*it).get_version() << std::endl 40 | << std::endl; 41 | } 42 | 43 | //Отобразим информацию о том, есть ли у файла оверлей в конце (у некоторых инсталляторов, например, есть) 44 | std::cout << "Has overlay in the end: " << (image.has_overlay() ? "YES" : "NO") << std::endl; 45 | } 46 | catch(const pe_exception& e) 47 | { 48 | //Если возникла ошибка 49 | std::cout << "Error: " << e.what() << std::endl; 50 | return -1; 51 | } 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /src/samples/section_adder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT section_adder) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/section_adder/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как добавить секцию в PE-файл и записать в нее какие-нибудь данные 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: section_adder.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Секцию можно добавить только после всех существующих, чтобы PE-файл не испортился 30 | //Создаем новую секцию 31 | section new_section; 32 | new_section.readable(true).writeable(true); //Делаем секцию доступной для чтения и записи 33 | new_section.set_name("kaimi.ru"); //Ставим имя секции - максимум 8 символов 34 | new_section.set_raw_data("Tralala"); //Устанавливаем данные секции 35 | 36 | //Добавляем секцию. Все адреса пересчитаются автоматически 37 | //Вызов вернет ссылку на уже добавленную секцию с пересчитанными адресами 38 | //Совсем пустую секцию к образу добавить нельзя, у нее должен быть ненулевой размер данных или виртуальный размер 39 | section& added_section = image.add_section(new_section); 40 | 41 | //Если нужно изменить виртуальный размер секции, то делается это так: 42 | image.set_section_virtual_size(added_section, 0x1000); 43 | 44 | //Создаем новый PE-файл 45 | std::string base_file_name(argv[1]); 46 | std::string::size_type slash_pos; 47 | if((slash_pos = base_file_name.find_last_of("/\\")) != std::string::npos) 48 | base_file_name = base_file_name.substr(slash_pos + 1); 49 | 50 | base_file_name = "new_" + base_file_name; 51 | std::ofstream new_pe_file(base_file_name.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); 52 | if(!new_pe_file) 53 | { 54 | std::cout << "Cannot create " << base_file_name << std::endl; 55 | return -1; 56 | } 57 | 58 | //Пересобираем PE-файл 59 | rebuild_pe(image, new_pe_file); 60 | 61 | std::cout << "PE was rebuilt and saved to " << base_file_name << std::endl; 62 | } 63 | catch(const pe_exception& e) 64 | { 65 | //Если возникла ошибка 66 | std::cout << "Error: " << e.what() << std::endl; 67 | return -1; 68 | } 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /src/samples/sections_and_addresses/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT sections_and_addresses) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/sections_and_addresses/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как работать с секциями в PE-файле 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: sections_and_addresses.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Выведем имя секции, в которой находится точка входа PE-файла 30 | //В хитрых PE-файлах точка входа может находиться в заголовке, тогда section_from_rva бросит исключение 31 | std::cout << "EP section name: " << image.section_from_rva(image.get_ep()).get_name() << std::endl; 32 | //Длина "сырых" (raw) данных секции 33 | std::cout << "EP section data length: " << image.section_data_length_from_rva(image.get_ep()) << std::endl; 34 | 35 | //Если у PE-файла есть импорты, выведем имя секции, в которой они находятся 36 | if(image.has_imports()) 37 | std::cout << "Import section name: " << image.section_from_directory(pe_win::image_directory_entry_import).get_name() << std::endl; 38 | } 39 | catch(const pe_exception& e) 40 | { 41 | //Если возникла ошибка 42 | std::cout << "Error: " << e.what() << std::endl; 43 | return -1; 44 | } 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /src/samples/tls_editor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT tls_editor) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/tls_editor/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как редактировать TLS (Thread Local Storage) у PE-файлов 8 | int main(int argc, char* argv[]) 9 | { 10 | if(argc != 2) 11 | { 12 | std::cout << "Usage: tls_editor.exe PE_FILE" << std::endl; 13 | return 0; 14 | } 15 | 16 | //Открываем файл 17 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 18 | if(!pe_file) 19 | { 20 | std::cout << "Cannot open " << argv[1] << std::endl; 21 | return -1; 22 | } 23 | 24 | try 25 | { 26 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 27 | pe_base image(pe_factory::create_pe(pe_file)); 28 | 29 | //Получим информацию о TLS PE-файла 30 | //Если TLS нет, этот вызов выбросит исключение 31 | tls_info info(get_tls_info(image)); 32 | 33 | //Пересоберем TLS 34 | //Он, вероятно, будет иметь больший размер, чем до нашего редактирования, 35 | //поэтому запишем его в новую секцию, чтобы все поместилось 36 | //(мы не можем расширять существующие секции, если только секция не в самом конце файла) 37 | section new_tls; 38 | new_tls.get_raw_data().resize(1); //Мы не можем добавлять пустые секции, поэтому пусть у нее будет начальный размер данных 1 39 | new_tls.set_name("new_tls"); //Имя секции 40 | new_tls.readable(true); //Доступна на чтение 41 | section& attached_section = image.add_section(new_tls); //Добавим секцию и получим ссылку на добавленную секцию с просчитанными размерами 42 | 43 | if(info.get_callbacks_rva() != 0) //Если у TLS есть хотя бы один коллбек 44 | info.add_tls_callback(0x100); //Добавим новый коллбек в TLS - относительный адрес, скорее всего, некорректен, поэтому программа не запустится (просто для примера) 45 | 46 | info.set_raw_data("Hello, world!"); //Установим или заменим "сырые" данные TLS 47 | info.set_raw_data_start_rva(image.rva_from_section_offset(attached_section, 0)); //Расположим их с начала добавленной секции 48 | info.recalc_raw_data_end_rva(); //Просчитаем новый конечный адрес "сырых" данных 49 | 50 | //Пересобираем TLS, расположив их с 50-го байта (будет выровнено, секция будет автоматически расширена) новой секции и записав новые данные TLS в PE-заголовок 51 | //По умолчанию функция пересобирает также TLS-коллбеки и "сырые" данные TLS, располагая их по указанным в структуре info адресам 52 | //Опция expand позволяет задать, как должны распологаться "сырые" данные 53 | //tls_data_expand_raw позволяет увеличить "сырой" размер секции, то есть размер в файле 54 | //tls_data_expand_virtual позволяет увеличить виртуальный размер секции с данными TLS 55 | //Если не хватит места под данные TLS, будет записана только их часть, или вообще ничего записано не будет 56 | rebuild_tls(image, info, attached_section, 50); 57 | 58 | //Создаем новый PE-файл 59 | std::string base_file_name(argv[1]); 60 | std::string::size_type slash_pos; 61 | if((slash_pos = base_file_name.find_last_of("/\\")) != std::string::npos) 62 | base_file_name = base_file_name.substr(slash_pos + 1); 63 | 64 | base_file_name = "new_" + base_file_name; 65 | std::ofstream new_pe_file(base_file_name.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); 66 | if(!new_pe_file) 67 | { 68 | std::cout << "Cannot create " << base_file_name << std::endl; 69 | return -1; 70 | } 71 | 72 | //Пересобираем PE-файл 73 | rebuild_pe(image, new_pe_file); 74 | 75 | std::cout << "PE was rebuilt and saved to " << base_file_name << std::endl; 76 | } 77 | catch(const pe_exception& e) 78 | { 79 | //Если возникла ошибка 80 | std::cout << "Error: " << e.what() << std::endl; 81 | return -1; 82 | } 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /src/samples/tls_reader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT tls_reader) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR}) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/samples/tls_reader/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace pe_bliss; 6 | 7 | //Пример, показывающий, как считать и получить информацию о статическом TLS (Thread Local Storage, локальная память потока) 8 | //PE или PE+ файла 9 | int main(int argc, char* argv[]) 10 | { 11 | if(argc != 2) 12 | { 13 | std::cout << "Usage: tls_reader.exe PE_FILE" << std::endl; 14 | return 0; 15 | } 16 | 17 | //Открываем файл 18 | std::ifstream pe_file(argv[1], std::ios::in | std::ios::binary); 19 | if(!pe_file) 20 | { 21 | std::cout << "Cannot open " << argv[1] << std::endl; 22 | return -1; 23 | } 24 | 25 | try 26 | { 27 | //Создаем экземпляр PE или PE+ класса с помощью фабрики 28 | pe_base image(pe_factory::create_pe(pe_file)); 29 | 30 | std::cout << "Reading PE TLS info..." << std::hex << std::showbase << std::endl << std::endl; 31 | 32 | //Получаем информацию о TLS 33 | const tls_info info = get_tls_info(image); 34 | 35 | //Выводим информацию о TLS 36 | std::cout << "Callbacks RVA: " << info.get_callbacks_rva() << std::endl 37 | << "Index RVA: " << info.get_index_rva() << std::endl 38 | << "Raw data start RVA: " << info.get_raw_data_start_rva() << std::endl 39 | << "Raw data end RVA: " << info.get_raw_data_end_rva() << std::endl 40 | << "Size of zero fill: " << info.get_size_of_zero_fill() << std::endl; 41 | 42 | //Выведем TLS-коллбеки: 43 | const tls_info::tls_callback_list& tls_callbacks = info.get_tls_callbacks(); 44 | for(tls_info::tls_callback_list::const_iterator it = tls_callbacks.begin(); it != tls_callbacks.end(); ++it) 45 | std::cout << "Callback: " << (*it) << std::endl; 46 | } 47 | catch(const pe_exception& e) 48 | { 49 | //Если возникла ошибка 50 | std::cout << "Error: " << e.what() << std::endl; 51 | return -1; 52 | } 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /src/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(COMPONENTS test_bound_import test_dotnet test_exports test_imports test_resource_bitmap test_resource_message_table test_resource_version_info test_runner test_tls test_checksum test_entropy test_load_config test_resource_icon_cursor test_resources test_resource_viewer tests_basic test_debug test_exception_directory test_relocations test_resource_manager test_resource_string_table test_rich_data tests_utils) 4 | 5 | foreach (COMPONENT ${COMPONENTS}) 6 | add_subdirectory(${COMPONENT}) 7 | endforeach () 8 | 9 | -------------------------------------------------------------------------------- /src/tests/pe_files/TestApp.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/tests/pe_files/TestApp.exe -------------------------------------------------------------------------------- /src/tests/pe_files/bound32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/tests/pe_files/bound32.exe -------------------------------------------------------------------------------- /src/tests/pe_files/bound64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/tests/pe_files/bound64.exe -------------------------------------------------------------------------------- /src/tests/pe_files/debug_test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/tests/pe_files/debug_test.exe -------------------------------------------------------------------------------- /src/tests/pe_files/image32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/tests/pe_files/image32.exe -------------------------------------------------------------------------------- /src/tests/pe_files/image64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/tests/pe_files/image64.exe -------------------------------------------------------------------------------- /src/tests/pe_files/message_table_resource.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/tests/pe_files/message_table_resource.exe -------------------------------------------------------------------------------- /src/tests/pe_files/test_dll_32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/tests/pe_files/test_dll_32.dll -------------------------------------------------------------------------------- /src/tests/pe_files/test_dll_64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/portable-executable-library/801202d94aa27075f2afa3b34a2d5b0526f01186/src/tests/pe_files/test_dll_64.dll -------------------------------------------------------------------------------- /src/tests/test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | enum test_level 9 | { 10 | test_level_normal, 11 | test_level_critical 12 | }; 13 | 14 | static void pe_test_print_error(const std::string& test_name, 15 | test_level level, 16 | const std::string& expression, 17 | const std::string& file, size_t line) 18 | { 19 | std::cerr << test_name << " - FAIL!" << std::endl 20 | << "File: " << file << ", line: " << line << std::endl 21 | << "Expression: " << expression << std::endl << std::endl; 22 | 23 | if(level == test_level_critical) 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | static void pe_test(bool result, 28 | const std::string& test_name, test_level level, 29 | const std::string& expression, 30 | const std::string& file, size_t line) 31 | { 32 | if(result) 33 | std::cout << test_name << " - OK" << std::endl; 34 | else 35 | pe_test_print_error(test_name, level, expression, file, line); 36 | } 37 | 38 | static void pe_test_error(const std::exception& e, 39 | const std::string& test_name, test_level level, 40 | const std::string& expression, 41 | const std::string& file, size_t line) 42 | { 43 | std::cerr << test_name << " FAIL!" << std::endl 44 | << "File: " << file << ", line: " << line << std::endl 45 | << "Expression: " << expression << std::endl 46 | << "Exception occured: " << e.what() << std::endl 47 | << "Exception type: " << typeid(e).name() << std::endl << std::endl; 48 | 49 | if(level == test_level_critical) 50 | exit(EXIT_FAILURE); 51 | } 52 | 53 | #define PE_TEST_TO_STRING(expression) #expression 54 | 55 | //Checks the result of expression (true) 56 | #define PE_TEST(expression, test_name, level) \ 57 | try \ 58 | { \ 59 | pe_test((expression), test_name, level, PE_TEST_TO_STRING(expression), __FILE__, __LINE__); \ 60 | } \ 61 | catch(const std::exception& e) \ 62 | { \ 63 | pe_test_error(e, test_name, level, PE_TEST_TO_STRING(expression), __FILE__, __LINE__); \ 64 | } 65 | 66 | //Runs expression and checks for exceptions 67 | #define PE_TEST_EXCEPTION(expression, test_name, level) \ 68 | try \ 69 | { \ 70 | (expression); \ 71 | std::cout << test_name << " - OK" << std::endl; \ 72 | } \ 73 | catch(const std::exception& e) \ 74 | { \ 75 | pe_test_error(e, test_name, level, PE_TEST_TO_STRING(expression), __FILE__, __LINE__); \ 76 | } 77 | 78 | //Awaits exception from expression 79 | #define PE_TEST_EXPECT_EXCEPTION(expression, pe_exception_code, test_name, level) \ 80 | try \ 81 | { \ 82 | (expression); \ 83 | std::cerr << "Expected exception: " << PE_TEST_TO_STRING(pe_exception_code) << std::endl; \ 84 | pe_test_print_error(test_name, level, PE_TEST_TO_STRING(expression), __FILE__, __LINE__); \ 85 | } \ 86 | catch(const pe_exception& e) \ 87 | { \ 88 | if(e.get_id() == pe_exception_code) \ 89 | std::cout << test_name << " - OK" << std::endl; \ 90 | else \ 91 | pe_test_error(e, test_name, level, PE_TEST_TO_STRING(expression), __FILE__, __LINE__); \ 92 | } 93 | 94 | 95 | #ifndef PE_FILES_UNUSED 96 | static bool open_pe_file(int argc, char* argv[], std::unique_ptr& pe_file) 97 | { 98 | if(argc != 2) 99 | { 100 | std::cerr << "Usage: test.exe PE_FILE" << std::endl; 101 | return false; 102 | } 103 | 104 | pe_file.reset(new std::ifstream(argv[1], std::ios::in | std::ios::binary)); 105 | if(!*pe_file) 106 | { 107 | std::cerr << "Cannot open " << argv[1] << std::endl; 108 | return false; 109 | } 110 | 111 | return true; 112 | } 113 | #endif 114 | 115 | #define PE_TEST_START \ 116 | try \ 117 | { 118 | 119 | 120 | #define PE_TEST_END } \ 121 | catch(const std::exception& e) \ 122 | { \ 123 | pe_test_error(e, "Global Test", test_level_critical, "global test exception handler", __FILE__, __LINE__); \ 124 | } 125 | -------------------------------------------------------------------------------- /src/tests/test_bound_import/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_bound_import) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_bound_import/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "test.h" 5 | 6 | using namespace pe_bliss; 7 | 8 | void test_bound_imports(const pe_base& image) 9 | { 10 | bound_import_module_list imports; 11 | PE_TEST_EXCEPTION(imports = get_bound_import_module_list(image), "Bound Import Parser test", test_level_critical); 12 | PE_TEST(imports.size() == 2, "Bound Import test 1", test_level_critical); 13 | PE_TEST(imports[0].get_module_name() == "USER32.dll" 14 | && imports[1].get_module_name() == "KERNEL32.dll", "Bound Import test 2", test_level_normal); 15 | 16 | if(image.get_pe_type() == pe_type_32) 17 | { 18 | PE_TEST(imports[0].get_timestamp() == 0x4a5bdb3c 19 | && imports[1].get_timestamp() == 0x4afc68c0, "Bound Import test 3", test_level_normal); 20 | } 21 | else 22 | { 23 | PE_TEST(imports[0].get_timestamp() == 0x4a5bdb3c 24 | && imports[1].get_timestamp() == 0, "Bound Import test 3", test_level_normal); 25 | } 26 | 27 | PE_TEST(imports[0].get_module_ref_count() == 0 28 | && imports[1].get_module_ref_count() == 1, "Bound Import test 4", test_level_critical); 29 | PE_TEST(imports[1].get_module_ref_list()[0].get_module_name() == "NTDLL.DLL" 30 | && imports[1].get_module_ref_list()[0].get_timestamp() == 0x4afc681b, "Bound Import test 5", test_level_normal); 31 | } 32 | 33 | int main(int argc, char* argv[]) 34 | { 35 | PE_TEST_START 36 | 37 | std::unique_ptr pe_file; 38 | if(!open_pe_file(argc, argv, pe_file)) 39 | return -1; 40 | 41 | pe_base image(pe_factory::create_pe(*pe_file)); 42 | test_bound_imports(image); 43 | 44 | { 45 | std::stringstream new_pe(std::ios::in | std::ios::out | std::ios::binary); 46 | PE_TEST_EXCEPTION(rebuild_pe(image, new_pe, false, true, true), "Bound Rebuild PE test 1", test_level_critical); 47 | PE_TEST_EXCEPTION(image = pe_factory::create_pe(new_pe), "Bound Rebuild PE test 2", test_level_critical); 48 | test_bound_imports(image); 49 | 50 | new_pe.str(""); 51 | PE_TEST_EXCEPTION(rebuild_pe(image, new_pe, true, true, true), "Bound Rebuild PE test 3", test_level_critical); 52 | PE_TEST_EXCEPTION(image = pe_factory::create_pe(new_pe), "Bound Rebuild PE test 4", test_level_critical); 53 | test_bound_imports(image); 54 | } 55 | 56 | 57 | section s; 58 | s.get_raw_data().resize(1); 59 | s.set_name("newbound"); 60 | s.readable(true); 61 | section& new_bound_import_section = image.add_section(s); 62 | bound_import_module_list imports; 63 | PE_TEST_EXCEPTION(imports = get_bound_import_module_list(image), "Bound Import Parser test", test_level_critical); 64 | 65 | uint32_t old_bound_import_rva = image.get_directory_rva(pe_win::image_directory_entry_bound_import); 66 | PE_TEST_EXCEPTION(rebuild_bound_imports(image, imports, new_bound_import_section, 0, true, true), "Bound Import Rebuilder test 1", test_level_critical); 67 | PE_TEST(old_bound_import_rva != image.get_directory_rva(pe_win::image_directory_entry_bound_import), "Bound Import Directory test", test_level_normal); 68 | test_bound_imports(image); 69 | 70 | new_bound_import_section.set_raw_data("111"); 71 | old_bound_import_rva = image.get_directory_rva(pe_win::image_directory_entry_bound_import); 72 | PE_TEST_EXCEPTION(rebuild_bound_imports(image, imports, new_bound_import_section, 3, true, true), "Bound Import Rebuilder test 2", test_level_critical); 73 | PE_TEST(new_bound_import_section.get_raw_data().substr(0, 3) == "111", "Bound Import Rebuilder Offset test", test_level_normal); 74 | PE_TEST(old_bound_import_rva != image.get_directory_rva(pe_win::image_directory_entry_bound_import), "Bound Import Directory test 2", test_level_normal); 75 | test_bound_imports(image); 76 | 77 | PE_TEST_END 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /src/tests/test_checksum/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_checksum) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_checksum/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "test.h" 5 | 6 | using namespace pe_bliss; 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | PE_TEST_START 11 | 12 | std::unique_ptr pe_file; 13 | if(!open_pe_file(argc, argv, pe_file)) 14 | return -1; 15 | 16 | pe_base image(pe_factory::create_pe(*pe_file)); 17 | 18 | uint32_t checksum = UINT32_MAX; 19 | PE_TEST_EXCEPTION(checksum = calculate_checksum(*pe_file), "Checksum test 1", test_level_normal); 20 | PE_TEST(image.get_checksum() == checksum, "Checksum test 2", test_level_normal); 21 | 22 | PE_TEST_END 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /src/tests/test_debug/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_debug) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_dotnet/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_dotnet) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_dotnet/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "test.h" 5 | 6 | using namespace pe_bliss; 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | PE_TEST_START 11 | 12 | std::unique_ptr pe_file; 13 | if(!open_pe_file(argc, argv, pe_file)) 14 | return -1; 15 | 16 | pe_base image(pe_factory::create_pe(*pe_file)); 17 | 18 | basic_dotnet_info info; 19 | PE_TEST_EXCEPTION(info = get_basic_dotnet_info(image), "Basic Dotnet Info Parser test", test_level_critical); 20 | PE_TEST(info.get_flags() == 1, "DotNet test 1", test_level_normal); 21 | PE_TEST(info.get_major_runtime_version() == 2 && info.get_minor_runtime_version() == 5, "DotNet test 2", test_level_normal); 22 | PE_TEST(info.get_rva_of_metadata() == 0x2064 && info.get_size_of_metadata() == 0x598, "DotNet test 3", test_level_normal); 23 | PE_TEST(info.get_rva_of_resources() == 0 && info.get_size_of_resources() == 0, "DotNet test 4", test_level_normal); 24 | PE_TEST(info.get_rva_of_strong_name_signature() == 0 && info.get_size_of_strong_name_signature() == 0, "DotNet test 5", test_level_normal); 25 | PE_TEST(info.get_rva_of_code_manager_table() == 0 && info.get_size_of_code_manager_table() == 0, "DotNet test 6", test_level_normal); 26 | PE_TEST(info.get_rva_of_vtable_fixups() == 0 && info.get_size_of_vtable_fixups() == 0, "DotNet test 7", test_level_normal); 27 | PE_TEST(info.get_rva_of_export_address_table_jumps() == 0 && info.get_size_of_export_address_table_jumps() == 0, "DotNet test 8", test_level_normal); 28 | PE_TEST(info.get_rva_of_managed_native_header() == 0 && info.get_size_of_managed_native_header() == 0, "DotNet test 9", test_level_normal); 29 | PE_TEST(info.get_entry_point_rva_or_token() == 0x06000001, "DotNet test 10", test_level_normal); 30 | PE_TEST(!info.is_native_entry_point(), "DotNet test 11", test_level_normal); 31 | PE_TEST(!info.is_32bit_required(), "DotNet test 12", test_level_normal); 32 | 33 | PE_TEST_END 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /src/tests/test_entropy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_entropy) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_entropy/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "test.h" 5 | 6 | using namespace pe_bliss; 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | PE_TEST_START 11 | 12 | std::unique_ptr pe_file; 13 | if(!open_pe_file(argc, argv, pe_file)) 14 | return -1; 15 | 16 | pe_base image(pe_factory::create_pe(*pe_file)); 17 | 18 | PE_TEST(entropy_calculator::calculate_entropy(image) > 3.0, "Entropy test 1", test_level_normal); 19 | PE_TEST(entropy_calculator::calculate_entropy(*pe_file) > 3.0, "Entropy test 2", test_level_normal); 20 | PE_TEST(entropy_calculator::calculate_entropy(image.get_image_sections().at(0)) > 3.0, "Entropy test 3", test_level_normal); 21 | 22 | const char data[] = "123456789"; 23 | PE_TEST(entropy_calculator::calculate_entropy(data, sizeof(data) - 1) > 3.0, "Entropy test 4", test_level_normal); 24 | 25 | PE_TEST_EXPECT_EXCEPTION(entropy_calculator::calculate_entropy("", 0), pe_exception::data_is_empty, "Entropy test 5", test_level_normal); 26 | PE_TEST_EXPECT_EXCEPTION(entropy_calculator::calculate_entropy(section()), pe_exception::section_is_empty, "Entropy test 6", test_level_normal); 27 | 28 | PE_TEST_END 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /src/tests/test_exception_directory/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_exception_directory) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_exception_directory/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "test.h" 5 | 6 | using namespace pe_bliss; 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | PE_TEST_START 11 | 12 | std::unique_ptr pe_file; 13 | if(!open_pe_file(argc, argv, pe_file)) 14 | return -1; 15 | 16 | pe_base image(pe_factory::create_pe(*pe_file)); 17 | 18 | if(image.get_pe_type() == pe_type_64) 19 | { 20 | exception_entry_list info; 21 | PE_TEST_EXCEPTION(info = get_exception_directory_data(image), "Exception directory parser test", test_level_critical); 22 | PE_TEST(info.size() == 0x1C6, "Exception directory test 1", test_level_normal); 23 | PE_TEST(info[5].get_begin_address() == 0x000011D5 24 | && info[5].get_end_address() == 0x00001220, "Exception directory test 2", test_level_normal); 25 | PE_TEST(info[5].get_flags() == 4, "Exception directory test 3", test_level_normal); 26 | PE_TEST(info[5].get_unwind_info_address() == 0x21528, "Exception directory test 4", test_level_normal); 27 | PE_TEST(info[5].get_unwind_info_version() == 1, "Exception directory test 5", test_level_normal); 28 | PE_TEST(info[5].get_size_of_prolog() == 0x5, "Exception directory test 6", test_level_normal); 29 | PE_TEST(info[5].get_number_of_unwind_slots() == 2, "Exception directory test 7", test_level_normal); 30 | PE_TEST(info[5].get_frame_pointer_register_number() == 0, "Exception directory test 8", test_level_normal); 31 | PE_TEST(info[5].get_scaled_rsp_offset() == 0, "Exception directory test 9", test_level_normal); 32 | } 33 | 34 | PE_TEST_END 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /src/tests/test_exports/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_exports) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_imports/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_imports) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_load_config/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_load_config) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_load_config/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "test.h" 5 | 6 | using namespace pe_bliss; 7 | 8 | void check_load_config(const image_config_info& info) 9 | { 10 | PE_TEST(info.get_security_cookie_va() == 0x41E7F4, "Load Config Values test 1", test_level_normal); 11 | PE_TEST(info.get_se_handler_count() == 0x20, "Load Config Values test 2", test_level_critical); 12 | PE_TEST(info.get_time_stamp() == 0, "Load Config Values test 3", test_level_normal); 13 | PE_TEST(info.get_se_handler_rvas()[1] == 0x731a, "Load Config Values test 4", test_level_normal); 14 | } 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | PE_TEST_START 19 | 20 | std::unique_ptr pe_file; 21 | if(!open_pe_file(argc, argv, pe_file)) 22 | return -1; 23 | 24 | pe_base image(pe_factory::create_pe(*pe_file)); 25 | 26 | if(image.get_pe_type() == pe_type_32) 27 | { 28 | image_config_info info; 29 | PE_TEST_EXCEPTION(info = get_image_config(image), "Load Config Parser test 1", test_level_critical); 30 | check_load_config(info); 31 | 32 | section s; 33 | s.get_raw_data().resize(1); 34 | s.set_name("newcfg"); 35 | section& new_config_section = image.add_section(s); 36 | 37 | uint32_t old_dir_rva = image.get_directory_rva(pe_win::image_directory_entry_load_config); 38 | 39 | PE_TEST_EXCEPTION(rebuild_image_config(image, info, new_config_section, 0, false, false, true, true), "Load Config Rebuilder test 1", test_level_critical); 40 | PE_TEST(old_dir_rva != image.get_directory_rva(pe_win::image_directory_entry_load_config), "Load Config test 5", test_level_normal); 41 | 42 | uint64_t old_se_handler_table_va = info.get_se_handler_table_va(); 43 | PE_TEST_EXCEPTION(info = get_image_config(image), "Load Config Parser test 2", test_level_critical); 44 | PE_TEST(old_se_handler_table_va == info.get_se_handler_table_va(), "Load Config test 5", test_level_normal); 45 | check_load_config(info); 46 | 47 | PE_TEST_EXCEPTION(rebuild_image_config(image, info, new_config_section, 0, true, false, true, true), "Load Config Rebuilder test 2", test_level_critical); 48 | PE_TEST_EXCEPTION(info = get_image_config(image), "Load Config Parser test 3", test_level_critical); 49 | PE_TEST(old_se_handler_table_va != info.get_se_handler_table_va(), "Load Config test 6", test_level_normal); 50 | check_load_config(info); 51 | 52 | info.add_lock_prefix_rva(0x123); 53 | info.add_lock_prefix_rva(0x456); 54 | info.add_lock_prefix_rva(0x789); 55 | 56 | PE_TEST_EXCEPTION(rebuild_image_config(image, info, new_config_section, 0, true, true, true, true), "Load Config Rebuilder test 3", test_level_critical); 57 | PE_TEST_EXCEPTION(info = get_image_config(image), "Load Config Parser test 4", test_level_critical); 58 | check_load_config(info); 59 | PE_TEST(info.get_lock_prefix_rvas().size() == 3, "Load Config Lock Prefix test 1", test_level_normal); 60 | PE_TEST(info.get_lock_prefix_rvas()[2] == 0x789, "Load Config Lock Prefix test 2", test_level_normal); 61 | 62 | PE_TEST_EXCEPTION(rebuild_image_config(image, info, new_config_section, 1, true, true, true, true), "Load Config Rebuilder test 4", test_level_critical); 63 | PE_TEST_EXCEPTION(info = get_image_config(image), "Load Config Parser test 5", test_level_critical); 64 | check_load_config(info); 65 | PE_TEST_EXCEPTION(rebuild_image_config(image, info, new_config_section, 12, true, true, true, true), "Load Config Rebuilder test 5", test_level_critical); 66 | PE_TEST_EXCEPTION(info = get_image_config(image), "Load Config Parser test 6", test_level_critical); 67 | check_load_config(info); 68 | 69 | info.add_se_handler_rva(0x001); //Check sorting 70 | info.set_lock_prefix_table_va(0); 71 | PE_TEST_EXCEPTION(rebuild_image_config(image, info, new_config_section, 0, true, false, true, true), "Load Config Rebuilder test 5", test_level_critical); 72 | PE_TEST_EXCEPTION(info = get_image_config(image), "Load Config Parser test 6", test_level_critical); 73 | PE_TEST(info.get_se_handler_count() == 0x21, "Load Config Values test 5", test_level_critical); 74 | PE_TEST(info.get_se_handler_rvas()[0] == 0x001, "Load Config Values test 6", test_level_normal); //Checks if list is sorted 75 | } 76 | 77 | PE_TEST_END 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /src/tests/test_relocations/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_relocations) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_resource_bitmap/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_resource_bitmap) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_resource_bitmap/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "test.h" 6 | 7 | using namespace pe_bliss; 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | PE_TEST_START 12 | 13 | std::unique_ptr pe_file; 14 | if(!open_pe_file(argc, argv, pe_file)) 15 | return -1; 16 | 17 | pe_base image(pe_factory::create_pe(*pe_file)); 18 | 19 | resource_directory root(get_resources(image)); 20 | 21 | pe_resource_manager res(root); 22 | resource_bitmap_reader bmp_read(res); 23 | resource_bitmap_writer bmp_write(res); 24 | 25 | PE_TEST_EXPECT_EXCEPTION(bmp_read.get_bitmap_by_name(L"TEST"), pe_exception::resource_directory_entry_not_found, "Bitmap Reader test 1", test_level_normal); 26 | PE_TEST_EXPECT_EXCEPTION(bmp_read.get_bitmap_by_name(123, L"TEST"), pe_exception::resource_directory_entry_not_found, "Bitmap Reader test 2", test_level_normal); 27 | PE_TEST_EXPECT_EXCEPTION(bmp_read.get_bitmap_by_id(123), pe_exception::resource_directory_entry_not_found, "Bitmap Reader test 3", test_level_normal); 28 | 29 | std::string bitmap; 30 | PE_TEST_EXCEPTION(bitmap = bmp_read.get_bitmap_by_id(102), "Bitmap Reader test 4", test_level_normal); 31 | PE_TEST_EXPECT_EXCEPTION(bmp_read.get_bitmap_by_id(102, 1), pe_exception::resource_data_entry_not_found, "Bitmap Reader test 5", test_level_normal); 32 | PE_TEST_EXCEPTION(bmp_write.add_bitmap(bitmap, L"TEST", 1049, 1234, 5678), "Bitmap Writer test 1", test_level_normal); 33 | 34 | std::string bitmap2; 35 | PE_TEST_EXCEPTION(bitmap2 = bmp_read.get_bitmap_by_name(1049, L"TEST"), "Bitmap Reader test 6", test_level_critical); 36 | PE_TEST(bitmap == bitmap2, "Bitmap Reader test 7", test_level_normal); 37 | 38 | PE_TEST_EXCEPTION(bmp_write.add_bitmap(bitmap, 9000, 1049, 1234, 5678), "Bitmap Writer test 2", test_level_critical); 39 | PE_TEST_EXCEPTION(bitmap2 = bmp_read.get_bitmap_by_id(9000), "Bitmap Reader test 8", test_level_normal); 40 | PE_TEST(bitmap == bitmap2, "Bitmap Reader test 9", test_level_normal); 41 | 42 | PE_TEST_EXCEPTION(bitmap = bmp_read.get_bitmap_by_id(103), "Bitmap Reader test 10", test_level_normal); 43 | PE_TEST_EXCEPTION(bmp_write.add_bitmap(bitmap, 9000, 1049, 1234, 5678), "Bitmap Writer test 3 (bitmap replace test)", test_level_critical); 44 | PE_TEST_EXCEPTION(bitmap2 = bmp_read.get_bitmap_by_id(9000), "Bitmap Reader test 11", test_level_normal); 45 | PE_TEST(bitmap == bitmap2, "Bitmap Reader test 12", test_level_normal); 46 | 47 | PE_TEST_EXCEPTION(bmp_write.remove_bitmap(9000, 1049), "Bitmap Writer test 4", test_level_critical); 48 | PE_TEST_EXPECT_EXCEPTION(bmp_read.get_bitmap_by_id(9000), pe_exception::resource_directory_entry_not_found, "Bitmap Reader test 13", test_level_normal); 49 | 50 | PE_TEST_EXCEPTION(bmp_write.remove_bitmap(L"TEST", 1049), "Bitmap Writer test 5", test_level_critical); 51 | PE_TEST_EXPECT_EXCEPTION(bmp_read.get_bitmap_by_name(L"TEST"), pe_exception::resource_directory_entry_not_found, "Bitmap Reader test 14", test_level_normal); 52 | 53 | PE_TEST_END 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /src/tests/test_resource_icon_cursor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_resource_icon_cursor) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_resource_manager/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_resource_manager) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_resource_message_table/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_resource_message_table) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PUBLIC pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_resource_message_table/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "test.h" 6 | 7 | using namespace pe_bliss; 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | PE_TEST_START 12 | 13 | std::unique_ptr pe_file; 14 | if(!open_pe_file(argc, argv, pe_file)) 15 | return -1; 16 | 17 | pe_base image(pe_factory::create_pe(*pe_file)); 18 | 19 | resource_directory root(get_resources(image)); 20 | 21 | pe_resource_manager res(root); 22 | resource_message_list_reader msg(res); 23 | 24 | resource_message_list messages; 25 | 26 | //Unicode tests 27 | PE_TEST_EXCEPTION(messages = msg.get_message_table_by_id_lang(1049, 1), "Message Table Parser test 1", test_level_critical); 28 | PE_TEST(messages.size() == 2, "Message Table Parser test 2", test_level_critical); 29 | PE_TEST(messages.find(0x01000000) != messages.end() 30 | && messages.find(0xC1000001) != messages.end(), "Message Table Parser test 3", test_level_critical); 31 | PE_TEST(messages[0xC1000001].is_unicode(), "Message Table Parser test 4", test_level_normal); 32 | PE_TEST(messages[0xC1000001].get_unicode_string() == L"Ошибка!\r\n", "Message Table Parser test 5", test_level_normal); 33 | 34 | PE_TEST_EXCEPTION(messages = msg.get_message_table_by_id_lang(1033, 1), "Message Table Parser test 6", test_level_critical); 35 | PE_TEST(messages.size() == 2, "Message Table Parser test 7", test_level_critical); 36 | PE_TEST(messages.find(0x01000000) != messages.end() 37 | && messages.find(0xC1000001) != messages.end(), "Message Table Parser test 8", test_level_critical); 38 | PE_TEST(messages[0xC1000001].is_unicode(), "Message Table Parser test 9", test_level_normal); 39 | PE_TEST(messages[0xC1000001].get_unicode_string() == L"Error!\r\n", "Message Table Parser test 10", test_level_normal); 40 | 41 | //ANSI Tests 42 | PE_TEST_EXCEPTION(messages = msg.get_message_table_by_id_lang(1049, 2), "Message Table Parser test 11", test_level_critical); 43 | PE_TEST(messages.size() == 2, "Message Table Parser test 12", test_level_critical); 44 | PE_TEST(messages.find(0x01000000) != messages.end() 45 | && messages.find(0xC1000001) != messages.end(), "Message Table Parser test 13", test_level_critical); 46 | PE_TEST(!messages[0xC1000001].is_unicode(), "Message Table Parser test 14", test_level_normal); 47 | PE_TEST(messages[0xC1000001].get_ansi_string() == "\xCE\xF8\xE8\xE1\xEA\xE0!\r\n", "Message Table Parser test 15", test_level_normal); //"Ошибка!\r\n" 48 | 49 | PE_TEST_EXCEPTION(messages = msg.get_message_table_by_id_lang(1033, 2), "Message Table Parser test 16", test_level_critical); 50 | PE_TEST(messages.size() == 2, "Message Table Parser test 17", test_level_critical); 51 | PE_TEST(messages.find(0x01000000) != messages.end() 52 | && messages.find(0xC1000001) != messages.end(), "Message Table Parser test 18", test_level_critical); 53 | PE_TEST(!messages[0xC1000001].is_unicode(), "Message Table Parser test 19", test_level_normal); 54 | PE_TEST(messages[0xC1000001].get_ansi_string() == "Error!\r\n", "Message Table Parser test 20", test_level_normal); 55 | 56 | PE_TEST_END 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /src/tests/test_resource_string_table/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_resource_string_table) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_resource_string_table/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "test.h" 6 | 7 | using namespace pe_bliss; 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | PE_TEST_START 12 | 13 | std::unique_ptr pe_file; 14 | if(!open_pe_file(argc, argv, pe_file)) 15 | return -1; 16 | 17 | pe_base image(pe_factory::create_pe(*pe_file)); 18 | 19 | resource_directory root(get_resources(image)); 20 | 21 | pe_resource_manager res(root); 22 | resource_string_table_reader str(res); 23 | 24 | resource_string_list strings; 25 | PE_TEST_EXCEPTION(strings = str.get_string_table_by_id_lang(1049, 7), "String List Parser test 1", test_level_critical); 26 | PE_TEST(strings.size() == 4, "String List Parser test 2", test_level_critical); 27 | PE_TEST(strings.find(111) != strings.end(), "String List Parser test 3", test_level_critical); 28 | PE_TEST(strings[111] == L"Test String 4", "String List Parser test 4", test_level_normal); 29 | 30 | std::wstring str_111; 31 | PE_TEST_EXCEPTION(str_111 = str.get_string_by_id(111), "String List Parser test 5", test_level_normal); 32 | PE_TEST(str_111 == L"Test String 4", "String List Parser test 6", test_level_normal); 33 | PE_TEST(str_111 == str.get_string_by_id_lang(1049, 111), "String List Parser test 7", test_level_normal); 34 | 35 | PE_TEST_END 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /src/tests/test_resource_version_info/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_resource_version_info) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_resource_viewer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_resource_viewer) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_resources/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_resources) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_rich_data/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_rich_data) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_rich_data/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "test.h" 5 | 6 | using namespace pe_bliss; 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | PE_TEST_START 11 | 12 | std::unique_ptr pe_file; 13 | if(!open_pe_file(argc, argv, pe_file)) 14 | return -1; 15 | 16 | pe_base image(pe_factory::create_pe(*pe_file)); 17 | 18 | rich_data_list data; 19 | PE_TEST_EXCEPTION(data = get_rich_data(image), "Rich Data test 1", test_level_critical); 20 | PE_TEST(data.size() == 8, "Rich Data test 2", test_level_normal); 21 | PE_TEST(data[0].get_number() == 158, "Rich Data test 3", test_level_normal); 22 | 23 | if(image.get_pe_type() == pe_type_32) 24 | { 25 | PE_TEST(data[1].get_times() == 47, "Rich Data test 4", test_level_normal); 26 | } 27 | else 28 | { 29 | PE_TEST(data[1].get_times() == 48, "Rich Data test 4", test_level_normal); 30 | } 31 | 32 | PE_TEST(data[2].get_version() == 40219, "Rich Data test 5", test_level_normal); 33 | 34 | PE_TEST_END 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /src/tests/test_runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_runner) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | add_test(${PROJECT} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT}) 14 | -------------------------------------------------------------------------------- /src/tests/test_tls/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT test_tls) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/test_tls/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "test.h" 5 | 6 | using namespace pe_bliss; 7 | 8 | void test_tls(const tls_info& info, const pe_base& image, bool check_callbacks = true) 9 | { 10 | PE_TEST(info.get_characteristics() == 0, "TLS test 1", test_level_normal); 11 | PE_TEST(info.get_size_of_zero_fill() == 0, "TLS test 2", test_level_normal); 12 | PE_TEST(info.get_raw_data_end_rva() - info.get_raw_data_start_rva() == 8, "TLS test 3", test_level_normal); 13 | PE_TEST(info.get_raw_data() == std::string("\0\0\0\0\x37\x02\0\0", 8), "TLS test 4", test_level_normal); 14 | 15 | if(check_callbacks) 16 | { 17 | PE_TEST(info.get_tls_callbacks().empty(), "TLS test 5", test_level_normal); 18 | } 19 | 20 | if(image.get_pe_type() == pe_type_32) 21 | { 22 | PE_TEST(info.get_index_rva() == 0x420738 - image.get_image_base_32(), "TLS test 6", test_level_normal); 23 | 24 | if(check_callbacks) 25 | { 26 | PE_TEST(info.get_callbacks_rva() == 0x418188 - image.get_image_base_32(), "TLS test 7", test_level_normal); 27 | } 28 | } 29 | else 30 | { 31 | PE_TEST(info.get_index_rva() == 0x14002647Cull - image.get_image_base_64(), "TLS test 6", test_level_normal); 32 | 33 | if(check_callbacks) 34 | { 35 | PE_TEST(info.get_callbacks_rva() == 0x14001B310ull - image.get_image_base_64(), "TLS test 7", test_level_normal); 36 | } 37 | } 38 | } 39 | 40 | int main(int argc, char* argv[]) 41 | { 42 | PE_TEST_START 43 | 44 | std::unique_ptr pe_file; 45 | if(!open_pe_file(argc, argv, pe_file)) 46 | return -1; 47 | 48 | pe_base image(pe_factory::create_pe(*pe_file)); 49 | 50 | tls_info info; 51 | PE_TEST_EXCEPTION(info = get_tls_info(image), "TLS Parser test 1", test_level_critical); 52 | test_tls(info, image); 53 | 54 | section s; 55 | s.get_raw_data().resize(1); 56 | s.set_name("newtls"); 57 | section& new_tls_section = image.add_section(s); 58 | uint32_t old_tls_rva = image.get_directory_rva(pe_win::image_directory_entry_tls); 59 | PE_TEST_EXCEPTION(rebuild_tls(image, info, new_tls_section, 0, false, false, tls_data_expand_raw, true, true), "TLS Rebuilder test 1", test_level_critical); 60 | PE_TEST(old_tls_rva != image.get_directory_rva(pe_win::image_directory_entry_tls), "TLS directory test", test_level_normal); 61 | 62 | PE_TEST_EXCEPTION(info = get_tls_info(image), "TLS Parser test 2", test_level_critical); 63 | test_tls(info, image); 64 | 65 | new_tls_section.set_raw_data("111"); 66 | PE_TEST_EXCEPTION(rebuild_tls(image, info, new_tls_section, 3, false, false, tls_data_expand_raw, true, true), "TLS Rebuilder test 2", test_level_critical); 67 | PE_TEST_EXCEPTION(info = get_tls_info(image), "TLS Parser test 3", test_level_critical); 68 | PE_TEST(new_tls_section.get_raw_data().substr(0, 3) == "111", "TLS Rebuilder offset test", test_level_normal); 69 | test_tls(info, image); 70 | 71 | PE_TEST_EXCEPTION(rebuild_tls(image, info, new_tls_section, 12, false, false, tls_data_expand_raw, true, true), "TLS Rebuilder test 3", test_level_critical); 72 | PE_TEST_EXCEPTION(info = get_tls_info(image), "TLS Parser test 4", test_level_critical); 73 | test_tls(info, image); 74 | 75 | image.set_section_virtual_size(new_tls_section, 0x2000); 76 | info.set_raw_data_start_rva(image.rva_from_section_offset(new_tls_section, 0x1000)); 77 | info.recalc_raw_data_end_rva(); 78 | PE_TEST_EXCEPTION(rebuild_tls(image, info, new_tls_section, 12, false, true, tls_data_expand_raw, true, true), "TLS Rebuilder test 4", test_level_critical); 79 | PE_TEST_EXCEPTION(info = get_tls_info(image), "TLS Parser test 5", test_level_critical); 80 | test_tls(info, image); 81 | 82 | info.add_tls_callback(0x111); 83 | info.add_tls_callback(0x222); 84 | info.add_tls_callback(0x333); 85 | info.add_tls_callback(0x444); 86 | info.add_tls_callback(0x555); 87 | info.set_callbacks_rva(image.rva_from_section_offset(new_tls_section, 0x1500)); 88 | 89 | PE_TEST_EXCEPTION(rebuild_tls(image, info, new_tls_section, 12, true, true, tls_data_expand_raw, true, true), "TLS Rebuilder test 5", test_level_critical); 90 | PE_TEST_EXCEPTION(info = get_tls_info(image), "TLS Parser test 6", test_level_critical); 91 | test_tls(info, image, false); 92 | PE_TEST(info.get_tls_callbacks().size() == 5, "TLS test 7", test_level_normal); 93 | PE_TEST(info.get_tls_callbacks()[2] == 0x333, "TLS test 8", test_level_normal); 94 | 95 | PE_TEST_END 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /src/tests/tests_basic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT tests_basic) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/tests_utils/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(PROJECT tests_utils) 4 | 5 | include (${pe_lib_root_SOURCE_DIR}/config.cmake) 6 | 7 | add_executable(${PROJECT} ${HEADERS} ${SOURCES}) 8 | 9 | target_include_directories(${PROJECT} PRIVATE ${pe_lib_SOURCE_DIR} ${pe_lib_root_SOURCE_DIR}/tests/) 10 | 11 | target_link_libraries(${PROJECT} PRIVATE pe_lib) 12 | 13 | -------------------------------------------------------------------------------- /src/tests/tests_utils/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define PE_FILES_UNUSED 5 | #include "test.h" 6 | 7 | using namespace pe_bliss; 8 | 9 | int main(int /*argc*/, char* argv[]) 10 | { 11 | PE_TEST_START 12 | 13 | const char data[] = "abcdefgh"; 14 | PE_TEST(pe_utils::is_null_terminated(data, sizeof(data)), "is_null_terminated test 1", test_level_normal); 15 | PE_TEST(!pe_utils::is_null_terminated(data, sizeof(data) - 1), "is_null_terminated test 2", test_level_normal); 16 | 17 | std::string str("test\0\0\0"); 18 | PE_TEST_EXCEPTION(pe_utils::strip_nullbytes(str), "strip_nullbytes test 1", test_level_normal); 19 | PE_TEST(str == "test", "strip_nullbytes test 2", test_level_normal); 20 | 21 | PE_TEST(pe_utils::is_power_of_2(8), "is_power_of_2 test 1", test_level_normal); 22 | PE_TEST(!pe_utils::is_power_of_2(7), "is_power_of_2 test 2", test_level_normal); 23 | 24 | PE_TEST(pe_utils::align_down(99, 4) == 96, "align_down test 1", test_level_normal); 25 | PE_TEST(pe_utils::align_down(100, 4) == 100, "align_down test 2", test_level_normal); 26 | 27 | PE_TEST(pe_utils::align_up(99, 4) == 100, "align_up test 1", test_level_normal); 28 | PE_TEST(pe_utils::align_up(100, 4) == 100, "align_up test 2", test_level_normal); 29 | 30 | PE_TEST(pe_utils::is_sum_safe(100, 100), "is_sum_safe test 1", test_level_normal); 31 | PE_TEST(!pe_utils::is_sum_safe(pe_utils::max_dword - 1, 2), "is_sum_safe test 2", test_level_normal); 32 | 33 | std::ifstream file(argv[0]); 34 | file.seekg(0, std::ios::end); 35 | std::streamoff size = file.tellg(); 36 | file.seekg(123); 37 | 38 | PE_TEST(pe_utils::get_file_size(file) == size, "get_file_size test 1", test_level_normal); 39 | PE_TEST(static_cast(file.tellg()) == static_cast(123), "get_file_size test 2", test_level_normal); //Restore position test 40 | 41 | #ifndef PE_BLISS_WINDOWS 42 | PE_TEST(pe_utils::from_ucs2(pe_utils::to_ucs2(L"alala")) == L"alala", "to_ucs2 & from_ucs2 test 1", test_level_normal); 43 | PE_TEST(pe_utils::from_ucs2(pe_utils::to_ucs2(L"")) == L"", "to_ucs2 & from_ucs2 test 2", test_level_normal); 44 | #endif 45 | 46 | PE_TEST_END 47 | 48 | return 0; 49 | } 50 | --------------------------------------------------------------------------------