├── .gitignore ├── CMakeLists.txt ├── LICENSE.md ├── README.md ├── includes ├── coff │ ├── archive.hpp │ ├── auxiliaries │ │ ├── aux_file_name.hpp │ │ ├── aux_function.hpp │ │ ├── aux_function_delimiter.hpp │ │ ├── aux_section.hpp │ │ └── aux_weak_external.hpp │ ├── file_header.hpp │ ├── image.hpp │ ├── import_library.hpp │ ├── line_number.hpp │ ├── reloc.hpp │ ├── section_header.hpp │ ├── string.hpp │ ├── symbol.hpp │ └── uleb128.hpp ├── img_common.hpp ├── linuxpe └── nt │ ├── data_directories.hpp │ ├── directories │ ├── dir_debug.hpp │ ├── dir_delay_load.hpp │ ├── dir_exceptions.hpp │ ├── dir_export.hpp │ ├── dir_iat.hpp │ ├── dir_import.hpp │ ├── dir_load_config.hpp │ ├── dir_relocs.hpp │ ├── dir_resource.hpp │ ├── dir_security.hpp │ └── dir_tls.hpp │ ├── image.hpp │ ├── nt_headers.hpp │ └── optional_header.hpp ├── linux-pe.licenseheader ├── linuxpe.vcxitems └── linuxpe.vcxitems.filters /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .vs/linux-pe/v16/.suo 3 | 4 | linuxpe.vcxproj.user 5 | 6 | x64/Debug/ 7 | x64/Release/ 8 | Debug/ 9 | Release/ 10 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.17) 2 | project(linux-pe) 3 | 4 | # Header only interface. 5 | add_library(${PROJECT_NAME} INTERFACE) 6 | target_include_directories(${PROJECT_NAME} INTERFACE includes) 7 | 8 | # C++20 requirement. 9 | target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20) 10 | set(CMAKE_CXX_STANDARD 20) 11 | set(CMAKE_CXX_STANDARD_REQUIRED true) -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2020, Can Bölük 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | * Neither the name of [project] nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # linux-pe 2 | 3 | *linux-pe* is a header only library aiming to simplify the parsing of Portable Executable (PE) and Common Object File Format (COFF) formats used to describe all things executable in 32-bit and 64-bit versions of Windows operating system with no dependencies on the Windows headers. 4 | 5 | # Supported Compilers 6 | linux-pe uses C++20 features, so make sure to include `-std=c++20` or equivalent in your compiler options. g++10 & clang++-10 and higher should be able to compile without any issues but the tested compilers known to be working are are: 7 | 8 | - g++12 9 | - clang++-14 10 | - MSVC VS 2022 11 | -------------------------------------------------------------------------------- /includes/coff/archive.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "../img_common.hpp" 37 | 38 | COFF_STRUCT_PACKING 39 | namespace ar 40 | { 41 | // Magic constants. 42 | // 43 | constexpr uint64_t format_magic = 0x0A3E686372613C21; // "!\n" 44 | constexpr uint16_t entry_terminator = 0x0A60; // "`\n" 45 | 46 | // Stupid string integers. 47 | // 48 | template 49 | struct string_integer 50 | { 51 | char string[ N ]; 52 | 53 | // Integer to string. 54 | // 55 | string_integer( uint64_t integer ) 56 | { 57 | // Handle zero: 58 | // 59 | if ( !integer ) 60 | { 61 | string[ 0 ] = '0'; 62 | memset( string + 1, ' ', N - 1 ); 63 | return; 64 | } 65 | 66 | // Until all characters are written: 67 | // 68 | static constexpr char dictionary[] = "0123456789ABCDEF"; 69 | char* it = std::end( string ); 70 | while ( integer ) 71 | { 72 | *--it = dictionary[ integer % B ]; 73 | integer /= B; 74 | 75 | // Overflow, malformed. 76 | // 77 | if ( it == std::begin( string ) ) 78 | { 79 | it = std::end( string ); 80 | break; 81 | } 82 | } 83 | 84 | // Move to leftmost and right pad with spaces. 85 | // 86 | size_t len = ( size_t ) ( std::end( string ) - it ); 87 | memmove( string, it, len ); 88 | memset( string + len, ' ', N - len ); 89 | } 90 | string_integer( const string_integer& ) = default; 91 | string_integer& operator=( const string_integer& ) = default; 92 | 93 | // String to integer. 94 | // 95 | uint64_t get() const 96 | { 97 | char* it = ( char* ) string; 98 | while ( it != std::end( string ) && *it && *it != ' ' ) 99 | ++it; 100 | return strtoull( string, &it, B ); 101 | } 102 | operator uint64_t() const { return get(); } 103 | }; 104 | 105 | // Big endian integers. 106 | // 107 | template 108 | struct big_endian_t 109 | { 110 | uint8_t bytes[ sizeof( T ) ]; 111 | 112 | big_endian_t( T val ) 113 | { 114 | for( size_t i = 0; i != sizeof( T ); i++ ) 115 | bytes[ sizeof( T ) - ( i + 1 ) ] = ( val >> ( 8 * i ) ) & 0xFF; 116 | } 117 | 118 | T get() const 119 | { 120 | T value = 0; 121 | for ( size_t i = 0; i != sizeof( T ); i++ ) 122 | value |= bytes[ sizeof( T ) - ( i + 1 ) ] << ( 8 * i ); 123 | return value; 124 | } 125 | operator T() const { return get(); } 126 | }; 127 | 128 | // File entry. 129 | // 130 | struct entry_t 131 | { 132 | union 133 | { 134 | char identifier[ 16 ]; 135 | struct 136 | { 137 | char _pad; 138 | string_integer<10, 15> long_string_offset; 139 | }; 140 | }; 141 | string_integer<10, 12> modify_timestamp; 142 | string_integer<10, 6> owner_id; 143 | string_integer<10, 6> group_id; 144 | string_integer<8, 8> mode; 145 | string_integer<10, 10> length; 146 | uint16_t terminator; 147 | 148 | // Data getter. 149 | // 150 | uint8_t* data() { return ( uint8_t* ) ( this + 1 ); }; 151 | const uint8_t* data() const { return ( const uint8_t* ) ( this + 1 ); }; 152 | uint8_t* begin() { return data(); }; 153 | const uint8_t* begin() const { return data(); }; 154 | uint8_t* end() { return data() + length; }; 155 | const uint8_t* end() const { return data() + length; }; 156 | 157 | // Forward to next. 158 | // 159 | entry_t* next() { return ( entry_t* ) ( data() + ( ( length + 1 ) & ~1 ) ); } 160 | const entry_t* next() const { return ( const entry_t* ) ( data() + ( ( length + 1 ) & ~1 ) ); } 161 | 162 | // System-V extension properties. 163 | // 164 | bool is_symbol_table() const { return identifier[ 0 ] == '/' && identifier[ 1 ] == ' '; } 165 | bool is_string_table() const { return identifier[ 0 ] == '/' && identifier[ 1 ] == '/' && identifier[ 2 ] == ' '; } 166 | bool has_long_name() const { return identifier[ 0 ] == '/' && '0' <= identifier[ 1 ] && identifier[ 1 ] <= '9'; } 167 | 168 | // Convert identifier to string view. 169 | // 170 | std::string_view to_string( const entry_t* string_table = nullptr ) const 171 | { 172 | const char* begin = std::begin( identifier ); 173 | const char* end = std::end( identifier ); 174 | char terminator = '/'; 175 | 176 | if ( has_long_name() ) 177 | { 178 | begin = ( const char* ) string_table->begin() + long_string_offset; 179 | end = ( const char* ) string_table->end(); 180 | terminator = '\n'; 181 | if ( begin >= end ) return {}; 182 | } 183 | 184 | auto it = begin; 185 | while ( it != end && *it != terminator && *it ) it++; 186 | if ( it != begin && it[ -1 ] == '/' ) --it; 187 | return { begin, ( size_t ) ( it - begin ) }; 188 | } 189 | }; 190 | 191 | // Archive header. 192 | // 193 | struct header_t 194 | { 195 | uint64_t magic; 196 | entry_t first_entry; 197 | }; 198 | 199 | // Archive view wrapping the AR format. 200 | // 201 | template 202 | struct view 203 | { 204 | // Typedefs. 205 | // 206 | using archive_type = std::conditional_t; 207 | using entry_type = std::conditional_t; 208 | 209 | // Declare iterator. 210 | // 211 | struct iterator 212 | { 213 | // Declare iterator traits 214 | // 215 | using iterator_category = std::forward_iterator_tag; 216 | using difference_type = int64_t; 217 | using reference = std::pair; 218 | using pointer = const void*; 219 | 220 | // Stores current location, the limit and the string table. 221 | // 222 | entry_type* str_table; 223 | entry_type* at; 224 | const void* limit; 225 | 226 | // Implement forward iteration and basic comparison. 227 | // 228 | iterator& operator++() { at = at->next(); return *this; } 229 | iterator operator++( int ) { auto s = *this; operator++(); return s; } 230 | bool operator==( const iterator& other ) const 231 | { 232 | if ( !at ) return !other.at || other.at >= other.limit || other.at->terminator != entry_terminator; 233 | if ( !other.at ) return !at || at >= limit || at->terminator != entry_terminator; 234 | else return at == other.at; 235 | } 236 | bool operator<( const iterator& other ) const 237 | { 238 | if ( !at ) return false; 239 | if ( !other.at ) return !operator==( other ); 240 | else return at < other.at; 241 | } 242 | bool operator!=( const iterator& other ) const { return !operator==( other ); } 243 | 244 | // Implement iterator interface and the name helper. 245 | // 246 | std::string_view to_string() const { return at->to_string( str_table ); } 247 | reference operator*() const { return reference{ to_string(), *at }; } 248 | entry_type* operator->() const { return at; } 249 | }; 250 | using const_iterator = iterator; 251 | 252 | // Holds the archive header and the region limit. 253 | // 254 | archive_type* archive; 255 | const void* limit; 256 | 257 | // Holds special tables discovered during construction. 258 | // 259 | entry_type* string_table = nullptr; 260 | std::vector symbol_tables = {}; 261 | entry_type* first_entry = nullptr; 262 | 263 | // Constructed by pointer and the region size. 264 | // 265 | view( const void* _archive, size_t size ) : archive( ( archive_type* ) _archive ), limit( ( uint8_t* ) _archive + size ) 266 | { 267 | // Validate magic. 268 | // 269 | if ( archive->magic != format_magic ) 270 | limit = &archive->first_entry; 271 | 272 | // Resolve special entries and assign the first non-special entry. 273 | // 274 | for ( entry_type* it = &archive->first_entry; it < limit; it = it->next() ) 275 | { 276 | if ( it->is_string_table() && !string_table ) 277 | { 278 | string_table = it; 279 | } 280 | else if ( it->is_symbol_table() ) 281 | { 282 | symbol_tables.emplace_back( it ); 283 | } 284 | else 285 | { 286 | first_entry = it; 287 | break; 288 | } 289 | } 290 | } 291 | view( view&& ) noexcept = default; 292 | view( const view& ) = default; 293 | view& operator=( view&& ) noexcept = default; 294 | view& operator=( const view& ) = default; 295 | 296 | // Make iterable. 297 | // 298 | iterator begin() const { return { string_table, first_entry, limit }; } 299 | iterator end() const { return { nullptr, nullptr, nullptr }; } 300 | 301 | // Parser for the System V symbol table. 302 | // 303 | std::unordered_multimap read_symbols() const 304 | { 305 | // Get the table descriptor. 306 | // 307 | if ( symbol_tables.empty() ) return {}; 308 | auto* table = symbol_tables.front(); 309 | const uint8_t* it = table->begin(); 310 | const uint8_t* end = table->end(); 311 | 312 | // Read entry count. 313 | // 314 | if ( ( it + 4 ) > end ) return {}; 315 | uint32_t entry_count = *( const big_endian_t* ) it; 316 | it += 4; 317 | 318 | // Reference the offset table. 319 | // 320 | if ( ( it + 4 * entry_count ) > end ) return {}; 321 | const big_endian_t* offsets = ( const big_endian_t* ) it; 322 | it += 4 * entry_count; 323 | 324 | // Read the entries one by one. 325 | // 326 | std::unordered_multimap entries; 327 | for ( size_t n = 0; n != entry_count; n++ ) 328 | { 329 | // Read a zero-terminated string. 330 | // 331 | const uint8_t* str_begin = it; 332 | while ( it != end && *it ) it++; 333 | if ( it == end ) return {}; // Malformed entry. 334 | std::string_view string{ ( const char* ) str_begin, ( size_t ) ( it++ - str_begin ) }; 335 | 336 | // Read the entry. 337 | // 338 | entry_type* entry = ( entry_type* ) ( ( uint8_t* ) archive + offsets[ n ].get() ); 339 | if ( entry >= limit || entry->terminator != entry_terminator ) return {}; // Malformed entry. 340 | iterator entry_iterator = { string_table, entry, limit }; 341 | entries.emplace( std::move( string ), std::move( entry_iterator ) ); 342 | } 343 | return entries; 344 | } 345 | }; 346 | template view( T*, size_t ) -> view>; 347 | }; 348 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/auxiliaries/aux_file_name.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include 30 | #include "../../img_common.hpp" 31 | #include "../symbol.hpp" 32 | 33 | COFF_STRUCT_PACKING 34 | namespace coff 35 | { 36 | // Declare the data type. 37 | // 38 | struct aux_file_name_t 39 | { 40 | // Name of the file, zero terminated, multiple entries will be used if longer than 18 chars. 41 | // 42 | char file_name[ 18 ]; 43 | std::string_view to_string() const { return file_name; } 44 | }; 45 | static_assert( sizeof( aux_file_name_t ) == sizeof( symbol_t ), "Invalid auxiliary symbol." ); 46 | 47 | // Declare the matching logic. 48 | // 49 | template<> 50 | inline bool symbol_t::valid_aux() const 51 | { 52 | return name.equals_s( ".file" ) && 53 | storage_class == storage_class_id::file_name; 54 | } 55 | }; 56 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/auxiliaries/aux_function.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../../img_common.hpp" 30 | #include "../symbol.hpp" 31 | 32 | COFF_STRUCT_PACKING 33 | namespace coff 34 | { 35 | // Declare the data type. 36 | // 37 | struct aux_function_t 38 | { 39 | uint32_t sym_begin_idx; // Symbol table index for the beginning of the function. 40 | uint32_t length; // Length of the code. 41 | uint32_t ptr_line_numbers; // Raw offset to the first COFF line number entry. 42 | uint32_t sym_next_function_idx; // Symbol table index for the next function index, if zero last entry. 43 | uint16_t _pad; 44 | }; 45 | static_assert( sizeof( aux_function_t ) == sizeof( symbol_t ), "Invalid auxiliary symbol." ); 46 | 47 | // Declare the matching logic. 48 | // 49 | template<> 50 | inline bool symbol_t::valid_aux() const 51 | { 52 | return storage_class == storage_class_id::public_symbol && 53 | derived_type == derived_type_id::function && 54 | has_section(); 55 | } 56 | }; 57 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/auxiliaries/aux_function_delimiter.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../../img_common.hpp" 30 | #include "../symbol.hpp" 31 | 32 | COFF_STRUCT_PACKING 33 | namespace coff 34 | { 35 | // Declare the data type. 36 | // 37 | struct aux_function_delimiter_t 38 | { 39 | uint32_t _pad0; 40 | uint16_t line_number; // Line number 41 | uint16_t _pad1; 42 | uint32_t _pad2; 43 | uint32_t sym_next_bf_idx; // Symbol table index for the next .bf index, if zero last entry. 44 | uint16_t _pad; 45 | }; 46 | static_assert( sizeof( aux_function_delimiter_t ) == sizeof( symbol_t ), "Invalid auxiliary symbol." ); 47 | 48 | // Declare the matching logic. 49 | // 50 | template<> 51 | inline bool symbol_t::valid_aux() const 52 | { 53 | return ( name.equals_s( ".bf" ) || name.equals_s( ".ef" ) ) && 54 | storage_class == storage_class_id::function_delimiter; 55 | } 56 | }; 57 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/auxiliaries/aux_section.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include 30 | #include "../../img_common.hpp" 31 | #include "../symbol.hpp" 32 | 33 | COFF_STRUCT_PACKING 34 | namespace coff 35 | { 36 | enum class comdat_select_id : uint8_t 37 | { 38 | invalid = 0, 39 | select_no_duplicates = 1, // Throw multiply defined symbol if matching entry found. 40 | select_any = 2, // Pick any, discard rest. 41 | select_same_size = 3, // If all options have equivalent sizes pick any, else throw multiply defined symbol. 42 | select_exact_match = 4, // If all options have equivalent size and checksums pick any, else throw multiply defined symbol. 43 | select_associative = 5, // Inherits COMDAT state of another section associated, useful for discaring multiple data and code with the same logic. 44 | select_largest = 6 // Picks the largest entry, if matching size arbitrarily chosen. 45 | }; 46 | 47 | // Declare the data type. 48 | // 49 | struct aux_section_t 50 | { 51 | // Generic information. 52 | // 53 | uint32_t length; // Length of the data, same as size of raw data. 54 | uint16_t num_relocs; // Number of relocation entries. 55 | uint16_t num_line_numbers; // Number of line number entries. 56 | 57 | // COMDAT information, applicable if characteristics.lnk_comdat == true. 58 | // 59 | uint32_t checksum; // Checksum of the data for COMDAT matching. 60 | uint16_t associative_section; // One-based index into section table, only used if selection type is ::select_associative. 61 | comdat_select_id comdat_select; // COMDAT selection type. 62 | 63 | uint8_t _pad[ 3 ]; 64 | }; 65 | static_assert( sizeof( aux_section_t ) == sizeof( symbol_t ), "Invalid auxiliary symbol." ); 66 | 67 | // Declare the matching logic. 68 | // 69 | template<> 70 | inline bool symbol_t::valid_aux() const 71 | { 72 | // Must also have matching names, but cannot be checked here. 73 | // 74 | return value == 0 && 75 | storage_class == storage_class_id::private_symbol && 76 | base_type == base_type_id::none && 77 | derived_type == derived_type_id::none; 78 | } 79 | }; 80 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/auxiliaries/aux_weak_external.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../../img_common.hpp" 30 | #include "../symbol.hpp" 31 | 32 | COFF_STRUCT_PACKING 33 | namespace coff 34 | { 35 | enum class weak_external_type : uint32_t 36 | { 37 | invalid = 0, 38 | no_library = 1, // No library search for sym1 should be performed. 39 | library = 2, // Library search for sym1 should be performed. 40 | alias = 3, // Sym1 is just an alias to Sym2. 41 | }; 42 | 43 | // Declare the data type. 44 | // 45 | struct aux_weak_external_t 46 | { 47 | uint32_t sym_alias_idx; // Index of sym2 that should be linked if sym1 does not exist. 48 | weak_external_type type; // Type of the weak external. 49 | uint8_t _pad[ 10 ]; 50 | }; 51 | static_assert( sizeof( aux_weak_external_t ) == sizeof( symbol_t ), "Invalid auxiliary symbol." ); 52 | 53 | // Declare the matching logic. 54 | // 55 | template<> 56 | inline bool symbol_t::valid_aux() const 57 | { 58 | return storage_class == storage_class_id::weak_external && 59 | section_index == special_section_id::symbol_undefined && 60 | value == 0; 61 | } 62 | }; 63 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/file_header.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../img_common.hpp" 30 | 31 | WIN_STRUCT_PACKING 32 | namespace win 33 | { 34 | // File target machine 35 | // 36 | enum class machine_id : uint16_t 37 | { 38 | unknown = 0x0000, 39 | target_host = 0x0001, // Useful for indicating we want to interact with the host and not a WoW guest. 40 | i386 = 0x014C, // Intel 386. 41 | r3000 = 0x0162, // MIPS little-endian, 0x160 big-endian 42 | r4000 = 0x0166, // MIPS little-endian 43 | r10000 = 0x0168, // MIPS little-endian 44 | wcemipsv2 = 0x0169, // MIPS little-endian WCE v2 45 | alpha = 0x0184, // Alpha_AXP 46 | sh3 = 0x01A2, // SH3 little-endian 47 | sh3dsp = 0x01A3, 48 | sh3e = 0x01A4, // SH3E little-endian 49 | sh4 = 0x01A6, // SH4 little-endian 50 | sh5 = 0x01A8, // SH5 51 | arm = 0x01C0, // ARM Little-Endian 52 | thumb = 0x01C2, // ARM Thumb/Thumb-2 Little-Endian 53 | armnt = 0x01C4, // ARM Thumb-2 Little-Endian 54 | am33 = 0x01D3, 55 | powerpc = 0x01F0, // IBM PowerPC Little-Endian 56 | powerpcfp = 0x01F1, 57 | ia64 = 0x0200, // Intel 64 58 | mips16 = 0x0266, // MIPS 59 | alpha64 = 0x0284, // ALPHA64 60 | mipsfpu = 0x0366, // MIPS 61 | mipsfpu16 = 0x0466, // MIPS 62 | axp64 = 0x0284, 63 | tricore = 0x0520, // Infineon 64 | cef = 0x0CEF, 65 | ebc = 0x0EBC, // EFI Byte Code 66 | amd64 = 0x8664, // AMD64 (K8) 67 | m32r = 0x9041, // M32R little-endian 68 | arm64 = 0xAA64, // ARM64 Little-Endian 69 | cee = 0xC0EE, 70 | }; 71 | 72 | // File characteristics 73 | // 74 | union file_characteristics_t 75 | { 76 | uint16_t flags; 77 | struct 78 | { 79 | uint16_t relocs_stripped : 1; // Relocation info stripped from file. 80 | uint16_t executable : 1; // File is executable (i.e. no unresolved external references). 81 | uint16_t lines_stripped : 1; // Line nunbers stripped from file. 82 | uint16_t local_symbols_stripped : 1; // Local symbols stripped from file. 83 | uint16_t aggressive_ws_trim : 1; // Aggressively trim working set 84 | uint16_t large_address_aware : 1; // App can handle >2gb addresses 85 | uint16_t _pad0 : 1; 86 | uint16_t bytes_reversed_lo : 1; // Bytes of machine word are reversed. 87 | uint16_t machine_32 : 1; // 32 bit word machine. 88 | uint16_t debug_stripped : 1; // Debugging info stripped from file in .DBG file 89 | uint16_t runnable_from_swap : 1; // If Image is on removable media, copy and run from the swap file. 90 | uint16_t net_run_from_swap : 1; // If Image is on Net, copy and run from the swap file. 91 | uint16_t system_file : 1; // System File. 92 | uint16_t dll_file : 1; // File is a DLL. 93 | uint16_t up_system_only : 1; // File should only be run on a UP machine 94 | uint16_t bytes_reversed_hi : 1; // Bytes of machine word are reversed. 95 | }; 96 | }; 97 | 98 | // File header 99 | // 100 | struct file_header_t 101 | { 102 | machine_id machine; 103 | uint16_t num_sections; 104 | uint32_t timedate_stamp; 105 | uint32_t ptr_symbols; 106 | uint32_t num_symbols; 107 | uint16_t size_optional_header; 108 | file_characteristics_t characteristics; 109 | }; 110 | }; 111 | namespace coff 112 | { 113 | using machine_id = win::machine_id; 114 | using file_header_t = win::file_header_t; 115 | using file_characteristics_t = win::file_characteristics_t; 116 | }; 117 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/image.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../img_common.hpp" 30 | #include "line_number.hpp" 31 | #include "reloc.hpp" 32 | #include "string.hpp" 33 | #include "symbol.hpp" 34 | #include "file_header.hpp" 35 | #include "import_library.hpp" 36 | #include "section_header.hpp" 37 | #include "auxiliaries/aux_file_name.hpp" 38 | #include "auxiliaries/aux_function.hpp" 39 | #include "auxiliaries/aux_function_delimiter.hpp" 40 | #include "auxiliaries/aux_section.hpp" 41 | #include "auxiliaries/aux_weak_external.hpp" 42 | 43 | COFF_STRUCT_PACKING 44 | namespace coff 45 | { 46 | // Optional header and the header collection. 47 | // 48 | struct optional_header_t 49 | { 50 | // Only standard fields as described in the common object file format. 51 | // 52 | uint16_t magic; 53 | version_t linker_version; 54 | 55 | uint32_t size_code; 56 | uint32_t size_init_data; 57 | uint32_t size_uninit_data; 58 | 59 | uint32_t entry_point; 60 | uint32_t base_of_code; 61 | uint32_t base_of_data; 62 | }; 63 | struct image_t 64 | { 65 | file_header_t file_header; 66 | optional_header_t optional_header; 67 | 68 | // Section getter 69 | // 70 | inline section_header_t* get_sections() { return ( section_header_t* ) ( ( uint8_t* ) &optional_header + file_header.size_optional_header ); } 71 | inline const section_header_t* get_sections() const { return const_cast< image_t*>( this )->get_sections(); } 72 | inline section_header_t* get_section( size_t n ) { return get_sections() + n; } 73 | inline const section_header_t* get_section( size_t n ) const { return get_sections() + n; } 74 | 75 | // Symbol table getter 76 | // 77 | inline symbol_t* get_symbols() { return ( symbol_t* ) ( ( uint8_t* ) this + file_header.ptr_symbols ); } 78 | inline const symbol_t* get_symbols() const { return const_cast< image_t* >( this )->get_symbols(); } 79 | inline symbol_t* get_symbol( size_t n ) { return get_symbols() + n; } 80 | inline const symbol_t* get_symbol( size_t n ) const { return get_symbols() + n; } 81 | 82 | // String table getter. 83 | // 84 | inline string_table_t* get_strings() { return ( string_table_t* ) ( get_symbols() + file_header.num_symbols ); } 85 | inline const string_table_t* get_strings() const { return const_cast< image_t* >( this )->get_strings(); } 86 | }; 87 | }; 88 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/import_library.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../img_common.hpp" 30 | #include "file_header.hpp" 31 | #include 32 | 33 | COFF_STRUCT_PACKING 34 | namespace coff 35 | { 36 | static constexpr uint32_t import_lib_magic = 0xFFFF0000; 37 | 38 | 39 | enum class import_type : uint16_t // :2 40 | { 41 | code = 0, // Executable code. 42 | data = 1, // Data. 43 | rdata = 2, // Specified as CONST in the .def file. 44 | }; 45 | enum class import_name_type : uint16_t // :3 46 | { 47 | ordinal = 0, // The import is by ordinal. This indicates that the value in the Ordinal/Hint field of the import header 48 | // is the import's ordinal. If this constant is not specified, then the Ordinal/Hint field should always be 49 | // interpreted as the import's hint. 50 | name = 1, // The import name is identical to the public symbol name. 51 | name_no_prefix = 2, // The import name is the public symbol name, but skipping the leading ?, @, or optionally _. 52 | name_no_undecorate = 3, // The import name is the public symbol name, but skipping the leading ?, @, or optionally _, and truncating at the first @. 53 | }; 54 | 55 | // Import library header. 56 | // 57 | struct import_header_t 58 | { 59 | uint32_t magic; 60 | version_t version; 61 | machine_id machine; 62 | uint32_t timedate_stamp; 63 | uint32_t data_size; 64 | union 65 | { 66 | uint16_t hint; 67 | uint16_t ordinal; 68 | }; 69 | import_type type : 2; 70 | import_name_type name_type : 3; 71 | uint16_t reserved : 11; 72 | 73 | const char* get_symbol_name() const { return ( const char* ) ( this + 1 ); } 74 | const char* get_library_name() const { return get_symbol_name() + strlen( get_symbol_name() ) + 1; } 75 | }; 76 | static_assert( sizeof( import_header_t ) == 20, "Invalid enum bitfield." ); 77 | }; 78 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/line_number.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../img_common.hpp" 30 | 31 | COFF_STRUCT_PACKING 32 | namespace coff 33 | { 34 | // Line number entry. 35 | // 36 | struct line_number_t 37 | { 38 | union 39 | { 40 | uint32_t symbol_index; // If first entry at line #0, symbol index to the function. 41 | uint32_t ptr_raw_data; // Else, raw offset from the beginning of the directory that this data relates to. 42 | }; 43 | uint16_t line_number; // Line number. 44 | }; 45 | }; 46 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/reloc.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../img_common.hpp" 30 | 31 | COFF_STRUCT_PACKING 32 | namespace coff 33 | { 34 | enum reloc_type : uint16_t 35 | { 36 | // AMD64: 37 | // 38 | rel_amd64_absolute = 0x0000, // The relocation is ignored. 39 | rel_amd64_addr64 = 0x0001, // The 64-bit VA of the relocation target. 40 | rel_amd64_addr32 = 0x0002, // The 32-bit VA of the relocation target. 41 | rel_amd64_addr32nb = 0x0003, // The 32-bit address without an image base (RVA). 42 | rel_amd64_rel32 = 0x0004, // The 32-bit relative address from the byte following the relocation. 43 | rel_amd64_rel32_1 = 0x0005, // The 32-bit address relative to byte distance 1 from the relocation. 44 | rel_amd64_rel32_2 = 0x0006, // The 32-bit address relative to byte distance 2 from the relocation. 45 | rel_amd64_rel32_3 = 0x0007, // The 32-bit address relative to byte distance 3 from the relocation. 46 | rel_amd64_rel32_4 = 0x0008, // The 32-bit address relative to byte distance 4 from the relocation. 47 | rel_amd64_rel32_5 = 0x0009, // The 32-bit address relative to byte distance 5 from the relocation. 48 | rel_amd64_section = 0x000A, // The 16-bit section index of the section that contains the target. This is used to support debugging information. 49 | rel_amd64_secrel = 0x000B, // The 32-bit offset of the target from the beginning of its section. This is used to support debugging information and static thread local storage. 50 | rel_amd64_secrel7 = 0x000C, // A 7-bit unsigned offset from the base of the section that contains the target. 51 | rel_amd64_token = 0x000D, // CLR tokens. 52 | rel_amd64_srel32 = 0x000E, // A 32-bit signed span-dependent value emitted into the object. 53 | rel_amd64_pair = 0x000F, // A pair that must immediately follow every span-dependent value. 54 | rel_amd64_sspan32 = 0x0010, // A 32-bit signed span-dependent value that is applied at link time. 55 | 56 | // I386: 57 | // 58 | rel_i386_absolute = 0x0000, // The relocation is ignored. 59 | rel_i386_dir16 = 0x0001, // Not supported. 60 | rel_i386_rel16 = 0x0002, // Not supported. 61 | rel_i386_dir32 = 0x0006, // The target's 32-bit VA. 62 | rel_i386_dir32nb = 0x0007, // The target's 32-bit RVA. 63 | rel_i386_seg12 = 0x0009, // Not supported. 64 | rel_i386_section = 0x000A, // The 16-bit section index of the section that contains the target. This is used to support debugging information. 65 | rel_i386_secrel = 0x000B, // The 32-bit offset of the target from the beginning of its section. This is used to support debugging information and static thread local storage. 66 | rel_i386_token = 0x000C, // The CLR token. 67 | rel_i386_secrel7 = 0x000D, // A 7-bit offset from the base of the section that contains the target. 68 | rel_i386_rel32 = 0x0014, // The 32-bit relative displacement to the target. This supports the x86 relative branch and call instructions. 69 | }; 70 | 71 | // Relocation entry. 72 | // 73 | struct reloc_t 74 | { 75 | uint32_t virtual_address; // Virtual address of the relocated data. 76 | uint32_t symbol_index; // Symbol index. 77 | reloc_type type; // Type of the relocation applied. 78 | }; 79 | }; 80 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/section_header.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../img_common.hpp" 30 | #include "string.hpp" 31 | 32 | WIN_STRUCT_PACKING 33 | namespace coff 34 | { 35 | // Section characteristics 36 | // 37 | union section_characteristics_t 38 | { 39 | uint32_t flags; 40 | struct 41 | { 42 | uint32_t _pad0 : 5; 43 | uint32_t cnt_code : 1; // Section contains code. 44 | uint32_t cnt_init_data : 1; // Section contains initialized data. 45 | uint32_t cnt_uninit_data : 1; // Section contains uninitialized data. 46 | uint32_t _pad1 : 1; 47 | uint32_t lnk_info : 1; // Section contains comments or some other type of information. 48 | uint32_t _pad2 : 1; 49 | uint32_t lnk_remove : 1; // Section contents will not become part of image. 50 | uint32_t lnk_comdat : 1; // Section contents comdat. 51 | uint32_t _pad3 : 1; 52 | uint32_t no_defer_spec_exc : 1; // Reset speculative exceptions handling bits in the TLB entries for this section. 53 | uint32_t mem_far : 1; 54 | uint32_t _pad4 : 1; 55 | uint32_t mem_purgeable : 1; 56 | uint32_t mem_locked : 1; 57 | uint32_t mem_preload : 1; 58 | uint32_t alignment : 4; // Alignment calculated as: n ? 1 << ( n - 1 ) : 16 59 | uint32_t lnk_nreloc_ovfl : 1; // Section contains extended relocations. 60 | uint32_t mem_discardable : 1; // Section can be discarded. 61 | uint32_t mem_not_cached : 1; // Section is not cachable. 62 | uint32_t mem_not_paged : 1; // Section is not pageable. 63 | uint32_t mem_shared : 1; // Section is shareable. 64 | uint32_t mem_execute : 1; // Section is executable. 65 | uint32_t mem_read : 1; // Section is readable. 66 | uint32_t mem_write : 1; // Section is writeable. 67 | }; 68 | 69 | inline size_t get_alignment() const { return win::convert_alignment( alignment ); } 70 | inline bool set_alignment( size_t align ) { return alignment = win::reflect_alignment( align ); } 71 | }; 72 | 73 | // Section header 74 | // 75 | struct section_header_t 76 | { 77 | scn_string_t name; 78 | union 79 | { 80 | uint32_t physical_address; 81 | uint32_t virtual_size; 82 | }; 83 | uint32_t virtual_address; 84 | 85 | uint32_t size_raw_data; 86 | uint32_t ptr_raw_data; 87 | 88 | uint32_t ptr_relocs; 89 | uint32_t ptr_line_numbers; 90 | uint16_t num_relocs; 91 | uint16_t num_line_numbers; 92 | 93 | section_characteristics_t characteristics; 94 | 95 | // Characteristics NT checks based on the name as well as the real flag 96 | // 97 | bool is_paged() const 98 | { 99 | return !characteristics.mem_not_paged && ( *( uint32_t* ) &name.short_name == 'ade.' || *( uint32_t* ) &name.short_name == 'EGAP' ); 100 | } 101 | bool is_discardable() const 102 | { 103 | return characteristics.mem_discardable || *( uint32_t* ) &name.short_name == 'TINI'; 104 | } 105 | }; 106 | }; 107 | namespace win 108 | { 109 | using section_header_t = coff::section_header_t; 110 | using section_characteristics_t = coff::section_characteristics_t; 111 | }; 112 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/string.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include 30 | #include 31 | #include 32 | #include "../img_common.hpp" 33 | 34 | COFF_STRUCT_PACKING 35 | namespace coff 36 | { 37 | // String table. 38 | // 39 | union string_table_t 40 | { 41 | uint32_t size; 42 | char raw_data[ VAR_LEN ]; 43 | 44 | // Resolves a string given the offset. 45 | // 46 | const char* begin() const { return size > 4 ? &raw_data[ 0 ] : nullptr; } 47 | const char* end() const { return size > 4 ? &raw_data[ size ] : nullptr; } 48 | std::string_view resolve( size_t offset ) const 49 | { 50 | // Fail if invalid offset. 51 | // 52 | if ( offset < 4 ) return {}; 53 | 54 | // Search for the null terminator, return if found. 55 | // 56 | const char* start = begin() + offset; 57 | const char* lim = end(); 58 | for ( const char* it = start; it < lim; it++ ) 59 | if ( !*it ) 60 | return { start, ( size_t ) ( it - start ) }; 61 | 62 | // Invalid string. 63 | // 64 | return {}; 65 | } 66 | }; 67 | 68 | // External reference to string table. 69 | // 70 | struct string_t 71 | { 72 | union 73 | { 74 | char short_name[ LEN_SHORT_STR ]; // Name as inlined string. 75 | struct 76 | { 77 | uint32_t is_short; // If non-zero, name is inline'd into short_name, else has a long name. 78 | uint32_t long_name_offset; // Offset into string table. 79 | }; 80 | }; 81 | 82 | // Convert to string view given an optional string table. 83 | // 84 | std::string_view to_string( const string_table_t* tbl = nullptr ) const 85 | { 86 | if ( tbl && !is_short ) 87 | return tbl->resolve( long_name_offset ); 88 | size_t len = 0; 89 | while ( len != LEN_SHORT_STR && short_name[ len ] ) len++; 90 | return { short_name, len }; 91 | } 92 | 93 | // Array lookup, only available for short strings. 94 | // 95 | char& operator[]( size_t n ) { return const_cast( to_string()[ n ] ); } 96 | const char& operator[]( size_t n ) const { return to_string()[ n ]; } 97 | 98 | // Basic comparison primitive. 99 | // 100 | bool equals( const char* str, const string_table_t* tbl = nullptr ) const { return to_string( tbl ) == str; } 101 | 102 | // Short string comparison primitive. 103 | // 104 | template requires( N <= ( LEN_SHORT_STR + 1 ) ) 105 | bool equals_s( const char( &str )[ N ] ) const 106 | { 107 | // Compare with against empty string. 108 | // 109 | if constexpr ( N == 1 ) 110 | return ( !is_short && !long_name_offset ) || ( is_short && !short_name[ 0 ] ); 111 | 112 | // Can skip is short check since if string is not null, is short will be overwritten. 113 | // 114 | if constexpr ( N == ( LEN_SHORT_STR + 1 ) ) 115 | return !memcmp( short_name, str, LEN_SHORT_STR ); 116 | else 117 | return !memcmp( short_name, str, N ); 118 | } 119 | }; 120 | 121 | // Same as above but archive convention, used for section names. 122 | // 123 | struct scn_string_t 124 | { 125 | char short_name[ LEN_SHORT_STR ]; 126 | 127 | // Convert to string view given an optional string table. 128 | // 129 | std::string_view to_string( const string_table_t* tbl = nullptr ) const 130 | { 131 | if ( tbl && short_name[ 0 ] == '/' ) 132 | { 133 | char* end = ( char* ) std::end( short_name ); 134 | return tbl->resolve( strtoll( short_name + 1, &end, 10 ) ); 135 | } 136 | 137 | size_t len = 0; 138 | while ( len != LEN_SHORT_STR && short_name[ len ] ) len++; 139 | return { short_name, len }; 140 | } 141 | 142 | // Array lookup, only available for short strings. 143 | // 144 | char& operator[]( size_t n ) { return const_cast( to_string()[ n ] ); } 145 | const char& operator[]( size_t n ) const { return to_string()[ n ]; } 146 | 147 | // Basic comparison primitive. 148 | // 149 | bool equals( const char* str, const string_table_t* tbl = nullptr ) const { return to_string( tbl ) == str; } 150 | 151 | // Short string comparison primitive. 152 | // 153 | template requires( N <= ( LEN_SHORT_STR + 1 ) ) 154 | bool equals_s( const char( &str )[ N ] ) const 155 | { 156 | // Compare with against empty string. 157 | // 158 | if constexpr ( N == 1 ) 159 | return !short_name[ 0 ]; 160 | 161 | // Can skip is short check since if string is not null, is short will be overwritten. 162 | // 163 | if constexpr ( N == ( LEN_SHORT_STR + 1 ) ) 164 | return !memcmp( short_name, str, LEN_SHORT_STR ); 165 | else 166 | return !memcmp( short_name, str, N ); 167 | } 168 | }; 169 | }; 170 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/symbol.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../img_common.hpp" 30 | #include "string.hpp" 31 | 32 | COFF_STRUCT_PACKING 33 | namespace coff 34 | { 35 | // Special section indices. 36 | // 37 | enum special_section_id : uint16_t 38 | { 39 | symbol_undefined = 0, // External symbol 40 | symbol_absolute = 0xFFFF, // Absolute symbol, non-relocatable value. 41 | symbol_debug = 0xFFFE, // Misc. debugging info, not within a section. 42 | }; 43 | 44 | // Storage class. 45 | // 46 | enum class storage_class_id : uint8_t 47 | { 48 | none = 0, // None. 49 | auto_variable = 1, // Automatic variable. 50 | public_symbol = 2, // Public symbol, global. 51 | private_symbol = 3, // Private symbol, static. 52 | register_variable = 4, // Register variable. 53 | external_definition = 5, // External definition. 54 | label = 6, // Label. 55 | undefined_label = 7, // Undefined label. 56 | struct_member = 8, // Struct field. 57 | function_argument = 9, // Function argument. 58 | struct_tag = 10, // Struct tag. 59 | union_member = 11, // Union field. 60 | union_tag = 12, // Union tag. 61 | type_definition = 13, // Type definition. 62 | undefined_static = 14, // Undefined static. 63 | enum_tag = 15, // Enumerator tag. 64 | enum_member = 16, // Enumerator entry. 65 | register_parameter = 17, // Register parameter. 66 | bitfield = 18, // Marks a bitfield. 67 | auto_argument = 19, // Automatic argument. 68 | end_of_block = 20, // Marks the end of a block. 69 | block_delimiter = 100, // Marks the beginning or the end of a block. 70 | function_delimiter = 101, // Marks the beginning or the end of a function 71 | struct_end = 102, // Marks the end of a structure definition. 72 | file_name = 103, // File name as symbol. 73 | line_number = 104, // a) Line number as symbol. 74 | section = 104, // b) Section entry. 75 | alias_entry = 105, // a) Alias to another entry. 76 | weak_external = 105, // b) Weak external. 77 | hidden_ext_symbol = 106, // Hidden external symbol. 78 | clr_token = 107, // CLR token. 79 | phys_end_of_function = 255, // Marks physical end of a function. 80 | }; 81 | 82 | // Type identifiers. 83 | // 84 | enum class base_type_id : uint16_t 85 | { 86 | none = 0, 87 | t_void = 1, 88 | t_char = 2, 89 | t_short = 3, 90 | t_int = 4, 91 | t_long = 5, 92 | t_float = 6, 93 | t_double = 7, 94 | t_struct = 8, 95 | t_union = 9, 96 | t_enum = 10, 97 | t_enum_mem = 11, 98 | t_uchar = 12, 99 | t_ushort = 13, 100 | t_uint = 14, 101 | t_ulong = 15, 102 | }; 103 | enum class derived_type_id : uint16_t 104 | { 105 | none = 0, // Not derived. 106 | pointer = 1, // Pointer to base type. 107 | function = 2, // Function returning base type. 108 | c_array = 3, // Array of base type. 109 | }; 110 | 111 | // Symbol table entry. 112 | // 113 | struct symbol_t 114 | { 115 | string_t name; // Name of the symbol. 116 | int32_t value; // Value associated with the symbol, interp. depends on the type, usually address of the entry. 117 | uint16_t section_index; // Special index or scn#+1. 118 | 119 | base_type_id base_type : 4; // Base and derived type describing the symbol. 120 | derived_type_id derived_type : 12; // 121 | 122 | storage_class_id storage_class; // Storage class as described above. 123 | uint8_t num_auxiliary; // Auxiliary data following this symbol. 124 | 125 | // Dynamic logic for auxiliary entries. 126 | // 127 | template bool valid_aux() const; 128 | 129 | // Checks whether or not this symbol has a section. 130 | // 131 | bool has_section() const 132 | { 133 | return section_index != symbol_debug && 134 | section_index != symbol_absolute && 135 | section_index != symbol_undefined; 136 | } 137 | }; 138 | static_assert( sizeof( symbol_t ) == 18, "Invalid enum bitfield." ); 139 | }; 140 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/coff/uleb128.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include 30 | #include 31 | #include 32 | 33 | namespace coff 34 | { 35 | // Utility to encode/decode a ULEB128 value commonly seen in address signifiance tables. 36 | // 37 | inline void encode_uleb128( uint64_t value, std::vector& out ) 38 | { 39 | while( 1 ) 40 | { 41 | // Push the value of the segment and shift the integer. 42 | // 43 | auto& segment = out.emplace_back( ( uint8_t ) ( value & 0x7F ) ); 44 | value >>= 7; 45 | 46 | // If we reached zero, break. 47 | // 48 | if ( !value ) break; 49 | segment |= 0x80; 50 | } 51 | } 52 | 53 | template 54 | inline std::pair decode_uleb128( It1& it, It2&& end ) 55 | { 56 | uint64_t value = 0; 57 | for ( size_t bitcnt = 0; it < end; ++it, bitcnt += 7 ) 58 | { 59 | // Read one segment and write it into value. 60 | // 61 | uint8_t segment = *it; 62 | value |= uint64_t( segment & 0x7F ) << bitcnt; 63 | 64 | // Make sure we did not overflow out of u64 range. 65 | // 66 | if ( ( value >> bitcnt ) != ( segment & 0x7F ) ) 67 | return { value, false }; 68 | 69 | // If stream is terminated, return the value. 70 | // 71 | if ( !( segment & 0x80 ) ) 72 | { 73 | ++it; 74 | return { value, true }; 75 | } 76 | } 77 | 78 | // Invalid stream. 79 | // 80 | return { value, false }; 81 | } 82 | 83 | inline std::vector encode_uleb128s( const std::vector& values ) 84 | { 85 | // Allocate a vector for the result and reserve the maximum size. 86 | // 87 | constexpr size_t max_size = ( 64 + 6 ) / 7; 88 | std::vector result; 89 | result.reserve( values.size() * max_size ); 90 | 91 | // Encode every value and return. 92 | // 93 | for ( uint64_t value : values ) 94 | encode_uleb128( value, result ); 95 | return result; 96 | } 97 | 98 | template 99 | inline std::vector decode_uleb128s( It1&& begin, It2&& end ) 100 | { 101 | // Allocate a vector for the result and reserve an average result size assuming average integer is 22 bits. 102 | // 103 | constexpr size_t avg_size = ( 22 + 6 ) / 7; 104 | std::vector result; 105 | result.reserve( ( end - begin ) * avg_size ); 106 | 107 | // Read until we reach the end, indicate failure by returning null. 108 | // 109 | auto it = begin; 110 | while ( it != end ) 111 | { 112 | auto [val, success] = decode_uleb128( it, end ); 113 | if ( !success ) return {}; 114 | result.emplace_back( val ); 115 | } 116 | return result; 117 | } 118 | 119 | }; -------------------------------------------------------------------------------- /includes/img_common.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include 30 | #include 31 | #include 32 | 33 | #define WIN_STRUCT_PACKING _Pragma("pack(push, 4)") // Structure packings of the variants. 34 | #define COFF_STRUCT_PACKING _Pragma("pack(push, 1)") // 35 | #define LEN_SHORT_STR 8 // Common short string length used in COFF and it's variants. 36 | 37 | // If your compiler does not support zero-len arrays, define VAR_LEN as 1 before including linuxpe. 38 | // 39 | #ifndef VAR_LEN 40 | #ifndef _MSC_VER 41 | #define VAR_LEN 1 42 | #else 43 | #pragma warning(disable:4200) 44 | #define VAR_LEN 45 | #endif 46 | #endif 47 | 48 | COFF_STRUCT_PACKING 49 | namespace win 50 | { 51 | // Default image architecture 52 | // 53 | static constexpr bool default_architecture = sizeof( void* ) == 8; 54 | 55 | // NT versioning 56 | // 57 | union version_t 58 | { 59 | uint16_t identifier; 60 | struct 61 | { 62 | uint8_t major; 63 | uint8_t minor; 64 | }; 65 | }; 66 | union ex_version_t 67 | { 68 | uint32_t identifier; 69 | struct 70 | { 71 | uint16_t major; 72 | uint16_t minor; 73 | }; 74 | }; 75 | 76 | struct guid_t 77 | { 78 | uint32_t dword; 79 | uint16_t word[ 2 ]; 80 | uint8_t byte[ 8 ]; 81 | }; 82 | 83 | // Common alignment helpers 84 | // - Both return 0 on failure. 85 | // 86 | static constexpr size_t convert_alignment( uint8_t align_flag /*: 4*/ ) 87 | { 88 | if ( align_flag == 0 ) 89 | return 16; 90 | if ( align_flag >= 0xF ) 91 | return 0; 92 | return 1ull << ( align_flag - 1 ); 93 | } 94 | static constexpr uint8_t reflect_alignment( size_t alignment ) 95 | { 96 | for ( uint8_t align_flag = 1; align_flag != 0xF; align_flag++ ) 97 | if ( ( 1ull << ( align_flag - 1 ) ) >= alignment ) 98 | return align_flag; 99 | return 0; 100 | } 101 | }; 102 | namespace coff 103 | { 104 | using version_t = win::version_t; 105 | using ex_version_t = win::ex_version_t; 106 | }; 107 | #pragma pack(pop) 108 | -------------------------------------------------------------------------------- /includes/linuxpe: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "coff/image.hpp" 3 | #include "nt/image.hpp" -------------------------------------------------------------------------------- /includes/nt/data_directories.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../img_common.hpp" 30 | 31 | WIN_STRUCT_PACKING 32 | namespace win 33 | { 34 | static constexpr uint32_t NUM_DATA_DIRECTORIES = 16; 35 | 36 | // Directory indices 37 | // 38 | enum directory_id : uint8_t 39 | { 40 | directory_entry_export = 0, // Export Directory 41 | directory_entry_import = 1, // Import Directory 42 | directory_entry_resource = 2, // Resource Directory 43 | directory_entry_exception = 3, // Exception Directory 44 | directory_entry_security = 4, // Security Directory 45 | directory_entry_basereloc = 5, // Base Relocation Table 46 | directory_entry_debug = 6, // Debug Directory 47 | directory_entry_copyright = 7, // (X86 usage) 48 | directory_entry_architecture = 7, // Architecture Specific Data 49 | directory_entry_globalptr = 8, // RVA of GP 50 | directory_entry_tls = 9, // TLS Directory 51 | directory_entry_load_config = 10, // Load Configuration Directory 52 | directory_entry_bound_import = 11, // Bound Import Directory in headers 53 | directory_entry_iat = 12, // Import Address Table 54 | directory_entry_delay_import = 13, // Delay Load Import Descriptors 55 | directory_entry_com_descriptor = 14, // COM Runtime descriptor 56 | directory_reserved0 = 15, // - 57 | }; 58 | 59 | // Declare generic mapping for indices 60 | // 61 | template 62 | struct directory_type { using type = char; }; 63 | template 64 | using directory_type_t = typename directory_type::type; 65 | 66 | // Generic directory descriptors 67 | // 68 | struct data_directory_t 69 | { 70 | uint32_t rva; 71 | uint32_t size; 72 | inline bool present() const { return size; } 73 | }; 74 | struct raw_data_directory_t 75 | { 76 | uint32_t ptr_raw_data; 77 | uint32_t size; 78 | inline bool present() const { return size; } 79 | }; 80 | 81 | // Data directories 82 | // 83 | struct data_directories_x86_t 84 | { 85 | union 86 | { 87 | struct 88 | { 89 | data_directory_t export_directory; 90 | data_directory_t import_directory; 91 | data_directory_t resource_directory; 92 | data_directory_t exception_directory; 93 | raw_data_directory_t security_directory; // File offset instead of RVA! 94 | data_directory_t basereloc_directory; 95 | data_directory_t debug_directory; 96 | data_directory_t copyright_directory; 97 | data_directory_t globalptr_directory; 98 | data_directory_t tls_directory; 99 | data_directory_t load_config_directory; 100 | data_directory_t bound_import_directory; 101 | data_directory_t iat_directory; 102 | data_directory_t delay_import_directory; 103 | data_directory_t com_descriptor_directory; 104 | data_directory_t _reserved0; 105 | }; 106 | data_directory_t entries[ NUM_DATA_DIRECTORIES ]; 107 | }; 108 | }; 109 | struct data_directories_x64_t 110 | { 111 | union 112 | { 113 | struct 114 | { 115 | data_directory_t export_directory; 116 | data_directory_t import_directory; 117 | data_directory_t resource_directory; 118 | data_directory_t exception_directory; 119 | raw_data_directory_t security_directory; // File offset instead of RVA! 120 | data_directory_t basereloc_directory; 121 | data_directory_t debug_directory; 122 | data_directory_t architecture_directory; 123 | data_directory_t globalptr_directory; 124 | data_directory_t tls_directory; 125 | data_directory_t load_config_directory; 126 | data_directory_t bound_import_directory; 127 | data_directory_t iat_directory; 128 | data_directory_t delay_import_directory; 129 | data_directory_t com_descriptor_directory; 130 | data_directory_t _reserved0; 131 | }; 132 | data_directory_t entries[ NUM_DATA_DIRECTORIES ]; 133 | }; 134 | }; 135 | template 136 | using data_directories_t = std::conditional_t; 137 | }; 138 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/nt/directories/dir_debug.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include 30 | #include 31 | 32 | #include "../../img_common.hpp" 33 | #include "../data_directories.hpp" 34 | 35 | WIN_STRUCT_PACKING 36 | namespace win 37 | { 38 | namespace impl 39 | { 40 | inline constexpr char hexdigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 41 | 42 | inline constexpr void fmt_u8_0pad( char*& out, uint8_t value ) 43 | { 44 | *out++ = hexdigits[ value >> 4 ]; 45 | *out++ = hexdigits[ value & 0xF ]; 46 | } 47 | 48 | template 49 | inline constexpr void fmt_uhex_0pad( char*& out, T value ) 50 | { 51 | if constexpr ( sizeof( T ) == 1 ) 52 | return fmt_u8_0pad( out, value ); 53 | for ( size_t n = 0; n != sizeof( T ); n++ ) 54 | fmt_u8_0pad( out, uint8_t( value >> ( ( sizeof( T ) - n - 1 ) * 8 ) ) ); 55 | } 56 | 57 | inline constexpr void fmt_udec( char*& out, uint32_t value ) 58 | { 59 | size_t idx = 0; 60 | do 61 | { 62 | out[ idx++ ] = ( value % 10 ) + '0'; 63 | value /= 10; 64 | } 65 | while ( value ); 66 | 67 | size_t swap_count = idx / 2; 68 | for ( size_t i = 0; i != swap_count; i++ ) 69 | std::swap( out[ i ], out[ idx - i - 1 ] ); 70 | 71 | out += idx; 72 | } 73 | }; 74 | 75 | enum class debug_directory_type_id : uint32_t 76 | { 77 | unknown = 0x00000000, 78 | coff = 0x00000001, 79 | codeview = 0x00000002, 80 | fpo = 0x00000003, 81 | misc = 0x00000004, 82 | exception = 0x00000005, 83 | fixup = 0x00000006, 84 | omap_to_src = 0x00000007, 85 | omap_from_src = 0x00000008, 86 | borland = 0x00000009, 87 | reserved10 = 0x0000000A, 88 | clsid = 0x0000000B, 89 | vc_feature = 0x0000000C, 90 | pogo = 0x0000000D, 91 | iltcg = 0x0000000E, 92 | mpx = 0x0000000F, 93 | repro = 0x00000010, 94 | }; 95 | 96 | // Codeview headers 97 | // 98 | enum class cv_signature : uint32_t 99 | { 100 | cv41 = 0x3930424E, // 'NB09' 101 | pdb20 = 0x3031424E, // 'NB10' 102 | cv50 = 0x3131424E, // 'NB11' 103 | pdb70 = 0x53445352, // 'RSDS' 104 | }; 105 | 106 | struct cv_header_t 107 | { 108 | cv_signature signature; 109 | }; 110 | 111 | struct cv_pdb20_t : cv_header_t 112 | { 113 | uint32_t offset; // If not zero, stored within the image. 114 | uint32_t timedate_stamp; 115 | uint32_t age; 116 | 117 | }; 118 | 119 | struct cv_pdb70_t : cv_header_t 120 | { 121 | guid_t guid; 122 | uint32_t age; 123 | char pdb_name[ VAR_LEN ]; 124 | 125 | // Formats into the MSDL format. 126 | // 127 | inline std::string format() const 128 | { 129 | std::string result; 130 | result.resize( 8 + 8 + 16 + 10 ); 131 | 132 | char* it = result.data(); 133 | // u32 * 1 = 8 digits 134 | impl::fmt_uhex_0pad( it, guid.dword ); 135 | // u16 * 2 = 8 digits 136 | for ( uint16_t v : guid.word ) 137 | impl::fmt_uhex_0pad( it, v ); 138 | // u8 * 8 = 16 digits 139 | for ( uint8_t v : guid.byte ) 140 | impl::fmt_uhex_0pad( it, v ); 141 | // u32 dec = max 10 digits 142 | impl::fmt_udec( it, age ); 143 | 144 | result.resize( it - result.data() ); 145 | return result; 146 | } 147 | }; 148 | 149 | // Misc headers 150 | // 151 | enum class misc_debug_data_id : uint32_t 152 | { 153 | exe_name = 1, 154 | }; 155 | 156 | struct misc_debug_data_t 157 | { 158 | misc_debug_data_id data_type; 159 | uint32_t record_length; 160 | uint8_t is_unicode; 161 | uint8_t _pad[ 3 ]; 162 | uint8_t data[ VAR_LEN ]; 163 | }; 164 | 165 | // Directory type. 166 | // 167 | struct debug_directory_entry_t 168 | { 169 | uint32_t characteristics; 170 | uint32_t timedate_stamp; 171 | ex_version_t version; 172 | debug_directory_type_id type; 173 | uint32_t size_raw_data; 174 | uint32_t rva_raw_data; 175 | uint32_t ptr_raw_data; 176 | }; 177 | 178 | struct debug_directory_t 179 | { 180 | debug_directory_entry_t entries[ VAR_LEN ]; 181 | }; 182 | 183 | template struct directory_type { using type = debug_directory_t; }; 184 | }; 185 | #pragma pack(pop) 186 | -------------------------------------------------------------------------------- /includes/nt/directories/dir_delay_load.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../../img_common.hpp" 30 | #include "../data_directories.hpp" 31 | 32 | WIN_STRUCT_PACKING 33 | namespace win 34 | { 35 | union delay_load_attributes_t 36 | { 37 | uint32_t flags; 38 | struct 39 | { 40 | uint32_t rva_based : 1; 41 | uint32_t reserved : 31; 42 | }; 43 | }; 44 | 45 | struct delay_load_directory_t 46 | { 47 | delay_load_attributes_t attributes; 48 | uint32_t dll_name_rva; 49 | uint32_t module_handle_rva; 50 | uint32_t import_address_table_rva; 51 | uint32_t import_name_table_rva; 52 | uint32_t bound_import_address_table_rva; 53 | uint32_t unload_information_table_rva; 54 | uint32_t time_date_stamp; 55 | }; 56 | 57 | template struct directory_type { using type = delay_load_directory_t; }; 58 | }; 59 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/nt/directories/dir_exceptions.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "../../img_common.hpp" 34 | #include "../data_directories.hpp" 35 | 36 | WIN_STRUCT_PACKING 37 | namespace win 38 | { 39 | using xmm_t = std::array; 40 | 41 | // Unwind opcodes. 42 | // 43 | enum class unwind_opcode : uint16_t // : 4 44 | { 45 | push_nonvol = 0x0, // info == register number 46 | alloc_large = 0x1, // no info, alloc size in next 2 slots 47 | alloc_small = 0x2, // info == size of allocation / 8 - 1 48 | set_frame = 0x3, // no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 49 | save_nonvol = 0x4, // info == register number, offset in next slot 50 | save_nonvol_far = 0x5, // info == register number, offset in next 2 slots 51 | epilog = 0x6, // (?) 52 | spare_code = 0x7, // (?) 53 | save_xmm128 = 0x8, // info == XMM reg number, offset in next slot 54 | save_xmm128_far = 0x9, // info == XMM reg number, offset in next 2 slots 55 | push_machframe = 0xa, // info == 0: no error-code, 1: error-code 56 | maximum 57 | }; 58 | 59 | // Unwind register identifiers. 60 | // 61 | enum class unwind_register_id : uint8_t // : 4 62 | { 63 | amd64_rax = 0, // GP 64 | amd64_rcx = 1, 65 | amd64_rdx = 2, 66 | amd64_rbx = 3, 67 | amd64_rsp = 4, 68 | amd64_rbp = 5, 69 | amd64_rsi = 6, 70 | amd64_rdi = 7, 71 | amd64_r8 = 8, 72 | amd64_r9 = 9, 73 | amd64_r10 = 10, 74 | amd64_r11 = 11, 75 | amd64_r12 = 12, 76 | amd64_r13 = 13, 77 | amd64_r14 = 14, 78 | amd64_r15 = 15, 79 | amd64_eflags = 16, // Fake GP entries used by our helper. 80 | amd64_rip = 17, // 81 | amd64_seg_ss = 18, // 82 | amd64_seg_cs = 19, // 83 | 84 | amd64_xmm0 = 24 + 0, // XMM, has artifical offset added. 85 | amd64_xmm1 = 24 + 1, // 86 | amd64_xmm2 = 24 + 2, // 87 | amd64_xmm3 = 24 + 3, // 88 | amd64_xmm4 = 24 + 4, // 89 | amd64_xmm5 = 24 + 5, // 90 | amd64_xmm6 = 24 + 6, // 91 | amd64_xmm7 = 24 + 7, // 92 | amd64_xmm8 = 24 + 8, // 93 | amd64_xmm9 = 24 + 9, // 94 | amd64_xmm10 = 24 + 10, // 95 | amd64_xmm11 = 24 + 11, // 96 | amd64_xmm12 = 24 + 12, // 97 | amd64_xmm13 = 24 + 13, // 98 | amd64_xmm14 = 24 + 14, // 99 | amd64_xmm15 = 24 + 15, // 100 | 101 | nat_amd64_xmm0 = 0, // XMM, original range found in the native structure. 102 | nat_amd64_xmm1 = 1, // 103 | nat_amd64_xmm2 = 2, // 104 | nat_amd64_xmm3 = 3, // 105 | nat_amd64_xmm4 = 4, // 106 | nat_amd64_xmm5 = 5, // 107 | nat_amd64_xmm6 = 6, // 108 | nat_amd64_xmm7 = 7, // 109 | nat_amd64_xmm8 = 8, // 110 | nat_amd64_xmm9 = 9, // 111 | nat_amd64_xmm10 = 10, // 112 | nat_amd64_xmm11 = 11, // 113 | nat_amd64_xmm12 = 12, // 114 | nat_amd64_xmm13 = 13, // 115 | nat_amd64_xmm14 = 14, // 116 | nat_amd64_xmm15 = 15, // 117 | }; 118 | 119 | // Unwind code and info descriptors. 120 | // 121 | struct runtime_function_t; 122 | struct unwind_code_t 123 | { 124 | union 125 | { 126 | struct 127 | { 128 | uint16_t code_offset : 8; 129 | unwind_opcode unwind_op : 4; 130 | uint16_t op_info : 4; 131 | }; 132 | }; 133 | }; 134 | struct unwind_info_t 135 | { 136 | uint8_t version : 3; 137 | 138 | uint8_t ex_handler : 1; 139 | uint8_t term_handler : 1; 140 | uint8_t chained : 1; 141 | uint8_t reserved_flags : 2; 142 | 143 | uint8_t size_prologue; 144 | uint8_t num_uw_codes; 145 | 146 | unwind_register_id frame_register : 4; 147 | uint8_t frame_offset : 4; 148 | 149 | unwind_code_t unwind_code[ VAR_LEN ]; // # = align( num_uw_codes, 2 ) 150 | 151 | // Getter for the scaled frame offset. 152 | // 153 | int64_t get_frame_offset() const { return ( int64_t ) ( ( ( uint32_t ) frame_offset ) * 16 ); } 154 | 155 | // Followed by rva of language specific information: 156 | // 157 | void* get_language_specific_data() { return &unwind_code[ ( num_uw_codes + 1 ) & ~1 ]; } 158 | const void* get_language_specific_data() const { return const_cast< unwind_info_t* >( this )->get_language_specific_data(); } 159 | 160 | uint32_t& exception_handler_rva() { return *( uint32_t* ) get_language_specific_data(); } 161 | const uint32_t& exception_handler_rva() const { return const_cast< unwind_info_t* >( this )->exception_handler_rva(); } 162 | 163 | runtime_function_t& chained_function_entry() { return *( runtime_function_t* ) get_language_specific_data(); } 164 | const runtime_function_t& chained_function_entry() const { return const_cast< unwind_info_t* >( this )->chained_function_entry(); } 165 | 166 | // Followed by optional exception data. 167 | // 168 | void* exception_specific_data() { return &exception_handler_rva() + 1; } 169 | const void* exception_specific_data() const { return const_cast< unwind_info_t* >( this )->exception_specific_data(); } 170 | }; 171 | 172 | // High level descriptors of the opcodes. 173 | // 174 | struct amd64_unwind_code_t : unwind_code_t 175 | { 176 | // Returns the number of entries occupied by this opcode. 177 | // 178 | //size_t get_size() const = 0; 179 | 180 | // Applies or reverts this record's described side effect. 181 | // 182 | struct state_t 183 | { 184 | using reg_resolver_t = void* ( * )( void* ctx, unwind_register_id reg ); 185 | using rmemcpy_t = bool( * )( void* ctx, void* dst, uint64_t src, size_t n ); 186 | using wmemcpy_t = bool( * )( void* ctx, uint64_t dst, const void* src, size_t n ); 187 | 188 | // Provided by the user. 189 | // 190 | uint8_t frame_offset = 0; // Information from the function entry. 191 | win::unwind_register_id frame_register = {}; // 192 | void* context = nullptr; // User-defined context. 193 | reg_resolver_t resolve_reg = nullptr; // Should get a pointer to the value of the register specified in the second argument. 194 | rmemcpy_t rmemcpy = nullptr; // Safe memory operations, if not set will use current process. 195 | wmemcpy_t wmemcpy = nullptr; // 196 | 197 | // Implement wrappers for some common operations. 198 | // 199 | uint64_t& gp( unwind_register_id gp_reg ) const { return *( uint64_t* ) resolve_reg( context, gp_reg ); } 200 | xmm_t& xmm( unwind_register_id xmm_reg ) const { return *( xmm_t* ) resolve_reg( context, xmm_reg ); } 201 | uint16_t& ss() const { return *( uint16_t* ) resolve_reg( context, unwind_register_id::amd64_seg_ss ); } 202 | uint16_t& cs() const { return *( uint16_t* ) resolve_reg( context, unwind_register_id::amd64_seg_cs ); } 203 | uint32_t& flags() const { return *( uint32_t* ) resolve_reg( context, unwind_register_id::amd64_eflags ); } 204 | 205 | uint64_t& sp() const { return gp( unwind_register_id::amd64_rsp ); } 206 | uint64_t& ip() const { return gp( unwind_register_id::amd64_rip ); } 207 | uint64_t& frame() const { return gp( frame_register ); } 208 | 209 | template 210 | bool read( T& out, uint64_t address ) const 211 | { 212 | if ( rmemcpy ) return rmemcpy( context, &out, address, sizeof( T ) ); 213 | if ( !address ) return false; 214 | memcpy( &out, ( const void* ) address, sizeof( T ) ); 215 | return true; 216 | } 217 | template 218 | bool write( uint64_t address, const T& data ) const 219 | { 220 | if ( wmemcpy ) return wmemcpy( context, address, &data, sizeof( T ) ); 221 | if ( !address ) return false; 222 | memcpy( ( void* ) address, &data, sizeof( T ) ); 223 | return true; 224 | } 225 | }; 226 | //bool rewind( const state_t& state ) const = 0; 227 | //bool unwind( const state_t& state ) const = 0; 228 | }; 229 | using amd64_unwind_state_t = amd64_unwind_code_t::state_t; 230 | struct amd64_unwind_set_frame_t : amd64_unwind_code_t 231 | { 232 | // Implement the interface. 233 | // 234 | size_t get_size() const { return 1; } 235 | bool rewind( const state_t& state ) const 236 | { 237 | state.frame() = state.sp() + ( size_t( state.frame_offset ) * 16 ); 238 | return true; 239 | } 240 | bool unwind( const state_t& state ) const 241 | { 242 | state.sp() = state.frame() - ( size_t( state.frame_offset ) * 16 ); 243 | return true; 244 | } 245 | }; 246 | struct amd64_unwind_alloc_t : amd64_unwind_code_t 247 | { 248 | // Implement helpers. 249 | // 250 | size_t get_allocation_size() const 251 | { 252 | if ( unwind_op == unwind_opcode::alloc_small ) 253 | return uint64_t( op_info ) * 8 + 8; 254 | if ( op_info ) return *( uint32_t* ) ( this + 1 ); 255 | else return 8 * ( uint64_t ) * ( uint16_t* ) ( this + 1 ); 256 | } 257 | 258 | // Implement the interface. 259 | // 260 | size_t get_size() const 261 | { 262 | if ( unwind_op == unwind_opcode::alloc_small ) 263 | return 1; 264 | return op_info ? 3 : 2; 265 | } 266 | bool rewind( const state_t& state ) const 267 | { 268 | state.sp() -= get_allocation_size(); 269 | return true; 270 | } 271 | bool unwind( const state_t& state ) const 272 | { 273 | state.sp() += get_allocation_size(); 274 | return true; 275 | } 276 | }; 277 | struct amd64_unwind_push_t : amd64_unwind_code_t 278 | { 279 | // Implement helpers. 280 | // 281 | unwind_register_id get_register() const { return ( unwind_register_id ) op_info; } 282 | 283 | // Implement the interface. 284 | // 285 | size_t get_size() const { return 1; } 286 | bool rewind( const state_t& state ) const 287 | { 288 | if ( !state.write( state.sp() - 8, state.gp( get_register() ) ) ) 289 | return false; 290 | state.sp() -= 8; 291 | return true; 292 | } 293 | bool unwind( const state_t& state ) const 294 | { 295 | if ( !state.read( state.gp( get_register() ), state.sp() ) ) 296 | return false; 297 | state.sp() += 8; 298 | return true; 299 | } 300 | }; 301 | struct amd64_unwind_save_gp_t : amd64_unwind_code_t 302 | { 303 | // Implement helpers. 304 | // 305 | int64_t get_sp_offset() const 306 | { 307 | if ( unwind_op == unwind_opcode::save_nonvol_far ) 308 | return ( int64_t ) ( *( uint32_t* ) ( this + 1 ) ); 309 | else 310 | return ( int64_t ) ( 8 * ( uint64_t ) * ( uint16_t* ) ( this + 1 ) ); 311 | } 312 | unwind_register_id get_register() const { return ( unwind_register_id ) op_info; } 313 | 314 | // Implement the interface. 315 | // 316 | size_t get_size() const { return unwind_op == unwind_opcode::save_nonvol_far ? 3 : 2; } 317 | bool rewind( const state_t& state ) const 318 | { 319 | return state.write( state.sp() + get_sp_offset(), state.gp( get_register() ) ); 320 | } 321 | bool unwind( const state_t& state ) const 322 | { 323 | return state.read( state.gp( get_register() ), state.sp() + get_sp_offset() ); 324 | } 325 | }; 326 | struct amd64_unwind_save_xmm_t : amd64_unwind_code_t 327 | { 328 | // Implement helpers. 329 | // 330 | int64_t get_sp_offset() const 331 | { 332 | if ( unwind_op == unwind_opcode::save_xmm128_far ) 333 | return ( int64_t ) ( *( uint32_t* ) ( this + 1 ) ); 334 | else 335 | return ( int64_t ) ( 16 * ( uint64_t ) * ( uint16_t* ) ( this + 1 ) ); 336 | } 337 | unwind_register_id get_register() const { return ( unwind_register_id ) ( size_t( unwind_register_id::amd64_xmm0 ) + op_info ); } 338 | 339 | // Implement the interface. 340 | // 341 | size_t get_size() const { return unwind_op == unwind_opcode::save_xmm128_far ? 3 : 2; } 342 | bool rewind( const state_t& state ) const 343 | { 344 | return state.write( state.sp() + get_sp_offset(), state.xmm( get_register() ) ); 345 | } 346 | bool unwind( const state_t& state ) const 347 | { 348 | return state.read( state.xmm( get_register() ), state.sp() + get_sp_offset() ); 349 | } 350 | }; 351 | struct amd64_unwind_iframe_t : amd64_unwind_code_t 352 | { 353 | // Implement helpers. 354 | // 355 | bool has_exception_code() const { return op_info; } 356 | 357 | // Implement the interface. 358 | // 359 | size_t get_size() const { return 1; } 360 | bool rewind( [[maybe_unused]] const state_t& state ) const 361 | { 362 | return false; 363 | } 364 | bool unwind( const state_t& state ) const 365 | { 366 | size_t offset = 0; 367 | if ( has_exception_code() ) offset += 8; 368 | 369 | bool success = 370 | state.read( state.ip(), state.sp() + offset + 8 * 0 ) && 371 | state.read( state.cs(), state.sp() + offset + 8 * 1 ) && 372 | state.read( state.flags(), state.sp() + offset + 8 * 2 ) && 373 | state.read( state.sp(), state.sp() + offset + 8 * 3 ) && 374 | state.read( state.ss(), state.sp() + offset + 8 * 4 ); 375 | if ( !success ) return false; 376 | state.sp() += offset + 8 * 4; 377 | return true; 378 | } 379 | }; 380 | struct amd64_unwind_nop_t : amd64_unwind_code_t 381 | { 382 | size_t get_size() const { return 1; } 383 | bool rewind( [[maybe_unused]] const state_t& state ) const { return true; } 384 | bool unwind( [[maybe_unused]] const state_t& state ) const { return true; } 385 | }; 386 | 387 | // Special unwind helper for unwinding after the function returns. 388 | // 389 | static bool amd64_unwind_call( const amd64_unwind_state_t& state ) 390 | { 391 | // Read the return pointer. 392 | // 393 | if ( !state.read( state.ip(), state.sp() ) ) 394 | return false; 395 | state.sp() += 8; 396 | 397 | // Basic attempt at decoding the instruction to unwind rip. 398 | // 399 | uint8_t call_region[ 16 ] = { 0 }; 400 | for ( size_t n = 0; n != 16; n++ ) 401 | state.read( call_region[ n ], state.ip() - n ); 402 | 403 | // call reg rel 404 | if ( call_region[ 6 ] == 0xFF && ( call_region[ 7 ] & 0xF0 ) == 0x40 ) 405 | state.ip() -= 7; 406 | else if ( call_region[ 6 ] == 0xFF ) 407 | state.ip() -= 6; 408 | // call imm 409 | else if ( call_region[ 5 ] == 0xE8 ) 410 | state.ip() -= 5; 411 | // call reg 412 | else if ( call_region[ 2 ] == 0xFF && ( call_region[ 3 ] & 0xF0 ) == 0x40 ) 413 | state.ip() -= 3; 414 | else if ( call_region[ 2 ] == 0xFF ) 415 | state.ip() -= 2; 416 | // int 417 | else if ( call_region[ 2 ] == 0xCD ) 418 | state.ip() -= 2; 419 | else if ( call_region[ 1 ] == 0xCC ) 420 | state.ip() -= 1; 421 | else if ( call_region[ 1 ] == 0xF1 ) 422 | state.ip() -= 1; 423 | return true; 424 | } 425 | 426 | template struct amd64_unwind; 427 | template<> struct amd64_unwind { using type = amd64_unwind_push_t; }; 428 | template<> struct amd64_unwind { using type = amd64_unwind_alloc_t; }; 429 | template<> struct amd64_unwind { using type = amd64_unwind_alloc_t; }; 430 | template<> struct amd64_unwind { using type = amd64_unwind_set_frame_t; }; 431 | template<> struct amd64_unwind { using type = amd64_unwind_save_gp_t; }; 432 | template<> struct amd64_unwind { using type = amd64_unwind_save_gp_t; }; 433 | template<> struct amd64_unwind { using type = amd64_unwind_save_xmm_t; }; 434 | template<> struct amd64_unwind { using type = amd64_unwind_save_xmm_t; }; 435 | template<> struct amd64_unwind { using type = amd64_unwind_iframe_t; }; 436 | template<> struct amd64_unwind { using type = amd64_unwind_nop_t; }; 437 | template<> struct amd64_unwind { using type = amd64_unwind_nop_t; }; 438 | template 439 | using amd64_unwind_t = typename amd64_unwind::type; 440 | 441 | template 442 | static bool visit_amd64_unwind( const unwind_code_t& code, T&& visitor ) 443 | { 444 | switch ( ( unwind_opcode ) code.unwind_op ) 445 | { 446 | case unwind_opcode::push_nonvol: visitor( ( const amd64_unwind_t * ) & code ); return true; 447 | case unwind_opcode::alloc_large: visitor( ( const amd64_unwind_t * ) & code ); return true; 448 | case unwind_opcode::alloc_small: visitor( ( const amd64_unwind_t * ) & code ); return true; 449 | case unwind_opcode::set_frame: visitor( ( const amd64_unwind_t * ) & code ); return true; 450 | case unwind_opcode::save_nonvol: visitor( ( const amd64_unwind_t * ) & code ); return true; 451 | case unwind_opcode::save_nonvol_far: visitor( ( const amd64_unwind_t * ) & code ); return true; 452 | case unwind_opcode::epilog: visitor( ( const amd64_unwind_t * ) & code ); return true; 453 | case unwind_opcode::spare_code: visitor( ( const amd64_unwind_t * ) & code ); return true; 454 | case unwind_opcode::save_xmm128: visitor( ( const amd64_unwind_t * ) & code ); return true; 455 | case unwind_opcode::save_xmm128_far: visitor( ( const amd64_unwind_t * ) & code ); return true; 456 | case unwind_opcode::push_machframe: visitor( ( const amd64_unwind_t * ) & code ); return true; 457 | default: return false; 458 | } 459 | } 460 | 461 | // Very commonly used language-specific data, C scope table. 462 | // 463 | struct c_scope_table_entry_t 464 | { 465 | uint32_t rva_begin; 466 | uint32_t rva_end; 467 | uint32_t rva_handler; 468 | uint32_t rva_target; 469 | }; 470 | struct c_scope_table_t 471 | { 472 | uint32_t num_entries; 473 | c_scope_table_entry_t entries[ VAR_LEN ]; 474 | }; 475 | 476 | // Function table and the directory itself. 477 | // 478 | struct runtime_function_t 479 | { 480 | uint32_t rva_begin; 481 | uint32_t rva_end; 482 | union 483 | { 484 | uint32_t unwind_info; 485 | uint32_t rva_unwind_info; 486 | }; 487 | }; 488 | struct exception_directory_t 489 | { 490 | // Length of this array is determined by the size of the directory 491 | // 492 | runtime_function_t functions[ VAR_LEN ]; 493 | }; 494 | template struct directory_type { using type = exception_directory_t; }; 495 | 496 | // Wrapper around exception directory. 497 | // 498 | struct exception_directory 499 | { 500 | // std::map like traits. 501 | // 502 | struct key_compare 503 | { 504 | constexpr bool operator()( const runtime_function_t& a, const runtime_function_t& b ) const noexcept 505 | { 506 | return a.rva_begin < b.rva_begin; 507 | } 508 | }; 509 | struct key_compare_end 510 | { 511 | constexpr bool operator()( const runtime_function_t& a, const runtime_function_t& b ) const noexcept 512 | { 513 | return a.rva_end < b.rva_end; 514 | } 515 | }; 516 | using key_type = uint32_t; 517 | using mapped_type = runtime_function_t; 518 | using value_type = runtime_function_t; 519 | using size_type = size_t; 520 | using difference_type = ptrdiff_t; 521 | using iterator = const runtime_function_t*; 522 | using const_iterator = const runtime_function_t*; 523 | using pointer = const runtime_function_t*; 524 | using const_pointer = const runtime_function_t*; 525 | using reference = const runtime_function_t&; 526 | using const_reference = const runtime_function_t&; 527 | using reverse_iterator = std::reverse_iterator; 528 | using const_reverse_iterator = std::reverse_iterator; 529 | 530 | // The range it's viewing. 531 | // 532 | const runtime_function_t* table; 533 | size_t length; 534 | 535 | // Constructed with a pointer to the data and the raw length in bytes. 536 | // 537 | constexpr exception_directory() : table( nullptr ), length( 0 ) {} 538 | constexpr exception_directory( const void* data, size_t length ) 539 | : table( ( runtime_function_t* ) data ), length( length / sizeof( runtime_function_t ) ) {} 540 | 541 | // Default copy/move. 542 | // 543 | constexpr exception_directory( exception_directory&& ) noexcept = default; 544 | constexpr exception_directory( const exception_directory& ) = default; 545 | constexpr exception_directory& operator=( exception_directory& ) noexcept = default; 546 | constexpr exception_directory& operator=( const exception_directory& ) = default; 547 | 548 | // Make it iterable. 549 | // 550 | constexpr iterator begin() const { return table; } 551 | constexpr iterator end() const { return table + length; } 552 | constexpr reverse_iterator rbegin() const { return reverse_iterator( end() ); } 553 | constexpr reverse_iterator rend() const { return reverse_iterator( begin() ); } 554 | 555 | // Basic properties. 556 | // 557 | constexpr size_t size() const { return length; } 558 | constexpr bool empty() const { return length == 0; } 559 | 560 | // Finds a function using binary search. 561 | // 562 | constexpr iterator find_overlapping( uint32_t rva ) const 563 | { 564 | iterator it = std::upper_bound( begin(), end(), runtime_function_t{ .rva_end = rva }, key_compare_end{} ); 565 | if ( it != end() && !( it->rva_begin <= rva && rva < it->rva_end ) ) 566 | it = end(); 567 | return it; 568 | } 569 | constexpr iterator find( uint32_t rva ) const 570 | { 571 | iterator it = std::upper_bound( begin(), end(), runtime_function_t{ .rva_end = rva }, key_compare_end{} ); 572 | if ( it != end() && it->rva_begin != rva ) 573 | it = end(); 574 | return it; 575 | } 576 | constexpr bool contains( uint32_t rva ) const 577 | { 578 | return find( rva ) != end(); 579 | } 580 | }; 581 | }; 582 | #pragma pack(pop) 583 | -------------------------------------------------------------------------------- /includes/nt/directories/dir_export.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../../img_common.hpp" 30 | #include "../data_directories.hpp" 31 | 32 | WIN_STRUCT_PACKING 33 | namespace win 34 | { 35 | struct export_directory_t 36 | { 37 | uint32_t characteristics; 38 | uint32_t timedate_stamp; 39 | ex_version_t version; 40 | uint32_t name; 41 | uint32_t base; 42 | uint32_t num_functions; 43 | uint32_t num_names; 44 | uint32_t rva_functions; 45 | uint32_t rva_names; 46 | uint32_t rva_name_ordinals; 47 | }; 48 | 49 | template struct directory_type { using type = export_directory_t; }; 50 | }; 51 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/nt/directories/dir_iat.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../../img_common.hpp" 30 | #include "../data_directories.hpp" 31 | 32 | WIN_STRUCT_PACKING 33 | namespace win 34 | { 35 | struct image_named_import_t 36 | { 37 | uint16_t hint; 38 | char name[ 1 ]; 39 | }; 40 | 41 | struct image_thunk_data_x64_t 42 | { 43 | union 44 | { 45 | uint64_t forwarder_string; 46 | uint64_t function; 47 | uint64_t address; // -> image_named_import_t 48 | struct 49 | { 50 | uint64_t ordinal : 16; 51 | uint64_t _reserved0 : 47; 52 | uint64_t is_ordinal : 1; 53 | }; 54 | }; 55 | }; 56 | 57 | struct image_thunk_data_x86_t 58 | { 59 | union 60 | { 61 | uint32_t forwarder_string; 62 | uint32_t function; 63 | uint32_t address; // -> image_named_import_t 64 | struct 65 | { 66 | uint32_t ordinal : 16; 67 | uint32_t _reserved0 : 15; 68 | uint32_t is_ordinal : 1; 69 | }; 70 | }; 71 | }; 72 | 73 | struct bound_forwarder_ref_t 74 | { 75 | uint32_t timedate_stamp; 76 | uint16_t offset_module_name; 77 | }; 78 | 79 | struct bound_import_descriptor_t 80 | { 81 | uint32_t timedate_stamp; 82 | uint16_t offset_module_name; 83 | uint16_t num_module_forwarder_refs; 84 | }; 85 | 86 | template 87 | using image_thunk_data_t = std::conditional_t; 88 | 89 | template struct directory_type { using type = image_thunk_data_t; }; 90 | }; 91 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/nt/directories/dir_import.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../../img_common.hpp" 30 | #include "../data_directories.hpp" 31 | 32 | WIN_STRUCT_PACKING 33 | namespace win 34 | { 35 | struct import_directory_t 36 | { 37 | union 38 | { 39 | uint32_t characteristics; // 0 for terminating null import descriptor 40 | uint32_t rva_original_first_thunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) 41 | }; 42 | uint32_t timedate_stamp; // 0 if not bound, 43 | // -1 if bound, and real date ime stamp 44 | // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) 45 | // O.W. date/time stamp of DLL bound to (Old BIND) 46 | 47 | uint32_t forwarder_chain; // -1 if no forwarders 48 | uint32_t rva_name; 49 | uint32_t rva_first_thunk; // RVA to IAT (if bound this IAT has actual addresses) 50 | }; 51 | 52 | template struct directory_type { using type = import_directory_t; }; 53 | }; 54 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/nt/directories/dir_load_config.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../../img_common.hpp" 30 | #include "../data_directories.hpp" 31 | #include "dir_relocs.hpp" 32 | 33 | WIN_STRUCT_PACKING 34 | namespace win 35 | { 36 | // Enclave configuration 37 | // 38 | struct enclave_config_x64_t 39 | { 40 | uint32_t size; 41 | uint32_t minimum_required_config_size; 42 | uint32_t policy_flags; 43 | uint32_t number_of_imports; 44 | uint32_t import_list; 45 | uint32_t import_entry_size; 46 | uint8_t family_id[ 16 ]; 47 | uint8_t image_id[ 16 ]; 48 | uint32_t image_version; 49 | uint32_t security_version; 50 | uint64_t enclave_size; 51 | uint32_t number_of_threads; 52 | uint32_t enclave_flags; 53 | }; 54 | struct enclave_config_x86_t 55 | { 56 | uint32_t size; 57 | uint32_t minimum_required_config_size; 58 | uint32_t policy_flags; 59 | uint32_t number_of_imports; 60 | uint32_t import_list; 61 | uint32_t import_entry_size; 62 | uint8_t family_id[ 16 ]; 63 | uint8_t image_id[ 16 ]; 64 | uint32_t image_version; 65 | uint32_t security_version; 66 | uint32_t enclave_size; 67 | uint32_t number_of_threads; 68 | uint32_t enclave_flags; 69 | }; 70 | template 71 | using enclave_config_t = std::conditional_t; 72 | 73 | // Dynamic relocations 74 | // 75 | enum class dynamic_reloc_entry_id 76 | { 77 | guard_rf_prologue = 1, 78 | guard_rf_epilogue = 2, 79 | guard_import_control_transfer = 3, 80 | guard_indir_control_transfer = 4, 81 | guard_switch_table_branch = 5, 82 | }; 83 | 84 | struct dynamic_reloc_guard_rf_prologue_t 85 | { 86 | uint8_t prologue_size; 87 | uint8_t prologue_bytes[ VAR_LEN ]; 88 | }; 89 | 90 | struct dynamic_reloc_guard_rf_epilogue_t 91 | { 92 | uint32_t epilogue_count; 93 | uint8_t epilogue_size; 94 | uint8_t branch_descriptor_element_size; 95 | uint16_t branch_descriptor_count; 96 | uint8_t branch_descriptors[ VAR_LEN ]; 97 | 98 | inline uint8_t* get_branch_descriptor_bit_map() { return branch_descriptors + branch_descriptor_count * branch_descriptor_element_size; } 99 | inline const uint8_t* get_branch_descriptor_bit_map() const { return const_cast< dynamic_reloc_guard_rf_epilogue_t* >( this )->get_branch_descriptor_bit_map(); } 100 | }; 101 | 102 | struct dynamic_reloc_import_control_transfer_t 103 | { 104 | uint32_t page_relative_offset : 12; 105 | uint32_t indirect_call : 1; 106 | uint32_t iat_index : 19; 107 | }; 108 | 109 | struct dynamic_reloc_indir_control_transfer_t 110 | { 111 | uint16_t page_relative_offset : 12; 112 | uint16_t indirect_call : 1; 113 | uint16_t rex_w_prefix : 1; 114 | uint16_t cfg_check : 1; 115 | uint16_t _pad0 : 1; 116 | }; 117 | 118 | struct dynamic_reloc_guard_switch_table_branch_t 119 | { 120 | uint16_t page_relative_offset : 12; 121 | uint16_t register_number : 4; 122 | }; 123 | 124 | template 125 | struct dynamic_reloc_v1_t 126 | { 127 | using va_t = std::conditional_t; 128 | 129 | va_t symbol; 130 | uint32_t size; 131 | reloc_block_t first_block; 132 | 133 | inline reloc_block_t* begin() { return &first_block; } 134 | inline const reloc_block_t* begin() const { return &first_block; } 135 | inline reloc_block_t* end() { return ( reloc_block_t* ) next(); } 136 | inline const reloc_block_t* end() const { return ( const reloc_block_t* ) next(); } 137 | 138 | inline dynamic_reloc_v1_t* next() { return ( dynamic_reloc_v1_t* ) ( ( char* ) &first_block + this->size ); } 139 | inline const dynamic_reloc_v1_t* next() const { return const_cast< dynamic_reloc_v1_t* >( this )->next(); } 140 | }; 141 | using dynamic_reloc_v1_x86_t = dynamic_reloc_v1_t; 142 | using dynamic_reloc_v1_x64_t = dynamic_reloc_v1_t; 143 | 144 | template 145 | struct dynamic_reloc_v2_t 146 | { 147 | using va_t = std::conditional_t; 148 | 149 | uint32_t header_size; 150 | uint32_t fixup_info_size; 151 | va_t symbol; 152 | uint32_t symbol_group; 153 | uint32_t flags; 154 | uint8_t fixup_info[ VAR_LEN ]; 155 | 156 | const void* end() const { return fixup_info + fixup_info_size; } 157 | }; 158 | using dynamic_reloc_v2_x86_t = dynamic_reloc_v2_t; 159 | using dynamic_reloc_v2_x64_t = dynamic_reloc_v2_t; 160 | 161 | // Dynamic relocation table 162 | // 163 | template 164 | struct dynamic_reloc_table_t 165 | { 166 | uint32_t version; 167 | uint32_t size; 168 | union 169 | { 170 | dynamic_reloc_v1_t v1_begin; // Variable length array. 171 | dynamic_reloc_v2_t v2_begin; // Variable length array. 172 | }; 173 | 174 | const void* end() const { return ( char* ) &v1_begin + size; } 175 | }; 176 | using dynamic_reloc_table_x86_t = dynamic_reloc_table_t; 177 | using dynamic_reloc_table_x64_t = dynamic_reloc_table_t; 178 | 179 | // Hot patch information 180 | // 181 | struct hotpatch_base_t 182 | { 183 | uint32_t sequence_number; 184 | uint32_t flags; 185 | uint32_t orginal_timedate_stamp; 186 | uint32_t orginal_checksum; 187 | uint32_t code_integrity_info; 188 | uint32_t code_integrity_size; 189 | uint32_t path_table; 190 | uint32_t buffer_offset; 191 | }; 192 | 193 | struct hotpatch_info_t 194 | { 195 | uint32_t version; 196 | uint32_t size; 197 | uint32_t sequence_number; 198 | uint32_t base_image_list; 199 | uint32_t base_image_count; 200 | uint32_t buffer_offset; 201 | uint32_t extra_patch_size; 202 | }; 203 | 204 | struct hotpatch_hashes_t 205 | { 206 | uint8_t sha256[ 32 ]; 207 | uint8_t sha1[ 20 ]; 208 | }; 209 | 210 | // Code integrity information 211 | // 212 | struct load_config_ci_t 213 | { 214 | uint16_t flags; // Flags to indicate if CI information is available, etc. 215 | uint16_t catalog; // 0xFFFF means not available 216 | uint32_t rva_catalog; 217 | uint32_t _pad0; // Additional bitmask to be defined later 218 | }; 219 | 220 | template 221 | struct load_config_directory_t 222 | { 223 | // Architecture dependent typedefs 224 | // 225 | using va_t = std::conditional_t; 226 | using vsize_t = va_t; 227 | 228 | struct table_t 229 | { 230 | va_t virtual_address; 231 | vsize_t count; 232 | }; 233 | 234 | // Directory description 235 | // 236 | uint32_t size; 237 | uint32_t timedate_stamp; 238 | ex_version_t version; 239 | uint32_t global_flags_clear; 240 | uint32_t global_flags_set; 241 | uint32_t critical_section_default_timeout; 242 | vsize_t decommit_free_block_threshold; 243 | vsize_t decommit_total_free_threshold; 244 | va_t lock_prefix_table; 245 | vsize_t maximum_allocation_size; 246 | vsize_t virtual_memory_threshold; 247 | vsize_t process_affinity_mask; 248 | uint32_t process_heap_flags; 249 | uint16_t csd_version; 250 | uint16_t dependent_load_flags; 251 | va_t edit_list; 252 | va_t security_cookie; 253 | table_t se_handler_table; 254 | va_t guard_cf_check_function_ptr; 255 | va_t guard_cf_dispatch_function_ptr; 256 | table_t guard_cf_function_table; 257 | uint32_t guard_flags; 258 | load_config_ci_t code_integrity; 259 | table_t guard_address_taken_iat_entry_table; 260 | table_t guard_long_jump_target_table; 261 | va_t dynamic_value_reloc_table; 262 | va_t chpe_metadata_ptr; // hybrid_metadata_ptr @ v1607 263 | va_t guard_rf_failure_routine; 264 | va_t guard_rf_failure_routine_function_ptr; 265 | uint32_t dynamic_value_reloc_table_offset; 266 | uint16_t dynamic_value_reloc_table_section; 267 | va_t guard_rf_verify_stack_ptr_function_ptr; 268 | uint32_t hotpatch_table_offset; 269 | uint32_t reserved; 270 | va_t enclave_configuration_ptr; 271 | va_t volatile_metadata_ptr; 272 | table_t guard_eh_continuation_table; 273 | }; 274 | using load_config_directory_x86_t = load_config_directory_t; 275 | using load_config_directory_x64_t = load_config_directory_t; 276 | template struct directory_type { using type = load_config_directory_t; }; 277 | }; 278 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/nt/directories/dir_relocs.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../../img_common.hpp" 30 | #include "../data_directories.hpp" 31 | 32 | WIN_STRUCT_PACKING 33 | namespace win 34 | { 35 | enum reloc_type_id : uint16_t 36 | { 37 | rel_based_absolute = 0, 38 | rel_based_high = 1, 39 | rel_based_low = 2, 40 | rel_based_high_low = 3, 41 | rel_based_high_adj = 4, 42 | rel_based_ia64_imm64 = 9, 43 | rel_based_dir64 = 10, 44 | }; 45 | 46 | struct reloc_entry_t 47 | { 48 | uint16_t offset : 12; 49 | reloc_type_id type : 4; 50 | }; 51 | static_assert( sizeof( reloc_entry_t ) == 2, "Enum bitfield is not supported." ); 52 | 53 | struct reloc_block_t 54 | { 55 | uint32_t base_rva; 56 | uint32_t size_block; 57 | reloc_entry_t entries[ VAR_LEN ]; 58 | 59 | inline reloc_block_t* next() { return ( reloc_block_t* ) ( ( char* ) this + this->size_block ); } 60 | inline const reloc_block_t* next() const { return const_cast< reloc_block_t* >( this )->next(); } 61 | inline size_t num_entries() const { return ( reloc_entry_t* ) next() - &entries[ 0 ]; } 62 | 63 | inline reloc_entry_t* begin() { return &entries[ 0 ]; } 64 | inline const reloc_entry_t* begin() const { return &entries[ 0 ]; } 65 | inline reloc_entry_t* end() { return ( reloc_entry_t* ) next(); } 66 | inline const reloc_entry_t* end() const { return ( const reloc_entry_t* ) next(); } 67 | }; 68 | 69 | struct reloc_directory_t 70 | { 71 | reloc_block_t first_block; 72 | }; 73 | 74 | template struct directory_type { using type = reloc_directory_t; }; 75 | }; 76 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/nt/directories/dir_resource.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "../../img_common.hpp" 34 | #include "../data_directories.hpp" 35 | 36 | WIN_STRUCT_PACKING 37 | namespace win 38 | { 39 | // Resource type identifiers 40 | // 41 | enum class resource_id : uint16_t 42 | { 43 | cursor = 1, 44 | bitmap = 2, 45 | icon = 3, 46 | menu = 4, 47 | dialog = 5, 48 | string = 6, 49 | font_dir = 7, 50 | font = 8, 51 | accelerator = 9, 52 | rcdata = 10, 53 | message_table = 11, 54 | group_cursor = 12, 55 | group_icon = 14, 56 | version = 16, 57 | dlg_include = 17, 58 | plug_play = 19, 59 | vxd = 20, 60 | ani_cursor = 21, 61 | ani_icon = 22, 62 | html = 23, 63 | manifest = 24, 64 | }; 65 | 66 | // String entry 67 | // 68 | struct rsrc_string_t 69 | { 70 | uint16_t length; 71 | wchar_t name[ VAR_LEN ]; 72 | inline std::wstring_view view() const { return { name, length }; } 73 | }; 74 | 75 | // Data entry 76 | // 77 | struct rsrc_data_t 78 | { 79 | uint32_t rva_data; 80 | uint32_t size_data; 81 | uint32_t code_page; 82 | uint32_t reserved; 83 | }; 84 | 85 | // Generic entry 86 | // 87 | struct rsrc_generic_t 88 | { 89 | union 90 | { 91 | struct 92 | { 93 | uint32_t offset_name : 31; 94 | uint32_t is_named : 1; 95 | }; 96 | uint16_t identifier; 97 | }; 98 | uint32_t offset : 31; 99 | uint32_t is_directory : 1; 100 | }; 101 | 102 | // Directory entry 103 | // 104 | struct rsrc_directory_t 105 | { 106 | uint32_t characteristics; 107 | uint32_t timedate_stamp; 108 | ex_version_t version; 109 | uint16_t num_named_entries; 110 | uint16_t num_id_entries; 111 | rsrc_generic_t entries[ VAR_LEN ]; 112 | 113 | inline size_t num_entries() const { return ( size_t ) num_named_entries + num_id_entries; } 114 | 115 | // (Tree root) Helper to resolve entry referenced by rsrc_generic_t::offset 116 | // 117 | template inline T* at( uint32_t offset ) { return ( T* ) ( ( char* ) this + offset ); } 118 | template inline const T* at( uint32_t offset ) const { return ( T* ) ( ( char* ) this + offset ); } 119 | 120 | // (Tree root) Explicit optional field accessors 121 | // 122 | inline rsrc_data_t* as_data( const rsrc_generic_t& entry ) { return !entry.is_directory ? at( entry.offset ) : nullptr; } 123 | inline rsrc_string_t* get_name( const rsrc_generic_t& entry ) { return entry.is_named ? at( entry.offset_name ) : nullptr; } 124 | inline rsrc_directory_t* as_directory( const rsrc_generic_t& entry ) { return entry.is_directory ? at( entry.offset ) : nullptr; } 125 | inline const rsrc_data_t* as_data( const rsrc_generic_t& entry ) const { return !entry.is_directory ? at( entry.offset ) : nullptr; } 126 | inline const rsrc_string_t* get_name( const rsrc_generic_t& entry ) const { return entry.is_named ? at( entry.offset_name ) : nullptr; } 127 | inline const rsrc_directory_t* as_directory( const rsrc_generic_t& entry ) const { return entry.is_directory ? at( entry.offset ) : nullptr; } 128 | }; 129 | 130 | // Iterator type propagating reference to tree root 131 | // 132 | enum rsrc_directory_depth : int32_t 133 | { 134 | rsrc_null = -1, 135 | rsrc_type_directory = 0, 136 | rsrc_name_directory = 1, 137 | rsrc_lang_directory = 2, 138 | rsrc_node = 3 139 | }; 140 | template 141 | struct base_rsrc_iterator_t 142 | { 143 | template using M = std::conditional_t, T>; 144 | 145 | // Declare tree traits 146 | // 147 | using entry_t = M; 148 | using data_t = M; 149 | using directory_t = M; 150 | 151 | // Declare container traits 152 | // 153 | using iterator = base_rsrc_iterator_t; 154 | using const_iterator = base_rsrc_iterator_t; 155 | 156 | // Declare iterator traits 157 | // 158 | using iterator_category = std::bidirectional_iterator_tag; 159 | using difference_type = int32_t; 160 | using reference = base_rsrc_iterator_t; 161 | using pointer = void*; 162 | 163 | // Tree root, current level and the current entry 164 | // 165 | directory_t* root = nullptr; 166 | directory_t* level = nullptr; 167 | size_t idx = 0; 168 | int32_t depth = rsrc_type_directory; 169 | 170 | // Implement bidirectional iteration and basic comparison 171 | // 172 | inline iterator& operator++() { idx++; return *this; } 173 | inline iterator& operator--() { idx--; return *this; } 174 | inline iterator operator++( int ) { auto s = *this; operator++(); return s; } 175 | inline iterator operator--( int ) { auto s = *this; operator--(); return s; } 176 | inline bool operator==( const iterator& other ) const { return root == other.root && level == other.level && idx == other.idx; } 177 | inline bool operator!=( const iterator& other ) const { return root != other.root || level != other.level || idx != other.idx; } 178 | 179 | // Implement tree interface 180 | // 181 | inline bool is_null() const { return !level; } 182 | inline entry_t& entry() { return level->entries[ idx ]; } 183 | inline const entry_t& entry() const { return level->entries[ idx ]; } 184 | inline bool has_name() const { return entry().is_named; } 185 | inline std::wstring_view name() const { return has_name() ? root->get_name( entry() )->view() : L""; } 186 | inline bool has_id() const { return !entry().is_named; } 187 | inline uint16_t id() const { return has_id() ? entry().identifier : 0; } 188 | inline resource_id rid() const { return ( resource_id ) id(); } 189 | inline bool is_data() const { return !entry().is_directory; } 190 | inline data_t* data() { return root->as_data( entry() ); } 191 | inline const data_t* data() const { return root->as_data( entry() ); } 192 | inline bool is_directory() const { return entry().is_directory; } 193 | inline directory_t* directory() { return root->as_directory( entry() ); } 194 | inline const directory_t* directory() const { return root->as_directory( entry() ); } 195 | inline explicit operator bool() const { return !is_null(); } 196 | 197 | // Implement iterator interface 198 | // 199 | inline iterator& operator*() { return *this; } 200 | inline const_iterator& operator*() const { return *this; } 201 | inline data_t* operator->() { return data(); } 202 | inline const data_t* operator->() const { return data(); } 203 | inline operator const const_iterator&() const { return *( const_iterator* ) this; } 204 | 205 | // Implement container interface 206 | // - operator[] is used for lookups. 207 | // 208 | inline bool empty() const { return size() == 0; } 209 | inline size_t size() const { return !is_null() && is_directory() ? directory()->num_entries() : 0; } 210 | inline iterator at( size_t n ) { return { .root = root, .level = directory(), .idx = n, .depth = depth + 1 }; } 211 | inline const_iterator at( size_t n ) const { return const_cast< iterator* >( this )->at( n ); } 212 | inline iterator begin() { return at( 0 ); } 213 | inline iterator end() { return at( size() ); } 214 | inline const_iterator begin() const { return at( 0 ); } 215 | inline const_iterator end() const { return at( size() ); } 216 | inline iterator front() { return at( 0 ); } 217 | inline iterator back() { return at( size() - 1 ); } 218 | inline const_iterator front() const { return at( 0 ); } 219 | inline const_iterator back() const { return at( size() - 1 ); } 220 | 221 | // Implement lookups. 222 | // 223 | template 224 | inline iterator find_if( T&& fn ) const 225 | { 226 | for ( auto it = begin(); it.idx != size(); ++it ) 227 | if ( fn( it ) ) return it; 228 | return { .root = root, .level = nullptr, .idx = 0, .depth = rsrc_null }; 229 | } 230 | inline iterator find( uint16_t u_id ) const { return find_if( [ & ] ( const auto& it ) { return it.has_id() && it.id() == u_id; } ); } 231 | inline iterator find( resource_id r_id ) const { return find( ( uint16_t ) r_id ); } 232 | inline iterator find( std::wstring_view name ) const { return find_if( [ & ] ( const auto& it ) { return it.has_name() && it.name() == name; } ); } 233 | template inline auto operator[]( T&& v ) const { return find( std::forward( v ) ); } 234 | }; 235 | 236 | // Resource directory, which is essentially the root of the tree. 237 | // - Type Directory 238 | // - Name Directory 239 | // - Lang Directory 240 | // 241 | struct resource_directory_t 242 | { 243 | // Container traits. 244 | // 245 | using iterator = base_rsrc_iterator_t; 246 | using const_iterator = base_rsrc_iterator_t; 247 | using value_type = iterator; 248 | 249 | // Root entry. 250 | // 251 | rsrc_directory_t type_directory; 252 | 253 | // Implement container interface 254 | // - operator[] is used for lookups. 255 | // 256 | inline bool empty() const { return size() == 0; } 257 | inline size_t size() const { return type_directory.num_entries(); } 258 | inline iterator at( size_t n ) { return { .root = &type_directory, .level = &type_directory, .idx = n, .depth = rsrc_type_directory }; } 259 | inline const_iterator at( size_t n ) const { return const_cast< resource_directory_t* >( this )->at( n ); } 260 | inline iterator begin() { return at( 0 ); } 261 | inline iterator end() { return at( size() ); } 262 | inline const_iterator begin() const { return at( 0 ); } 263 | inline const_iterator end() const { return at( size() ); } 264 | inline iterator front() { return at( 0 ); } 265 | inline iterator back() { return at( size() - 1 ); } 266 | inline const_iterator front() const { return at( 0 ); } 267 | inline const_iterator back() const { return at( size() - 1 ); } 268 | 269 | // Implement lookups. 270 | // 271 | template 272 | inline const_iterator find_if( T&& fn ) const 273 | { 274 | for ( auto it = begin(); it.idx != size(); ++it ) 275 | if ( fn( it ) ) return it; 276 | return { .root = &type_directory, .level = nullptr, .idx = 0, .depth = rsrc_null }; 277 | } 278 | inline const_iterator find( uint16_t u_id ) const { return find_if( [ & ] ( const auto& it ) { return it.has_id() && it.id() == u_id; } ); } 279 | inline const_iterator find( resource_id r_id ) const { return find( ( uint16_t ) r_id ); } 280 | inline const_iterator find( std::wstring_view name ) const { return find_if( [ & ] ( const auto& it ) { return it.has_name() && it.name() == name; } ); } 281 | template inline auto find( T&& v ) { return acquire( ( ( const resource_directory_t* ) this )->find( std::forward( v ) ) ); } 282 | template inline auto find_if( T&& fn ) { return acquire( ( ( const resource_directory_t* ) this )->find_if( std::forward( fn ) ) ); } 283 | template inline auto operator[]( T&& v ) { return acquire( ( ( const resource_directory_t* ) this )->find( std::forward( v ) ) ); } 284 | template inline auto operator[]( T&& v ) const { return find( std::forward( v ) ); } 285 | inline iterator acquire( const const_iterator& i ) { return *( iterator* ) &i; } 286 | }; 287 | 288 | template struct directory_type { using type = resource_directory_t; }; 289 | }; 290 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/nt/directories/dir_security.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../../img_common.hpp" 30 | #include "../data_directories.hpp" 31 | 32 | WIN_STRUCT_PACKING 33 | namespace win 34 | { 35 | enum class certificate_type_id : uint16_t 36 | { 37 | x509 = 0x0001, 38 | pkcs_signed_data = 0x0002, 39 | reserved_1 = 0x0003, 40 | ts_stack_signed = 0x0004, 41 | pkcs1_sign = 0x0009, 42 | }; 43 | 44 | struct win_certificate_t 45 | { 46 | uint32_t length; 47 | version_t revision; 48 | certificate_type_id certificate_type; 49 | uint8_t raw_data[ VAR_LEN ]; 50 | }; 51 | using security_directory_t = win_certificate_t; 52 | 53 | template struct directory_type { using type = security_directory_t; }; 54 | }; 55 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/nt/directories/dir_tls.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../../img_common.hpp" 30 | #include "../data_directories.hpp" 31 | 32 | WIN_STRUCT_PACKING 33 | namespace win 34 | { 35 | union tls_characteristics_t 36 | { 37 | uint32_t flags; 38 | struct 39 | { 40 | uint32_t _reserved0 : 20; 41 | uint32_t alignment : 4; 42 | uint32_t _reserved1 : 8; 43 | }; 44 | 45 | inline size_t get_alignment() const { return convert_alignment( alignment ); } 46 | inline bool set_alignment( size_t align ) { return alignment = reflect_alignment( align ); } 47 | }; 48 | 49 | struct tls_directory_x64_t 50 | { 51 | uint64_t address_raw_data_start; 52 | uint64_t address_raw_data_end; 53 | uint64_t address_index; 54 | uint64_t address_callbacks; 55 | uint32_t size_zero_fill; 56 | tls_characteristics_t characteristics; 57 | }; 58 | 59 | struct tls_directory_x86_t 60 | { 61 | uint32_t address_raw_data_start; 62 | uint32_t address_raw_data_end; 63 | uint32_t address_index; 64 | uint32_t address_callbacks; 65 | uint32_t size_zero_fill; 66 | tls_characteristics_t characteristics; 67 | }; 68 | 69 | template 70 | using tls_directory_t = std::conditional_t; 71 | 72 | template struct directory_type { using type = tls_directory_t; }; 73 | }; 74 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/nt/image.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../img_common.hpp" 30 | #include "nt_headers.hpp" 31 | #include "directories/dir_debug.hpp" 32 | #include "directories/dir_exceptions.hpp" 33 | #include "directories/dir_export.hpp" 34 | #include "directories/dir_iat.hpp" 35 | #include "directories/dir_import.hpp" 36 | #include "directories/dir_relocs.hpp" 37 | #include "directories/dir_tls.hpp" 38 | #include "directories/dir_load_config.hpp" 39 | #include "directories/dir_resource.hpp" 40 | #include "directories/dir_security.hpp" 41 | #include "directories/dir_delay_load.hpp" 42 | 43 | namespace win { 44 | static constexpr uint32_t img_npos = 0xFFFFFFFF; 45 | 46 | // Image wrapper 47 | // 48 | template 49 | struct image_t { 50 | dos_header_t dos_header; 51 | 52 | // Basic getters. 53 | // 54 | inline dos_header_t* get_dos_headers() { return &dos_header; } 55 | inline const dos_header_t* get_dos_headers() const { return &dos_header; } 56 | inline file_header_t* get_file_header() { return dos_header.get_file_header(); } 57 | inline const file_header_t* get_file_header() const { return dos_header.get_file_header(); } 58 | inline nt_headers_t* get_nt_headers() { return dos_header.get_nt_headers(); } 59 | inline const nt_headers_t* get_nt_headers() const { return dos_header.get_nt_headers(); } 60 | 61 | // Calculation of optional header checksum. 62 | // 63 | inline uint32_t compute_checksum( size_t file_len ) const 64 | { 65 | // Sum over each word. 66 | // 67 | uint32_t chksum = 0; 68 | const uint16_t* wdata = ( const uint16_t* ) this; 69 | for ( size_t n = 0; n != file_len / 2; n++ ) { 70 | uint32_t sum = wdata[ n ] + chksum; 71 | chksum = ( uint16_t ) sum + ( sum >> 16 ); 72 | } 73 | 74 | // If there's a byte left append it. 75 | // 76 | uint16_t presult = chksum + ( chksum >> 16 ); 77 | if ( file_len & 1 ) 78 | presult += *( ( ( const char* ) this ) + file_len - 1 ); 79 | 80 | // Adjust for the previous .checkum field (=0) 81 | // 82 | uint16_t* adjust_sum = ( uint16_t* ) &get_nt_headers()->optional_header.checksum; 83 | for ( size_t i = 0; i != 2; i++ ) { 84 | presult -= presult < adjust_sum[ i ]; 85 | presult -= adjust_sum[ i ]; 86 | } 87 | return presult + ( uint32_t ) file_len; 88 | } 89 | inline void update_checksum( size_t file_len ) 90 | { 91 | get_nt_headers()->optional_header.checksum = compute_checksum( file_len ); 92 | } 93 | 94 | // Directory getter 95 | // 96 | inline data_directory_t* get_directory( directory_id id ) 97 | { 98 | auto nt_hdrs = get_nt_headers(); 99 | if ( nt_hdrs->optional_header.num_data_directories <= id ) return nullptr; 100 | data_directory_t* dir = &nt_hdrs->optional_header.data_directories.entries[ id ]; 101 | return dir->present() ? dir : nullptr; 102 | } 103 | inline const data_directory_t* get_directory( directory_id id ) const { return const_cast< image_t* >( this )->get_directory( id ); } 104 | 105 | // Gets the max raw offset referenced. 106 | // 107 | inline size_t get_raw_limit() const 108 | { 109 | // Initialize the length with the header size. 110 | // 111 | auto* nt_hdrs = get_nt_headers(); 112 | size_t max_raw = nt_hdrs->optional_header.size_headers; 113 | 114 | // Calculate max length from the sections. 115 | // 116 | auto* scn = nt_hdrs->get_sections(); 117 | for ( size_t i = 0; i != nt_hdrs->file_header.num_sections; i++ ) 118 | max_raw = std::max( scn[ i ].ptr_raw_data + scn[ i ].size_raw_data, max_raw ); 119 | 120 | // If there is a security directory, which usually is at the end of the image unmapped, also consider that. 121 | // 122 | if ( auto dir = get_directory( directory_entry_security ) ) 123 | max_raw = std::max( dir->rva + dir->size, max_raw ); 124 | return max_raw; 125 | } 126 | 127 | // Section mapping 128 | // 129 | inline section_header_t* rva_to_section( uint32_t rva ) 130 | { 131 | auto nt_hdrs = get_nt_headers(); 132 | for ( size_t i = 0; i != nt_hdrs->file_header.num_sections; i++ ) { 133 | auto section = nt_hdrs->get_section( i ); 134 | if ( section->virtual_address <= rva && rva < ( section->virtual_address + section->virtual_size ) ) 135 | return section; 136 | } 137 | return nullptr; 138 | } 139 | inline section_header_t* fo_to_section( uint32_t offset ) 140 | { 141 | auto nt_hdrs = get_nt_headers(); 142 | for ( size_t i = 0; i != nt_hdrs->file_header.num_sections; i++ ) { 143 | auto section = nt_hdrs->get_section( i ); 144 | if ( section->ptr_raw_data <= offset && offset < ( section->ptr_raw_data + section->size_raw_data ) ) 145 | return section; 146 | } 147 | return nullptr; 148 | } 149 | inline const section_header_t* rva_to_section( uint32_t rva ) const { return const_cast< image_t* >( this )->rva_to_section( rva ); } 150 | inline const section_header_t* fo_to_section( uint32_t offset ) const { return const_cast< image_t* >( this )->fo_to_section( offset ); } 151 | 152 | // RVA mappings. 153 | // - Conversions using pointers are only safe on raw views. 154 | // 155 | template 156 | inline T* rva_to_ptr( uint32_t rva, size_t length = 1 ) 157 | { 158 | // Find the section, try mapping to header if none found. 159 | // 160 | auto scn = rva_to_section( rva ); 161 | if ( !scn ) { 162 | uint32_t rva_hdr_end = get_nt_headers()->optional_header.size_headers; 163 | if ( rva < rva_hdr_end && ( rva + length ) <= rva_hdr_end ) 164 | return ( T* ) ( ( uint8_t* ) &dos_header + rva ); 165 | return nullptr; 166 | } 167 | 168 | // Apply the boundary check. 169 | // 170 | size_t offset = rva - scn->virtual_address; 171 | if ( ( offset + length ) > scn->size_raw_data ) 172 | return nullptr; 173 | 174 | // Return the final pointer. 175 | // 176 | return ( T* ) ( ( uint8_t* ) &dos_header + scn->ptr_raw_data + offset ); 177 | } 178 | template 179 | inline const T* rva_to_ptr( uint32_t rva, size_t length = 1 ) const { return const_cast< image_t* >( this )->template rva_to_ptr( rva, length ); } 180 | inline uint32_t rva_to_fo( uint32_t rva, size_t length = 1 ) const { return ptr_to_raw( rva_to_ptr( rva, length ) ); } 181 | 182 | // RAW offset mappings. 183 | // - Conversions using pointers are only safe on mapped views. 184 | // 185 | template 186 | inline T* fo_to_ptr( uint32_t offset, size_t length = 1 ) 187 | { 188 | // Find the section, try mapping to header if none found. 189 | // 190 | auto scn = fo_to_section( offset ); 191 | if ( !scn ) { 192 | uint32_t rva_hdr_end = get_nt_headers()->optional_header.size_headers; 193 | if ( offset < rva_hdr_end && ( offset + length ) <= rva_hdr_end ) 194 | return ( T* ) ( ( uint8_t* ) &dos_header + offset ); 195 | return nullptr; 196 | } 197 | 198 | // Apply the boundary check. 199 | // 200 | size_t soffset = offset - scn->ptr_raw_data; 201 | if ( ( soffset + length ) > scn->virtual_size ) 202 | return nullptr; 203 | 204 | // Return the final pointer. 205 | // 206 | return ( T* ) ( ( uint8_t* ) &dos_header + scn->virtual_address + soffset ); 207 | } 208 | template 209 | inline const T* fo_to_ptr( uint32_t offset, size_t length = 1 ) const { return const_cast< image_t* >( this )->template fo_to_ptr( offset, length ); } 210 | inline uint32_t fo_to_rva( uint32_t offset, size_t length = 1 ) const { return ptr_to_raw( fo_to_ptr( offset, length ) ); } 211 | 212 | // Raw offset to pointer mapping, no boundary checks by default so this can 213 | // be used to translate RVA as well if image is mapped. 214 | // - If length is given, should not be used for RVA translation on mapped images. 215 | // 216 | template 217 | inline T* raw_to_ptr( uint32_t offset, size_t length = 0 ) 218 | { 219 | // Do a basic boundary check if length is given. 220 | // 221 | if ( length != 0 && ( offset + length ) > get_raw_limit() ) 222 | return nullptr; 223 | 224 | // Return the final pointer. 225 | // 226 | return ( T* ) ( ( uint8_t* ) &dos_header + offset ); 227 | } 228 | template 229 | inline const T* raw_to_ptr( uint32_t rva, size_t length = 0 ) const { return const_cast< image_t* >( this )->template raw_to_ptr( rva, length ); } 230 | inline uint32_t ptr_to_raw( const void* ptr ) const { return ptr ? uint32_t( uintptr_t( ptr ) - uintptr_t( &dos_header ) ) : img_npos; } 231 | }; 232 | using image_x64_t = image_t; 233 | using image_x86_t = image_t; 234 | }; 235 | -------------------------------------------------------------------------------- /includes/nt/nt_headers.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../img_common.hpp" 30 | #include "../coff/file_header.hpp" 31 | #include "../coff/section_header.hpp" 32 | #include "optional_header.hpp" 33 | 34 | WIN_STRUCT_PACKING 35 | namespace win 36 | { 37 | // Magic constants 38 | // 39 | static constexpr uint16_t DOS_HDR_MAGIC = 0x5A4D; // "MZ" 40 | static constexpr uint32_t NT_HDR_MAGIC = 0x00004550; // "PE\x0\x0" 41 | 42 | // NT headers 43 | // 44 | template 45 | struct nt_headers_t 46 | { 47 | uint32_t signature; 48 | file_header_t file_header; 49 | optional_header_t optional_header; 50 | 51 | // Section getters 52 | // 53 | inline section_header_t* get_sections() { return ( section_header_t* ) ( ( uint8_t* ) &optional_header + file_header.size_optional_header ); } 54 | inline section_header_t* get_section( size_t n ) { return n >= file_header.num_sections ? nullptr : get_sections() + n; } 55 | inline const section_header_t* get_sections() const { return const_cast< nt_headers_t* >( this )->get_sections(); } 56 | inline const section_header_t* get_section( size_t n ) const { return const_cast< nt_headers_t* >( this )->get_section( n ); } 57 | 58 | // Section iterator 59 | // 60 | template 61 | struct proxy 62 | { 63 | T* base; 64 | uint16_t count; 65 | T* begin() const { return base; } 66 | T* end() const { return base + count; } 67 | }; 68 | inline proxy sections() { return { get_sections(), file_header.num_sections }; } 69 | inline proxy sections() const { return { get_sections(), file_header.num_sections }; } 70 | }; 71 | using nt_headers_x64_t = nt_headers_t; 72 | using nt_headers_x86_t = nt_headers_t; 73 | 74 | // DOS header 75 | // 76 | struct dos_header_t 77 | { 78 | uint16_t e_magic; 79 | uint16_t e_cblp; 80 | uint16_t e_cp; 81 | uint16_t e_crlc; 82 | uint16_t e_cparhdr; 83 | uint16_t e_minalloc; 84 | uint16_t e_maxalloc; 85 | uint16_t e_ss; 86 | uint16_t e_sp; 87 | uint16_t e_csum; 88 | uint16_t e_ip; 89 | uint16_t e_cs; 90 | uint16_t e_lfarlc; 91 | uint16_t e_ovno; 92 | uint16_t e_res[ 4 ]; 93 | uint16_t e_oemid; 94 | uint16_t e_oeminfo; 95 | uint16_t e_res2[ 10 ]; 96 | uint32_t e_lfanew; 97 | 98 | inline file_header_t* get_file_header() { return &get_nt_headers<>()->file_header; } 99 | inline const file_header_t* get_file_header() const { return &get_nt_headers<>()->file_header; } 100 | template inline nt_headers_t* get_nt_headers() { return ( nt_headers_t* ) ( ( uint8_t* ) this + e_lfanew ); } 101 | template inline const nt_headers_t* get_nt_headers() const { return const_cast< dos_header_t* >( this )->template get_nt_headers(); } 102 | }; 103 | }; 104 | #pragma pack(pop) -------------------------------------------------------------------------------- /includes/nt/optional_header.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Can Boluk 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // 1. Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // 2. Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // 3. Neither the name of the copyright holder nor the names of its contributors 13 | // may be used to endorse or promote products derived from this software 14 | // without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | #pragma once 29 | #include "../img_common.hpp" 30 | #include "data_directories.hpp" 31 | 32 | WIN_STRUCT_PACKING 33 | namespace win 34 | { 35 | // Magic numbers. 36 | // 37 | static constexpr uint16_t OPT_HDR32_MAGIC = 0x010B; 38 | static constexpr uint16_t OPT_HDR64_MAGIC = 0x020B; 39 | 40 | // Subsystems 41 | // 42 | enum class subsystem_id : uint16_t 43 | { 44 | unknown = 0x0000, // Unknown subsystem. 45 | native = 0x0001, // Image doesn't require a subsystem. 46 | windows_gui = 0x0002, // Image runs in the Windows GUI subsystem. 47 | windows_cui = 0x0003, // Image runs in the Windows character subsystem 48 | os2_cui = 0x0005, // image runs in the OS/2 character subsystem. 49 | posix_cui = 0x0007, // image runs in the Posix character subsystem. 50 | native_windows = 0x0008, // image is a native Win9x driver. 51 | windows_ce_gui = 0x0009, // Image runs in the Windows CE subsystem. 52 | efi_application = 0x000A, // 53 | efi_boot_service_driver = 0x000B, // 54 | efi_runtime_driver = 0x000C, // 55 | efi_rom = 0x000D, 56 | xbox = 0x000E, 57 | windows_boot_application = 0x0010, 58 | xbox_code_catalog = 0x0011, 59 | }; 60 | 61 | // DLL characteristics 62 | // 63 | union dll_characteristics_t 64 | { 65 | uint16_t flags; 66 | struct 67 | { 68 | uint16_t _pad0 : 5; 69 | uint16_t high_entropy_va : 1; // Image can handle a high entropy 64-bit virtual address space. 70 | uint16_t dynamic_base : 1; // DLL can move. 71 | uint16_t force_integrity : 1; // Code Integrity Image 72 | uint16_t nx_compat : 1; // Image is NX compatible 73 | uint16_t no_isolation : 1; // Image understands isolation and doesn't want it 74 | uint16_t no_seh : 1; // Image does not use SEH. No SE handler may reside in this image 75 | uint16_t no_bind : 1; // Do not bind this image. 76 | uint16_t appcontainer : 1; // Image should execute in an AppContainer 77 | uint16_t wdm_driver : 1; // Driver uses WDM model 78 | uint16_t guard_cf : 1; // Image supports Control Flow Guard. 79 | uint16_t terminal_server_aware : 1; 80 | }; 81 | }; 82 | 83 | // Optional header 84 | // 85 | struct optional_header_x64_t 86 | { 87 | // Standard fields. 88 | uint16_t magic; 89 | version_t linker_version; 90 | 91 | uint32_t size_code; 92 | uint32_t size_init_data; 93 | uint32_t size_uninit_data; 94 | 95 | uint32_t entry_point; 96 | uint32_t base_of_code; 97 | 98 | // NT additional fields. 99 | uint64_t image_base; 100 | uint32_t section_alignment; 101 | uint32_t file_alignment; 102 | 103 | ex_version_t os_version; 104 | ex_version_t img_version; 105 | ex_version_t subsystem_version; 106 | uint32_t win32_version_value; 107 | 108 | uint32_t size_image; 109 | uint32_t size_headers; 110 | 111 | uint32_t checksum; 112 | subsystem_id subsystem; 113 | dll_characteristics_t characteristics; 114 | 115 | uint64_t size_stack_reserve; 116 | uint64_t size_stack_commit; 117 | uint64_t size_heap_reserve; 118 | uint64_t size_heap_commit; 119 | 120 | uint32_t ldr_flags; 121 | 122 | uint32_t num_data_directories; 123 | data_directories_x64_t data_directories; 124 | }; 125 | struct optional_header_x86_t 126 | { 127 | // Standard fields. 128 | uint16_t magic; 129 | version_t linker_version; 130 | 131 | uint32_t size_code; 132 | uint32_t size_init_data; 133 | uint32_t size_uninit_data; 134 | 135 | uint32_t entry_point; 136 | uint32_t base_of_code; 137 | uint32_t base_of_data; 138 | 139 | // NT additional fields. 140 | uint32_t image_base; 141 | uint32_t section_alignment; 142 | uint32_t file_alignment; 143 | 144 | ex_version_t os_version; 145 | ex_version_t img_version; 146 | ex_version_t subsystem_version; 147 | uint32_t win32_version_value; 148 | 149 | uint32_t size_image; 150 | uint32_t size_headers; 151 | 152 | uint32_t checksum; 153 | subsystem_id subsystem; 154 | dll_characteristics_t characteristics; 155 | 156 | uint32_t size_stack_reserve; 157 | uint32_t size_stack_commit; 158 | uint32_t size_heap_reserve; 159 | uint32_t size_heap_commit; 160 | 161 | uint32_t ldr_flags; 162 | 163 | uint32_t num_data_directories; 164 | data_directories_x86_t data_directories; 165 | 166 | inline bool has_directory( const data_directory_t* dir ) const { return &data_directories.entries[ num_data_directories ] < dir && dir->present(); } 167 | inline bool has_directory( directory_id id ) const { return has_directory( &data_directories.entries[ id ] ); } 168 | }; 169 | template 170 | using optional_header_t = std::conditional_t; 171 | }; 172 | #pragma pack(pop) -------------------------------------------------------------------------------- /linux-pe.licenseheader: -------------------------------------------------------------------------------- 1 | extensions: .cpp .hpp 2 | // Copyright (c) 2020 Can Boluk 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are met: 7 | // 8 | // 1. Redistributions of source code must retain the above copyright notice, 9 | // this list of conditions and the following disclaimer. 10 | // 2. Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // 3. Neither the name of the copyright holder nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | // POSSIBILITY OF SUCH DAMAGE. 28 | // -------------------------------------------------------------------------------- /linuxpe.vcxitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | {B1F1BC0E-862F-4172-A34B-99EB4FAF5229} 7 | linux-pe 8 | 9 | 10 | 11 | %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)includes 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /linuxpe.vcxitems.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {3bdb67a9-81e9-48e7-817c-784235cb7d32} 6 | 7 | 8 | {6338239a-3c88-4097-9ec5-a626e3d71197} 9 | 10 | 11 | {ac8943f0-065d-49f4-826d-b868dbb560d0} 12 | 13 | 14 | {a64faa92-6ec6-420d-8ece-db6264aeca99} 15 | 16 | 17 | {b42cdc57-0360-426e-8521-100f62a7bf2e} 18 | 19 | 20 | 21 | 22 | COFF Auxiliaries 23 | 24 | 25 | COFF Auxiliaries 26 | 27 | 28 | COFF Auxiliaries 29 | 30 | 31 | COFF Auxiliaries 32 | 33 | 34 | COFF Auxiliaries 35 | 36 | 37 | COFF Types 38 | 39 | 40 | COFF Types 41 | 42 | 43 | NT Directories 44 | 45 | 46 | NT Directories 47 | 48 | 49 | NT Directories 50 | 51 | 52 | NT Directories 53 | 54 | 55 | NT Directories 56 | 57 | 58 | NT Directories 59 | 60 | 61 | NT Directories 62 | 63 | 64 | NT Directories 65 | 66 | 67 | NT Directories 68 | 69 | 70 | NT Directories 71 | 72 | 73 | NT Directories 74 | 75 | 76 | NT Types 77 | 78 | 79 | NT Types 80 | 81 | 82 | NT Types 83 | 84 | 85 | NT Types 86 | 87 | 88 | Includes 89 | 90 | 91 | COFF Types 92 | 93 | 94 | COFF Types 95 | 96 | 97 | COFF Types 98 | 99 | 100 | COFF Types 101 | 102 | 103 | COFF Types 104 | 105 | 106 | Includes 107 | 108 | 109 | COFF Types 110 | 111 | 112 | COFF Types 113 | 114 | 115 | COFF Types 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | --------------------------------------------------------------------------------