/
Binary.hpp
538 lines (396 loc) · 19.3 KB
/
Binary.hpp
1
2
3
4
5
6
7
8
9
10
11
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_ELF_BINARY_H_
#define LIEF_ELF_BINARY_H_
#include <vector>
#include <memory>
#include "LIEF/visibility.h"
#include "LIEF/iterators.hpp"
#include "LIEF/Abstract/Binary.hpp"
#include "LIEF/ELF/type_traits.hpp"
#include "LIEF/ELF/Header.hpp"
#include "LIEF/ELF/Section.hpp"
#include "LIEF/ELF/Segment.hpp"
#include "LIEF/ELF/DynamicEntry.hpp"
#include "LIEF/ELF/DynamicEntryLibrary.hpp"
#include "LIEF/ELF/DynamicSharedObject.hpp"
#include "LIEF/ELF/DynamicEntryRpath.hpp"
#include "LIEF/ELF/DynamicEntryRunPath.hpp"
#include "LIEF/ELF/DynamicEntryArray.hpp"
#include "LIEF/ELF/DynamicEntryFlags.hpp"
#include "LIEF/ELF/Symbol.hpp"
#include "LIEF/ELF/Relocation.hpp"
#include "LIEF/ELF/SymbolVersion.hpp"
#include "LIEF/ELF/SymbolVersionRequirement.hpp"
#include "LIEF/ELF/SymbolVersionDefinition.hpp"
#include "LIEF/ELF/utils.hpp"
#include "LIEF/ELF/DataHandler/Handler.hpp"
#include "LIEF/ELF/GnuHash.hpp"
#include "LIEF/ELF/Note.hpp"
#include "LIEF/ELF/SysvHash.hpp"
namespace LIEF {
namespace ELF {
class Parser;
class Builder;
//! @brief Class which represent an ELF binary
class DLL_PUBLIC Binary : public LIEF::Binary {
friend class Parser;
friend class Builder;
public:
Binary(const std::string& name, ELF_CLASS type);
Binary& operator=(const Binary& copy) = delete;
Binary(const Binary& copy) = delete;
//! @brief Return binary's class (ELF32 or ELF64)
ELF_CLASS type(void) const;
//! @brief Return @link ELF::Header Elf header @endlink
Header& header(void);
const Header& header(void) const;
//! @brief Return the last offset used in binary
//! according to section headers
uint64_t last_offset_section(void) const;
//! @brief Return the last offset used in binary
//! according to segment headers
uint64_t last_offset_segment(void) const;
//! @brief Return the next virtual address available
uint64_t next_virtual_address(void) const;
//! @brief Return binary's sections
//!
//! @warning
//! This method return a vector of references thus you can
//! modify vector's elements (section) but not add elements.
it_sections sections(void);
it_const_sections sections(void) const;
//! @brief Return binary entrypoint
virtual uint64_t entrypoint(void) const override;
//! @brief Return binary's segments
it_segments segments(void);
it_const_segments segments(void) const;
//! @brief Return binary's dynamic entries
it_dynamic_entries dynamic_entries(void);
it_const_dynamic_entries dynamic_entries(void) const;
//! @brief Add the given dynamic entry and return the entry added
DynamicEntry& add(const DynamicEntry& entry);
//! @brief Add the given note and return the entry added
Note& add(const Note& note);
//! @brief Remove the given dynamic entry
void remove(const DynamicEntry& entry);
//! @brief Remove **all** dynamic entries with the given tag
void remove(DYNAMIC_TAGS tag);
//! @brief Remove the given section
void remove(const Section& section, bool clear = false);
//! @brief Remove the given note
void remove(const Note& note);
//! @brief Remove **all** notes with the given type
void remove(NOTE_TYPES tag);
//! @brief Return binary's dynamic symbols
it_symbols dynamic_symbols(void);
it_const_symbols dynamic_symbols(void) const;
//! @brief Return symbols which are exported by the binary
it_exported_symbols exported_symbols(void);
it_const_exported_symbols exported_symbols(void) const;
//! @brief Return symbols which are imported by the binary
it_imported_symbols imported_symbols(void);
it_const_imported_symbols imported_symbols(void) const;
//! @brief Return statics symbols
it_symbols static_symbols(void);
it_const_symbols static_symbols(void) const;
//! @brief Return symbol versions
it_symbols_version symbols_version(void);
it_const_symbols_version symbols_version(void) const;
//! @brief Return symbols version definition
it_symbols_version_definition symbols_version_definition(void);
it_const_symbols_version_definition symbols_version_definition(void) const;
//! @brief Return Symbol version requirement
it_symbols_version_requirement symbols_version_requirement(void);
it_const_symbols_version_requirement symbols_version_requirement(void) const;
//! @brief Return dynamic relocations
it_dynamic_relocations dynamic_relocations(void);
it_const_dynamic_relocations dynamic_relocations(void) const;
Relocation& add_dynamic_relocation(const Relocation& relocation);
Relocation& add_pltgot_relocation(const Relocation& relocation);
//! @brief Return `plt.got` relocations
it_pltgot_relocations pltgot_relocations(void);
it_const_pltgot_relocations pltgot_relocations(void) const;
//! @brief Return relocations used in an object file (``*.o``)
it_object_relocations object_relocations(void);
it_const_object_relocations object_relocations(void) const;
//! @brief Return **all** relocations present in the binary
it_relocations relocations(void);
it_const_relocations relocations(void) const;
//! @brief ``true`` if GNU hash is used
//!
//! @see gnu_hash and use_sysv_hash
bool use_gnu_hash(void) const;
//! @brief Return the GnuHash object in **readonly**
const GnuHash& gnu_hash(void) const;
//! @brief ``true`` if SYSV hash is used
//!
//! @see sysv_hash and use_gnu_hash
bool use_sysv_hash(void) const;
//! @brief Return the SysvHash object in **readonly**
const SysvHash& sysv_hash(void) const;
//! @brief Check if a section with the given name exists in the binary
bool has_section(const std::string& name) const;
//! @brief Return Section with the given `name`
Section& get_section(const std::string& name);
const Section& get_section(const std::string& name) const;
//! @brief Return `.text` section
Section& text_section(void);
//! @brief Return `.dynamic` section
Section& dynamic_section(void);
//! @brief Return hash section
Section& hash_section(void);
//! @brief Return section which holds static symbols
Section& static_symbols_section(void);
//! @brief Return program image base. For instance 0x40000
//!
//! To compute the image base, we look for the PT_PHDR segment header (phdr),
//! and we return phdr->p_vaddr - phdr->p_offset
uint64_t imagebase(void) const;
//! @brief Return the size of the mapped binary
uint64_t virtual_size(void) const;
//! @brief Check if the binary uses a loader
//! @see interpreter
bool has_interpreter(void) const;
//! @brief Return ELF interprer if any. (e.g. `/lib64/ld-linux-x86-64.so.2`)
const std::string& interpreter(void) const;
//! @brief Change the interpreter
void interpreter(const std::string& interpreter);
//! @brief Return both static and dynamic symbols
it_symbols symbols(void);
it_const_symbols symbols(void) const;
//! @brief Remove symbols with the given name in boths
//! * dynamic symbols
//! * static symbols
//! @see remove_static_symbol, remove_dynamic_symbol
void remove_symbol(const std::string& name);
//void remove_symbol(Symbol* symbol);
//!@brief Remove static symbols with the given name
void remove_static_symbol(const std::string& name);
void remove_static_symbol(Symbol* symbol);
//!@brief Remove dynamic symbols with the given name
void remove_dynamic_symbol(const std::string& name);
//! @brief Remove the given symbol from the dynamic symbol table.
//!
//! As a side effect, it will remove any ELF::Relocation
//! that refer to this symbol and the SymbolVersion (if any)
//! associated with this symbol
void remove_dynamic_symbol(Symbol* symbol);
//! @brief Return the address of the given function name
virtual uint64_t get_function_address(const std::string& func_name) const override;
//! @brief Return the address of the given function name
//! @param func_name The function's name target
//! @param demangled Use the demangled name
uint64_t get_function_address(const std::string& func_name, bool demangled) const;
//! Add a new section in the binary
//!
//! @param[in] section The section object to insert
//! @param[in] loaded Boolean value to indicate that sections's data must be loaded
//!
//! @return The section added. The `size` and the `virtual address` may have changed.
Section& add(const Section& section, bool loaded = true);
Section& extend(const Section& section, uint64_t size);
//! @brief Add a static symbol
Symbol& add_static_symbol(const Symbol& symbol);
//! @brief Add a dynamic symbol
Symbol& add_dynamic_symbol(const Symbol& symbol);
//! @brief Add a library as dependency
DynamicEntryLibrary& add_library(const std::string& library_name);
//! @brief Remove the given library
void remove_library(const std::string& library_name);
//! @brief Get the library object (DynamicEntryLibrary) from the given name
DynamicEntryLibrary& get_library(const std::string& library_name);
//! @brief Get the library object (DynamicEntryLibrary) from the given name
const DynamicEntryLibrary& get_library(const std::string& library_name) const;
//! @brief Check if the given library name exists in the current binary
bool has_library(const std::string& name) const;
//! @brief Add a new segment in the binary
//!
//! The segment is inserted at the end
//! @warning We assume that the binary is not position independent
//!
//! @return The segment added. `Virtual address` and `File Offset` may have changed
Segment& add(const Segment& segment, uint64_t base = 0);
Segment& replace(const Segment& new_segment, const Segment& original_segment, uint64_t base = 0);
Segment& extend(const Segment& segment, uint64_t size);
//! @brief Patch the content at virtual address @p address with @p patch_value
//!
//! @param[in] address Address to patch
//! @param[in] patch_value Patch to apply
virtual void patch_address(uint64_t address, const std::vector<uint8_t>& patch_value) override;
//! @brief Patch the address with the given value
//!
//! @param[in] address Address to patch
//! @param[in] patch_value Patch to apply
//! @param[in] size Size of the value in **bytes** (1, 2, ... 8)
virtual void patch_address(uint64_t address, uint64_t patch_value, size_t size = sizeof(uint64_t)) override;
//! @brief Patch the imported symbol with the ``address``
//!
//! @param[in] symbol Imported symbol to patch
//! @param[in] address New address
void patch_pltgot(const Symbol& symbol, uint64_t address);
//! @brief Patch the imported symbol's name with the ``address``
//!
//! @param[in] symbol_name Imported symbol's name to patch
//! @param[in] address New address
void patch_pltgot(const std::string& symbol_name, uint64_t address);
//! @brief Strip the binary by removing static symbols
void strip(void);
//! @brief Remove a binary's section.
//!
//! We clear data used by this section and it's removed from
//! section table
void remove_section(const std::string& name, bool clear = false);
//! @brief Reconstruct the binary object and write it in `filename`
//! @param filename Path to write the reconstructed binary
void write(const std::string& filename);
//! @brief Reconstruct the binary object and return his content as bytes
std::vector<uint8_t> raw(void);
//! @brief Convert a virtual address to an offset in the file
uint64_t virtual_address_to_offset(uint64_t virtual_address) const;
//! @brief Check if the binary has been compiled with `-fpie -pie` flags
//!
//! To do so we check if there is a `PT_INTERP` segment and if
//! the binary type is `ET_DYN` (Shared object)
virtual bool is_pie(void) const override;
//! @brief Check if the binary uses ``NX`` protection
virtual bool has_nx(void) const override;
//! @brief Return the @link ELF::Section Section @endlink
//! from the @p offset
const Section& section_from_offset(uint64_t offset) const;
Section& section_from_offset(uint64_t offset);
//! @brief Return the @link ELF::Section Section @endlink
//! from the @p address
const Section& section_from_virtual_address(uint64_t address) const;
Section& section_from_virtual_address(uint64_t address);
//! @brief Return the @link ELF::Segment Segment @endlink
//! from the @p address
const Segment& segment_from_virtual_address(uint64_t address) const;
Segment& segment_from_virtual_address(uint64_t address);
//! @brief Return the @link ELF::Segment Segment @endlink
//! from the @p offset
const Segment& segment_from_offset(uint64_t offset) const;
Segment& segment_from_offset(uint64_t offset);
//! @brief Return the **first** ELF::DynamicEntry associated with the given tag
const DynamicEntry& get(DYNAMIC_TAGS tag) const;
DynamicEntry& get(DYNAMIC_TAGS tag);
//! @brief Return the **first** ELF::Segment associated with the given type
const Segment& get(SEGMENT_TYPES type) const;
Segment& get(SEGMENT_TYPES type);
//! @brief Return the **first** ELF::Note associated with the given type
const Note& get(NOTE_TYPES type) const;
Note& get(NOTE_TYPES type);
//! @brief Check if an ELF::DynamicEntry associated with the given tag
//! exists.
bool has(DYNAMIC_TAGS tag) const;
//! @brief Check if ELF::Segment associated with the given type
//! exists.
bool has(SEGMENT_TYPES type) const;
//! @brief Check if a ELF::Note associated with the given type
//! exists.
bool has(NOTE_TYPES type) const;
//! @brief Return the content located at virtual address
virtual std::vector<uint8_t> get_content_from_virtual_address(uint64_t virtual_address, uint64_t size) const override;
//! @brief Method so that the ``visitor`` can visit us
virtual void accept(LIEF::Visitor& visitor) const override;
//! @brief Apply the given permutation on the dynamic symbols table
//!
//! To avoid override by the ELF::Builder, one should set ELF::Builder::empties_gnuhash
//! to ``true``
void permute_dynamic_symbols(const std::vector<size_t>& permutation);
//! @brief ``true`` if the binary embed notes
bool has_notes(void) const;
//! @brief Return the Note object if any
//! @see has_note
it_const_notes notes(void) const;
it_notes notes(void);
size_t hash(const std::string& name);
virtual ~Binary(void);
virtual std::ostream& print(std::ostream& os) const override;
Binary& operator+=(const DynamicEntry& entry);
Binary& operator+=(const Section& section);
Binary& operator+=(const Segment& segment);
Binary& operator+=(const Note& note);
Binary& operator-=(const DynamicEntry& entry);
Binary& operator-=(DYNAMIC_TAGS tag);
Binary& operator-=(const Note& note);
Binary& operator-=(NOTE_TYPES type);
Segment& operator[](SEGMENT_TYPES type);
const Segment& operator[](SEGMENT_TYPES type) const;
DynamicEntry& operator[](DYNAMIC_TAGS tag);
const DynamicEntry& operator[](DYNAMIC_TAGS tag) const;
Note& operator[](NOTE_TYPES type);
const Note& operator[](NOTE_TYPES type) const;
private:
Binary(void);
//! @brief Return an abstraction of binary's section: LIEF::Section
virtual LIEF::sections_t get_abstract_sections(void) override;
virtual LIEF::Header get_abstract_header(void) const override;
virtual std::vector<std::string> get_abstract_exported_functions(void) const override;
virtual std::vector<std::string> get_abstract_imported_functions(void) const override;
virtual std::vector<std::string> get_abstract_imported_libraries(void) const override;
virtual LIEF::symbols_t get_abstract_symbols(void) override;
virtual LIEF::relocations_t get_abstract_relocations(void) override;
template<int ARCH>
void patch_relocations(uint64_t from, uint64_t shift);
template<class T>
void patch_addend(Relocation& relocatio, uint64_t from, uint64_t shift);
void shift_sections(uint64_t from, uint64_t shift);
void shift_segments(uint64_t from, uint64_t shift);
void shift_dynamic_entries(uint64_t from, uint64_t shift);
void shift_symbols(uint64_t from, uint64_t shift);
void shift_relocations(uint64_t from, uint64_t shift);
template<int OBJECT_TYPE, bool note = false>
Segment& add_segment(const Segment& segment, uint64_t base);
template<int PT>
Segment& extend_segment(const Segment& segment, uint64_t size);
template<bool LOADED>
Section& add_section(const Section& section);
//! The binary type
//! (i.e. `ELF32` or `ELF64`)
ELF_CLASS type_;
//! The binary's header as an object
Header header_;
//! The binary's sections if any
sections_t sections_;
//! The binary's segments if any
segments_t segments_;
//! A list of the diffrents dynamic entries.
dynamic_entries_t dynamic_entries_;
//! A list of dynamic symbols
symbols_t dynamic_symbols_;
//! A list of static symbols
symbols_t static_symbols_;
relocations_t relocations_;
//! .gnu.version
symbols_version_t symbol_version_table_;
//! gnu.version_r
symbols_version_requirement_t symbol_version_requirements_;
//! .gnu.version_d
symbols_version_definition_t symbol_version_definition_;
//! .gnu.hash
GnuHash gnu_hash_;
//! .note
notes_t notes_;
//! .hash
SysvHash sysv_hash_;
//! object used to manage segments/sections
DataHandler::Handler* datahandler_;
std::string interpreter_;
};
}
}
#endif