Projects STRLCPY LIEF Commits c6dfec98
🤬
  • ■ ■ ■ ■ ■ ■
    api/python/PE/objects/pyBuilder.cpp
    skipped 41 lines
    42 42   py::arg("enable") = true,
    43 43   py::return_value_policy::reference)
    44 44   
    45  - .def("patch_imports",
    46  - &Builder::patch_imports,
    47  - "Patch the original import table in order to redirect functions to "
    48  - "the new import table.\n\n"
    49  - "This setting should be used with ``build_imports`` set to ``True``",
    50  - py::arg("enable") = true,
    51  - py::return_value_policy::reference)
    52  - 
    53 45   .def("build_relocations",
    54 46   &Builder::build_relocations,
    55 47   "Rebuild the relocation table in another section",
    skipped 51 lines
  • examples/python/abstract_reader.py | 100644 /~icons-ver-BEF942F0F42935333EFA072090F4E956.svg#arrow3 100755
    Content is identical
  • examples/python/elf_reader.py | 100644 /~icons-ver-BEF942F0F42935333EFA072090F4E956.svg#arrow3 100755
    Content is identical
  • examples/python/macho_reader.py | 100644 /~icons-ver-BEF942F0F42935333EFA072090F4E956.svg#arrow3 100755
    Content is identical
  • examples/python/pe_reader.py | 100644 /~icons-ver-BEF942F0F42935333EFA072090F4E956.svg#arrow3 100755
    Content is identical
  • ■ ■ ■ ■ ■ ■
    include/LIEF/PE/Builder.hpp
    skipped 62 lines
    63 63   //! @brief Rebuild the import table in another section
    64 64   Builder& build_imports(bool flag = true);
    65 65   
    66  - //! @brief Patch the original import table in order to
    67  - //! redirect functions to the new import table.
    68  - //!
    69  - //! This setting should be used with LIEF::PE::Builder::build_imports set to ``true``
    70  - Builder& patch_imports(bool flag = true);
    71  - 
    72 66   //! @brief Rebuild the relocation table in another section
    73 67   Builder& build_relocations(bool flag = true);
    74 68   
    skipped 27 lines
    102 96   template<typename PE_T>
    103 97   void build_optional_header(const OptionalHeader& optional_header);
    104 98   
    105  - 
    106  - //! @brief Rebuild Import Table
    107  - // TODO: Bug with x86
    108 99   template<typename PE_T>
    109 100   void build_import_table(void);
    110 101   
    skipped 27 lines
    138 129   Binary *binary_;
    139 130   
    140 131   bool build_imports_;
    141  - bool patch_imports_;
    142 132   bool build_relocations_;
    143 133   bool build_tls_;
    144 134   bool build_resources_;
    skipped 9 lines
  • ■ ■ ■ ■ ■ ■
    include/LIEF/PE/Import.hpp
    skipped 123 lines
    124 124   uint32_t import_address_table_RVA_;
    125 125   std::string name_;
    126 126   PE_TYPE type_;
     127 + 
     128 + size_t original_number_of_entries_{0};
     129 + 
    127 130  };
    128 131   
    129 132  }
    skipped 4 lines
  • ■ ■ ■ ■
    src/PE/Binary.cpp
    skipped 195 lines
    196 196   
    197 197   builder.
    198 198   build_imports(false).
    199  - patch_imports(false).
    200 199   build_relocations(false).
    201 200   build_tls(false).
    202 201   build_resources(true);
    skipped 487 lines
    690 689   if (type == PE_SECTION_TYPES::IMPORT) {
    691 690   
    692 691   new_section->add_characteristic(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_READ);
    693  - new_section->add_characteristic(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_EXECUTE);
    694 692   new_section->add_characteristic(SECTION_CHARACTERISTICS::IMAGE_SCN_MEM_WRITE);
     693 + new_section->add_characteristic(SECTION_CHARACTERISTICS::IMAGE_SCN_CNT_INITIALIZED_DATA);
    695 694   
    696 695   this->data_directory(DATA_DIRECTORY::IMPORT_TABLE).RVA(new_section->virtual_address());
    697 696   this->data_directory(DATA_DIRECTORY::IMPORT_TABLE).size(new_section->sizeof_raw_data());
    698 697   this->data_directory(DATA_DIRECTORY::IMPORT_TABLE).section_ = new_section;
    699  - this->data_directory(DATA_DIRECTORY::IAT).RVA(0);
    700  - this->data_directory(DATA_DIRECTORY::IAT).size(0);
    701 698   }
    702 699   
    703 700   if (type == PE_SECTION_TYPES::RELOCATION) {
    skipped 1010 lines
  • ■ ■ ■ ■ ■ ■
    src/PE/Builder.cpp
    skipped 47 lines
    48 48  Builder::Builder(Binary* binary) :
    49 49   binary_{binary},
    50 50   build_imports_{false},
    51  - patch_imports_{false},
    52 51   build_relocations_{false},
    53 52   build_tls_{false},
    54 53   build_resources_{false},
    skipped 4 lines
    59 58   
    60 59  Builder& Builder::build_imports(bool flag) {
    61 60   this->build_imports_ = flag;
    62  - return *this;
    63  -}
    64  -Builder& Builder::patch_imports(bool flag) {
    65  - this->patch_imports_ = flag;
    66 61   return *this;
    67 62  }
    68 63   
    skipped 506 lines
    575 570   os << std::left;
    576 571   os << std::boolalpha;
    577 572   os << std::setw(20) << "Build imports:" << b.build_imports_ << std::endl;
    578  - os << std::setw(20) << "Patch imports:" << b.patch_imports_ << std::endl;
    579 573   os << std::setw(20) << "Build relocations:" << b.build_relocations_ << std::endl;
    580 574   os << std::setw(20) << "Build TLS:" << b.build_tls_ << std::endl;
    581 575   os << std::setw(20) << "Build resources:" << b.build_resources_ << std::endl;
    skipped 9 lines
  • ■ ■ ■ ■ ■ ■
    src/PE/Builder.tcc
    skipped 12 lines
    13 13   * See the License for the specific language governing permissions and
    14 14   * limitations under the License.
    15 15   */
     16 +#include <map>
    16 17  namespace LIEF {
    17 18  namespace PE {
    18 19   
    19  -template<typename PE_T>
    20  -std::vector<uint8_t> Builder::build_jmp(uint64_t from, uint64_t address) {
    21  - std::vector<uint8_t> instruction;
     20 +/*********************************
    22 21   
    23  - // call $+5
    24  - instruction.push_back(0xe8);
    25  - instruction.push_back(0x00);
    26  - instruction.push_back(0x00);
    27  - instruction.push_back(0x00);
    28  - instruction.push_back(0x00);
     22 + PE Import
    29 23   
    30  - // pop eax/pop rax
    31  - instruction.push_back(0x58); // eax/rax holds the current PC
     24 + +-----------------------+
     25 + | ILT RVA | --+
     26 + +-----------------------+ |
     27 + | Name RVA | |
     28 + +-----------------------+ |
     29 + ---| IAT RVA | |
     30 + | +-----------------------+ |
     31 + | | | |
     32 + | | | |
     33 + | | | |
     34 + | +-----------------------+ |
     35 + | | 000000000000000000000 | |
     36 + | +-----------------------+ |
     37 + | |
     38 + | +---- Ordinal Flag |
     39 + | v |
     40 + | +-+---------------------+ <-+-------- ILT
     41 + | | | Hint/Name RVA |---+
     42 + | +-+---------------------+ |
     43 + | | | .... | |
     44 + | +-+---------------------+ |
     45 + | |
     46 + | IAT |
     47 + +->+-+---------------------+ |
     48 + | | Same Value as ILT[0]| |
     49 + +-+---------------------+ |
     50 + | | | |
     51 + +-+---------------------+ |
     52 + |
     53 + |
     54 + +---+---------------+---+ |
     55 + | 9 | LoadLibrary | 0 | <-+
     56 + +---+---------------+---+
     57 + ^ ^ ^
     58 + | | |
     59 + Hint Name Padding
    32 60   
    33  - // add rax/eax (signed)
    34  - if (std::is_same<PE_T, PE64>::value) {
    35  - instruction.push_back(0x48); //x64
    36  - }
    37  - instruction.push_back(0x05);
     61 +*********************************/
    38 62   
    39  - uint64_t diff = address - (from + 5);
    40 63   
    41  - for (size_t i = 0; i < sizeof(uint32_t); ++i) {
    42  - instruction.push_back(static_cast<uint8_t>((diff >> (8 * i)) & 0xFF));
    43  - }
    44  - // jmp [rax/eax]
    45  - instruction.push_back(0xff);
    46  - instruction.push_back(0x20);
    47  - 
    48  - return instruction;
    49  -}
    50 64   
    51 65   
    52 66  template<typename PE_T>
    53  -std::vector<uint8_t> Builder::build_jmp_hook(uint64_t from, uint64_t address) {
    54  - std::vector<uint8_t> instruction;
    55  - instruction.push_back(0xe9); // jmp xxxx
    56  - uint64_t disp = address - from - 5;
    57  - 
    58  - for (size_t i = 0; i < sizeof(uint32_t); ++i) {
    59  - instruction.push_back(static_cast<uint8_t>((disp >> (8 * i)) & 0xFF));
    60  - }
    61  - 
    62  - return instruction;
    63  -}
    64  - 
    65  - 
    66  -/*
    67  - Original IAT New IAT
    68  - +------------------+ +------------------+
    69  - |Trampoline 1 addr |------+ | new address 1 |-+
    70  - +------------------+ | +------------------+ |
    71  - |Trampoline 2 addr | | | new address 1 | |
    72  - +------------------+ | +------------------+ |
    73  - |Trampoline 3 addr | | | new address 1 | |
    74  - +------------------+ | +------------------+ |
    75  - | |
    76  - | Trampoline 1 +--+
    77  - | +-----------------v-----+ Kernel32.dll
    78  - +----->| mov rax, [new addr1] | +--------------+
    79  - | jmp rax |---------->| GetLocalTime |
    80  - +-----------------------+ +--------------+
    81  - +--->| LocalSize |
    82  - Trampoline 2 | +--------------+
    83  - +-----------------------+ | | WriteFile |
    84  - | mov rax, [new addr2] | | +--------------+
    85  - | jmp rax |------+
    86  - +-----------------------+
    87  - 
    88  -*/
    89  - 
    90  -template<typename PE_T>
    91 67  void Builder::build_import_table(void) {
    92  - using uint__ = typename PE_T::uint;
     68 + using uint__ = typename PE_T::uint;
     69 + using patches_t = std::map<uint__, uint__>;
    93 70   
    94  - // Compute size of the the diffrent (sub)sections
    95  - // inside the future import section
    96  - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     71 + /**************************************
    97 72   
    98  - // Size of pe_import + 1 for the null entry
    99  - uint32_t import_table_size = static_cast<uint32_t>((this->binary_->imports().size() + 1) * sizeof(pe_import)); // +1 for the null entry
     73 + +----------------------------------+
     74 + | pe_import[0] |
     75 + +----------------------------------+
     76 + | pe_import[1] |
     77 + +----------------------------------+
     78 + | |
     79 + | Import Lookup Tables |
     80 + | |
     81 + +----------------------------------+
     82 + | Library Names |
     83 + +----------------------------------+
     84 + | |
     85 + | Hint/Names table |
     86 + | |
     87 + +----------------------------------+
     88 + | |
     89 + | |
     90 + | New IAT (For new imports) |
     91 + | |
     92 + | |
     93 + +----------------------------------+
    100 94   
    101  - // Size of import entries
    102  - uint32_t entries_size = 0;
     95 + **************************************/
    103 96   
    104  - // Size of the section which will holds imported functions names
    105  - uint32_t functions_name_size = 0;
     97 + it_imports imports = this->binary_->imports();
     98 + patches_t iat_patches;
    106 99   
    107  - // Size of the section which will holds library name (e.g. kernel32.dll)
    108  - uint32_t libraries_name_size = 0;
     100 + uint32_t import_table_size = static_cast<uint32_t>((imports.size() + 1) * sizeof(pe_import)); // +1 for the null entry
     101 + uint32_t ilt_size = 0;
     102 + uint32_t library_names_size = 0;
     103 + uint32_t hint_name_sizes = 0;
     104 + uint32_t new_iat_size = 0;
     105 + for (const Import& import : imports) {
    109 106   
    110  - // Size of the trampoline section
    111  - uint32_t trampolines_size = 0;
     107 + library_names_size += import.name().size() + 1;
     108 + ilt_size += (import.entries().size() + 1) * sizeof(uint__);
    112 109   
    113  - // Size of the instructions in the trampoline
    114  - uint32_t trampoline_size = build_jmp<PE_T>(0, 0).size();
     110 + // Added by the user
     111 + if (import.import_address_table_rva() == 0) {
     112 + new_iat_size += (import.entries().size() + 1) * sizeof(uint__);
     113 + }
    115 114   
    116  - // Compute size of each imports's sections
    117  - for (const Import& import : this->binary_->imports()) {
    118 115   for (const ImportEntry& entry : import.entries()) {
     116 + if (not entry.is_ordinal()) {
     117 + hint_name_sizes += sizeof(uint16_t) + entry.name().size() + 1;
     118 + hint_name_sizes += hint_name_sizes % 2;
     119 + }
    119 120   
    120  - functions_name_size += 2 + entry.name().size() + 1; // [Hint] [Name\0]
    121  - functions_name_size += functions_name_size % 2; // [padding]
    122 121   }
    123  - 
    124  - libraries_name_size += import.name().size() + 1; // [Name\0]
    125  - entries_size += 2 * (import.entries().size() + 1) * sizeof(uint__); // Once for Lookup table and the other for Import Address Table (IAT). +1 for the null entry
    126  - trampolines_size += import.entries().size() * trampoline_size;
    127 122   }
    128  - 
    129  - // Offset of the diffrents sections inside *import section*
    130  - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    131  - 
    132  - // Offset to the import table (i.e list of pe_import)
    133  - uint32_t import_table_offset = 0;
     123 + uint32_t import_table_offset = 0;
     124 + uint32_t ilt_offset = import_table_offset + import_table_size;
     125 + uint32_t library_names_offset = ilt_offset + ilt_size;
     126 + uint32_t hint_names_offset = library_names_offset + library_names_size;
     127 + uint32_t new_iat_offset = align(hint_names_offset + hint_name_sizes, 4);
     128 + uint32_t end_off = new_iat_offset + new_iat_size;
    134 129   
    135  - // Offset to the lookup table: After import table
    136  - uint32_t lookuptable_offset = import_table_offset + import_table_size;
    137 130   
    138  - // Address table (IAT). Identical to the lookup table until the library is bound
    139  - uint32_t iat_offset = lookuptable_offset + entries_size / 2;
    140  - 
    141  - // Offset to the section which will contains hints/names of the imported functions name
    142  - uint32_t functions_name_offset = iat_offset + entries_size / 2;
    143  - 
    144  - // Offset of the section which will holds libraries name
    145  - uint32_t libraries_name_offset = functions_name_offset + functions_name_size;
    146  - 
    147  - // Offset of the section where trampolines will be written
    148  - uint32_t trampolines_offset = libraries_name_offset + libraries_name_size;
    149  - 
    150  - // Create empty content of the required size and align it
    151  - std::vector<uint8_t> content(trampolines_offset + trampolines_size, 0);
    152  - size_t content_size_aligned = align(content.size(), this->binary_->optional_header().file_alignment());
    153  - content.insert(std::end(content), content_size_aligned - content.size(), 0);
     131 + std::vector<uint8_t> new_imports(end_off, 0);
     132 + size_t content_size_aligned = align(new_imports.size(), this->binary_->optional_header().file_alignment());
     133 + new_imports.insert(std::end(new_imports), content_size_aligned - new_imports.size(), 0);
    154 134   
    155 135   // Create a new section to handle imports
    156 136   Section new_import_section{".l" + std::to_string(static_cast<uint32_t>(DATA_DIRECTORY::IMPORT_TABLE))};
    157  - new_import_section.content(content);
     137 + new_import_section.content(new_imports);
    158 138   
    159  - new_import_section.add_characteristic(SECTION_CHARACTERISTICS::IMAGE_SCN_CNT_CODE);
     139 + //new_import_section.add_characteristic(SECTION_CHARACTERISTICS::IMAGE_SCN_CNT_CODE);
    160 140   
    161 141   auto&& it_import_section = std::find_if(
    162 142   std::begin(this->binary_->sections_),
    skipped 7 lines
    170 150   (*it_import_section)->remove_type(PE_SECTION_TYPES::IMPORT);
    171 151   }
    172 152   
    173  - // As add_section will change DATA_DIRECTORY::IMPORT_TABLE we have to save it before
    174  - uint32_t offset_imports = this->binary_->rva_to_offset(this->binary_->data_directory(DATA_DIRECTORY::IMPORT_TABLE).RVA());
    175 153   Section& import_section = this->binary_->add_section(new_import_section, PE_SECTION_TYPES::IMPORT);
    176 154   
    177 155   
    skipped 30 lines
    208 186   }
    209 187   
    210 188   // Process libraries
    211  - for (const Import& import : this->binary_->imports()) {
     189 + for (const Import& import : imports) {
     190 + uint32_t iat_rva = import.import_address_table_rva();
     191 + 
     192 + // If IAT is 0 it means that it's a user import
     193 + if (import.import_address_table_rva() == 0) {
     194 + iat_rva = import_section.virtual_address() + new_iat_offset;
     195 + }
    212 196   // Header
    213 197   pe_import header;
    214  - header.ImportLookupTableRVA = static_cast<uint__>(import_section.virtual_address() + lookuptable_offset);
     198 + header.ImportLookupTableRVA = static_cast<uint32_t>(import_section.virtual_address() + ilt_offset);
    215 199   header.TimeDateStamp = static_cast<uint32_t>(import.timedatestamp());
    216 200   header.ForwarderChain = static_cast<uint32_t>(import.forwarder_chain());
    217  - header.NameRVA = static_cast<uint__>(import_section.virtual_address() + libraries_name_offset);
    218  - header.ImportAddressTableRVA = static_cast<uint__>(import_section.virtual_address() + iat_offset);
     201 + header.NameRVA = static_cast<uint32_t>(import_section.virtual_address() + library_names_offset);
     202 + header.ImportAddressTableRVA = static_cast<uint32_t>(iat_rva);
    219 203   
    220 204   // Copy the header in the "header section"
    221 205   std::copy(
    222 206   reinterpret_cast<uint8_t*>(&header),
    223 207   reinterpret_cast<uint8_t*>(&header) + sizeof(pe_import),
    224  - content.data() + import_table_offset);
     208 + new_imports.data() + import_table_offset);
    225 209   
    226 210   import_table_offset += sizeof(pe_import);
    227 211   
    228 212   // Copy the name in the "string section"
    229 213   const std::string& import_name = import.name();
     214 + std::cout << import_name << std::endl;
    230 215   std::copy(
    231 216   std::begin(import_name),
    232 217   std::end(import_name),
    233  - content.data() + libraries_name_offset);
     218 + new_imports.data() + library_names_offset);
    234 219   
    235  - libraries_name_offset += import_name.size() + 1; // +1 for '\0'
     220 + library_names_offset += import_name.size() + 1; // +1 for '\0'
     221 + uint__ ilt_value = 0;
    236 222   
    237 223   // Process imported functions
    238 224   for (const ImportEntry& entry : import.entries()) {
    239  - 
    240  - // If patch is enabled, we have to create a trampoline for this function
    241  - if (this->patch_imports_) {
    242  - std::vector<uint8_t> instructions;
    243  - uint64_t address = this->binary_->optional_header().imagebase() + import_section.virtual_address() + iat_offset;
    244  - if (this->binary_->hooks_.count(import_name) > 0 and this->binary_->hooks_[import_name].count(entry.name())) {
    245  - address = this->binary_->hooks_[import_name][entry.name()];
    246  - instructions = Builder::build_jmp_hook<PE_T>(this->binary_->optional_header().imagebase() + import_section.virtual_address() + trampolines_offset, address);
    247  - } else {
    248  - instructions = Builder::build_jmp<PE_T>(this->binary_->optional_header().imagebase() + import_section.virtual_address() + trampolines_offset, address);
    249  - }
    250  - std::copy(
    251  - std::begin(instructions),
    252  - std::end(instructions),
    253  - content.data() + trampolines_offset);
    254  - 
    255  - trampolines_offset += trampoline_size;
    256  - }
    257  - 
    258 225   // Default: ordinal case
    259  - uint__ lookup_table_value = entry.data();
     226 + ilt_value = entry.data();
    260 227   
    261 228   if (not entry.is_ordinal()) {
    262  - 
    263  - lookup_table_value = import_section.virtual_address() + functions_name_offset;
     229 + ilt_value = import_section.virtual_address() + hint_names_offset;
    264 230   
    265 231   // Insert entry in hint/name table
    266 232   // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    267 233   
    268 234   // First: hint
    269 235   const uint16_t hint = entry.hint();
     236 + 
    270 237   std::copy(
    271 238   reinterpret_cast<const uint8_t*>(&hint),
    272 239   reinterpret_cast<const uint8_t*>(&hint) + sizeof(uint16_t),
    273  - content.data() + functions_name_offset); //hintIdx
     240 + new_imports.data() + hint_names_offset); //hintIdx
    274 241   
    275  - functions_name_offset += sizeof(uint16_t);
     242 + hint_names_offset += sizeof(uint16_t);
    276 243   
    277 244   // Then: name
    278 245   const std::string& name = entry.name();
     246 + std::cout << name << std::endl;
    279 247   std::copy(
    280 248   std::begin(name),
    281 249   std::end(name),
    282  - content.data() + functions_name_offset);
     250 + new_imports.data() + hint_names_offset);
     251 + 
     252 + hint_names_offset += name.size() + 1; // +1 for \0
     253 + hint_names_offset += hint_names_offset % 2; //Require to be even
     254 + } // is_ordinal
    283 255   
    284  - functions_name_offset += name.size() + 1; // +1 for \0
     256 + // Write ILT Value
     257 + std::copy(
     258 + reinterpret_cast<const uint8_t*>(&ilt_value),
     259 + reinterpret_cast<const uint8_t*>(&ilt_value) + sizeof(uint__),
     260 + new_imports.data() + ilt_offset);
    285 261   
    286  - functions_name_offset += functions_name_offset % 2; //Require to be even
     262 + // Patch IAT value
     263 + if (import.import_address_table_rva() == 0) {
     264 + uint32_t off = iat_rva - import_section.virtual_address();
     265 + 
     266 + std::copy(
     267 + reinterpret_cast<const uint8_t*>(&ilt_value),
     268 + reinterpret_cast<const uint8_t*>(&ilt_value) + sizeof(uint__),
     269 + new_imports.data() + off);
     270 + new_iat_offset += sizeof(uint__);
     271 + } else {
     272 + 
     273 + iat_patches.emplace(iat_rva, ilt_value);
    287 274   }
    288 275   
    289  - uint__ iat_value = 0;
     276 + ilt_offset += sizeof(uint__);
     277 + iat_rva += sizeof(uint__);
     278 + } // </end> ImportEntry iterator
     279 + 
     280 + // Null value at the end
     281 + ilt_value = 0;
    290 282   
    291  - // Check if manually set
    292  - if (entry.data() != entry.iat_value() and entry.iat_value() > 0) {
    293  - iat_value = entry.iat_value();
    294  - } else { // default value same that in the lookup table
    295  - iat_value = lookup_table_value;
    296  - }
     283 + std::copy(
     284 + reinterpret_cast<const uint8_t*>(&ilt_value),
     285 + reinterpret_cast<const uint8_t*>(&ilt_value) + sizeof(uint__),
     286 + new_imports.data() + ilt_offset);
     287 + 
     288 + // Patch IAT value
     289 + if (import.import_address_table_rva() == 0) {
     290 + uint32_t off = iat_rva - import_section.virtual_address();
    297 291   
    298  - // Insert entry in lookup table and address table
    299 292   std::copy(
    300  - reinterpret_cast<const uint8_t*>(&lookup_table_value),
    301  - reinterpret_cast<const uint8_t*>(&lookup_table_value) + sizeof(uint__),
    302  - content.data() + lookuptable_offset);
     293 + reinterpret_cast<const uint8_t*>(&ilt_value),
     294 + reinterpret_cast<const uint8_t*>(&ilt_value) + sizeof(uint__),
     295 + new_imports.data() + off);
     296 + new_iat_offset += sizeof(uint__);
     297 + } else {
     298 + iat_patches.emplace(iat_rva, ilt_value);
     299 + }
     300 + ilt_offset += sizeof(uint__);
     301 + iat_rva += sizeof(uint__);
    303 302   
    304  - std::copy(
    305  - reinterpret_cast<const uint8_t*>(&iat_value),
    306  - reinterpret_cast<const uint8_t*>(&iat_value) + sizeof(uint__),
    307  - content.data() + iat_offset);
     303 + } // </end> Import Iterator
    308 304   
    309  - lookuptable_offset += sizeof(uint__);
    310  - iat_offset += sizeof(uint__);
     305 + // Insert null entry at the end
     306 + std::fill(
     307 + new_imports.data() + import_table_offset,
     308 + new_imports.data() + import_table_offset + sizeof(pe_import),
     309 + 0);
    311 310   
    312  - }
     311 + import_table_offset += sizeof(pe_import);
     312 + import_section.content(std::move(new_imports));
    313 313   
    314  - // Insert null entry at the end
    315  - std::fill(
    316  - content.data() + lookuptable_offset,
    317  - content.data() + lookuptable_offset + sizeof(uint__),
    318  - 0);
     314 + for (auto&& p : iat_patches) {
     315 + this->binary_->patch_address(p.first, p.second, sizeof(uint__), LIEF::Binary::VA_TYPES::RVA);
     316 + }
    319 317   
    320  - std::fill(
    321  - content.data() + iat_offset,
    322  - content.data() + iat_offset + sizeof(uint__),
    323  - 0);
     318 +}
    324 319   
    325  - lookuptable_offset += sizeof(uint__);
    326  - iat_offset += sizeof(uint__);
     320 +template<typename PE_T>
     321 +std::vector<uint8_t> Builder::build_jmp(uint64_t from, uint64_t address) {
     322 + std::vector<uint8_t> instruction;
    327 323   
     324 + // call $+5
     325 + instruction.push_back(0xe8);
     326 + instruction.push_back(0x00);
     327 + instruction.push_back(0x00);
     328 + instruction.push_back(0x00);
     329 + instruction.push_back(0x00);
     330 + 
     331 + // pop eax/pop rax
     332 + instruction.push_back(0x58); // eax/rax holds the current PC
     333 + 
     334 + // add rax/eax (signed)
     335 + if (std::is_same<PE_T, PE64>::value) {
     336 + instruction.push_back(0x48); //x64
    328 337   }
     338 + instruction.push_back(0x05);
    329 339   
    330  - // Insert null entry at the end
    331  - std::fill(
    332  - content.data() + import_table_offset,
    333  - content.data() + import_table_offset + sizeof(pe_import),
    334  - 0);
     340 + uint64_t diff = address - (from + 5);
    335 341   
    336  - import_table_offset += sizeof(pe_import);
     342 + for (size_t i = 0; i < sizeof(uint32_t); ++i) {
     343 + instruction.push_back(static_cast<uint8_t>((diff >> (8 * i)) & 0xFF));
     344 + }
     345 + // jmp [rax/eax]
     346 + instruction.push_back(0xff);
     347 + instruction.push_back(0x20);
     348 + 
     349 + return instruction;
     350 +}
     351 + 
     352 + 
     353 +template<typename PE_T>
     354 +std::vector<uint8_t> Builder::build_jmp_hook(uint64_t from, uint64_t address) {
     355 + std::vector<uint8_t> instruction;
     356 + instruction.push_back(0xe9); // jmp xxxx
     357 + uint64_t disp = address - from - 5;
    337 358   
    338  - // Fill the section
    339  - import_section.content(content);
     359 + for (size_t i = 0; i < sizeof(uint32_t); ++i) {
     360 + instruction.push_back(static_cast<uint8_t>((disp >> (8 * i)) & 0xFF));
     361 + }
    340 362   
    341  - // Update IAT data directory
    342  - const uint32_t rva = static_cast<uint32_t>(import_section.virtual_address() + iat_offset);
    343  - this->binary_->data_directory(DATA_DIRECTORY::IAT).RVA(rva);
    344  - this->binary_->data_directory(DATA_DIRECTORY::IAT).size(functions_name_offset - iat_offset + 1);
     363 + return instruction;
    345 364  }
     365 + 
     366 + 
    346 367   
    347 368  template<typename PE_T>
    348 369  void Builder::build_optional_header(const OptionalHeader& optional_header) {
    skipped 212 lines
  • ■ ■ ■ ■ ■ ■
    src/PE/Import.cpp
    skipped 38 lines
    39 39   name_RVA_{other.name_RVA_},
    40 40   import_address_table_RVA_{other.import_address_table_RVA_},
    41 41   name_{other.name_},
    42  - type_{other.type_}
     42 + type_{other.type_},
     43 + original_number_of_entries_{0}
    43 44  {}
    44 45   
    45 46   
    skipped 3 lines
    49 50  }
    50 51   
    51 52  void Import::swap(Import& other) {
    52  - std::swap(this->entries_, other.entries_);
    53  - std::swap(this->directory_, other.directory_);
    54  - std::swap(this->iat_directory_, other.iat_directory_);
    55  - std::swap(this->import_lookup_table_RVA_, other.import_lookup_table_RVA_);
    56  - std::swap(this->timedatestamp_, other.timedatestamp_);
    57  - std::swap(this->forwarder_chain_, other.forwarder_chain_);
    58  - std::swap(this->name_RVA_, other.name_RVA_);
    59  - std::swap(this->import_address_table_RVA_, other.import_address_table_RVA_);
    60  - std::swap(this->name_, other.name_);
    61  - std::swap(this->type_, other.type_);
     53 + std::swap(this->entries_, other.entries_);
     54 + std::swap(this->directory_, other.directory_);
     55 + std::swap(this->iat_directory_, other.iat_directory_);
     56 + std::swap(this->import_lookup_table_RVA_, other.import_lookup_table_RVA_);
     57 + std::swap(this->timedatestamp_, other.timedatestamp_);
     58 + std::swap(this->forwarder_chain_, other.forwarder_chain_);
     59 + std::swap(this->name_RVA_, other.name_RVA_);
     60 + std::swap(this->import_address_table_RVA_, other.import_address_table_RVA_);
     61 + std::swap(this->name_, other.name_);
     62 + std::swap(this->type_, other.type_);
     63 + std::swap(this->original_number_of_entries_, other.original_number_of_entries_);
    62 64  }
    63 65   
    64 66  Import::Import(void) :
    skipped 6 lines
    71 73   name_RVA_{0},
    72 74   import_address_table_RVA_{0},
    73 75   name_{""},
    74  - type_{PE_TYPE::PE32} // Arbitrary value
    75  - 
     76 + type_{PE_TYPE::PE32}, // Arbitrary value
     77 + original_number_of_entries_{0}
    76 78  {}
    77 79   
    78 80  Import::Import(const pe_import *import) :
    skipped 6 lines
    85 87   name_RVA_(import->NameRVA),
    86 88   import_address_table_RVA_(import->ImportAddressTableRVA),
    87 89   name_{""},
    88  - type_{PE_TYPE::PE32} // Arbitrary value
     90 + type_{PE_TYPE::PE32}, // Arbitrary value
     91 + original_number_of_entries_{0}
    89 92  {}
    90 93   
    91 94   
    skipped 7 lines
    99 102   name_RVA_{0},
    100 103   import_address_table_RVA_{0},
    101 104   name_{name},
    102  - type_{PE_TYPE::PE32} // Arbitrary value
     105 + type_{PE_TYPE::PE32}, // Arbitrary value
     106 + original_number_of_entries_{0}
    103 107  {}
    104 108   
    105 109   
    skipped 161 lines
  • ■ ■ ■ ■ ■
    src/PE/Parser.tcc
    skipped 355 lines
    356 356   table = 0;
    357 357   }
    358 358   }
     359 + import.original_number_of_entries_ = import.entries_.size();
    359 360   this->binary_->imports_.push_back(std::move(import));
    360 361   }
    361 362   
    skipped 233 lines
Please wait...
Page is in error, reload to recover