mirror of
https://github.com/QuasarApp/LIEF.git
synced 2025-05-04 08:09:33 +00:00
Enhance BinaryStream Interface
This commit is contained in:
parent
a16e1c4d13
commit
4ef839c3d8
api/python/PE/objects
examples
include/LIEF
src
BinaryStream
ELF
MachO
PE
visitors
tests/pe
@ -130,9 +130,10 @@ void init_PE_Binary_class(py::module& m) {
|
||||
.def_property_readonly("has_signature", &Binary::has_signature,
|
||||
"``True`` if the binary is signed (" RST_CLASS_REF(lief.PE.Signature) ")")
|
||||
|
||||
.def("predict_function_rva", &Binary::predict_function_rva,
|
||||
.def("predict_function_rva",
|
||||
static_cast<uint32_t(Binary::*)(const std::string&, const std::string&)>(&Binary::predict_function_rva),
|
||||
"Try to predict the RVA of the given function name in the given import library name",
|
||||
py::arg("library"), py::arg("function"))
|
||||
"library"_a, "function"_a)
|
||||
|
||||
.def_property_readonly("signature",
|
||||
static_cast<const Signature& (Binary::*)(void) const>(&Binary::signature),
|
||||
|
@ -24,7 +24,7 @@ using namespace LIEF::ELF;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
LIEF::Logger::set_level(LIEF::LOGGING_LEVEL::LOG_INFO);
|
||||
LIEF::Logger::set_level(LIEF::LOGGING_LEVEL::LOG_DEBUG);
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " <ELF binary>" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
|
@ -14,7 +14,7 @@ import traceback
|
||||
import textwrap
|
||||
|
||||
from lief import Logger
|
||||
Logger.set_level(lief.LOGGING_LEVEL.INFO)
|
||||
Logger.set_level(lief.LOGGING_LEVEL.FATAL)
|
||||
|
||||
from optparse import OptionParser
|
||||
terminal_rows, terminal_columns = 100, 100
|
||||
|
@ -9,7 +9,7 @@ from lief import PE
|
||||
from lief.PE import oid_to_string
|
||||
|
||||
from lief import Logger
|
||||
Logger.set_level(lief.LOGGING_LEVEL.INFO)
|
||||
Logger.set_level(lief.LOGGING_LEVEL.FATAL)
|
||||
|
||||
from optparse import OptionParser
|
||||
import sys
|
||||
|
@ -24,31 +24,65 @@
|
||||
|
||||
class BinaryStream {
|
||||
public:
|
||||
virtual ~BinaryStream();
|
||||
virtual uint64_t size(void) const = 0;
|
||||
virtual const void* read(uint64_t offset, uint64_t size) const = 0;
|
||||
virtual const char* read_string(uint64_t offset, uint64_t size) const = 0;
|
||||
virtual std::string get_string(uint64_t offset, uint64_t size) const = 0;
|
||||
BinaryStream(void);
|
||||
virtual ~BinaryStream();
|
||||
virtual uint64_t size(void) const = 0;
|
||||
|
||||
template<typename T>
|
||||
T read_integer(uint64_t offset, bool swap = false) const;
|
||||
uint64_t read_uleb128(void) const;
|
||||
uint64_t read_sleb128(void) const;
|
||||
|
||||
std::pair<uint64_t, uint64_t> read_uleb128(uint64_t offset) const;
|
||||
std::pair<int64_t, uint64_t> read_sleb128(uint64_t offset) const;
|
||||
std::string read_string(size_t maxsize = -1u) const;
|
||||
std::string peek_string(size_t maxsize = -1u) const;
|
||||
std::string peek_string_at(size_t offset, size_t maxsize = -1u) const;
|
||||
|
||||
template<typename T>
|
||||
static T swap_endian(T u);
|
||||
std::u16string read_u16string(void) const;
|
||||
std::u16string peek_u16string(void) const;
|
||||
|
||||
std::u16string read_u16string(size_t length) const;
|
||||
std::u16string peek_u16string(size_t length) const;
|
||||
std::u16string peek_u16string_at(size_t offset, size_t length) const;
|
||||
|
||||
void setpos(size_t pos) const;
|
||||
void increment_pos(size_t value) const;
|
||||
size_t pos(void) const;
|
||||
|
||||
operator bool() const;
|
||||
|
||||
template<class T>
|
||||
const T* read_array(size_t size) const;
|
||||
|
||||
template<class T>
|
||||
const T& peek(void) const;
|
||||
|
||||
template<class T>
|
||||
const T& peek(size_t offset) const;
|
||||
|
||||
template<class T>
|
||||
const T* peek_array(size_t size) const;
|
||||
|
||||
template<class T>
|
||||
const T* peek_array(size_t offset, size_t size) const;
|
||||
|
||||
template<class T>
|
||||
const T& read(void) const;
|
||||
|
||||
template<typename T>
|
||||
static T swap_endian(T u);
|
||||
|
||||
template<typename T>
|
||||
bool can_read(void) const;
|
||||
|
||||
template<typename T>
|
||||
bool can_read(size_t offset) const;
|
||||
|
||||
size_t align(size_t align_on) const;
|
||||
|
||||
protected:
|
||||
virtual const void* read_at(uint64_t offset, uint64_t size) const = 0;
|
||||
mutable size_t pos_{0};
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
T BinaryStream::read_integer(uint64_t offset, bool swap) const {
|
||||
static_assert(std::is_integral<T>::value, "Interger required");
|
||||
const T* value = reinterpret_cast<const T*>(this->read(offset, sizeof(T)));
|
||||
return swap ? swap_endian(*value) : *value;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
T BinaryStream::swap_endian(T u) {
|
||||
// From http://stackoverflow.com/a/4956493
|
||||
@ -69,5 +103,67 @@ T BinaryStream::swap_endian(T u) {
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
const T& BinaryStream::read(void) const {
|
||||
const T& tmp = this->peek<T>();
|
||||
this->increment_pos(sizeof(T));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
const T& BinaryStream::peek(void) const {
|
||||
const void* raw = this->read_at(this->pos(), sizeof(T));
|
||||
return *reinterpret_cast<const T*>(raw);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
const T& BinaryStream::peek(size_t offset) const {
|
||||
size_t saved_offset = this->pos();
|
||||
this->setpos(offset);
|
||||
const T& r = this->peek<T>();
|
||||
this->setpos(saved_offset);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
const T* BinaryStream::peek_array(size_t size) const {
|
||||
const void* raw = this->read_at(this->pos(), sizeof(T) * size);
|
||||
return reinterpret_cast<const T*>(raw);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
const T* BinaryStream::peek_array(size_t offset, size_t size) const {
|
||||
size_t saved_offset = this->pos();
|
||||
this->setpos(offset);
|
||||
const T* r = this->peek_array<T>(size);
|
||||
this->setpos(saved_offset);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool BinaryStream::can_read(void) const {
|
||||
const void* raw = this->read_at(this->pos_, sizeof(T));
|
||||
return raw != nullptr;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool BinaryStream::can_read(size_t offset) const {
|
||||
const void* raw = this->read_at(offset, sizeof(T));
|
||||
return raw != nullptr;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
const T* BinaryStream::read_array(size_t size) const {
|
||||
const T* tmp = this->peek_array<T>(size);
|
||||
this->increment_pos(sizeof(T) * size);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -23,20 +23,18 @@
|
||||
|
||||
class VectorStream : public BinaryStream {
|
||||
public:
|
||||
//using BinaryStream::read_integer;
|
||||
VectorStream(const std::string& filename);
|
||||
VectorStream(const std::vector<uint8_t>& data);
|
||||
//using BinaryStream::read_integer;
|
||||
VectorStream(const std::string& filename);
|
||||
VectorStream(const std::vector<uint8_t>& data);
|
||||
|
||||
virtual uint64_t size(void) const override;
|
||||
virtual const void* read(uint64_t offset, uint64_t size) const override;
|
||||
virtual const char* read_string(uint64_t offset, uint64_t size = 0) const override;
|
||||
virtual std::string get_string(uint64_t offset, uint64_t size = 0) const override;
|
||||
virtual uint64_t size(void) const override;
|
||||
|
||||
const std::vector<uint8_t>& content(void) const;
|
||||
const std::vector<uint8_t>& content(void) const;
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> binary_;
|
||||
uint64_t size_;
|
||||
protected:
|
||||
virtual const void* read_at(uint64_t offset, uint64_t size) const override;
|
||||
std::vector<uint8_t> binary_;
|
||||
uint64_t size_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -56,6 +56,8 @@ class LIEF_API Parser : public LIEF::Parser {
|
||||
static constexpr uint32_t NB_MAX_DYNAMIC_ENTRIES = 1000;
|
||||
static constexpr uint32_t NB_MAX_MASKWORD = 512;
|
||||
static constexpr uint32_t MAX_NOTE_DESCRIPTION = 1_MB;
|
||||
static constexpr uint32_t MAX_SECTION_SIZE = 100_MB;
|
||||
static constexpr uint32_t MAX_SEGMENT_SIZE = MAX_SECTION_SIZE;
|
||||
|
||||
|
||||
//! @brief Parse an ELF file an return a LIEF::ELF::Binary object
|
||||
@ -96,7 +98,7 @@ class LIEF_API Parser : public LIEF::Parser {
|
||||
void parse_binary(void);
|
||||
|
||||
template<typename ELF_T>
|
||||
void parse_header(void);
|
||||
bool parse_header(void);
|
||||
|
||||
//! @brief Parse binary's Section
|
||||
//!
|
||||
|
@ -117,7 +117,7 @@ class LIEF_API BinaryParser : public LIEF::Parser {
|
||||
// -------
|
||||
void parse_dyldinfo_export(void);
|
||||
|
||||
void parse_export_trie(uint64_t start, uint64_t current_offset, uint64_t end, const std::string& prefix);
|
||||
void parse_export_trie(uint64_t start, uint64_t end, const std::string& prefix);
|
||||
|
||||
std::unique_ptr<VectorStream> stream_;
|
||||
Binary* binary_ ;
|
||||
|
@ -238,7 +238,7 @@ class LIEF_API DyldInfo : public LoadCommand {
|
||||
private:
|
||||
void show_bindings(std::ostream& os, const buffer_t& buffer, bool is_lazy = false) const;
|
||||
|
||||
void show_trie(std::ostream& output, std::string output_prefix, VectorStream& stream, uint64_t start, uint64_t current_offset, uint64_t end, const std::string& prefix) const;
|
||||
void show_trie(std::ostream& output, std::string output_prefix, VectorStream& stream, uint64_t start, uint64_t end, const std::string& prefix) const;
|
||||
|
||||
info_t rebase_;
|
||||
buffer_t rebase_opcodes_;
|
||||
|
@ -529,6 +529,22 @@ struct arm_thread_state64_t {
|
||||
uint32_t cpsr; // cpsr
|
||||
};
|
||||
|
||||
struct code_directory {
|
||||
uint32_t version;
|
||||
uint32_t flags;
|
||||
uint32_t hash_offset;
|
||||
uint32_t ident_offset;
|
||||
uint32_t nb_special_slots;
|
||||
uint32_t nb_code_slots;
|
||||
uint32_t code_limit;
|
||||
uint8_t hash_size;
|
||||
uint8_t hash_type;
|
||||
uint8_t reserved;
|
||||
uint8_t page_size;
|
||||
uint32_t reserved2;
|
||||
uint32_t scatter_offset;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -73,7 +73,7 @@ class LIEF_API Parser : public LIEF::Parser {
|
||||
void parse_sections(void);
|
||||
|
||||
template<typename PE_T>
|
||||
void parse_headers(void);
|
||||
bool parse_headers(void);
|
||||
|
||||
void parse_configuration(void);
|
||||
|
||||
|
@ -137,10 +137,10 @@ class LIEF_API ResourcesManager : public Object {
|
||||
uint32_t max_depth) const;
|
||||
|
||||
//! @brief Build the ResourceStringFileInfo from the RT_VERSION node
|
||||
ResourceStringFileInfo get_string_file_info(const VectorStream& stream, uint64_t& offset) const;
|
||||
ResourceStringFileInfo get_string_file_info(const VectorStream& stream, uint16_t type, std::u16string key, size_t start, size_t struct_length) const;
|
||||
|
||||
//! @brief Build the ResourceVarFileInfo from the RT_VERSION node
|
||||
ResourceVarFileInfo get_var_file_info(const VectorStream& stream, uint64_t& offset) const;
|
||||
ResourceVarFileInfo get_var_file_info(const VectorStream& stream, uint16_t type, std::u16string key, size_t start, size_t struct_length) const;
|
||||
|
||||
|
||||
ResourceNode *resources_;
|
||||
|
@ -42,7 +42,7 @@ LIEF_API PE_TYPE get_type(const std::string& file);
|
||||
LIEF_API PE_TYPE get_type(const std::vector<uint8_t>& raw);
|
||||
|
||||
//! @brief Convert a UTF-16 string to a UTF-8 one
|
||||
LIEF_API std::string u16tou8(const std::u16string& string);
|
||||
LIEF_API std::string u16tou8(const std::u16string& string, bool remove_null_char = false);
|
||||
|
||||
//! @brief Convert a UTF-8 string to a UTF-16 one
|
||||
LIEF_API std::u16string u8tou16(const std::string& string);
|
||||
|
@ -9,6 +9,22 @@
|
||||
#define VLOG(...) NULL_STREAM
|
||||
#define LOG(...) NULL_STREAM
|
||||
#define LOG_IF(...) NULL_STREAM
|
||||
|
||||
#define CHECK(...)
|
||||
#define CHECK_EQ(...)
|
||||
#define CHECK_NE(...)
|
||||
#define CHECK_LT(...)
|
||||
#define CHECK_LE(...)
|
||||
#define CHECK_GE(...)
|
||||
#define CHECK_GT(...)
|
||||
|
||||
#define DCHECK(...)
|
||||
#define DCHECK_EQ(...)
|
||||
#define DCHECK_NE(...)
|
||||
#define DCHECK_LT(...)
|
||||
#define DCHECK_LE(...)
|
||||
#define DCHECK_GE(...)
|
||||
#define DCHECK_GT(...)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -23,29 +23,21 @@
|
||||
#include "LIEF/json.hpp"
|
||||
|
||||
#include "LIEF/visitors/json.hpp"
|
||||
|
||||
#ifdef LIEF_ELF_SUPPORT
|
||||
#include "LIEF/ELF/json.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef LIEF_PE_SUPPORT
|
||||
#include "LIEF/PE/json.hpp"
|
||||
#endif
|
||||
|
||||
#include "LIEF/Abstract/json.hpp"
|
||||
|
||||
#include "LIEF/Abstract.hpp"
|
||||
#include "LIEF/ELF.hpp"
|
||||
#include "LIEF/PE.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
//template<class T, class VISITOR = JsonVisitor>
|
||||
//json to_json(const T& obj) {
|
||||
// VISITOR visitor;
|
||||
// visitor(obj);
|
||||
// return visitor.get();
|
||||
//}
|
||||
//
|
||||
//template<class T, class VISITOR = JsonVisitor>
|
||||
//std::string to_json_str(const T& obj) {
|
||||
// return to_json<T, VISITOR>(obj).dump();
|
||||
//}
|
||||
|
||||
} // namespace LIEF
|
||||
|
||||
#endif // LIEF_JSON_SUPPORT
|
||||
|
||||
#endif
|
||||
|
@ -16,33 +16,49 @@
|
||||
#include "LIEF/BinaryStream/BinaryStream.hpp"
|
||||
|
||||
BinaryStream::~BinaryStream(void) = default;
|
||||
BinaryStream::BinaryStream(void) = default;
|
||||
|
||||
void BinaryStream::setpos(size_t pos) const {
|
||||
this->pos_ = pos;
|
||||
}
|
||||
|
||||
std::pair<uint64_t, uint64_t> BinaryStream::read_uleb128(uint64_t offset) const {
|
||||
uint64_t value = 0;
|
||||
unsigned shift = 0;
|
||||
uint64_t current_offset = offset - sizeof(uint8_t);
|
||||
do {
|
||||
current_offset += sizeof(uint8_t);
|
||||
value += static_cast<uint64_t>(this->read_integer<uint8_t>(current_offset) & 0x7f) << shift;
|
||||
shift += 7;
|
||||
} while (this->read_integer<uint8_t>(current_offset) >= 128);
|
||||
|
||||
uint64_t delta = current_offset - offset;
|
||||
delta++;
|
||||
return {value, delta};
|
||||
void BinaryStream::increment_pos(size_t value) const {
|
||||
this->pos_ += value;
|
||||
}
|
||||
|
||||
|
||||
std::pair<int64_t, uint64_t> BinaryStream::read_sleb128(uint64_t offset) const {
|
||||
BinaryStream::operator bool() const {
|
||||
return this->pos_ < this->size();
|
||||
}
|
||||
|
||||
size_t BinaryStream::pos(void) const {
|
||||
return this->pos_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint64_t BinaryStream::read_uleb128(void) const {
|
||||
uint64_t value = 0;
|
||||
unsigned shift = 0;
|
||||
uint8_t byte_read;
|
||||
do {
|
||||
byte_read = this->read<uint8_t>();
|
||||
value += static_cast<uint64_t>(byte_read & 0x7f) << shift;
|
||||
shift += 7;
|
||||
} while (byte_read >= 128);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64_t BinaryStream::read_sleb128(void) const {
|
||||
int64_t value = 0;
|
||||
unsigned shift = 0;
|
||||
uint64_t current_offset = offset - sizeof(uint8_t);
|
||||
uint8_t byte_read;
|
||||
do {
|
||||
current_offset += sizeof(uint8_t);
|
||||
value += static_cast<uint64_t>(this->read_integer<uint8_t>(current_offset) & 0x7f) << shift;
|
||||
byte_read = this->read<uint8_t>();
|
||||
value += static_cast<uint64_t>(byte_read & 0x7f) << shift;
|
||||
shift += 7;
|
||||
} while (this->read_integer<uint8_t>(current_offset) >= 128);
|
||||
} while (byte_read >= 128);
|
||||
|
||||
|
||||
// Sign extend
|
||||
@ -50,9 +66,106 @@ std::pair<int64_t, uint64_t> BinaryStream::read_sleb128(uint64_t offset) const {
|
||||
value |= static_cast<int64_t>(-1) << shift;
|
||||
}
|
||||
|
||||
uint64_t delta = current_offset - offset;
|
||||
delta++;
|
||||
|
||||
return {value, delta};
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string BinaryStream::read_string(size_t maxsize) const {
|
||||
std::string str = this->peek_string(maxsize);
|
||||
this->increment_pos(str.size() + 1); // +1 for'\0'
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string BinaryStream::peek_string(size_t maxsize) const {
|
||||
std::string result;
|
||||
result.reserve(10);
|
||||
char c = '\0';
|
||||
size_t off = this->pos();
|
||||
|
||||
if (not this->can_read<char>()) {
|
||||
return result.c_str();
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
do {
|
||||
c = this->peek<char>(off);
|
||||
off += sizeof(char);
|
||||
result.push_back(c);
|
||||
++count;
|
||||
} while (count < maxsize and c != '\0' and this->pos() < this->size());
|
||||
result.back() = '\0';
|
||||
return result.c_str();
|
||||
|
||||
}
|
||||
|
||||
std::string BinaryStream::peek_string_at(size_t offset, size_t maxsize) const {
|
||||
size_t saved_offset = this->pos();
|
||||
this->setpos(offset);
|
||||
std::string tmp = this->peek_string(maxsize);
|
||||
this->setpos(saved_offset);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
std::u16string BinaryStream::read_u16string(void) const {
|
||||
std::u16string str = this->peek_u16string();
|
||||
this->increment_pos((str.size() + 1) * sizeof(uint16_t)); // +1 for'\0'
|
||||
return str;
|
||||
}
|
||||
|
||||
std::u16string BinaryStream::peek_u16string(void) const {
|
||||
std::u16string result;
|
||||
result.reserve(10);
|
||||
char16_t c = '\0';
|
||||
size_t off = this->pos();
|
||||
|
||||
if (not this->can_read<char16_t>()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
do {
|
||||
c = this->peek<char16_t>(off);
|
||||
off += sizeof(char16_t);
|
||||
result.push_back(c);
|
||||
++count;
|
||||
} while (c != 0 and this->pos() < this->size());
|
||||
result.back() = '\0';
|
||||
return result.c_str();
|
||||
}
|
||||
|
||||
|
||||
std::u16string BinaryStream::read_u16string(size_t length) const {
|
||||
std::u16string str = this->peek_u16string(length);
|
||||
this->increment_pos(length * sizeof(uint16_t)); // +1 for'\0'
|
||||
return str;
|
||||
}
|
||||
|
||||
std::u16string BinaryStream::peek_u16string(size_t length) const {
|
||||
if (length == static_cast<size_t>(-1u)) {
|
||||
return this->peek_u16string();
|
||||
}
|
||||
const char16_t* raw = this->peek_array<char16_t>(this->pos(), length);
|
||||
if (raw == nullptr) {
|
||||
return {};
|
||||
}
|
||||
return {raw, length};
|
||||
}
|
||||
|
||||
std::u16string BinaryStream::peek_u16string_at(size_t offset, size_t length) const {
|
||||
size_t saved_offset = this->pos();
|
||||
this->setpos(offset);
|
||||
std::u16string tmp = this->peek_u16string(length);
|
||||
this->setpos(saved_offset);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
size_t BinaryStream::align(size_t align_on) const {
|
||||
if (align_on == 0 or (this->pos() % align_on) == 0) {
|
||||
return 0;
|
||||
}
|
||||
size_t padding = align_on - (this->pos() % align_on);
|
||||
this->increment_pos(padding);
|
||||
return padding;
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <fstream>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <algorithm>
|
||||
|
||||
#include "LIEF/logging++.hpp"
|
||||
|
||||
@ -61,61 +61,21 @@ uint64_t VectorStream::size(void) const {
|
||||
}
|
||||
|
||||
|
||||
const void* VectorStream::read(uint64_t offset, uint64_t size) const {
|
||||
const void* VectorStream::read_at(uint64_t offset, uint64_t size) const {
|
||||
|
||||
if (offset > this->size() or (offset + size) > this->size()) {
|
||||
VLOG(VDEBUG) << "Offset: " << std::hex << offset;
|
||||
VLOG(VDEBUG) << "Size: " << std::hex << size;
|
||||
VLOG(VDEBUG) << "Binary Size: " << std::hex << this->size();
|
||||
|
||||
if (offset > this->size()) {
|
||||
throw LIEF::read_out_of_bound(offset);
|
||||
}
|
||||
|
||||
if ((offset + size) > this->size()) {
|
||||
throw LIEF::read_out_of_bound(offset, size);
|
||||
}
|
||||
size_t out_size = (offset + size) - this->size();
|
||||
LOG(ERROR) << "Can't read "
|
||||
<< std::dec << size << " bytes at "
|
||||
<< std::hex << std::showbase << offset
|
||||
<< " (" << std::hex << (out_size) << " bytes out of bound)";
|
||||
//throw LIEF::read_out_of_bound(offset, size);
|
||||
return nullptr;
|
||||
}
|
||||
return this->binary_.data() + offset;
|
||||
|
||||
}
|
||||
|
||||
|
||||
const char* VectorStream::read_string(uint64_t offset, uint64_t size) const {
|
||||
|
||||
if ((offset + size) > this->size()) {
|
||||
throw LIEF::read_out_of_bound(offset);
|
||||
}
|
||||
|
||||
|
||||
uint64_t max_size = this->size() - (offset + size);
|
||||
if (size > 0) {
|
||||
max_size = std::min<uint64_t>(max_size, size);
|
||||
}
|
||||
|
||||
return reinterpret_cast<const char*>(this->read(offset, max_size));
|
||||
}
|
||||
|
||||
std::string VectorStream::get_string(uint64_t offset, uint64_t size) const {
|
||||
|
||||
if ((offset + size) > this->size()) {
|
||||
throw LIEF::read_out_of_bound(offset);
|
||||
}
|
||||
|
||||
size_t max_size = static_cast<size_t>(this->size() - (offset + size));
|
||||
if (size > 0) {
|
||||
max_size = std::min<size_t>(max_size, size);
|
||||
}
|
||||
const char* str = this->read_string(offset);
|
||||
const char* end = str + max_size;
|
||||
const char* it_null = std::find(str, end, '\0');
|
||||
if (it_null == end) {
|
||||
throw LIEF::read_out_of_bound(offset);
|
||||
}
|
||||
std::string tmp{str, it_null};
|
||||
tmp.push_back('\0');
|
||||
return tmp.c_str();
|
||||
}
|
||||
|
||||
|
||||
const std::vector<uint8_t>& VectorStream::content(void) const {
|
||||
|
@ -699,9 +699,9 @@ void Builder::build_symbol_hash(void) {
|
||||
|
||||
std::vector<uint8_t> content = (*it_hash_section)->content();
|
||||
VectorStream hashtable_stream{content};
|
||||
|
||||
uint32_t nbucket = hashtable_stream.read_integer<uint32_t>(0);
|
||||
uint32_t nchain = hashtable_stream.read_integer<uint32_t>(0 + sizeof(uint32_t));
|
||||
hashtable_stream.setpos(0);
|
||||
uint32_t nbucket = hashtable_stream.read<uint32_t>();
|
||||
uint32_t nchain = hashtable_stream.read<uint32_t>();
|
||||
|
||||
|
||||
std::vector<uint8_t> new_hash_table((nbucket + nchain + 2) * sizeof(uint32_t), 0);
|
||||
|
@ -82,10 +82,10 @@ void Parser::init(const std::string& name) {
|
||||
this->binary_->name(name);
|
||||
this->binary_->datahandler_ = new DataHandler::Handler{this->stream_->content()};
|
||||
|
||||
uint32_t type = reinterpret_cast<const Elf32_Ehdr*>(
|
||||
this->stream_->read(0, sizeof(Elf32_Ehdr)))->e_ident[static_cast<size_t>(IDENTITY::EI_CLASS)];
|
||||
uint32_t type = this->stream_->peek<Elf32_Ehdr>(0).e_ident[static_cast<size_t>(IDENTITY::EI_CLASS)];
|
||||
|
||||
this->binary_->type_ = static_cast<ELF_CLASS>(type);
|
||||
this->type_ = static_cast<ELF_CLASS>(type);
|
||||
switch (this->binary_->type_) {
|
||||
case ELF_CLASS::ELFCLASS32:
|
||||
{
|
||||
@ -112,7 +112,8 @@ void Parser::init(const std::string& name) {
|
||||
|
||||
Binary* Parser::parse(const std::string& filename, DYNSYM_COUNT_METHODS count_mtd) {
|
||||
if (not is_elf(filename)) {
|
||||
throw LIEF::bad_format("'" + filename + "' is not an ELF");
|
||||
LOG(ERROR) << filename << " is not an ELF";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Parser parser{filename, count_mtd};
|
||||
@ -125,7 +126,8 @@ Binary* Parser::parse(
|
||||
DYNSYM_COUNT_METHODS count_mtd) {
|
||||
|
||||
if (not is_elf(data)) {
|
||||
throw LIEF::bad_format("'" + name + "' is not an ELF");
|
||||
LOG(ERROR) << "'" << name << "' is not an ELF";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Parser parser{data, name, count_mtd};
|
||||
@ -139,11 +141,13 @@ void Parser::parse_symbol_version(uint64_t symbol_version_offset) {
|
||||
VLOG(VDEBUG) << "Symbol version offset: 0x" << std::hex << symbol_version_offset << std::endl;
|
||||
|
||||
const uint32_t nb_entries = static_cast<uint32_t>(this->binary_->dynamic_symbols_.size());
|
||||
const uint16_t* array = reinterpret_cast<const uint16_t*>(
|
||||
this->stream_->read(symbol_version_offset, nb_entries * sizeof(uint16_t)));
|
||||
|
||||
this->stream_->setpos(symbol_version_offset);
|
||||
for (size_t i = 0; i < nb_entries; ++i) {
|
||||
this->binary_->symbol_version_table_.push_back(new SymbolVersion{array[i]});
|
||||
if (not this->stream_->can_read<uint16_t>()) {
|
||||
break;
|
||||
}
|
||||
this->binary_->symbol_version_table_.push_back(new SymbolVersion{this->stream_->read<uint16_t>()});
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,42 +162,47 @@ uint64_t Parser::get_dynamic_string_table_from_segments(void) const {
|
||||
return segment != nullptr and segment->type() == SEGMENT_TYPES::PT_DYNAMIC;
|
||||
});
|
||||
|
||||
if (it_segment_dynamic == std::end(this->binary_->segments_)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t va_offset = 0;
|
||||
if (it_segment_dynamic != std::end(this->binary_->segments_)) {
|
||||
uint64_t offset = (*it_segment_dynamic)->file_offset();
|
||||
uint64_t size = (*it_segment_dynamic)->physical_size();
|
||||
uint64_t offset = (*it_segment_dynamic)->file_offset();
|
||||
uint64_t size = (*it_segment_dynamic)->physical_size();
|
||||
|
||||
if (this->type_ == ELF_CLASS::ELFCLASS32) {
|
||||
this->stream_->setpos(offset);
|
||||
|
||||
size_t nb_entries = size / sizeof(Elf32_Dyn);
|
||||
const Elf32_Dyn* entries = reinterpret_cast<const Elf32_Dyn*>(
|
||||
this->stream_->read(offset, size));
|
||||
for (size_t i = 0; i < nb_entries; ++i) {
|
||||
if (static_cast<DYNAMIC_TAGS>(entries[i].d_tag) ==
|
||||
DYNAMIC_TAGS::DT_STRTAB) {
|
||||
va_offset = this->binary_->virtual_address_to_offset(entries[i].d_un.d_val);
|
||||
}
|
||||
if (this->binary_->type_ == ELF_CLASS::ELFCLASS32) {
|
||||
|
||||
size_t nb_entries = size / sizeof(Elf32_Dyn);
|
||||
|
||||
for (size_t i = 0; i < nb_entries; ++i) {
|
||||
if (not this->stream_->can_read<Elf32_Dyn>()) {
|
||||
return 0;
|
||||
}
|
||||
const Elf32_Dyn& e = this->stream_->read<Elf32_Dyn>();
|
||||
|
||||
} else {
|
||||
const Elf64_Dyn* entries = reinterpret_cast<const Elf64_Dyn*>(
|
||||
this->stream_->read(offset, size));
|
||||
size_t nb_entries = size / sizeof(Elf64_Dyn);
|
||||
for (size_t i = 0; i < nb_entries; ++i) {
|
||||
if (static_cast<DYNAMIC_TAGS>(entries[i].d_tag) ==
|
||||
DYNAMIC_TAGS::DT_STRTAB) {
|
||||
va_offset = this->binary_->virtual_address_to_offset(entries[i].d_un.d_val);
|
||||
}
|
||||
if (static_cast<DYNAMIC_TAGS>(e.d_tag) == DYNAMIC_TAGS::DT_STRTAB) {
|
||||
return this->binary_->virtual_address_to_offset(e.d_un.d_val);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
size_t nb_entries = size / sizeof(Elf64_Dyn);
|
||||
for (size_t i = 0; i < nb_entries; ++i) {
|
||||
|
||||
if (not this->stream_->can_read<Elf64_Dyn>()) {
|
||||
return 0;
|
||||
}
|
||||
const Elf64_Dyn& e = this->stream_->read<Elf64_Dyn>();
|
||||
|
||||
if (static_cast<DYNAMIC_TAGS>(e.d_tag) == DYNAMIC_TAGS::DT_STRTAB) {
|
||||
return this->binary_->virtual_address_to_offset(e.d_un.d_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (va_offset > 0) {
|
||||
return va_offset;
|
||||
} else {
|
||||
throw LIEF::conversion_error("Unable to convert VA to offset from segments");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t Parser::get_dynamic_string_table_from_sections(void) const {
|
||||
@ -212,21 +221,15 @@ uint64_t Parser::get_dynamic_string_table_from_sections(void) const {
|
||||
va_offset = (*it_dynamic_string_section)->file_offset();
|
||||
}
|
||||
|
||||
if (va_offset > 0) {
|
||||
return va_offset;
|
||||
} else {
|
||||
throw LIEF::conversion_error("Unable to convert VA to offset from sections");
|
||||
}
|
||||
|
||||
return va_offset;
|
||||
}
|
||||
|
||||
uint64_t Parser::get_dynamic_string_table(void) const {
|
||||
uint64_t offset = 0;
|
||||
try {
|
||||
offset = this->get_dynamic_string_table_from_segments();
|
||||
} catch (const LIEF::conversion_error&) {
|
||||
uint64_t offset = this->get_dynamic_string_table_from_segments();
|
||||
if (offset == 0) {
|
||||
offset = this->get_dynamic_string_table_from_sections();
|
||||
}
|
||||
CHECK_NE(offset, 0);
|
||||
return offset;
|
||||
}
|
||||
|
||||
@ -244,49 +247,38 @@ void Parser::parse_symbol_sysv_hash(uint64_t offset) {
|
||||
VLOG(VDEBUG) << "[+] Parse symbol SYSV hash";
|
||||
SysvHash sysvhash;
|
||||
|
||||
uint64_t current_offset = offset;
|
||||
this->stream_->setpos(offset);
|
||||
const uint32_t* header = this->stream_->read_array<uint32_t>(2);
|
||||
|
||||
const uint32_t* header = reinterpret_cast<const uint32_t*>(
|
||||
this->stream_->read(current_offset, 2 * sizeof(uint32_t)));
|
||||
|
||||
current_offset += 2 * sizeof(uint32_t);
|
||||
if (header == nullptr) {
|
||||
LOG(ERROR) << "Can't read SYSV Hash header";
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t nbuckets = std::min<uint32_t>(header[0], Parser::NB_MAX_BUCKETS);
|
||||
const uint32_t nchain = std::min<uint32_t>(header[1], Parser::NB_MAX_CHAINS);
|
||||
|
||||
try {
|
||||
std::vector<uint32_t> buckets(nbuckets);
|
||||
std::vector<uint32_t> buckets(nbuckets);
|
||||
|
||||
for (size_t i = 0; i < nbuckets; ++i) {
|
||||
buckets[i] = this->stream_->read_integer<uint32_t>(current_offset);
|
||||
current_offset += sizeof(uint32_t);
|
||||
for (size_t i = 0; i < nbuckets; ++i) {
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
break;
|
||||
}
|
||||
|
||||
sysvhash.buckets_ = std::move(buckets);
|
||||
}
|
||||
catch (const read_out_of_bound&) {
|
||||
throw corrupted("SYSV Hash, nbuckets corrupted");
|
||||
}
|
||||
catch (const std::bad_alloc&) {
|
||||
throw corrupted("SYSV Hash, nbuckets corrupted");
|
||||
buckets[i] = this->stream_->read<uint32_t>();
|
||||
}
|
||||
|
||||
try {
|
||||
std::vector<uint32_t> chains(nchain);
|
||||
sysvhash.buckets_ = std::move(buckets);
|
||||
|
||||
for (size_t i = 0; i < nchain; ++i) {
|
||||
chains[i] = this->stream_->read_integer<uint32_t>(current_offset);
|
||||
current_offset += sizeof(uint32_t);
|
||||
std::vector<uint32_t> chains(nchain);
|
||||
|
||||
for (size_t i = 0; i < nchain; ++i) {
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
break;
|
||||
}
|
||||
chains[i] = this->stream_->read<uint32_t>();
|
||||
}
|
||||
|
||||
sysvhash.chains_ = std::move(chains);
|
||||
}
|
||||
catch (const read_out_of_bound&) {
|
||||
throw corrupted("SYSV Hash, nchain corrupted");
|
||||
}
|
||||
catch (const std::bad_alloc&) {
|
||||
throw corrupted("SYSV Hash, nchain corrupted");
|
||||
}
|
||||
sysvhash.chains_ = std::move(chains);
|
||||
|
||||
this->binary_->sysv_hash_ = std::move(sysvhash);
|
||||
|
||||
@ -294,41 +286,46 @@ void Parser::parse_symbol_sysv_hash(uint64_t offset) {
|
||||
|
||||
void Parser::parse_notes(uint64_t offset, uint64_t size) {
|
||||
VLOG(VDEBUG) << "Parsing Note segment";
|
||||
uint64_t current_offset = offset;
|
||||
|
||||
this->stream_->setpos(offset);
|
||||
uint64_t last_offset = offset + size;
|
||||
|
||||
while(current_offset < last_offset) {
|
||||
uint32_t namesz = this->stream_->read_integer<uint32_t>(current_offset);
|
||||
current_offset += sizeof(uint32_t);
|
||||
while(this->stream_->pos() < last_offset) {
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
break;
|
||||
}
|
||||
uint32_t namesz = this->stream_->read<uint32_t>();
|
||||
VLOG(VDEBUG) << "Name size: " << std::hex << namesz;
|
||||
|
||||
uint32_t descsz = std::min(this->stream_->read_integer<uint32_t>(current_offset), Parser::MAX_NOTE_DESCRIPTION);
|
||||
|
||||
current_offset += sizeof(uint32_t);
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
break;
|
||||
}
|
||||
uint32_t descsz = std::min(this->stream_->read<uint32_t>(), Parser::MAX_NOTE_DESCRIPTION);
|
||||
|
||||
VLOG(VDEBUG) << "Description size: " << std::hex << descsz;
|
||||
|
||||
NOTE_TYPES type = static_cast<NOTE_TYPES>(this->stream_->read_integer<uint32_t>(current_offset));
|
||||
current_offset += sizeof(uint32_t);
|
||||
if (not this->stream_->can_read<uint32_t>()) {
|
||||
break;
|
||||
}
|
||||
NOTE_TYPES type = static_cast<NOTE_TYPES>(this->stream_->read<uint32_t>());
|
||||
VLOG(VDEBUG) << "Type: " << std::hex << static_cast<size_t>(type);
|
||||
|
||||
if (namesz == 0) { // System reserves
|
||||
break;
|
||||
}
|
||||
|
||||
std::string name = this->stream_->get_string(current_offset, namesz);
|
||||
std::string name = this->stream_->read_string(namesz);
|
||||
VLOG(VDEBUG) << "Name: " << name << std::endl;
|
||||
current_offset += namesz;
|
||||
current_offset = align(current_offset, sizeof(uint32_t));
|
||||
this->stream_->align(sizeof(uint32_t));
|
||||
|
||||
std::vector<uint8_t> description;
|
||||
if (descsz > 0) {
|
||||
const uint8_t* desc_ptr = reinterpret_cast<const uint8_t*>(
|
||||
this->stream_->read(current_offset, descsz));
|
||||
|
||||
description = {desc_ptr, desc_ptr + descsz};
|
||||
|
||||
current_offset += descsz;
|
||||
current_offset = align(current_offset, sizeof(uint32_t));
|
||||
const uint8_t* desc_ptr = this->stream_->read_array<uint8_t>(descsz);
|
||||
if (desc_ptr != nullptr) {
|
||||
description = {desc_ptr, desc_ptr + descsz};
|
||||
}
|
||||
this->stream_->align(sizeof(uint32_t));
|
||||
}
|
||||
std::unique_ptr<Note> note;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,8 @@
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
|
||||
#include "LIEF/ELF/Parser.hpp"
|
||||
|
||||
#include "LIEF/logging++.hpp"
|
||||
|
||||
#include "LIEF/ELF/hash.hpp"
|
||||
@ -246,16 +248,19 @@ void Section::offset(uint64_t offset) {
|
||||
|
||||
std::vector<uint8_t> Section::content(void) const {
|
||||
if (this->size() == 0) {
|
||||
VLOG(VDEBUG) << "Section '" << this->name() << "' is empty";
|
||||
//VLOG(VDEBUG) << "Section '" << this->name() << "' is empty";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (this->datahandler_ == nullptr) {
|
||||
VLOG(VDEBUG) << "Content from cache";
|
||||
//VLOG(VDEBUG) << "Content from cache";
|
||||
return this->content_c_;
|
||||
}
|
||||
|
||||
VLOG(VDEBUG) << std::hex << "Content from Data Handler [0x" << this->offset_ << ", 0x" << this->size_ << "]";
|
||||
//VLOG(VDEBUG) << std::hex << "Content from Data Handler [0x" << this->offset_ << ", 0x" << this->size_ << "]";
|
||||
if (this->size() > Parser::MAX_SECTION_SIZE) {
|
||||
return {};
|
||||
}
|
||||
|
||||
DataHandler::Node& node = this->datahandler_->get(this->offset(), this->size(), DataHandler::Node::SECTION);
|
||||
const std::vector<uint8_t>& binary_content = this->datahandler_->content();
|
||||
|
@ -90,8 +90,7 @@ BinaryParser::BinaryParser(const std::string& file, const ParserConfig& conf) :
|
||||
void BinaryParser::init(void) {
|
||||
VLOG(VDEBUG) << "Parsing MachO" << std::endl;
|
||||
try {
|
||||
MACHO_TYPES type = static_cast<MACHO_TYPES>(
|
||||
*reinterpret_cast<const uint32_t*>(this->stream_->read(0, sizeof(uint32_t))));
|
||||
MACHO_TYPES type = static_cast<MACHO_TYPES>(this->stream_->peek<uint32_t>(0));
|
||||
|
||||
if (type == MACHO_TYPES::MH_MAGIC_64 or
|
||||
type == MACHO_TYPES::MH_CIGAM_64 )
|
||||
@ -118,31 +117,23 @@ void BinaryParser::init(void) {
|
||||
}
|
||||
|
||||
|
||||
void BinaryParser::parse_export_trie(uint64_t start, uint64_t current_offset, uint64_t end, const std::string& prefix) {
|
||||
std::pair<uint64_t, uint64_t> value_delta = {0, 0};
|
||||
if (current_offset >= end) {
|
||||
void BinaryParser::parse_export_trie(uint64_t start, uint64_t end, const std::string& prefix) {
|
||||
if (this->stream_->pos() >= end) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (start > current_offset) {
|
||||
if (start > this->stream_->pos()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t terminal_size = this->stream_->read_integer<uint8_t>(current_offset);
|
||||
current_offset += sizeof(uint8_t);
|
||||
|
||||
uint64_t children_offset = current_offset + terminal_size;
|
||||
const uint8_t terminal_size = this->stream_->read<uint8_t>();
|
||||
uint64_t children_offset = this->stream_->pos() + terminal_size;
|
||||
|
||||
if (terminal_size != 0) {
|
||||
uint64_t offset = current_offset - start;
|
||||
uint64_t offset = this->stream_->pos() - start;
|
||||
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
uint64_t flags = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
uint64_t address = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
uint64_t flags = this->stream_->read_uleb128();
|
||||
uint64_t address = this->stream_->read_uleb128();
|
||||
|
||||
const std::string& symbol_name = prefix;
|
||||
std::unique_ptr<ExportInfo> export_info{new ExportInfo{address, flags, offset}};
|
||||
@ -167,22 +158,21 @@ void BinaryParser::parse_export_trie(uint64_t start, uint64_t current_offset, ui
|
||||
this->binary_->dyld_info().export_info_.push_back(export_info.release());
|
||||
|
||||
}
|
||||
|
||||
const uint8_t nb_children = this->stream_->read_integer<uint8_t>(children_offset);
|
||||
children_offset += sizeof(uint8_t);
|
||||
this->stream_->setpos(children_offset);
|
||||
const uint8_t nb_children = this->stream_->read<uint8_t>();
|
||||
for (size_t i = 0; i < nb_children; ++i) {
|
||||
std::string suffix = this->stream_->get_string(children_offset);
|
||||
std::string suffix = this->stream_->read_string();
|
||||
std::string name = prefix + suffix;
|
||||
|
||||
children_offset += suffix.size() + 1;
|
||||
uint32_t child_node_offet = static_cast<uint32_t>(this->stream_->read_uleb128());
|
||||
|
||||
value_delta = this->stream_->read_uleb128(children_offset);
|
||||
uint32_t child_node_offet = static_cast<uint32_t>(std::get<0>(value_delta));
|
||||
children_offset += std::get<1>(value_delta);
|
||||
if (start + child_node_offet == start) {
|
||||
if (child_node_offet == 0) {
|
||||
break;
|
||||
}
|
||||
this->parse_export_trie(start, start + child_node_offet, end, name);
|
||||
size_t current_pos = this->stream_->pos();
|
||||
this->stream_->setpos(start + child_node_offet);
|
||||
this->parse_export_trie(start, end, name);
|
||||
this->stream_->setpos(current_pos);
|
||||
}
|
||||
|
||||
}
|
||||
@ -198,17 +188,17 @@ void BinaryParser::parse_dyldinfo_export(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t current_offset = offset;
|
||||
uint64_t end_offset = offset + size;
|
||||
uint64_t end_offset = offset + size;
|
||||
|
||||
try {
|
||||
const uint8_t* raw_trie = reinterpret_cast<const uint8_t*>(this->stream_->read(offset, size));
|
||||
const uint8_t* raw_trie = this->stream_->peek_array<uint8_t>(offset, size);
|
||||
dyldinfo.export_trie({raw_trie, raw_trie + size});
|
||||
} catch (const exception& e) {
|
||||
LOG(WARNING) << e.what();
|
||||
}
|
||||
|
||||
this->parse_export_trie(offset, current_offset, end_offset, "");
|
||||
this->stream_->setpos(offset);
|
||||
this->parse_export_trie(offset, end_offset, "");
|
||||
}
|
||||
|
||||
Binary* BinaryParser::get_binary(void) {
|
||||
|
@ -71,7 +71,7 @@ void BinaryParser::parse(void) {
|
||||
template<class MACHO_T>
|
||||
void BinaryParser::parse_header(void) {
|
||||
using header_t = typename MACHO_T::header;
|
||||
this->binary_->header_ = {reinterpret_cast<const header_t*>(this->stream_->read(0, sizeof(header_t)))};
|
||||
this->binary_->header_ = &this->stream_->peek<header_t>(0);
|
||||
}
|
||||
|
||||
|
||||
@ -98,11 +98,13 @@ void BinaryParser::parse_load_commands(void) {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < nbcmds; ++i) {
|
||||
const load_command* command = reinterpret_cast<const load_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(load_command)));
|
||||
if (not this->stream_->can_read<load_command>(loadcommands_offset)) {
|
||||
break;
|
||||
}
|
||||
const load_command& command = this->stream_->peek<load_command>(loadcommands_offset);
|
||||
|
||||
std::unique_ptr<LoadCommand> load_command{nullptr};
|
||||
switch (static_cast<LOAD_COMMAND_TYPES>(command->cmd)) {
|
||||
switch (static_cast<LOAD_COMMAND_TYPES>(command.cmd)) {
|
||||
|
||||
// ===============
|
||||
// Segment command
|
||||
@ -111,16 +113,13 @@ void BinaryParser::parse_load_commands(void) {
|
||||
case LOAD_COMMAND_TYPES::LC_SEGMENT:
|
||||
{
|
||||
uint64_t local_offset = loadcommands_offset;
|
||||
load_command = std::unique_ptr<SegmentCommand>{new SegmentCommand{
|
||||
reinterpret_cast<const segment_command_t*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(segment_command_t)))}};
|
||||
load_command = std::unique_ptr<SegmentCommand>{new SegmentCommand{&this->stream_->peek<segment_command_t>(loadcommands_offset)}};
|
||||
|
||||
local_offset += sizeof(segment_command_t);
|
||||
|
||||
SegmentCommand* segment = dynamic_cast<SegmentCommand*>(load_command.get());
|
||||
|
||||
const uint8_t* content = static_cast<const uint8_t*>(
|
||||
this->stream_->read(segment->file_offset(), segment->file_size()));
|
||||
const uint8_t* content = this->stream_->peek_array<uint8_t>(segment->file_offset(), segment->file_size());
|
||||
|
||||
segment->content({
|
||||
content,
|
||||
@ -131,7 +130,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
// Sections
|
||||
// --------
|
||||
for (size_t j = 0; j < segment->numberof_sections(); ++j) {
|
||||
const section_t* section_header = reinterpret_cast<const section_t*>(this->stream_->read(local_offset, sizeof(section_t)));
|
||||
const section_t* section_header = &this->stream_->peek<section_t>(local_offset);
|
||||
std::unique_ptr<Section> section{new Section{section_header}};
|
||||
section->segment_ = segment;
|
||||
segment->sections_.push_back(section.release());
|
||||
@ -148,13 +147,11 @@ void BinaryParser::parse_load_commands(void) {
|
||||
case LOAD_COMMAND_TYPES::LC_ID_DYLIB:
|
||||
case LOAD_COMMAND_TYPES::LC_LOAD_DYLIB:
|
||||
{
|
||||
const dylib_command* cmd =
|
||||
reinterpret_cast<const dylib_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(dylib_command)));
|
||||
const dylib_command* cmd = &this->stream_->peek<dylib_command>(loadcommands_offset);
|
||||
|
||||
load_command = std::unique_ptr<DylibCommand>{new DylibCommand{cmd}};
|
||||
const uint32_t str_name_offset = cmd->dylib.name;
|
||||
std::string name = this->stream_->get_string(loadcommands_offset + str_name_offset);
|
||||
std::string name = this->stream_->peek_string_at(loadcommands_offset + str_name_offset);
|
||||
|
||||
dynamic_cast<DylibCommand*>(load_command.get())->name(name);
|
||||
break;
|
||||
@ -165,13 +162,11 @@ void BinaryParser::parse_load_commands(void) {
|
||||
// =============
|
||||
case LOAD_COMMAND_TYPES::LC_RPATH:
|
||||
{
|
||||
const rpath_command* cmd =
|
||||
reinterpret_cast<const rpath_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(rpath_command)));
|
||||
const rpath_command* cmd = &this->stream_->peek<rpath_command>(loadcommands_offset);
|
||||
|
||||
load_command = std::unique_ptr<RPathCommand>{new RPathCommand{cmd}};
|
||||
const uint32_t str_path_offset = cmd->path;
|
||||
std::string path = this->stream_->get_string(loadcommands_offset + str_path_offset);
|
||||
std::string path = this->stream_->peek_string_at(loadcommands_offset + str_path_offset);
|
||||
|
||||
dynamic_cast<RPathCommand*>(load_command.get())->path(path);
|
||||
break;
|
||||
@ -183,9 +178,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
case LOAD_COMMAND_TYPES::LC_UUID:
|
||||
{
|
||||
VLOG(VDEBUG) << "[+] Building UUID";
|
||||
const uuid_command* cmd =
|
||||
reinterpret_cast<const uuid_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(uuid_command)));
|
||||
const uuid_command* cmd = &this->stream_->peek<uuid_command>(loadcommands_offset);
|
||||
load_command = std::unique_ptr<UUIDCommand>{new UUIDCommand{cmd}};
|
||||
break;
|
||||
}
|
||||
@ -196,12 +189,10 @@ void BinaryParser::parse_load_commands(void) {
|
||||
case LOAD_COMMAND_TYPES::LC_LOAD_DYLINKER:
|
||||
case LOAD_COMMAND_TYPES::LC_ID_DYLINKER:
|
||||
{
|
||||
const dylinker_command* cmd =
|
||||
reinterpret_cast<const dylinker_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(dylinker_command)));
|
||||
const dylinker_command* cmd = &this->stream_->peek<dylinker_command>(loadcommands_offset);
|
||||
|
||||
const uint32_t linker_name_offset = cmd->name;
|
||||
std::string name = this->stream_->get_string(
|
||||
std::string name = this->stream_->peek_string_at(
|
||||
loadcommands_offset +
|
||||
linker_name_offset);
|
||||
|
||||
@ -217,13 +208,11 @@ void BinaryParser::parse_load_commands(void) {
|
||||
{
|
||||
VLOG(VDEBUG) << "[+] Parsing LC_PREBOUND_DYLIB";
|
||||
|
||||
load_command = std::unique_ptr<LoadCommand>{new LoadCommand{command}};
|
||||
const prebound_dylib_command* cmd =
|
||||
reinterpret_cast<const prebound_dylib_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(prebound_dylib_command)));
|
||||
load_command = std::unique_ptr<LoadCommand>{new LoadCommand{&command}};
|
||||
const prebound_dylib_command* cmd = &this->stream_->peek<prebound_dylib_command>(loadcommands_offset);
|
||||
|
||||
|
||||
std::string name = this->stream_->get_string(
|
||||
std::string name = this->stream_->peek_string_at(
|
||||
loadcommands_offset +
|
||||
cmd->name);
|
||||
|
||||
@ -240,9 +229,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
{
|
||||
VLOG(VDEBUG) << "[+] Parsing LC_THREAD";
|
||||
|
||||
const thread_command* cmd =
|
||||
reinterpret_cast<const thread_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(thread_command)));
|
||||
const thread_command* cmd = &this->stream_->peek<thread_command>(loadcommands_offset);
|
||||
load_command = std::unique_ptr<ThreadCommand>{new ThreadCommand{cmd}};
|
||||
|
||||
ThreadCommand* thread = dynamic_cast<ThreadCommand*>(load_command.get());
|
||||
@ -252,8 +239,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
switch(this->binary_->header().cpu_type()) {
|
||||
case CPU_TYPES::CPU_TYPE_X86:
|
||||
{
|
||||
const uint8_t* pstart = reinterpret_cast<const uint8_t*>(
|
||||
this->stream_->read(loadcommands_offset + sizeof(thread_command), sizeof(x86_thread_state_t)));
|
||||
const uint8_t* pstart = this->stream_->peek_array<uint8_t>(loadcommands_offset + sizeof(thread_command), sizeof(x86_thread_state_t));
|
||||
thread->state_ = {pstart, pstart + sizeof(x86_thread_state_t)};
|
||||
|
||||
break;
|
||||
@ -261,24 +247,21 @@ void BinaryParser::parse_load_commands(void) {
|
||||
|
||||
case CPU_TYPES::CPU_TYPE_X86_64:
|
||||
{
|
||||
const uint8_t* pstart = reinterpret_cast<const uint8_t*>(
|
||||
this->stream_->read(loadcommands_offset + sizeof(thread_command), sizeof(x86_thread_state64_t)));
|
||||
const uint8_t* pstart = this->stream_->peek_array<uint8_t>(loadcommands_offset + sizeof(thread_command), sizeof(x86_thread_state64_t));
|
||||
thread->state_ = {pstart, pstart + sizeof(x86_thread_state64_t)};
|
||||
break;
|
||||
}
|
||||
|
||||
case CPU_TYPES::CPU_TYPE_ARM:
|
||||
{
|
||||
const uint8_t* pstart = reinterpret_cast<const uint8_t*>(
|
||||
this->stream_->read(loadcommands_offset + sizeof(thread_command), sizeof(arm_thread_state_t)));
|
||||
const uint8_t* pstart = this->stream_->peek_array<uint8_t>(loadcommands_offset + sizeof(thread_command), sizeof(arm_thread_state_t));
|
||||
thread->state_ = {pstart, pstart + sizeof(arm_thread_state_t)};
|
||||
break;
|
||||
}
|
||||
|
||||
case CPU_TYPES::CPU_TYPE_ARM64:
|
||||
{
|
||||
const uint8_t* pstart = reinterpret_cast<const uint8_t*>(
|
||||
this->stream_->read(loadcommands_offset + sizeof(thread_command), sizeof(arm_thread_state64_t)));
|
||||
const uint8_t* pstart = this->stream_->peek_array<uint8_t>(loadcommands_offset + sizeof(thread_command), sizeof(arm_thread_state64_t));
|
||||
thread->state_ = {pstart, pstart + sizeof(arm_thread_state64_t)};
|
||||
break;
|
||||
}
|
||||
@ -299,7 +282,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
|
||||
VLOG(VDEBUG) << "[+] Parsing LC_ROUTINE";
|
||||
|
||||
load_command = std::unique_ptr<LoadCommand>{new LoadCommand{command}};
|
||||
load_command = std::unique_ptr<LoadCommand>{new LoadCommand{&command}};
|
||||
break;
|
||||
}
|
||||
|
||||
@ -311,23 +294,20 @@ void BinaryParser::parse_load_commands(void) {
|
||||
using nlist_t = typename MACHO_T::nlist;
|
||||
VLOG(VDEBUG) << "[+] Parsing symbols";
|
||||
|
||||
const symtab_command* cmd =
|
||||
reinterpret_cast<const symtab_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(symtab_command)));
|
||||
const symtab_command* cmd = &this->stream_->peek<symtab_command>(loadcommands_offset);
|
||||
|
||||
|
||||
load_command = std::unique_ptr<SymbolCommand>{new SymbolCommand{cmd}};
|
||||
|
||||
|
||||
const nlist_t* nlist = reinterpret_cast<const nlist_t*>(
|
||||
this->stream_->read(cmd->symoff, sizeof(nlist_t)));
|
||||
const nlist_t* nlist = this->stream_->peek_array<nlist_t>(cmd->symoff, cmd->nsyms);
|
||||
|
||||
for (size_t j = 0; j < cmd->nsyms; ++j) {
|
||||
std::unique_ptr<Symbol> symbol{new Symbol{&nlist[j]}};
|
||||
uint32_t idx = nlist[j].n_strx;
|
||||
if (idx > 0) {
|
||||
symbol->name(
|
||||
this->stream_->get_string(cmd->stroff + idx));
|
||||
this->stream_->peek_string_at(cmd->stroff + idx));
|
||||
}
|
||||
this->binary_->symbols_.push_back(symbol.release());
|
||||
}
|
||||
@ -341,9 +321,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
case LOAD_COMMAND_TYPES::LC_DYSYMTAB:
|
||||
{
|
||||
VLOG(VDEBUG) << "[+] Parsing dynamic symbols";
|
||||
const dysymtab_command* cmd =
|
||||
reinterpret_cast<const dysymtab_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(dysymtab_command)));
|
||||
const dysymtab_command* cmd = &this->stream_->peek<dysymtab_command>(loadcommands_offset);
|
||||
|
||||
load_command = std::unique_ptr<DynamicSymbolCommand>{new DynamicSymbolCommand{cmd}};
|
||||
break;
|
||||
@ -356,9 +334,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
case LOAD_COMMAND_TYPES::LC_DYLD_INFO_ONLY:
|
||||
{
|
||||
VLOG(VDEBUG) << "[+] Parsing dyld information";
|
||||
const dyld_info_command* cmd =
|
||||
reinterpret_cast<const dyld_info_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(dyld_info_command)));
|
||||
const dyld_info_command* cmd = &this->stream_->peek<dyld_info_command>(loadcommands_offset);
|
||||
|
||||
load_command = std::unique_ptr<DyldInfo>{new DyldInfo{cmd}};
|
||||
dynamic_cast<DyldInfo*>(load_command.get())->binary_ = this->binary_;
|
||||
@ -372,9 +348,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
{
|
||||
VLOG(VDEBUG) << "[+] Parsing LC_SOURCE_VERSION";
|
||||
|
||||
const source_version_command* cmd =
|
||||
reinterpret_cast<const source_version_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(version_min_command)));
|
||||
const source_version_command* cmd = &this->stream_->peek<source_version_command>(loadcommands_offset);
|
||||
|
||||
load_command = std::unique_ptr<SourceVersion>{new SourceVersion{cmd}};
|
||||
VLOG(VDEBUG) << "Version: " << std::hex << cmd->version;
|
||||
@ -384,11 +358,9 @@ void BinaryParser::parse_load_commands(void) {
|
||||
case LOAD_COMMAND_TYPES::LC_VERSION_MIN_MACOSX:
|
||||
case LOAD_COMMAND_TYPES::LC_VERSION_MIN_IPHONEOS:
|
||||
{
|
||||
VLOG(VDEBUG) << "[+] Parsing " << to_string(static_cast<LOAD_COMMAND_TYPES>(command->cmd));
|
||||
VLOG(VDEBUG) << "[+] Parsing " << to_string(static_cast<LOAD_COMMAND_TYPES>(command.cmd));
|
||||
|
||||
const version_min_command* cmd =
|
||||
reinterpret_cast<const version_min_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(version_min_command)));
|
||||
const version_min_command* cmd = &this->stream_->peek<version_min_command>(loadcommands_offset);
|
||||
VLOG(VDEBUG) << "Version: " << std::hex << cmd->version;
|
||||
VLOG(VDEBUG) << "SDK: " << std::hex << cmd->sdk;
|
||||
|
||||
@ -399,13 +371,11 @@ void BinaryParser::parse_load_commands(void) {
|
||||
case LOAD_COMMAND_TYPES::LC_CODE_SIGNATURE:
|
||||
{
|
||||
|
||||
const linkedit_data_command* cmd =
|
||||
reinterpret_cast<const linkedit_data_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(linkedit_data_command)));
|
||||
const linkedit_data_command* cmd = &this->stream_->peek<linkedit_data_command>(loadcommands_offset);
|
||||
load_command = std::unique_ptr<CodeSignature>{new CodeSignature{cmd}};
|
||||
CodeSignature* sig = load_command.get()->as<CodeSignature>();
|
||||
|
||||
const uint8_t* content = reinterpret_cast<const uint8_t*>(this->stream_->read(sig->data_offset(), sig->data_size()));
|
||||
const uint8_t* content = this->stream_->peek_array<uint8_t>(sig->data_offset(), sig->data_size());
|
||||
sig->raw_signature_ = {content, content + sig->data_size()};
|
||||
|
||||
break;
|
||||
@ -414,14 +384,12 @@ void BinaryParser::parse_load_commands(void) {
|
||||
case LOAD_COMMAND_TYPES::LC_DATA_IN_CODE:
|
||||
{
|
||||
|
||||
const linkedit_data_command* cmd =
|
||||
reinterpret_cast<const linkedit_data_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(linkedit_data_command)));
|
||||
const linkedit_data_command* cmd = &this->stream_->peek<linkedit_data_command>(loadcommands_offset);
|
||||
load_command = std::unique_ptr<DataInCode>{new DataInCode{cmd}};
|
||||
DataInCode* datacode = load_command.get()->as<DataInCode>();
|
||||
|
||||
const data_in_code_entry* entries = reinterpret_cast<const data_in_code_entry*>(this->stream_->read(datacode->data_offset(), datacode->data_size()));
|
||||
const size_t nb_entries = datacode->data_size() / sizeof(data_in_code_entry);
|
||||
const data_in_code_entry* entries = this->stream_->peek_array<data_in_code_entry>(datacode->data_offset(), nb_entries);
|
||||
for (size_t i = 0; i < nb_entries; ++i) {
|
||||
datacode->add(&entries[i]);
|
||||
}
|
||||
@ -478,9 +446,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
{
|
||||
VLOG(VDEBUG) << "[+] Parsing LC_MAIN";
|
||||
|
||||
const entry_point_command* cmd =
|
||||
reinterpret_cast<const entry_point_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(entry_point_command)));
|
||||
const entry_point_command* cmd = &this->stream_->peek<entry_point_command>(loadcommands_offset);
|
||||
|
||||
load_command = std::unique_ptr<MainCommand>{new MainCommand{cmd}};
|
||||
break;
|
||||
@ -492,26 +458,23 @@ void BinaryParser::parse_load_commands(void) {
|
||||
case LOAD_COMMAND_TYPES::LC_FUNCTION_STARTS:
|
||||
{
|
||||
VLOG(VDEBUG) << "[+] Parsing LC_FUNCTION_STARTS";
|
||||
const linkedit_data_command* cmd =
|
||||
reinterpret_cast<const linkedit_data_command*>(
|
||||
this->stream_->read(loadcommands_offset, sizeof(linkedit_data_command)));
|
||||
const linkedit_data_command* cmd = &this->stream_->peek<linkedit_data_command>(loadcommands_offset);
|
||||
load_command = std::unique_ptr<FunctionStarts>{new FunctionStarts{cmd}};
|
||||
|
||||
uint64_t offset = cmd->dataoff;
|
||||
std::pair<uint64_t, uint64_t> value_delta;
|
||||
uint64_t value = 0;
|
||||
FunctionStarts* fstart = dynamic_cast<FunctionStarts*>(load_command.get());
|
||||
this->stream_->setpos(cmd->dataoff);
|
||||
|
||||
do {
|
||||
value_delta = this->stream_->read_uleb128(offset);
|
||||
if (std::get<0>(value_delta) == 0) {
|
||||
uint64_t val = this->stream_->read_uleb128();
|
||||
if (val == 0) {
|
||||
break;
|
||||
}
|
||||
value += std::get<0>(value_delta);
|
||||
offset += std::get<1>(value_delta);
|
||||
value += val;
|
||||
|
||||
VLOG(VDEBUG) << "Value: " << std::hex << value;
|
||||
fstart->add_function(value);
|
||||
} while(offset < (cmd->dataoff + cmd->datasize) and std::get<0>(value_delta) > 0);
|
||||
} while(this->stream_->pos() < (cmd->dataoff + cmd->datasize));
|
||||
|
||||
break;
|
||||
}
|
||||
@ -525,26 +488,25 @@ void BinaryParser::parse_load_commands(void) {
|
||||
|
||||
default:
|
||||
{
|
||||
LOG(WARNING) << "Command '" << to_string(static_cast<LOAD_COMMAND_TYPES>(command->cmd))
|
||||
LOG(WARNING) << "Command '" << to_string(static_cast<LOAD_COMMAND_TYPES>(command.cmd))
|
||||
<< "' not parsed";
|
||||
|
||||
load_command = std::unique_ptr<LoadCommand>{new LoadCommand{command}};
|
||||
load_command = std::unique_ptr<LoadCommand>{new LoadCommand{&command}};
|
||||
}
|
||||
}
|
||||
|
||||
if (load_command != nullptr) {
|
||||
const uint8_t* content = static_cast<const uint8_t*>(
|
||||
this->stream_->read(loadcommands_offset, command->cmdsize));
|
||||
const uint8_t* content = this->stream_->peek_array<uint8_t>(loadcommands_offset, command.cmdsize);
|
||||
|
||||
load_command->data({
|
||||
content,
|
||||
content + command->cmdsize
|
||||
content + command.cmdsize
|
||||
});
|
||||
|
||||
load_command->command_offset(loadcommands_offset);
|
||||
this->binary_->commands_.push_back(load_command.release());
|
||||
}
|
||||
loadcommands_offset += command->cmdsize;
|
||||
loadcommands_offset += command.cmdsize;
|
||||
}
|
||||
}
|
||||
|
||||
@ -573,17 +535,15 @@ void BinaryParser::parse_relocations(Section& section) {
|
||||
|
||||
std::unique_ptr<RelocationObject> reloc{nullptr};
|
||||
for (size_t i = 0; i < numberof_relocations; ++i) {
|
||||
int32_t address = this->stream_->read_integer<int32_t>(current_reloc_offset);
|
||||
int32_t address = this->stream_->peek<int32_t>(current_reloc_offset);
|
||||
bool is_scattered = static_cast<bool>(address & R_SCATTERED);
|
||||
|
||||
if (is_scattered) {
|
||||
const scattered_relocation_info* reloc_info = reinterpret_cast<const scattered_relocation_info*>(
|
||||
this->stream_->read(current_reloc_offset, sizeof(scattered_relocation_info)));
|
||||
const scattered_relocation_info* reloc_info = &this->stream_->peek<scattered_relocation_info>(current_reloc_offset);
|
||||
reloc = std::unique_ptr<RelocationObject>{new RelocationObject{reloc_info}};
|
||||
reloc->section_ = §ion;
|
||||
} else {
|
||||
const relocation_info* reloc_info = reinterpret_cast<const relocation_info*>(
|
||||
this->stream_->read(current_reloc_offset, sizeof(relocation_info)));
|
||||
const relocation_info* reloc_info = &this->stream_->peek<relocation_info>(current_reloc_offset);
|
||||
reloc = std::unique_ptr<RelocationObject>{new RelocationObject{reloc_info}};
|
||||
reloc->section_ = §ion;
|
||||
|
||||
@ -640,13 +600,12 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
}
|
||||
|
||||
try {
|
||||
const uint8_t* raw_rebase = reinterpret_cast<const uint8_t*>(this->stream_->read(offset, size));
|
||||
const uint8_t* raw_rebase = this->stream_->peek_array<uint8_t>(offset, size);
|
||||
dyldinfo.rebase_opcodes({raw_rebase, raw_rebase + size});
|
||||
} catch (const exception& e) {
|
||||
LOG(WARNING) << e.what();
|
||||
}
|
||||
|
||||
uint64_t current_offset = offset;
|
||||
uint64_t end_offset = offset + size;
|
||||
|
||||
bool done = false;
|
||||
@ -655,12 +614,13 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
uint64_t segment_offset = 0;
|
||||
uint32_t count = 0;
|
||||
uint32_t skip = 0;
|
||||
std::pair<uint64_t, uint64_t> value_delta = {0, 0};
|
||||
|
||||
while (not done and current_offset < end_offset) {
|
||||
uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & REBASE_IMMEDIATE_MASK;
|
||||
uint8_t opcode = this->stream_->read_integer<uint8_t>(current_offset) & REBASE_OPCODE_MASK;
|
||||
current_offset += sizeof(uint8_t);
|
||||
this->stream_->setpos(offset);
|
||||
|
||||
while (not done and this->stream_->pos() < end_offset) {
|
||||
uint8_t imm = this->stream_->peek<uint8_t>() & REBASE_IMMEDIATE_MASK;
|
||||
uint8_t opcode = this->stream_->read<uint8_t>() & REBASE_OPCODE_MASK;
|
||||
|
||||
switch(static_cast<REBASE_OPCODES>(opcode)) {
|
||||
case REBASE_OPCODES::REBASE_OPCODE_DONE:
|
||||
{
|
||||
@ -676,23 +636,16 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
|
||||
case REBASE_OPCODES::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
|
||||
{
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
|
||||
segment_index = imm;
|
||||
segment_offset = std::get<0>(value_delta);
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
segment_offset = this->stream_->read_uleb128();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case REBASE_OPCODES::REBASE_OPCODE_ADD_ADDR_ULEB:
|
||||
{
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
segment_offset += this->stream_->read_uleb128();
|
||||
|
||||
segment_offset += std::get<0>(value_delta);
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -713,12 +666,7 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
case REBASE_OPCODES::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
|
||||
{
|
||||
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
|
||||
count = std::get<0>(value_delta);
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
|
||||
count = this->stream_->read_uleb128();
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
this->do_rebase<MACHO_T>(type, segment_index, segment_offset);
|
||||
segment_offset += sizeof(pint_t);
|
||||
@ -731,29 +679,19 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
|
||||
this->do_rebase<MACHO_T>(type, segment_index, segment_offset);
|
||||
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
segment_offset += this->stream_->read_uleb128() + sizeof(pint_t);
|
||||
|
||||
segment_offset += std::get<0>(value_delta) + sizeof(pint_t);
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
break;
|
||||
}
|
||||
|
||||
case REBASE_OPCODES::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
|
||||
{
|
||||
// Count
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
|
||||
count += std::get<0>(value_delta);
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
count += this->stream_->read_uleb128();
|
||||
|
||||
// Skip
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
skip += this->stream_->read_uleb128();
|
||||
|
||||
skip += std::get<0>(value_delta);
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
this->do_rebase<MACHO_T>(type, segment_index, segment_offset);
|
||||
@ -863,13 +801,12 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
}
|
||||
|
||||
try {
|
||||
const uint8_t* raw_binding = reinterpret_cast<const uint8_t*>(this->stream_->read(offset, size));
|
||||
const uint8_t* raw_binding = this->stream_->peek_array<uint8_t>(offset, size);
|
||||
dyldinfo.bind_opcodes({raw_binding, raw_binding + size});
|
||||
} catch (const exception& e) {
|
||||
LOG(WARNING) << e.what();
|
||||
}
|
||||
|
||||
uint64_t current_offset = offset;
|
||||
uint64_t end_offset = offset + size;
|
||||
|
||||
uint8_t type = 0;
|
||||
@ -885,14 +822,12 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
bool is_weak_import = false;
|
||||
bool done = false;
|
||||
|
||||
std::pair<uint64_t, uint64_t> value_delta = {0, 0};
|
||||
std::pair<int64_t, uint64_t> svalue_delta = {0, 0};
|
||||
|
||||
it_segments segments = this->binary_->segments();
|
||||
while (not done and current_offset < end_offset) {
|
||||
uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & BIND_IMMEDIATE_MASK;
|
||||
BIND_OPCODES opcode = static_cast<BIND_OPCODES>(this->stream_->read_integer<uint8_t>(current_offset) & BIND_OPCODE_MASK);
|
||||
current_offset += sizeof(uint8_t);
|
||||
this->stream_->setpos(offset);
|
||||
while (not done and this->stream_->pos() < end_offset) {
|
||||
uint8_t imm = this->stream_->peek<uint8_t>() & BIND_IMMEDIATE_MASK;
|
||||
BIND_OPCODES opcode = static_cast<BIND_OPCODES>(this->stream_->read<uint8_t>() & BIND_OPCODE_MASK);
|
||||
|
||||
switch (opcode) {
|
||||
case BIND_OPCODES::BIND_OPCODE_DONE:
|
||||
@ -910,9 +845,7 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
|
||||
{
|
||||
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
library_ordinal = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
library_ordinal = this->stream_->read_uleb128();
|
||||
|
||||
break;
|
||||
}
|
||||
@ -931,8 +864,7 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
||||
{
|
||||
symbol_name = this->stream_->get_string(current_offset);
|
||||
current_offset += symbol_name.size() + 1;
|
||||
symbol_name = this->stream_->read_string();
|
||||
|
||||
if ((imm & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) {
|
||||
is_weak_import = true;
|
||||
@ -950,28 +882,21 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_ADDEND_SLEB:
|
||||
{
|
||||
svalue_delta = this->stream_->read_sleb128(current_offset);
|
||||
addend = std::get<0>(svalue_delta);
|
||||
current_offset += std::get<1>(svalue_delta);
|
||||
addend = this->stream_->read_sleb128();
|
||||
break;
|
||||
}
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
|
||||
{
|
||||
segment_idx = imm;
|
||||
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
segment_offset = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
segment_idx = imm;
|
||||
segment_offset = this->stream_->read_uleb128();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_ADD_ADDR_ULEB:
|
||||
{
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
segment_offset += std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
segment_offset += this->stream_->read_uleb128();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1003,9 +928,7 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
addend,
|
||||
is_weak_import,
|
||||
segments);
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
segment_offset += std::get<0>(value_delta) + sizeof(pint_t);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
segment_offset += this->stream_->read_uleb128() + sizeof(pint_t);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1029,14 +952,10 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
{
|
||||
|
||||
// Count
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
count = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
count = this->stream_->read_uleb128();
|
||||
|
||||
// Skip
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
skip = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
skip = this->stream_->read_uleb128();
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
this->do_bind<MACHO_T>(
|
||||
@ -1080,13 +999,12 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
}
|
||||
|
||||
try {
|
||||
const uint8_t* raw_binding = reinterpret_cast<const uint8_t*>(this->stream_->read(offset, size));
|
||||
const uint8_t* raw_binding = this->stream_->peek_array<uint8_t>(offset, size);
|
||||
dyldinfo.weak_bind_opcodes({raw_binding, raw_binding + size});
|
||||
} catch (const exception& e) {
|
||||
LOG(WARNING) << e.what();
|
||||
}
|
||||
|
||||
uint64_t current_offset = offset;
|
||||
uint64_t end_offset = offset + size;
|
||||
|
||||
uint8_t type = 0;
|
||||
@ -1101,15 +1019,13 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
bool is_weak_import = true;
|
||||
bool done = false;
|
||||
|
||||
std::pair<uint64_t, uint64_t> value_delta = {0, 0};
|
||||
std::pair<int64_t, uint64_t> svalue_delta = {0, 0};
|
||||
|
||||
it_segments segments = this->binary_->segments();
|
||||
|
||||
while (not done and current_offset < end_offset) {
|
||||
uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & BIND_IMMEDIATE_MASK;
|
||||
BIND_OPCODES opcode = static_cast<BIND_OPCODES>(this->stream_->read_integer<uint8_t>(current_offset) & BIND_OPCODE_MASK);
|
||||
current_offset += sizeof(uint8_t);
|
||||
this->stream_->setpos(offset);
|
||||
|
||||
while (not done and this->stream_->pos() < end_offset) {
|
||||
uint8_t imm = this->stream_->peek<uint8_t>() & BIND_IMMEDIATE_MASK;
|
||||
BIND_OPCODES opcode = static_cast<BIND_OPCODES>(this->stream_->read<uint8_t>() & BIND_OPCODE_MASK);
|
||||
|
||||
switch (opcode) {
|
||||
case BIND_OPCODES::BIND_OPCODE_DONE:
|
||||
@ -1121,8 +1037,7 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
||||
{
|
||||
symbol_name = this->stream_->get_string(current_offset);
|
||||
current_offset += symbol_name.size() + 1;
|
||||
symbol_name = this->stream_->read_string();
|
||||
|
||||
if ((imm & BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) != 0) {
|
||||
// TODO: STRONG
|
||||
@ -1139,20 +1054,15 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_ADDEND_SLEB:
|
||||
{
|
||||
svalue_delta = this->stream_->read_sleb128(current_offset);
|
||||
addend = std::get<0>(svalue_delta);
|
||||
current_offset += std::get<1>(svalue_delta);
|
||||
addend = this->stream_->read_sleb128();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
|
||||
{
|
||||
segment_idx = imm;
|
||||
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
segment_offset = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
segment_idx = imm;
|
||||
segment_offset = this->stream_->read_uleb128();
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1160,9 +1070,7 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_ADD_ADDR_ULEB:
|
||||
{
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
segment_offset += std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
segment_offset += this->stream_->read_uleb128();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1196,9 +1104,7 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
addend,
|
||||
is_weak_import,
|
||||
segments);
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
segment_offset += std::get<0>(value_delta) + sizeof(pint_t);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
segment_offset += this->stream_->read_uleb128() + sizeof(pint_t);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1224,14 +1130,10 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
{
|
||||
|
||||
// Count
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
count = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
count = this->stream_->read_uleb128();
|
||||
|
||||
// Skip
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
skip = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
skip = this->stream_->read_uleb128();
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
this->do_bind<MACHO_T>(
|
||||
@ -1277,7 +1179,7 @@ void BinaryParser::parse_dyldinfo_lazy_bind() {
|
||||
}
|
||||
|
||||
try {
|
||||
const uint8_t* raw_binding = reinterpret_cast<const uint8_t*>(this->stream_->read(offset, size));
|
||||
const uint8_t* raw_binding = this->stream_->peek_array<uint8_t>(offset, size);
|
||||
dyldinfo.lazy_bind_opcodes({raw_binding, raw_binding + size});
|
||||
} catch (const exception& e) {
|
||||
LOG(WARNING) << e.what();
|
||||
@ -1286,7 +1188,7 @@ void BinaryParser::parse_dyldinfo_lazy_bind() {
|
||||
uint64_t current_offset = offset;
|
||||
uint64_t end_offset = offset + size;
|
||||
|
||||
uint32_t lazy_offset = 0;
|
||||
//uint32_t lazy_offset = 0;
|
||||
uint8_t segment_idx = 0;
|
||||
uint64_t segment_offset = 0;
|
||||
std::string symbol_name = "";
|
||||
@ -1294,20 +1196,17 @@ void BinaryParser::parse_dyldinfo_lazy_bind() {
|
||||
int64_t addend = 0;
|
||||
bool is_weak_import = false;
|
||||
|
||||
std::pair<uint64_t, uint64_t> value_delta = {0, 0};
|
||||
std::pair< int64_t, uint64_t> svalue_delta = {0, 0};
|
||||
|
||||
it_segments segments = this->binary_->segments();
|
||||
|
||||
while (current_offset < end_offset) {
|
||||
uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & BIND_IMMEDIATE_MASK;
|
||||
BIND_OPCODES opcode = static_cast<BIND_OPCODES>(this->stream_->read_integer<uint8_t>(current_offset) & BIND_OPCODE_MASK);
|
||||
this->stream_->setpos(offset);
|
||||
while (this->stream_->pos() < end_offset) {
|
||||
uint8_t imm = this->stream_->peek<uint8_t>() & BIND_IMMEDIATE_MASK;
|
||||
BIND_OPCODES opcode = static_cast<BIND_OPCODES>(this->stream_->read<uint8_t>() & BIND_OPCODE_MASK);
|
||||
current_offset += sizeof(uint8_t);
|
||||
|
||||
switch (opcode) {
|
||||
case BIND_OPCODES::BIND_OPCODE_DONE:
|
||||
{
|
||||
lazy_offset = current_offset - offset;
|
||||
//lazy_offset = current_offset - offset;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1319,11 +1218,7 @@ void BinaryParser::parse_dyldinfo_lazy_bind() {
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
|
||||
{
|
||||
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
library_ordinal = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
|
||||
library_ordinal = this->stream_->read_uleb128();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1341,8 +1236,7 @@ void BinaryParser::parse_dyldinfo_lazy_bind() {
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
||||
{
|
||||
symbol_name = this->stream_->get_string(current_offset);
|
||||
current_offset += symbol_name.size() + 1;
|
||||
symbol_name = this->stream_->read_string();
|
||||
|
||||
if ((imm & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) {
|
||||
is_weak_import = true;
|
||||
@ -1354,19 +1248,14 @@ void BinaryParser::parse_dyldinfo_lazy_bind() {
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_ADDEND_SLEB:
|
||||
{
|
||||
svalue_delta = this->stream_->read_sleb128(current_offset);
|
||||
addend = std::get<0>(svalue_delta);
|
||||
current_offset += std::get<1>(svalue_delta);
|
||||
addend = this->stream_->read_sleb128();;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
|
||||
{
|
||||
segment_idx = imm;
|
||||
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
segment_offset = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
segment_idx = imm;
|
||||
segment_offset = this->stream_->read_uleb128();
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -156,9 +156,6 @@ std::string DyldInfo::show_rebases_opcodes(void) const {
|
||||
std::ostringstream output;
|
||||
const buffer_t& rebase_opcodes = this->rebase_opcodes();
|
||||
|
||||
uint64_t current_offset = 0;
|
||||
uint64_t end_offset = rebase_opcodes.size();
|
||||
|
||||
bool done = false;
|
||||
uint8_t type = 0;
|
||||
uint32_t segment_index = 0;
|
||||
@ -166,15 +163,13 @@ std::string DyldInfo::show_rebases_opcodes(void) const {
|
||||
uint32_t count = 0;
|
||||
uint32_t skip = 0;
|
||||
VectorStream rebase_stream{rebase_opcodes};
|
||||
std::pair<uint64_t, uint64_t> value_delta = {0, 0};
|
||||
const std::string tab = " ";
|
||||
|
||||
it_segments segments = this->binary_->segments();
|
||||
|
||||
while (not done and current_offset < end_offset) {
|
||||
uint8_t imm = rebase_stream.read_integer<uint8_t>(current_offset) & REBASE_IMMEDIATE_MASK;
|
||||
uint8_t opcode = rebase_stream.read_integer<uint8_t>(current_offset) & REBASE_OPCODE_MASK;
|
||||
current_offset += sizeof(uint8_t);
|
||||
while (not done and rebase_stream.pos() < rebase_opcodes.size()) {
|
||||
uint8_t imm = rebase_stream.peek<uint8_t>() & REBASE_IMMEDIATE_MASK;
|
||||
uint8_t opcode = rebase_stream.read<uint8_t>() & REBASE_OPCODE_MASK;
|
||||
|
||||
switch(static_cast<REBASE_OPCODES>(opcode)) {
|
||||
case REBASE_OPCODES::REBASE_OPCODE_DONE:
|
||||
@ -195,12 +190,10 @@ std::string DyldInfo::show_rebases_opcodes(void) const {
|
||||
|
||||
case REBASE_OPCODES::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
|
||||
{
|
||||
value_delta = rebase_stream.read_uleb128(current_offset);
|
||||
|
||||
segment_index = imm;
|
||||
segment_offset = std::get<0>(value_delta);
|
||||
segment_offset = rebase_stream.read_uleb128();
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
|
||||
output << "[" << to_string(static_cast<REBASE_OPCODES>(opcode)) << "] ";
|
||||
output << "Segment Index := " << std::dec << segment_index << " (" << segments[segment_index].name() << ") ";
|
||||
@ -212,14 +205,12 @@ std::string DyldInfo::show_rebases_opcodes(void) const {
|
||||
|
||||
case REBASE_OPCODES::REBASE_OPCODE_ADD_ADDR_ULEB:
|
||||
{
|
||||
value_delta = rebase_stream.read_uleb128(current_offset);
|
||||
|
||||
segment_offset += std::get<0>(value_delta);
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
uint64_t val = rebase_stream.read_uleb128();
|
||||
segment_offset += val;
|
||||
|
||||
output << "[" << to_string(static_cast<REBASE_OPCODES>(opcode)) << "] ";
|
||||
output << "Segment Offset += " << std::hex << std::showbase << std::get<0>(value_delta) << " (" << segment_offset << ")";
|
||||
output << "Segment Offset += " << std::hex << std::showbase << val << " (" << segment_offset << ")";
|
||||
output << std::endl;
|
||||
break;
|
||||
}
|
||||
@ -260,12 +251,7 @@ std::string DyldInfo::show_rebases_opcodes(void) const {
|
||||
case REBASE_OPCODES::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
|
||||
{
|
||||
|
||||
value_delta = rebase_stream.read_uleb128(current_offset);
|
||||
|
||||
count = std::get<0>(value_delta);
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
|
||||
count = rebase_stream.read_uleb128();
|
||||
|
||||
output << "[" << to_string(static_cast<REBASE_OPCODES>(opcode)) << "]" << std::endl;
|
||||
|
||||
@ -305,14 +291,12 @@ std::string DyldInfo::show_rebases_opcodes(void) const {
|
||||
output << std::hex << std::showbase << segment_offset;
|
||||
output << ")" << std::endl;
|
||||
|
||||
value_delta = rebase_stream.read_uleb128(current_offset);
|
||||
uint64_t val = rebase_stream.read_uleb128();
|
||||
segment_offset += val + pint_v;
|
||||
|
||||
segment_offset += std::get<0>(value_delta) + pint_v;
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
|
||||
output << tab;
|
||||
output << "Segment Offset += " << std::hex << std::showbase << (std::get<0>(value_delta) + pint_v) << " (" << segment_offset << ")";
|
||||
output << "Segment Offset += " << std::hex << std::showbase << (val + pint_v) << " (" << segment_offset << ")";
|
||||
output << std::endl;
|
||||
|
||||
break;
|
||||
@ -324,18 +308,10 @@ std::string DyldInfo::show_rebases_opcodes(void) const {
|
||||
output << "[" << to_string(static_cast<REBASE_OPCODES>(opcode)) << "]" << std::endl;
|
||||
|
||||
// Count
|
||||
value_delta = rebase_stream.read_uleb128(current_offset);
|
||||
|
||||
count += std::get<0>(value_delta);
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
count += rebase_stream.read_uleb128();
|
||||
|
||||
// Skip
|
||||
value_delta = rebase_stream.read_uleb128(current_offset);
|
||||
|
||||
skip += std::get<0>(value_delta);
|
||||
|
||||
current_offset += std::get<1>(value_delta);
|
||||
skip += rebase_stream.read_uleb128();
|
||||
|
||||
output << tab << "for i in range(" << std::dec << static_cast<uint32_t>(count) << "):" << std::endl;
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
@ -411,9 +387,6 @@ void DyldInfo::show_bindings(std::ostream& output, const buffer_t& bind_opcodes,
|
||||
|
||||
size_t pint_v = static_cast<LIEF::Binary*>(this->binary_)->header().is_64() ? sizeof(uint64_t) : sizeof(uint32_t);
|
||||
|
||||
uint64_t current_offset = 0;
|
||||
uint64_t end_offset = bind_opcodes.size();
|
||||
|
||||
uint8_t type = is_lazy ? static_cast<uint8_t>(BIND_TYPES::BIND_TYPE_POINTER) : 0;
|
||||
uint8_t segment_idx = 0;
|
||||
uint64_t segment_offset = 0;
|
||||
@ -427,9 +400,6 @@ void DyldInfo::show_bindings(std::ostream& output, const buffer_t& bind_opcodes,
|
||||
bool is_weak_import = false;
|
||||
bool done = false;
|
||||
|
||||
std::pair<uint64_t, uint64_t> value_delta = {0, 0};
|
||||
std::pair<int64_t, uint64_t> svalue_delta = {0, 0};
|
||||
|
||||
it_segments segments = this->binary_->segments();
|
||||
it_libraries libraries = this->binary_->libraries();
|
||||
|
||||
@ -437,12 +407,9 @@ void DyldInfo::show_bindings(std::ostream& output, const buffer_t& bind_opcodes,
|
||||
|
||||
VectorStream bind_stream{bind_opcodes};
|
||||
|
||||
while (not done and current_offset < end_offset) {
|
||||
uint8_t imm = bind_stream.read_integer<uint8_t>(current_offset) & BIND_IMMEDIATE_MASK;
|
||||
BIND_OPCODES opcode = static_cast<BIND_OPCODES>(
|
||||
bind_stream.read_integer<uint8_t>(current_offset) & BIND_OPCODE_MASK);
|
||||
|
||||
current_offset += sizeof(uint8_t);
|
||||
while (not done and bind_stream.pos() < bind_opcodes.size()) {
|
||||
uint8_t imm = bind_stream.peek<uint8_t>() & BIND_IMMEDIATE_MASK;
|
||||
BIND_OPCODES opcode = static_cast<BIND_OPCODES>(bind_stream.read<uint8_t>() & BIND_OPCODE_MASK);
|
||||
|
||||
switch (opcode) {
|
||||
case BIND_OPCODES::BIND_OPCODE_DONE:
|
||||
@ -469,9 +436,7 @@ void DyldInfo::show_bindings(std::ostream& output, const buffer_t& bind_opcodes,
|
||||
|
||||
output << "[" << to_string(static_cast<BIND_OPCODES>(opcode)) << "]" << std::endl;
|
||||
|
||||
value_delta = bind_stream.read_uleb128(current_offset);
|
||||
library_ordinal = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
library_ordinal = bind_stream.read_uleb128();
|
||||
|
||||
output << tab << "Library Ordinal := " << std::dec << library_ordinal << std::endl;
|
||||
|
||||
@ -498,8 +463,7 @@ void DyldInfo::show_bindings(std::ostream& output, const buffer_t& bind_opcodes,
|
||||
{
|
||||
|
||||
output << "[" << to_string(static_cast<BIND_OPCODES>(opcode)) << "]" << std::endl;
|
||||
symbol_name = bind_stream.get_string(current_offset);
|
||||
current_offset += symbol_name.size() + 1;
|
||||
symbol_name = bind_stream.read_string();
|
||||
|
||||
if ((imm & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) {
|
||||
is_weak_import = true;
|
||||
@ -527,9 +491,7 @@ void DyldInfo::show_bindings(std::ostream& output, const buffer_t& bind_opcodes,
|
||||
{
|
||||
|
||||
output << "[" << to_string(static_cast<BIND_OPCODES>(opcode)) << "]" << std::endl;
|
||||
svalue_delta = bind_stream.read_sleb128(current_offset);
|
||||
addend = std::get<0>(svalue_delta);
|
||||
current_offset += std::get<1>(svalue_delta);
|
||||
addend = bind_stream.read_sleb128();
|
||||
|
||||
output << tab << "Addend := " << std::dec << addend << std::endl;
|
||||
break;
|
||||
@ -541,9 +503,7 @@ void DyldInfo::show_bindings(std::ostream& output, const buffer_t& bind_opcodes,
|
||||
output << "[" << to_string(static_cast<BIND_OPCODES>(opcode)) << "]" << std::endl;
|
||||
segment_idx = imm;
|
||||
|
||||
value_delta = bind_stream.read_uleb128(current_offset);
|
||||
segment_offset = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
segment_offset = bind_stream.read_uleb128();
|
||||
|
||||
output << tab << "Segment := " << segments[segment_idx].name() << std::endl;
|
||||
output << tab << "Segment Offset := " << std::hex << std::showbase << segment_offset << std::endl;
|
||||
@ -556,11 +516,10 @@ void DyldInfo::show_bindings(std::ostream& output, const buffer_t& bind_opcodes,
|
||||
|
||||
output << "[" << to_string(static_cast<BIND_OPCODES>(opcode)) << "]" << std::endl;
|
||||
|
||||
value_delta = bind_stream.read_uleb128(current_offset);
|
||||
segment_offset += std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
uint64_t val = bind_stream.read_uleb128();
|
||||
segment_offset += val;
|
||||
|
||||
output << tab << "Segment Offset += " << std::hex << std::showbase << std::get<0>(value_delta) << " (" << segment_offset << ")" << std::endl;
|
||||
output << tab << "Segment Offset += " << std::hex << std::showbase << val << " (" << segment_offset << ")" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -616,11 +575,10 @@ void DyldInfo::show_bindings(std::ostream& output, const buffer_t& bind_opcodes,
|
||||
output << std::boolalpha << is_weak_import;
|
||||
output << ")" << std::endl;
|
||||
|
||||
value_delta = bind_stream.read_uleb128(current_offset);
|
||||
segment_offset += std::get<0>(value_delta) + pint_v;
|
||||
current_offset += std::get<1>(value_delta);
|
||||
uint64_t v = bind_stream.read_uleb128();
|
||||
segment_offset += v + pint_v;
|
||||
|
||||
output << tab << "Segment Offset += " << std::hex << std::showbase << std::get<0>(value_delta) + pint_v << " (" << segment_offset << ")" << std::endl;
|
||||
output << tab << "Segment Offset += " << std::hex << std::showbase << v + pint_v << " (" << segment_offset << ")" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -658,14 +616,10 @@ void DyldInfo::show_bindings(std::ostream& output, const buffer_t& bind_opcodes,
|
||||
|
||||
output << "[" << to_string(static_cast<BIND_OPCODES>(opcode)) << "]" << std::endl;
|
||||
// Count
|
||||
value_delta = bind_stream.read_uleb128(current_offset);
|
||||
count = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
count = bind_stream.read_uleb128();
|
||||
|
||||
// Skip
|
||||
value_delta = bind_stream.read_uleb128(current_offset);
|
||||
skip = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
skip = bind_stream.read_uleb128();;
|
||||
|
||||
output << tab << "for i in range(" << std::dec << static_cast<uint32_t>(count) << "):" << std::endl;
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
@ -790,38 +744,30 @@ std::string DyldInfo::show_export_trie(void) const {
|
||||
|
||||
VectorStream stream{buffer};
|
||||
|
||||
this->show_trie(output, "", stream, 0, 0, end_offset, "");
|
||||
this->show_trie(output, "", stream, 0, end_offset, "");
|
||||
return output.str();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void DyldInfo::show_trie(std::ostream& output, std::string output_prefix, VectorStream& stream, uint64_t start, uint64_t current_offset, uint64_t end, const std::string& prefix) const {
|
||||
void DyldInfo::show_trie(std::ostream& output, std::string output_prefix, VectorStream& stream, uint64_t start, uint64_t end, const std::string& prefix) const {
|
||||
|
||||
std::pair<uint64_t, uint64_t> value_delta = {0, 0};
|
||||
if (current_offset >= end) {
|
||||
if (stream.pos() >= end) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (start > current_offset) {
|
||||
if (start > stream.pos()) {
|
||||
return;
|
||||
}
|
||||
const uint64_t saved_offset = current_offset;
|
||||
const uint8_t terminal_size = stream.read_integer<uint8_t>(current_offset);
|
||||
current_offset += sizeof(uint8_t);
|
||||
|
||||
uint64_t children_offset = current_offset + terminal_size;
|
||||
const uint8_t terminal_size = stream.read<uint8_t>();
|
||||
|
||||
uint64_t children_offset = stream.pos() + terminal_size;
|
||||
|
||||
if (terminal_size != 0) {
|
||||
uint64_t offset = current_offset - start;
|
||||
|
||||
value_delta = stream.read_uleb128(current_offset);
|
||||
uint64_t flags = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
|
||||
value_delta = stream.read_uleb128(current_offset);
|
||||
uint64_t address = std::get<0>(value_delta);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
uint64_t flags = stream.read_uleb128();
|
||||
uint64_t address = stream.read_uleb128();
|
||||
|
||||
const std::string& symbol_name = prefix;
|
||||
output << output_prefix;
|
||||
@ -838,25 +784,26 @@ void DyldInfo::show_trie(std::ostream& output, std::string output_prefix, Vector
|
||||
output << std::endl;
|
||||
|
||||
}
|
||||
|
||||
const uint8_t nb_children = stream.read_integer<uint8_t>(children_offset);
|
||||
children_offset += sizeof(uint8_t);
|
||||
stream.setpos(children_offset);
|
||||
const uint8_t nb_children = stream.read<uint8_t>();
|
||||
|
||||
output_prefix += " ";
|
||||
for (size_t i = 0; i < nb_children; ++i) {
|
||||
std::string suffix = stream.get_string(children_offset);
|
||||
std::string suffix = stream.read_string();
|
||||
std::string name = prefix + suffix;
|
||||
|
||||
children_offset += suffix.size() + 1;
|
||||
uint32_t child_node_offet = static_cast<uint32_t>(stream.read_uleb128());
|
||||
|
||||
value_delta = stream.read_uleb128(children_offset);
|
||||
uint32_t child_node_offet = static_cast<uint32_t>(std::get<0>(value_delta));
|
||||
children_offset += std::get<1>(value_delta);
|
||||
if (start + child_node_offet == start) {
|
||||
if (child_node_offet == 0) {
|
||||
break;
|
||||
}
|
||||
output << output_prefix << name << "@off." << std::hex << std::showbase << children_offset << std::endl;
|
||||
this->show_trie(output, output_prefix, stream, start, start + child_node_offet, end, name);
|
||||
|
||||
output << output_prefix << name << "@off." << std::hex << std::showbase << stream.pos() << std::endl;
|
||||
|
||||
size_t current_pos = stream.pos();
|
||||
stream.setpos(start + child_node_offet);
|
||||
this->show_trie(output, output_prefix, stream, start, end, name);
|
||||
stream.setpos(current_pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,8 +88,7 @@ FatBinary* Parser::parse(const std::vector<uint8_t>& data, const std::string& na
|
||||
|
||||
void Parser::build_fat(void) {
|
||||
|
||||
const fat_header *header = reinterpret_cast<const fat_header*>(
|
||||
this->stream_->read(0, sizeof(fat_header)));
|
||||
const fat_header *header = &this->stream_->peek<fat_header>(0);
|
||||
uint32_t nb_arch = Swap4Bytes(header->nfat_arch);
|
||||
VLOG(VDEBUG) << "In this Fat binary there is " << std::dec << nb_arch << " archs" << std::endl;
|
||||
|
||||
@ -97,8 +96,7 @@ void Parser::build_fat(void) {
|
||||
throw parser_error("Too much architectures");
|
||||
}
|
||||
|
||||
const fat_arch* arch = reinterpret_cast<const fat_arch*>(
|
||||
this->stream_->read(sizeof(fat_header), sizeof(fat_arch)));
|
||||
const fat_arch* arch = &this->stream_->peek<fat_arch>(sizeof(fat_header));
|
||||
|
||||
for (size_t i = 0; i < nb_arch; ++i) {
|
||||
|
||||
@ -109,8 +107,7 @@ void Parser::build_fat(void) {
|
||||
VLOG(VDEBUG) << "[" << std::dec << i << "] offset: 0x" << std::hex << offset << std::endl;
|
||||
VLOG(VDEBUG) << "[" << std::dec << i << "] size: 0x" << std::hex << size << std::endl;
|
||||
|
||||
const uint8_t* raw = reinterpret_cast<const uint8_t*>(
|
||||
this->stream_->read(offset, size));
|
||||
const uint8_t* raw = this->stream_->peek_array<uint8_t>(offset, size);
|
||||
|
||||
std::vector<uint8_t> data = {raw, raw + size};
|
||||
|
||||
@ -121,8 +118,7 @@ void Parser::build_fat(void) {
|
||||
|
||||
void Parser::build(void) {
|
||||
try {
|
||||
MACHO_TYPES type = static_cast<MACHO_TYPES>(
|
||||
*reinterpret_cast<const uint32_t*>(this->stream_->read(0, sizeof(uint32_t))));
|
||||
MACHO_TYPES type = static_cast<MACHO_TYPES>(this->stream_->peek<uint32_t>(0));
|
||||
|
||||
// Fat binary
|
||||
if (type == MACHO_TYPES::FAT_MAGIC or
|
||||
|
@ -767,7 +767,8 @@ uint32_t Binary::predict_function_rva(const std::string& library, const std::str
|
||||
});
|
||||
|
||||
if (it_import == std::end(this->imports_)) {
|
||||
throw not_found("Unable to find library '" + library + "'");
|
||||
LOG(ERROR) << "Unable to find library '" << library << "'";
|
||||
return 0;
|
||||
}
|
||||
|
||||
it_const_import_entries entries = it_import->entries();
|
||||
@ -782,11 +783,13 @@ uint32_t Binary::predict_function_rva(const std::string& library, const std::str
|
||||
});
|
||||
|
||||
if (nb_functions == 0) {
|
||||
throw not_found("Unable to find the function '" + function + "' in '" + library + "'.");
|
||||
LOG(ERROR) << "Unable to find the function '" << function << "' in '" << library + "'.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nb_functions > 1) {
|
||||
throw not_supported("'" + function + "' is defined " + std::to_string(nb_functions) + " in '" + library + "'.");
|
||||
LOG(ERROR) << "'" << function << "' is defined " << std::to_string(nb_functions) << " in '" << library << "'.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t import_table_size = static_cast<uint32_t>((this->imports().size() + 1) * sizeof(pe_import)); // +1 for the null entry
|
||||
@ -878,11 +881,7 @@ Export& Binary::get_export(void) {
|
||||
|
||||
|
||||
const Export& Binary::get_export(void) const {
|
||||
if (this->has_exports()) {
|
||||
return this->export_;
|
||||
} else {
|
||||
throw not_found("The binary doesn't have exports");
|
||||
}
|
||||
return this->export_;
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
@ -892,14 +891,12 @@ const Export& Binary::get_export(void) const {
|
||||
/////////////////////////////////////
|
||||
|
||||
void Binary::set_resources(const ResourceDirectory& resource) {
|
||||
// TODO: DELETE !!!!!!!!!
|
||||
delete this->resources_;
|
||||
this->resources_ = new ResourceDirectory{resource};
|
||||
}
|
||||
|
||||
|
||||
void Binary::set_resources(const ResourceData& resource) {
|
||||
// TODO: DELETE !!!!!!!!!
|
||||
delete this->resources_;
|
||||
this->resources_ = new ResourceData{resource};
|
||||
}
|
||||
@ -947,9 +944,6 @@ const Debug& Binary::debug(void) const {
|
||||
/////////////////////
|
||||
|
||||
const Signature& Binary::signature(void) const {
|
||||
if (not this->has_signature()) {
|
||||
throw not_found("Signature not found");
|
||||
}
|
||||
return this->signature_;
|
||||
}
|
||||
|
||||
@ -1045,7 +1039,7 @@ void Binary::hook_function(const std::string& function, uint64_t address) {
|
||||
}
|
||||
}
|
||||
|
||||
throw not_found("Unable to find library associated with function '" + function + "'");
|
||||
LOG(WARNING) << "Unable to find library associated with function '" << function << "'";
|
||||
}
|
||||
|
||||
|
||||
@ -1083,7 +1077,8 @@ void Binary::patch_address(uint64_t address, const std::vector<uint8_t>& patch_v
|
||||
|
||||
void Binary::patch_address(uint64_t address, uint64_t patch_value, size_t size, LIEF::Binary::VA_TYPES addr_type) {
|
||||
if (size > sizeof(patch_value)) {
|
||||
throw std::runtime_error("Invalid size (" + std::to_string(size) + ")");
|
||||
LOG(ERROR) << "Invalid size (" << std::to_string(size) << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t rva = address;
|
||||
@ -1171,9 +1166,6 @@ RichHeader& Binary::rich_header(void) {
|
||||
}
|
||||
|
||||
const RichHeader& Binary::rich_header(void) const {
|
||||
if (not this->has_rich_header()) {
|
||||
throw not_found("Rich Header not found");
|
||||
}
|
||||
return this->rich_header_;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,21 +24,15 @@ namespace PE {
|
||||
template<typename PE_T>
|
||||
void Parser::parse(void) {
|
||||
|
||||
try {
|
||||
this->parse_headers<PE_T>();
|
||||
} catch (const corrupted& e) {
|
||||
LOG(WARNING) << e.what();
|
||||
if (not this->parse_headers<PE_T>()) {
|
||||
return;
|
||||
}
|
||||
|
||||
VLOG(VDEBUG) << "[+] Retreive Dos stub";
|
||||
|
||||
this->parse_dos_stub();
|
||||
|
||||
try {
|
||||
this->parse_rich_header();
|
||||
} catch (const corrupted& e) {
|
||||
LOG(WARNING) << e.what();
|
||||
}
|
||||
this->parse_rich_header();
|
||||
|
||||
VLOG(VDEBUG) << "[+] Decomposing Sections";
|
||||
|
||||
@ -65,38 +59,37 @@ void Parser::parse(void) {
|
||||
}
|
||||
|
||||
template<typename PE_T>
|
||||
void Parser::parse_headers(void) {
|
||||
bool Parser::parse_headers(void) {
|
||||
using pe_optional_header = typename PE_T::pe_optional_header;
|
||||
|
||||
//DOS Header
|
||||
try {
|
||||
this->binary_->dos_header_ = {reinterpret_cast<const pe_dos_header*>(
|
||||
this->stream_->read(0, sizeof(pe_dos_header)))};
|
||||
|
||||
} catch (const read_out_of_bound&) {
|
||||
throw corrupted("Dos Header corrupted");
|
||||
if (this->stream_->can_read<pe_dos_header>(0)) {
|
||||
this->binary_->dos_header_ = &this->stream_->peek<pe_dos_header>(0);
|
||||
} else {
|
||||
LOG(FATAL) << "Dos Header corrupted";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//PE32 Header
|
||||
try {
|
||||
this->binary_->header_ = {reinterpret_cast<const pe_header*>(
|
||||
this->stream_->read(
|
||||
this->binary_->dos_header().addressof_new_exeheader(),
|
||||
sizeof(pe_header)))};
|
||||
} catch (const read_out_of_bound&) {
|
||||
throw corrupted("PE32 Header corrupted");
|
||||
const size_t pe32_header_off = this->binary_->dos_header().addressof_new_exeheader();
|
||||
if (this->stream_->can_read<pe_header>(pe32_header_off)) {
|
||||
this->binary_->header_ = &this->stream_->peek<pe_header>(pe32_header_off);
|
||||
} else {
|
||||
LOG(FATAL) << "PE32 Header corrupted";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Optional Header
|
||||
try {
|
||||
this->binary_->optional_header_ = {reinterpret_cast<const pe_optional_header*>(
|
||||
this->stream_->read(
|
||||
this->binary_->dos_header().addressof_new_exeheader() + sizeof(pe_header),
|
||||
sizeof(pe_optional_header)))};
|
||||
} catch (const read_out_of_bound&) {
|
||||
throw corrupted("Optional header corrupted");
|
||||
const size_t optional_header_off = this->binary_->dos_header().addressof_new_exeheader() + sizeof(pe_header);
|
||||
if (this->stream_->can_read<pe_optional_header>(optional_header_off)) {
|
||||
this->binary_->optional_header_ = &this->stream_->peek<pe_optional_header>(optional_header_off);
|
||||
} else {
|
||||
LOG(FATAL) << "Optional header corrupted";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename PE_T>
|
||||
@ -105,28 +98,25 @@ void Parser::parse_data_directories(void) {
|
||||
|
||||
VLOG(VDEBUG) << "[+] Parsing data directories";
|
||||
|
||||
const uint32_t dirOffset =
|
||||
const uint32_t directories_offset =
|
||||
this->binary_->dos_header().addressof_new_exeheader() +
|
||||
sizeof(pe_header) +
|
||||
sizeof(pe_optional_header);
|
||||
const uint32_t nbof_datadir = static_cast<uint32_t>(DATA_DIRECTORY::NUM_DATA_DIRECTORIES);
|
||||
|
||||
const pe_data_directory* dataDirectory = [&] () {
|
||||
try {
|
||||
return reinterpret_cast<const pe_data_directory*>(
|
||||
this->stream_->read(dirOffset, nbof_datadir * sizeof(pe_data_directory)));
|
||||
} catch (const read_out_of_bound&) {
|
||||
throw corrupted("Data directories corrupted");
|
||||
}
|
||||
}();
|
||||
const pe_data_directory* data_directory = this->stream_->peek_array<pe_data_directory>(directories_offset, nbof_datadir);
|
||||
if (data_directory == nullptr) {
|
||||
LOG(ERROR) << "Data Directories corrupted!";
|
||||
return;
|
||||
}
|
||||
|
||||
this->binary_->data_directories_.reserve(nbof_datadir);
|
||||
for (size_t i = 0; i < nbof_datadir; ++i) {
|
||||
std::unique_ptr<DataDirectory> directory{new DataDirectory{&dataDirectory[i], static_cast<DATA_DIRECTORY>(i)}};
|
||||
std::unique_ptr<DataDirectory> directory{new DataDirectory{&data_directory[i], static_cast<DATA_DIRECTORY>(i)}};
|
||||
|
||||
VLOG(VDEBUG) << "Processing directory: " << to_string(static_cast<DATA_DIRECTORY>(i));
|
||||
VLOG(VDEBUG) << "- RVA: 0x" << std::hex << dataDirectory[i].RelativeVirtualAddress;
|
||||
VLOG(VDEBUG) << "- Size: 0x" << std::hex << dataDirectory[i].Size;
|
||||
VLOG(VDEBUG) << "- RVA: 0x" << std::hex << data_directory[i].RelativeVirtualAddress;
|
||||
VLOG(VDEBUG) << "- Size: 0x" << std::hex << data_directory[i].Size;
|
||||
if (directory->RVA() > 0) {
|
||||
// Data directory is not always associated with section
|
||||
const uint64_t offset = this->binary_->rva_to_offset(directory->RVA());
|
||||
@ -273,25 +263,31 @@ template<typename PE_T>
|
||||
void Parser::parse_import_table(void) {
|
||||
using uint__ = typename PE_T::uint;
|
||||
|
||||
this->binary_->has_imports_ = true;
|
||||
|
||||
const uint32_t import_rva = this->binary_->data_directory(DATA_DIRECTORY::IMPORT_TABLE).RVA();
|
||||
const uint64_t offset = this->binary_->rva_to_offset(import_rva);
|
||||
const uint32_t import_rva = this->binary_->data_directory(DATA_DIRECTORY::IMPORT_TABLE).RVA();
|
||||
const uint64_t import_offset = this->binary_->rva_to_offset(import_rva);
|
||||
|
||||
const pe_import* header = reinterpret_cast<const pe_import*>(
|
||||
this->stream_->read(offset, sizeof(pe_import)));
|
||||
if (not this->stream_->can_read<pe_import>(import_offset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (header->ImportAddressTableRVA != 0) {
|
||||
Import import = {header};
|
||||
|
||||
this->stream_->setpos(import_offset);
|
||||
while (this->stream_->can_read<pe_import>()) {
|
||||
pe_import header = this->stream_->read<pe_import>();
|
||||
Import import = &header;
|
||||
import.directory_ = &(this->binary_->data_directory(DATA_DIRECTORY::IMPORT_TABLE));
|
||||
import.iat_directory_ = &(this->binary_->data_directory(DATA_DIRECTORY::IAT));
|
||||
import.type_ = this->type_;
|
||||
|
||||
if (import.name_RVA_ == 0) {
|
||||
throw parser_error("Name's RVA is null");
|
||||
LOG(ERROR) << "Name's RVA is null";
|
||||
break;
|
||||
}
|
||||
|
||||
// Offset to the Import (Library) name
|
||||
const uint64_t offsetName = this->binary_->rva_to_offset(import.name_RVA_);
|
||||
import.name_ = this->stream_->get_string(offsetName);
|
||||
import.name_ = this->stream_->peek_string_at(offsetName);
|
||||
|
||||
|
||||
// We assume that a DLL name should be at least 4 length size and "printable
|
||||
@ -301,71 +297,71 @@ void Parser::parse_import_table(void) {
|
||||
std::end(import.name()),
|
||||
std::bind(std::isprint<char>, std::placeholders::_1, std::locale("C"))))
|
||||
{
|
||||
header++;
|
||||
continue; // skip
|
||||
}
|
||||
|
||||
// Offset to import lookup table
|
||||
uint64_t LT_offset = 0;
|
||||
uint64_t LT_offset = 0;
|
||||
if (import.import_lookup_table_RVA_ > 0) {
|
||||
LT_offset = this->binary_->rva_to_offset(import.import_lookup_table_RVA_);
|
||||
}
|
||||
|
||||
// Offset to the import address table
|
||||
uint64_t IAT_offset = 0;
|
||||
uint64_t IAT_offset = 0;
|
||||
if (import.import_address_table_RVA_ > 0) {
|
||||
IAT_offset = this->binary_->rva_to_offset(import.import_address_table_RVA_);
|
||||
}
|
||||
|
||||
const uint__ *lookupTable = nullptr, *IAT = nullptr, *table = nullptr;
|
||||
uint__ IAT = 0, table = 0;
|
||||
|
||||
if (IAT_offset > 0) {
|
||||
try {
|
||||
IAT = reinterpret_cast<const uint__*>(
|
||||
this->stream_->read(IAT_offset, sizeof(uint__)));
|
||||
table = IAT;
|
||||
} catch (const LIEF::exception&) {
|
||||
}
|
||||
if (IAT_offset > 0 and this->stream_->can_read<uint__>(IAT_offset)) {
|
||||
IAT = this->stream_->peek<uint__>(IAT_offset);
|
||||
table = IAT;
|
||||
IAT_offset += sizeof(uint__);
|
||||
}
|
||||
|
||||
if (LT_offset > 0) {
|
||||
try {
|
||||
lookupTable = reinterpret_cast<const uint__*>(
|
||||
this->stream_->read(LT_offset, sizeof(uint__)));
|
||||
|
||||
table = lookupTable;
|
||||
} catch (const LIEF::exception&) {
|
||||
}
|
||||
|
||||
if (LT_offset > 0 and this->stream_->can_read<uint__>(LT_offset)) {
|
||||
table = this->stream_->peek<uint__>(LT_offset);;
|
||||
LT_offset += sizeof(uint__);
|
||||
}
|
||||
|
||||
size_t idx = 0;
|
||||
while (table != nullptr and *table != 0) {
|
||||
while (table != 0) {
|
||||
ImportEntry entry;
|
||||
entry.iat_value_ = IAT != nullptr ? *(IAT++) : 0;
|
||||
entry.data_ = *table;
|
||||
entry.iat_value_ = IAT;
|
||||
entry.data_ = table;
|
||||
entry.type_ = this->type_;
|
||||
entry.rva_ = import.import_address_table_RVA_ + sizeof(uint__) * (idx++);
|
||||
|
||||
if(not entry.is_ordinal()) {
|
||||
|
||||
entry.name_ = this->stream_->get_string(
|
||||
this->binary_->rva_to_offset(entry.hint_name_rva()) + sizeof(uint16_t));
|
||||
|
||||
entry.hint_ = *reinterpret_cast<const uint16_t*>(
|
||||
this->stream_->read(
|
||||
this->binary_->rva_to_offset(entry.hint_name_rva()),
|
||||
sizeof(uint16_t)));
|
||||
const size_t hint_off = this->binary_->rva_to_offset(entry.hint_name_rva());
|
||||
const size_t name_off = hint_off + sizeof(uint16_t);
|
||||
entry.name_ = this->stream_->peek_string_at(name_off);
|
||||
if (this->stream_->can_read<uint16_t>(hint_off)) {
|
||||
entry.hint_ = this->stream_->peek<uint16_t>(hint_off);
|
||||
}
|
||||
}
|
||||
|
||||
import.entries_.push_back(std::move(entry));
|
||||
|
||||
table++;
|
||||
if (IAT_offset > 0 and this->stream_->can_read<uint__>(IAT_offset)) {
|
||||
IAT = this->stream_->peek<uint__>(IAT_offset);
|
||||
IAT_offset += sizeof(uint__);
|
||||
} else {
|
||||
IAT = 0;
|
||||
}
|
||||
|
||||
if (LT_offset > 0 and this->stream_->can_read<uint__>(LT_offset)) {
|
||||
table = this->stream_->peek<uint__>(LT_offset);
|
||||
LT_offset += sizeof(uint__);
|
||||
} else {
|
||||
table = 0;
|
||||
}
|
||||
}
|
||||
this->binary_->imports_.push_back(std::move(import));
|
||||
header++;
|
||||
}
|
||||
|
||||
this->binary_->has_imports_ = this->binary_->imports_.size() > 0;
|
||||
}
|
||||
|
||||
template<typename PE_T>
|
||||
@ -375,58 +371,59 @@ void Parser::parse_tls(void) {
|
||||
|
||||
VLOG(VDEBUG) << "[+] Parsing TLS";
|
||||
|
||||
this->binary_->has_tls_ = true;
|
||||
|
||||
const uint32_t tls_rva = this->binary_->data_directory(DATA_DIRECTORY::TLS_TABLE).RVA();
|
||||
const uint64_t offset = this->binary_->rva_to_offset(tls_rva);
|
||||
|
||||
const pe_tls *tls_header = reinterpret_cast<const pe_tls*>(
|
||||
this->stream_->read(offset, sizeof(pe_tls)));
|
||||
this->stream_->setpos(offset);
|
||||
if (not this->stream_->can_read<pe_tls>()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pe_tls& tls_header = this->stream_->read<pe_tls>();
|
||||
|
||||
this->binary_->tls_ = {tls_header};
|
||||
TLS& tls = this->binary_->tls_;
|
||||
tls = &tls_header;
|
||||
|
||||
const uint64_t imagebase = this->binary_->optional_header().imagebase();
|
||||
|
||||
|
||||
if (tls_header->RawDataStartVA > 0 and tls_header->RawDataEndVA > tls_header->RawDataStartVA) {
|
||||
const uint64_t start_data_rva = tls_header->RawDataStartVA - imagebase;
|
||||
const uint64_t stop_data_rva = tls_header->RawDataEndVA - imagebase;
|
||||
if (tls_header.RawDataStartVA >= imagebase and tls_header.RawDataEndVA > tls_header.RawDataStartVA) {
|
||||
CHECK(tls_header.RawDataStartVA >= imagebase);
|
||||
CHECK(tls_header.RawDataEndVA >= imagebase);
|
||||
const uint64_t start_data_rva = tls_header.RawDataStartVA - imagebase;
|
||||
const uint64_t stop_data_rva = tls_header.RawDataEndVA - imagebase;
|
||||
|
||||
const uint__ start_template_offset = this->binary_->rva_to_offset(start_data_rva);
|
||||
const uint__ end_template_offset = this->binary_->rva_to_offset(stop_data_rva);
|
||||
|
||||
const size_t size_to_read = end_template_offset - start_template_offset;
|
||||
|
||||
try {
|
||||
if (size_to_read > Parser::MAX_DATA_SIZE) {
|
||||
LOG(WARNING) << "TLS's template is too large!";
|
||||
if (size_to_read > Parser::MAX_DATA_SIZE) {
|
||||
LOG(WARNING) << "TLS's template is too large!";
|
||||
} else {
|
||||
const uint8_t* template_ptr = this->stream_->peek_array<uint8_t>(start_template_offset, size_to_read);
|
||||
if (template_ptr == nullptr) {
|
||||
LOG(WARNING) << "TLS's template corrupted";
|
||||
} else {
|
||||
const uint8_t* template_ptr = reinterpret_cast<const uint8_t*>(
|
||||
this->stream_->read(start_template_offset, size_to_read));
|
||||
std::vector<uint8_t> template_data = {
|
||||
template_ptr,
|
||||
template_ptr + size_to_read
|
||||
};
|
||||
tls.data_template(std::move(template_data));
|
||||
tls.data_template({
|
||||
template_ptr,
|
||||
template_ptr + size_to_read
|
||||
});
|
||||
}
|
||||
|
||||
} catch (const read_out_of_bound&) {
|
||||
LOG(WARNING) << "TLS corrupted (data template)";
|
||||
} catch (const std::bad_alloc&) {
|
||||
LOG(WARNING) << "TLS corrupted (data template)";
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t callbacks_offset = this->binary_->rva_to_offset(tls.addressof_callbacks() - imagebase);
|
||||
uint__ callback_rva = this->stream_->read_integer<uint__>(callbacks_offset);
|
||||
callbacks_offset += sizeof(uint__);
|
||||
|
||||
size_t count = 0;
|
||||
while (static_cast<uint32_t>(callback_rva) > 0 and count < Parser::MAX_TLS_CALLBACKS) {
|
||||
tls.callbacks_.push_back(static_cast<uint64_t>(callback_rva));
|
||||
callback_rva = this->stream_->read_integer<uint__>(callbacks_offset);
|
||||
callbacks_offset += sizeof(uint__);
|
||||
if (tls.addressof_callbacks() > imagebase) {
|
||||
uint64_t callbacks_offset = this->binary_->rva_to_offset(tls.addressof_callbacks() - imagebase);
|
||||
this->stream_->setpos(callbacks_offset);
|
||||
size_t count = 0;
|
||||
while (this->stream_->can_read<uint__>() and count++ < Parser::MAX_TLS_CALLBACKS) {
|
||||
uint__ callback_rva = this->stream_->read<uint__>();
|
||||
if (static_cast<uint32_t>(callback_rva) == 0) {
|
||||
break;
|
||||
}
|
||||
tls.callbacks_.push_back(callback_rva);
|
||||
}
|
||||
}
|
||||
|
||||
tls.directory_ = &(this->binary_->data_directory(DATA_DIRECTORY::TLS_TABLE));
|
||||
@ -437,6 +434,8 @@ void Parser::parse_tls(void) {
|
||||
} catch (const not_found&) {
|
||||
LOG(WARNING) << "No section associated with TLS";
|
||||
}
|
||||
|
||||
this->binary_->has_tls_ = true;
|
||||
}
|
||||
|
||||
|
||||
@ -459,7 +458,10 @@ void Parser::parse_load_config(void) {
|
||||
const uint32_t ldc_rva = this->binary_->data_directory(DATA_DIRECTORY::LOAD_CONFIG_TABLE).RVA();
|
||||
const uint64_t offset = this->binary_->rva_to_offset(ldc_rva);
|
||||
|
||||
const uint32_t size_from_header = this->stream_->read_integer<uint32_t>(offset);
|
||||
if (not this->stream_->can_read<uint32_t>(offset)) {
|
||||
return;
|
||||
}
|
||||
const uint32_t size_from_header = this->stream_->peek<uint32_t>(offset);
|
||||
|
||||
if (directory_size != size_from_header) {
|
||||
LOG(WARNING) << "The size of directory '" << to_string(DATA_DIRECTORY::LOAD_CONFIG_TABLE)
|
||||
@ -481,93 +483,110 @@ void Parser::parse_load_config(void) {
|
||||
|
||||
case WIN_VERSION::WIN_SEH:
|
||||
{
|
||||
if (not this->stream_->can_read<load_configuration_v0_t>(offset)) {
|
||||
break;
|
||||
}
|
||||
|
||||
const load_configuration_v0_t* header = reinterpret_cast<const load_configuration_v0_t*>(
|
||||
this->stream_->read(offset, sizeof(load_configuration_v0_t)));
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV0>{new LoadConfigurationV0{header}};
|
||||
const load_configuration_v0_t& header = this->stream_->peek<load_configuration_v0_t>(offset);
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV0>{new LoadConfigurationV0{&header}};
|
||||
break;
|
||||
}
|
||||
|
||||
case WIN_VERSION::WIN8_1:
|
||||
{
|
||||
|
||||
const load_configuration_v1_t* header = reinterpret_cast<const load_configuration_v1_t*>(
|
||||
this->stream_->read(offset, sizeof(load_configuration_v1_t)));
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV1>{new LoadConfigurationV1{header}};
|
||||
if (not this->stream_->can_read<load_configuration_v1_t>(offset)) {
|
||||
break;
|
||||
}
|
||||
const load_configuration_v1_t& header = this->stream_->peek<load_configuration_v1_t>(offset);
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV1>{new LoadConfigurationV1{&header}};
|
||||
break;
|
||||
}
|
||||
|
||||
case WIN_VERSION::WIN10_0_9879:
|
||||
{
|
||||
|
||||
const load_configuration_v2_t* header = reinterpret_cast<const load_configuration_v2_t*>(
|
||||
this->stream_->read(offset, sizeof(load_configuration_v2_t)));
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV2>{new LoadConfigurationV2{header}};
|
||||
if (not this->stream_->can_read<load_configuration_v2_t>(offset)) {
|
||||
break;
|
||||
}
|
||||
const load_configuration_v2_t& header = this->stream_->peek<load_configuration_v2_t>(offset);
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV2>{new LoadConfigurationV2{&header}};
|
||||
break;
|
||||
}
|
||||
|
||||
case WIN_VERSION::WIN10_0_14286:
|
||||
{
|
||||
|
||||
const load_configuration_v3_t* header = reinterpret_cast<const load_configuration_v3_t*>(
|
||||
this->stream_->read(offset, sizeof(load_configuration_v3_t)));
|
||||
if (not this->stream_->can_read<load_configuration_v3_t>(offset)) {
|
||||
break;
|
||||
}
|
||||
const load_configuration_v3_t& header = this->stream_->peek<load_configuration_v3_t>(offset);
|
||||
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV3>{new LoadConfigurationV3{header}};
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV3>{new LoadConfigurationV3{&header}};
|
||||
break;
|
||||
}
|
||||
|
||||
case WIN_VERSION::WIN10_0_14383:
|
||||
{
|
||||
|
||||
const load_configuration_v4_t* header = reinterpret_cast<const load_configuration_v4_t*>(
|
||||
this->stream_->read(offset, sizeof(load_configuration_v4_t)));
|
||||
if (not this->stream_->can_read<load_configuration_v4_t>(offset)) {
|
||||
break;
|
||||
}
|
||||
const load_configuration_v4_t& header = this->stream_->peek<load_configuration_v4_t>(offset);
|
||||
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV4>{new LoadConfigurationV4{header}};
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV4>{new LoadConfigurationV4{&header}};
|
||||
break;
|
||||
}
|
||||
|
||||
case WIN_VERSION::WIN10_0_14901:
|
||||
{
|
||||
|
||||
const load_configuration_v5_t* header = reinterpret_cast<const load_configuration_v5_t*>(
|
||||
this->stream_->read(offset, sizeof(load_configuration_v5_t)));
|
||||
if (not this->stream_->can_read<load_configuration_v5_t>(offset)) {
|
||||
break;
|
||||
}
|
||||
const load_configuration_v5_t& header = this->stream_->peek<load_configuration_v5_t>(offset);
|
||||
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV5>{new LoadConfigurationV5{header}};
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV5>{new LoadConfigurationV5{&header}};
|
||||
break;
|
||||
}
|
||||
|
||||
case WIN_VERSION::WIN10_0_15002:
|
||||
{
|
||||
|
||||
const load_configuration_v6_t* header = reinterpret_cast<const load_configuration_v6_t*>(
|
||||
this->stream_->read(offset, sizeof(load_configuration_v6_t)));
|
||||
if (not this->stream_->can_read<load_configuration_v6_t>(offset)) {
|
||||
break;
|
||||
}
|
||||
const load_configuration_v6_t& header = this->stream_->peek<load_configuration_v6_t>(offset);
|
||||
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV6>{new LoadConfigurationV6{header}};
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV6>{new LoadConfigurationV6{&header}};
|
||||
break;
|
||||
}
|
||||
|
||||
case WIN_VERSION::WIN10_0_16237:
|
||||
{
|
||||
|
||||
const load_configuration_v7_t* header = reinterpret_cast<const load_configuration_v7_t*>(
|
||||
this->stream_->read(offset, sizeof(load_configuration_v7_t)));
|
||||
if (not this->stream_->can_read<load_configuration_v7_t>(offset)) {
|
||||
break;
|
||||
}
|
||||
const load_configuration_v7_t& header = this->stream_->peek<load_configuration_v7_t>(offset);
|
||||
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV7>{new LoadConfigurationV7{header}};
|
||||
ld_conf = std::unique_ptr<LoadConfigurationV7>{new LoadConfigurationV7{&header}};
|
||||
break;
|
||||
}
|
||||
|
||||
case WIN_VERSION::WIN_UNKNOWN:
|
||||
default:
|
||||
{
|
||||
|
||||
const load_configuration_t* header = reinterpret_cast<const load_configuration_t*>(
|
||||
this->stream_->read(offset, sizeof(load_configuration_t)));
|
||||
ld_conf = std::unique_ptr<LoadConfiguration>{new LoadConfiguration{header}};
|
||||
if (not this->stream_->can_read<load_configuration_t>(offset)) {
|
||||
break;
|
||||
}
|
||||
const load_configuration_t& header = this->stream_->peek<load_configuration_t>(offset);
|
||||
ld_conf = std::unique_ptr<LoadConfiguration>{new LoadConfiguration{&header}};
|
||||
}
|
||||
}
|
||||
|
||||
this->binary_->has_configuration_ = static_cast<bool>(ld_conf);
|
||||
this->binary_->load_configuration_ = ld_conf.release();
|
||||
this->binary_->has_configuration_ = true;
|
||||
|
||||
|
||||
|
||||
|
@ -401,23 +401,19 @@ ResourceVersion ResourcesManager::version(void) const {
|
||||
VectorStream stream{content};
|
||||
ResourceVersion version;
|
||||
|
||||
uint64_t offset = 0;
|
||||
|
||||
stream.setpos(0);
|
||||
// Size of the current "struct"
|
||||
const uint16_t length = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint16_t);
|
||||
const uint16_t length = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Lenght of the struct: 0x" << std::hex << length;
|
||||
|
||||
// Size of the fixed file info struct
|
||||
const uint16_t value_length = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint16_t);
|
||||
const uint16_t value_length = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Size of the 'FixedFileInfo' struct" << std::hex << value_length;
|
||||
|
||||
// Type of the data in the version resource
|
||||
// 1: Text data
|
||||
// 0: Binary data
|
||||
const uint16_t type = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint16_t);
|
||||
const uint16_t type = stream.read<uint16_t>();
|
||||
version.type_ = type;
|
||||
if (type != 0 and type != 1) {
|
||||
LOG(WARNING) << "\"type\" of the resource version should be equal to 0 or 1 (" << std::dec << type << ")";
|
||||
@ -425,18 +421,17 @@ ResourceVersion ResourcesManager::version(void) const {
|
||||
|
||||
|
||||
// Magic key: VS_VERSION_INFO
|
||||
std::u16string key = {reinterpret_cast<const char16_t*>(content.data() + offset)};
|
||||
if (u16tou8(key) != "VS_VERSION_INFO") {
|
||||
std::u16string key = stream.read_u16string();
|
||||
if (u16tou8(key, true) != "VS_VERSION_INFO") {
|
||||
LOG(WARNING) << "\"key\" of the resource version should be equal to 'VS_VERSION_INFO' (" << u16tou8(key) << ")";
|
||||
}
|
||||
|
||||
version.key_ = key;
|
||||
offset += (key.size() + 1) * sizeof(char16_t);
|
||||
offset = align(offset, sizeof(uint32_t));
|
||||
stream.align(sizeof(uint32_t));
|
||||
|
||||
if (value_length > 0) {
|
||||
if (value_length == sizeof(pe_resource_fixed_file_info)) {
|
||||
const pe_resource_fixed_file_info* fixed_file_info_header = reinterpret_cast<const pe_resource_fixed_file_info*>(stream.read(offset, sizeof(pe_resource_fixed_file_info)));
|
||||
const pe_resource_fixed_file_info* fixed_file_info_header = &stream.peek<pe_resource_fixed_file_info>();
|
||||
if (fixed_file_info_header->signature != 0xFEEF04BD) {
|
||||
LOG(WARNING) << "Bad magic value for the Fixed file info structure";
|
||||
} else {
|
||||
@ -446,42 +441,41 @@ ResourceVersion ResourcesManager::version(void) const {
|
||||
} else {
|
||||
LOG(WARNING) << "The 'value' member contains an unknown structure";
|
||||
}
|
||||
|
||||
offset += value_length * sizeof(uint8_t);
|
||||
stream.increment_pos(value_length * sizeof(uint8_t));
|
||||
}
|
||||
offset = align(offset, sizeof(uint32_t));
|
||||
stream.align(sizeof(uint32_t));
|
||||
|
||||
|
||||
{ // First entry
|
||||
VLOG(VDEBUG) << "Parsing first entry";
|
||||
const uint16_t struct_file_info_length = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
uint64_t local_offset = offset;
|
||||
const uint16_t struct_file_info_length = stream.peek<uint16_t>();
|
||||
VLOG(VDEBUG) << "Length: " << std::hex << struct_file_info_length;
|
||||
if (struct_file_info_length > 0) {
|
||||
local_offset += sizeof(uint16_t);
|
||||
|
||||
const uint16_t struct_length = *reinterpret_cast<const uint16_t*>(stream.read(local_offset, sizeof(uint16_t)));
|
||||
local_offset += sizeof(uint16_t);
|
||||
const size_t start = stream.pos();
|
||||
|
||||
if (struct_file_info_length > 0) {
|
||||
stream.increment_pos(sizeof(uint16_t));
|
||||
|
||||
const uint16_t struct_length = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Lenght of the struct: 0x" << std::hex << struct_length;
|
||||
|
||||
const uint16_t type = *reinterpret_cast<const uint16_t*>(stream.read(local_offset, sizeof(uint16_t)));
|
||||
local_offset += sizeof(uint16_t);
|
||||
const uint16_t type = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Type of the struct: " << std::dec << type;
|
||||
|
||||
std::u16string key = {reinterpret_cast<const char16_t*>(content.data() + local_offset)};
|
||||
std::u16string key = stream.read_u16string();
|
||||
VLOG(VDEBUG) << "First entry (key) " << u16tou8(key);
|
||||
if (u16tou8(key) == "StringFileInfo") {
|
||||
if (u16tou8(key, true) == "StringFileInfo") {
|
||||
try {
|
||||
version.string_file_info_ = this->get_string_file_info(stream, offset);
|
||||
version.string_file_info_ = this->get_string_file_info(stream, type, key, start, struct_file_info_length);
|
||||
version.has_string_file_info_ = true;
|
||||
} catch (const LIEF::exception& e) {
|
||||
LOG(ERROR) << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
if (u16tou8(key) == "VarFileInfo") {
|
||||
if (u16tou8(key, true) == "VarFileInfo") {
|
||||
try {
|
||||
version.var_file_info_ = this->get_var_file_info(stream, offset);
|
||||
version.var_file_info_ = this->get_var_file_info(stream, type, key, start, struct_file_info_length);
|
||||
version.has_var_file_info_ = true;
|
||||
} catch (const LIEF::exception& e) {
|
||||
LOG(ERROR) << e.what();
|
||||
@ -494,36 +488,36 @@ ResourceVersion ResourcesManager::version(void) const {
|
||||
{ // Second entry
|
||||
|
||||
VLOG(VDEBUG) << "Parsing second entry";
|
||||
const uint16_t struct_file_info_length = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
uint64_t local_offset = offset;
|
||||
const uint16_t struct_file_info_length = stream.peek<uint16_t>();
|
||||
VLOG(VDEBUG) << "Length: " << std::hex << struct_file_info_length;
|
||||
|
||||
if (struct_file_info_length > 0) {
|
||||
local_offset += sizeof(uint16_t);
|
||||
const size_t start = stream.pos();
|
||||
|
||||
const uint16_t struct_length = *reinterpret_cast<const uint16_t*>(stream.read(local_offset, sizeof(uint16_t)));
|
||||
local_offset += sizeof(uint16_t);
|
||||
if (struct_file_info_length > 0) {
|
||||
stream.increment_pos(sizeof(uint16_t));
|
||||
|
||||
const uint16_t struct_length = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Lenght of the struct: 0x" << std::hex << struct_length;
|
||||
|
||||
const uint16_t type = *reinterpret_cast<const uint16_t*>(stream.read(local_offset, sizeof(uint16_t)));
|
||||
local_offset += sizeof(uint16_t);
|
||||
const uint16_t type = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Type of the struct: " << std::dec << type;
|
||||
|
||||
std::u16string key = {reinterpret_cast<const char16_t*>(content.data() + local_offset)};
|
||||
std::u16string key = stream.read_u16string();
|
||||
stream.align(sizeof(uint32_t));
|
||||
|
||||
VLOG(VDEBUG) << "Second entry (key) " << u16tou8(key);
|
||||
if (u16tou8(key) == "StringFileInfo") {
|
||||
if (u16tou8(key, true) == "StringFileInfo") {
|
||||
try {
|
||||
version.string_file_info_ = this->get_string_file_info(stream, offset);
|
||||
version.string_file_info_ = this->get_string_file_info(stream, type, key, start, struct_file_info_length);
|
||||
version.has_string_file_info_ = true;
|
||||
} catch (const LIEF::exception& e) {
|
||||
LOG(ERROR) << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
if (u16tou8(key) == "VarFileInfo") {
|
||||
if (u16tou8(key, true) == "VarFileInfo") {
|
||||
try {
|
||||
version.var_file_info_ = this->get_var_file_info(stream, offset);
|
||||
version.var_file_info_ = this->get_var_file_info(stream, type, key, start, struct_file_info_length);
|
||||
version.has_var_file_info_ = true;
|
||||
} catch (const LIEF::exception& e) {
|
||||
LOG(ERROR) << e.what();
|
||||
@ -536,186 +530,129 @@ ResourceVersion ResourcesManager::version(void) const {
|
||||
}
|
||||
|
||||
|
||||
ResourceStringFileInfo ResourcesManager::get_string_file_info(const VectorStream& stream, uint64_t& offset) const {
|
||||
ResourceStringFileInfo ResourcesManager::get_string_file_info(const VectorStream& stream, uint16_t type, std::u16string key, size_t start, size_t struct_length) const {
|
||||
VLOG(VDEBUG) << "Getting StringFileInfo object";
|
||||
|
||||
// String File Info
|
||||
// ================
|
||||
ResourceStringFileInfo string_file_info;
|
||||
const uint16_t string_file_info_length = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
uint64_t str_local_offset = offset;
|
||||
if (string_file_info_length > 0) {
|
||||
str_local_offset += sizeof(uint16_t);
|
||||
|
||||
const uint16_t value_length = *reinterpret_cast<const uint16_t*>(stream.read(str_local_offset, sizeof(uint16_t)));
|
||||
str_local_offset += sizeof(uint16_t);
|
||||
VLOG(VDEBUG) << "Value length: " << std::dec << value_length << " (should be 0)";
|
||||
string_file_info.type_ = type;
|
||||
string_file_info.key_ = key;
|
||||
|
||||
const uint16_t type = *reinterpret_cast<const uint16_t*>(stream.read(str_local_offset, sizeof(uint16_t)));
|
||||
VLOG(VDEBUG) << "Type: " << std::dec << type;
|
||||
|
||||
str_local_offset += sizeof(uint16_t);
|
||||
string_file_info.type_ = type;
|
||||
// Parse 'StringTable' childs
|
||||
// ==========================
|
||||
VLOG(VDEBUG) << "Parsing 'StringTable' struct";
|
||||
const size_t end_string_stable = start + struct_length * sizeof(uint8_t);
|
||||
|
||||
std::u16string key = {reinterpret_cast<const char16_t*>(stream.content().data() + str_local_offset)};
|
||||
if (u16tou8(key) != "StringFileInfo") {
|
||||
LOG(WARNING) << "\"key\" of the resource version should be equal to 'StringFileInfo' (" << u16tou8(key) << ")";
|
||||
while (stream.pos() < end_string_stable) {
|
||||
LangCodeItem lang_code_item;
|
||||
const uint16_t stringtable_length = stream.peek<uint16_t>();
|
||||
|
||||
// End of the structure including childs
|
||||
const uint64_t end_offset = stream.pos() + stringtable_length * sizeof(uint8_t);
|
||||
stream.increment_pos(sizeof(uint16_t));
|
||||
|
||||
const uint16_t stringtable_value_length = stream.read<uint16_t>();
|
||||
|
||||
VLOG(VDEBUG) << "Value length: " << std::dec << stringtable_value_length << " (should be 0)";
|
||||
|
||||
const uint16_t stringtable_type = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Type: " << std::dec << stringtable_type;
|
||||
|
||||
// 1: Text data
|
||||
// 0: Binary data
|
||||
if (type != 0 and type != 1) {
|
||||
LOG(WARNING) << "\"type\" of the StringTable should be equal to 0 or 1 (" << std::dec << type << ")";
|
||||
}
|
||||
string_file_info.key_ = key;
|
||||
|
||||
str_local_offset += (key.size() + 1) * sizeof(char16_t);
|
||||
str_local_offset = align(str_local_offset, sizeof(uint32_t));
|
||||
|
||||
// Parse 'StringTable' childs
|
||||
// ==========================
|
||||
VLOG(VDEBUG) << "Parsing 'StringTable' struct";
|
||||
while (str_local_offset < offset + string_file_info_length * sizeof(uint8_t)) {
|
||||
LangCodeItem lang_code_item;
|
||||
const uint16_t stringtable_length = *reinterpret_cast<const uint16_t*>(stream.read(str_local_offset, sizeof(uint16_t)));
|
||||
|
||||
// End of the structure including childs
|
||||
const uint64_t end_offset = str_local_offset + stringtable_length * sizeof(uint8_t);
|
||||
|
||||
str_local_offset += sizeof(uint16_t);
|
||||
|
||||
const uint16_t stringtable_value_length = *reinterpret_cast<const uint16_t*>(stream.read(str_local_offset, sizeof(uint16_t)));
|
||||
str_local_offset += sizeof(uint16_t);
|
||||
|
||||
VLOG(VDEBUG) << "Value length: " << std::dec << stringtable_value_length << " (should be 0)";
|
||||
|
||||
const uint16_t stringtable_type = *reinterpret_cast<const uint16_t*>(stream.read(str_local_offset, sizeof(uint16_t)));
|
||||
VLOG(VDEBUG) << "Type: " << std::dec << stringtable_type;
|
||||
str_local_offset += sizeof(uint16_t);
|
||||
|
||||
// 1: Text data
|
||||
// 0: Binary data
|
||||
if (type != 0 and type != 1) {
|
||||
LOG(WARNING) << "\"type\" of the StringTable should be equal to 0 or 1 (" << std::dec << type << ")";
|
||||
}
|
||||
lang_code_item.type_ = type;
|
||||
lang_code_item.type_ = type;
|
||||
|
||||
|
||||
std::u16string key = {reinterpret_cast<const char16_t*>(stream.content().data() + str_local_offset)};
|
||||
lang_code_item.key_ = key;
|
||||
VLOG(VDEBUG) << "ID: " << u16tou8(key);
|
||||
std::u16string key = stream.read_u16string();
|
||||
lang_code_item.key_ = key;
|
||||
VLOG(VDEBUG) << "ID: " << u16tou8(key);
|
||||
|
||||
std::string key_str = u16tou8(key);
|
||||
std::string key_str = u16tou8(key);
|
||||
|
||||
if (key.length() != 8) {
|
||||
LOG(ERROR) << "Corrupted key (" << u16tou8(key) << key_str << ")";
|
||||
} else {
|
||||
uint64_t lang_id = std::stoul(u16tou8(key.substr(0, 4)), 0, 16);
|
||||
uint64_t code_page = std::stoul(u16tou8(key.substr(4, 8)), 0, 16);
|
||||
VLOG(VDEBUG) << "Lang ID: " << std::dec << lang_id;
|
||||
VLOG(VDEBUG) << "Code page: " << std::hex << code_page;
|
||||
}
|
||||
|
||||
str_local_offset += (key.size() + 1) * sizeof(char16_t);
|
||||
str_local_offset = align(str_local_offset, sizeof(uint32_t));
|
||||
|
||||
// Parse 'String'
|
||||
// ==============
|
||||
while (str_local_offset < end_offset) {
|
||||
const uint16_t string_length = *reinterpret_cast<const uint16_t*>(stream.read(str_local_offset, sizeof(uint16_t)));
|
||||
str_local_offset += sizeof(uint16_t);
|
||||
VLOG(VDEBUG) << "Length of the 'string' struct: 0x" << std::hex << string_length;
|
||||
|
||||
const uint16_t string_value_length = *reinterpret_cast<const uint16_t*>(stream.read(str_local_offset, sizeof(uint16_t)));
|
||||
str_local_offset += sizeof(uint16_t);
|
||||
VLOG(VDEBUG) << "Size of the 'value' member: 0x" << std::hex << string_value_length;
|
||||
|
||||
const uint16_t string_type = *reinterpret_cast<const uint16_t*>(stream.read(str_local_offset, sizeof(uint16_t)));
|
||||
str_local_offset += sizeof(uint16_t);
|
||||
VLOG(VDEBUG) << "Type of the 'string' struct: " << std::dec << string_type;
|
||||
|
||||
std::u16string key = {reinterpret_cast<const char16_t*>(stream.content().data() + str_local_offset)};
|
||||
VLOG(VDEBUG) << "Key: " << u16tou8(key);
|
||||
str_local_offset += (key.size() + 1) * sizeof(char16_t);
|
||||
str_local_offset = align(str_local_offset, sizeof(uint32_t));
|
||||
|
||||
std::u16string value = {reinterpret_cast<const char16_t*>(stream.content().data() + str_local_offset)};
|
||||
VLOG(VDEBUG) << "Value: " << u16tou8(value);
|
||||
str_local_offset += (value.size() + 1) * sizeof(char16_t);
|
||||
|
||||
str_local_offset = align(str_local_offset, sizeof(uint32_t));
|
||||
lang_code_item.items_.emplace(key, value);
|
||||
}
|
||||
string_file_info.childs_.push_back(std::move(lang_code_item));
|
||||
if (key.length() != 8) {
|
||||
LOG(ERROR) << "Corrupted key (" << u16tou8(key) << key_str << ")";
|
||||
} else {
|
||||
uint64_t lang_id = std::stoul(u16tou8(key.substr(0, 4)), 0, 16);
|
||||
uint64_t code_page = std::stoul(u16tou8(key.substr(4, 8)), 0, 16);
|
||||
VLOG(VDEBUG) << "Lang ID: " << std::dec << lang_id;
|
||||
VLOG(VDEBUG) << "Code page: " << std::hex << code_page;
|
||||
}
|
||||
|
||||
stream.align(sizeof(uint32_t));
|
||||
|
||||
// Parse 'String'
|
||||
// ==============
|
||||
while (stream.pos() < end_offset) {
|
||||
const uint16_t string_length = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Length of the 'string' struct: 0x" << std::hex << string_length;
|
||||
|
||||
const uint16_t string_value_length = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Size of the 'value' member: 0x" << std::hex << string_value_length;
|
||||
|
||||
const uint16_t string_type = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Type of the 'string' struct: " << std::dec << string_type;
|
||||
|
||||
std::u16string key = stream.read_u16string();
|
||||
VLOG(VDEBUG) << "Key: " << u16tou8(key);
|
||||
stream.align(sizeof(uint32_t));
|
||||
|
||||
std::u16string value = stream.read_u16string();
|
||||
VLOG(VDEBUG) << "Value: " << u16tou8(value);
|
||||
|
||||
stream.align(sizeof(uint32_t));
|
||||
lang_code_item.items_.emplace(key, value);
|
||||
}
|
||||
string_file_info.childs_.push_back(std::move(lang_code_item));
|
||||
}
|
||||
//offset += string_file_info_length * sizeof(uint8_t);
|
||||
offset = str_local_offset;
|
||||
//stream.setpos(end_string_stable);
|
||||
return string_file_info;
|
||||
}
|
||||
|
||||
|
||||
ResourceVarFileInfo ResourcesManager::get_var_file_info(const VectorStream& stream, uint64_t& offset) const {
|
||||
ResourceVarFileInfo ResourcesManager::get_var_file_info(const VectorStream& stream, uint16_t type, std::u16string key, size_t start, size_t struct_length) const {
|
||||
VLOG(VDEBUG) << "Getting VarFileInfo object";
|
||||
// Var file info
|
||||
// =============
|
||||
ResourceVarFileInfo var_file_info;
|
||||
const uint16_t var_file_info_length = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
uint64_t var_local_offset = offset;
|
||||
|
||||
if (var_file_info_length > 0) {
|
||||
var_local_offset += sizeof(uint16_t);
|
||||
var_file_info.type_ = type;
|
||||
var_file_info.key_ = key;
|
||||
|
||||
const uint16_t value_length = *reinterpret_cast<const uint16_t*>(stream.read(var_local_offset, sizeof(uint16_t)));
|
||||
var_local_offset += sizeof(uint16_t);
|
||||
VLOG(VDEBUG) << "Value length: " << std::dec << value_length << " (should be 0)";
|
||||
// Parse 'Var' childs
|
||||
// ==================
|
||||
VLOG(VDEBUG) << "Parsing 'Var' childs";
|
||||
const size_t end_var_file_info = start + struct_length * sizeof(uint8_t);
|
||||
while (stream.pos() < end_var_file_info) {
|
||||
const uint16_t var_length = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Size of the 'Var' struct: 0x" << std::hex << var_length;
|
||||
|
||||
const uint16_t type = *reinterpret_cast<const uint16_t*>(stream.read(var_local_offset, sizeof(uint16_t)));
|
||||
var_local_offset += sizeof(uint16_t);
|
||||
var_file_info.type_ = type;
|
||||
VLOG(VDEBUG) << "Type: " << std::dec << type;
|
||||
const uint16_t var_value_length = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Size of the 'Value' member: 0x" << std::hex << var_value_length;
|
||||
|
||||
std::u16string key = {reinterpret_cast<const char16_t*>(stream.content().data() + var_local_offset)};
|
||||
if (u16tou8(key) != "VarFileInfo") {
|
||||
LOG(WARNING) << "\"key\" of the resource version should be equal to 'VarFileInfo' (" << u16tou8(key) << ")";
|
||||
const uint16_t var_type = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Type: " << std::dec << var_type;
|
||||
|
||||
std::u16string key = stream.read_u16string();
|
||||
if (u16tou8(key) != "Translation") {
|
||||
LOG(WARNING) << "\"key\" of the var key should be equal to 'Translation' (" << u16tou8(key) << ")";
|
||||
}
|
||||
var_file_info.key_ = key;
|
||||
stream.align(sizeof(uint32_t));
|
||||
|
||||
var_local_offset += (key.size() + 1) * sizeof(char16_t);
|
||||
var_local_offset = align(var_local_offset, sizeof(uint32_t));
|
||||
|
||||
// Parse 'Var' childs
|
||||
// ==================
|
||||
VLOG(VDEBUG) << "Parsing 'Var' childs";
|
||||
while (var_local_offset < offset + var_file_info_length * sizeof(uint8_t)) {
|
||||
const uint16_t var_length = *reinterpret_cast<const uint16_t*>(stream.read(var_local_offset, sizeof(uint16_t)));
|
||||
var_local_offset += sizeof(uint16_t);
|
||||
VLOG(VDEBUG) << "Size of the 'Var' struct: 0x" << std::hex << var_length;
|
||||
|
||||
const uint16_t var_value_length = *reinterpret_cast<const uint16_t*>(stream.read(var_local_offset, sizeof(uint16_t)));
|
||||
var_local_offset += sizeof(uint16_t);
|
||||
VLOG(VDEBUG) << "Size of the 'Value' member: 0x" << std::hex << var_value_length;
|
||||
|
||||
const uint16_t var_type = *reinterpret_cast<const uint16_t*>(stream.read(var_local_offset, sizeof(uint16_t)));
|
||||
var_local_offset += sizeof(uint16_t);
|
||||
VLOG(VDEBUG) << "Type: " << std::dec << var_type;
|
||||
|
||||
std::u16string key = {reinterpret_cast<const char16_t*>(stream.content().data() + var_local_offset)};
|
||||
if (u16tou8(key) != "Translation") {
|
||||
LOG(WARNING) << "\"key\" of the var key should be equal to 'Translation' (" << u16tou8(key) << ")";
|
||||
}
|
||||
|
||||
var_local_offset += (key.size() + 1) * sizeof(char16_t);
|
||||
var_local_offset = align(var_local_offset, sizeof(uint32_t));
|
||||
|
||||
const uint32_t *value_array = reinterpret_cast<const uint32_t*>(stream.read(var_local_offset, var_value_length * sizeof(uint8_t)));
|
||||
const size_t nb_items = var_value_length / sizeof(uint32_t);
|
||||
for (size_t i = 0; i < nb_items; ++i) {
|
||||
VLOG(VDEBUG) << "item[" << std::dec << i << "] = " << std::hex << value_array[i];
|
||||
var_file_info.translations_.push_back(value_array[i]);
|
||||
}
|
||||
var_local_offset += var_value_length;
|
||||
const size_t nb_items = var_value_length / sizeof(uint32_t);
|
||||
const uint32_t *value_array = stream.read_array<uint32_t>(nb_items);
|
||||
for (size_t i = 0; i < nb_items; ++i) {
|
||||
VLOG(VDEBUG) << "item[" << std::dec << i << "] = " << std::hex << value_array[i];
|
||||
var_file_info.translations_.push_back(value_array[i]);
|
||||
}
|
||||
}
|
||||
// offset += var_file_info_length * sizeof(uint8_t);
|
||||
|
||||
offset = var_local_offset;
|
||||
stream.setpos(end_var_file_info);
|
||||
return var_file_info;
|
||||
|
||||
}
|
||||
|
||||
// Icons
|
||||
@ -1007,7 +944,7 @@ std::vector<ResourceDialog> ResourcesManager::dialogs(void) const {
|
||||
const ResourceData* data_node = dynamic_cast<const ResourceData*>(&langs[j]);
|
||||
const std::vector<uint8_t>& content = data_node->content();
|
||||
VectorStream stream{content};
|
||||
|
||||
stream.setpos(0);
|
||||
|
||||
if (content.size() < std::min(sizeof(pe_dialog_template_ext), sizeof(pe_dialog_template))) {
|
||||
LOG(WARNING) << "Dialog is corrupted!";
|
||||
@ -1021,18 +958,15 @@ std::vector<ResourceDialog> ResourcesManager::dialogs(void) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
const pe_dialog_template_ext* header = reinterpret_cast<const pe_dialog_template_ext*>(stream.read(0, sizeof(pe_dialog_template_ext)));
|
||||
const pe_dialog_template_ext* header = &stream.read<pe_dialog_template_ext>();
|
||||
|
||||
ResourceDialog new_dialog{header};
|
||||
new_dialog.lang(ResourcesManager::lang_from_id(data_node->id()));
|
||||
new_dialog.sub_lang(ResourcesManager::sublang_from_id(data_node->id()));
|
||||
|
||||
size_t offset = sizeof(pe_dialog_template_ext);
|
||||
|
||||
// Menu
|
||||
// ====
|
||||
const uint16_t menu_hint = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint16_t);
|
||||
const uint16_t menu_hint = stream.read<uint16_t>();
|
||||
switch(menu_hint) {
|
||||
case 0x0000:
|
||||
{
|
||||
@ -1042,8 +976,7 @@ std::vector<ResourceDialog> ResourcesManager::dialogs(void) const {
|
||||
|
||||
case 0xFFFF:
|
||||
{
|
||||
const uint16_t menu_ordinal = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint16_t);
|
||||
const uint16_t menu_ordinal = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Menu uses ordinal number " << std::dec << menu_ordinal;
|
||||
break;
|
||||
}
|
||||
@ -1051,15 +984,17 @@ std::vector<ResourceDialog> ResourcesManager::dialogs(void) const {
|
||||
default:
|
||||
{
|
||||
VLOG(VDEBUG) << "Menu uses unicode string";
|
||||
std::u16string menu_name = {reinterpret_cast<const char16_t*>(content.data() + offset)};
|
||||
offset += (menu_name.size() + 1)* sizeof(char16_t);
|
||||
std::u16string menu_name = stream.read_u16string();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Window Class
|
||||
// ============
|
||||
const uint16_t window_class_hint = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint16_t);
|
||||
stream.align(sizeof(uint16_t));
|
||||
|
||||
const uint16_t window_class_hint = stream.read<uint16_t>();
|
||||
|
||||
switch(window_class_hint) {
|
||||
case 0x0000:
|
||||
{
|
||||
@ -1069,112 +1004,97 @@ std::vector<ResourceDialog> ResourcesManager::dialogs(void) const {
|
||||
|
||||
case 0xFFFF:
|
||||
{
|
||||
const uint16_t windows_class_ordinal = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
const uint16_t windows_class_ordinal = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Windows class uses ordinal number " << std::dec << windows_class_ordinal;
|
||||
offset += sizeof(uint16_t);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
VLOG(VDEBUG) << "Windows class uses unicode string";
|
||||
std::u16string window_class_name = {reinterpret_cast<const char16_t*>(content.data() + offset)};
|
||||
offset += (window_class_name.size() + 1) * sizeof(char16_t);
|
||||
std::u16string window_class_name = stream.read_u16string();
|
||||
}
|
||||
}
|
||||
|
||||
// Title
|
||||
// =====
|
||||
VLOG(VDEBUG) << "Title offset: " << std::hex << offset;
|
||||
new_dialog.title_ = std::u16string{reinterpret_cast<const char16_t*>(content.data() + offset)};
|
||||
offset += sizeof(uint16_t) * (new_dialog.title().size() + 1);
|
||||
stream.align(sizeof(uint16_t));
|
||||
VLOG(VDEBUG) << "Title offset: " << std::hex << stream.pos();
|
||||
new_dialog.title_ = stream.read_u16string();
|
||||
|
||||
// 2nd part
|
||||
// ========
|
||||
const std::set<DIALOG_BOX_STYLES>& dialogbox_styles = new_dialog.dialogbox_style_list();
|
||||
if (dialogbox_styles.count(DIALOG_BOX_STYLES::DS_SHELLFONT) > 0 or dialogbox_styles.count(DIALOG_BOX_STYLES::DS_SETFONT) > 0) {
|
||||
const uint16_t point_size = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint16_t);
|
||||
const uint16_t point_size = stream.read<uint16_t>();
|
||||
new_dialog.point_size_ = point_size;
|
||||
|
||||
const uint16_t weight = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint16_t);
|
||||
const uint16_t weight = stream.read<uint16_t>();
|
||||
new_dialog.weight_ = weight;
|
||||
|
||||
const uint8_t is_italic = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint8_t);
|
||||
const uint8_t is_italic = stream.read<uint8_t>();
|
||||
new_dialog.italic_ = static_cast<bool>(is_italic);
|
||||
|
||||
const uint8_t charset = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint8_t);
|
||||
const uint8_t charset = stream.read<uint8_t>();
|
||||
new_dialog.charset_ = static_cast<bool>(charset);
|
||||
|
||||
new_dialog.typeface_ = std::u16string{reinterpret_cast<const char16_t*>(content.data() + offset)};
|
||||
offset += (new_dialog.typeface().size() + 1) * sizeof(char16_t);
|
||||
new_dialog.typeface_ = stream.read_u16string();
|
||||
}
|
||||
|
||||
VLOG(VDEBUG) << "Offset to the items: 0x" << std::hex << offset;
|
||||
VLOG(VDEBUG) << "Offset to the items: 0x" << std::hex << stream.pos();
|
||||
VLOG(VDEBUG) << std::endl << std::endl << "####### Items #######" << std::endl;
|
||||
|
||||
// Items
|
||||
// =====
|
||||
for (size_t i = 0; i < header->nbof_items; ++i) {
|
||||
offset = align(offset, sizeof(uint32_t));
|
||||
VLOG(VDEBUG) << "item[" << std::dec << i << "] offset: 0x" << std::hex << offset;
|
||||
stream.align(sizeof(uint32_t));
|
||||
VLOG(VDEBUG) << "item[" << std::dec << i << "] offset: 0x" << std::hex << stream.pos();
|
||||
ResourceDialogItem dialog_item;
|
||||
|
||||
if (new_dialog.is_extended()) {
|
||||
const pe_dialog_item_template_ext* item_header = reinterpret_cast<const pe_dialog_item_template_ext*>(stream.read(offset, sizeof(pe_dialog_item_template_ext)));
|
||||
offset += sizeof(pe_dialog_item_template_ext);
|
||||
dialog_item = {item_header};
|
||||
const pe_dialog_item_template_ext* item_header = &stream.read<pe_dialog_item_template_ext>();
|
||||
dialog_item = item_header;
|
||||
VLOG(VDEBUG) << "Item ID: " << std::dec << item_header->id;
|
||||
} else {
|
||||
const pe_dialog_item_template* item_header = reinterpret_cast<const pe_dialog_item_template*>(stream.read(offset, sizeof(pe_dialog_item_template)));
|
||||
offset += sizeof(pe_dialog_item_template);
|
||||
const pe_dialog_item_template* item_header = &stream.read<pe_dialog_item_template>();
|
||||
new_dialog.items_.emplace_back(item_header);
|
||||
continue;
|
||||
}
|
||||
|
||||
// window class
|
||||
// ------------
|
||||
offset = align(offset, sizeof(uint32_t));
|
||||
const uint16_t window_class_hint = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint16_t);
|
||||
stream.align(sizeof(uint32_t));
|
||||
const uint16_t window_class_hint = stream.read<uint16_t>();
|
||||
|
||||
if (window_class_hint == 0xFFFF) {
|
||||
const uint16_t windows_class_ordinal = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
const uint16_t windows_class_ordinal = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Windows class uses ordinal number " << std::dec << windows_class_ordinal;
|
||||
offset += sizeof(uint16_t);
|
||||
} else {
|
||||
VLOG(VDEBUG) << "Windows class uses unicode string";
|
||||
std::u16string window_class_name = {reinterpret_cast<const char16_t*>(stream.read(offset, sizeof(uint16_t)))};
|
||||
offset += (window_class_name.size() + 1) * sizeof(char16_t);
|
||||
std::u16string window_class_name = stream.read_u16string();
|
||||
}
|
||||
|
||||
// Title
|
||||
// -----
|
||||
offset = align(offset, sizeof(uint32_t));
|
||||
const uint16_t title_hint = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
stream.align(sizeof(uint32_t));
|
||||
const uint16_t title_hint = stream.peek<uint16_t>();
|
||||
|
||||
if (title_hint == 0xFFFF) {
|
||||
offset += sizeof(uint16_t);
|
||||
const uint16_t title_ordinal = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
stream.increment_pos(sizeof(uint16_t));
|
||||
const uint16_t title_ordinal = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Title uses ordinal number " << std::dec << title_ordinal;
|
||||
offset += sizeof(uint16_t);
|
||||
} else {
|
||||
std::u16string title_name = {reinterpret_cast<const char16_t*>(content.data() + offset)};
|
||||
offset += (title_name.size() + 1) * sizeof(char16_t);
|
||||
std::u16string title_name = stream.read_u16string();
|
||||
VLOG(VDEBUG) << "Title uses unicode string: \"" << u16tou8(title_name) << "\"";
|
||||
dialog_item.title_ = std::u16string{title_name};
|
||||
dialog_item.title_ = title_name;
|
||||
}
|
||||
|
||||
// Extra count
|
||||
// -----------
|
||||
const uint16_t extra_count = *reinterpret_cast<const uint16_t*>(stream.read(offset, sizeof(uint16_t)));
|
||||
offset += sizeof(uint16_t);
|
||||
const uint16_t extra_count = stream.read<uint16_t>();
|
||||
VLOG(VDEBUG) << "Extra count: " << std::hex << extra_count << std::endl;
|
||||
dialog_item.extra_count_ = extra_count;
|
||||
offset += extra_count * sizeof(uint8_t);
|
||||
stream.increment_pos(extra_count * sizeof(uint8_t));
|
||||
new_dialog.items_.push_back(std::move(dialog_item));
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ SignatureParser::SignatureParser(const std::vector<uint8_t>& data) :
|
||||
stream_{std::unique_ptr<VectorStream>(new VectorStream{data})}
|
||||
{
|
||||
|
||||
this->signature_ptr_ = reinterpret_cast<const uint8_t*>(this->stream_->read(8, this->stream_->size() - 8));
|
||||
this->signature_ptr_ = this->stream_->peek_array<uint8_t>(8, this->stream_->size() - 8);
|
||||
this->end_ = this->signature_ptr_ + this->stream_->size() - 8;
|
||||
this->p_ = const_cast<uint8_t*>(this->signature_ptr_);
|
||||
try {
|
||||
|
@ -150,9 +150,13 @@ PE_TYPE get_type(const std::vector<uint8_t>& raw) {
|
||||
}
|
||||
|
||||
|
||||
std::string u16tou8(const std::u16string& string) {
|
||||
std::string u16tou8(const std::u16string& string, bool remove_null_char) {
|
||||
std::string name;
|
||||
utf8::utf16to8(std::begin(string), std::end(string), std::back_inserter(name));
|
||||
if (remove_null_char) {
|
||||
return std::string{name.c_str()};
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,13 @@
|
||||
#include "LIEF/visitors/json.hpp"
|
||||
#include "LIEF/Abstract/EnumToString.hpp"
|
||||
|
||||
#if defined(LIEF_PE_SUPPORT)
|
||||
#include "LIEF/PE/json.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(LIEF_ELF_SUPPORT)
|
||||
#include "LIEF/ELF/json.hpp"
|
||||
#endif
|
||||
|
||||
#include "LIEF/config.h"
|
||||
|
||||
|
@ -96,12 +96,9 @@ TEST_CASE("Test parse", "[pe][parser]")
|
||||
for (size_t j = 0; j < entries_lhs.size(); ++j) {
|
||||
if (not entries_lhs[j].is_ordinal()) {
|
||||
INFO("Library: " << imports_lhs[i].name() << ". Function: " << entries_lhs[j].name());
|
||||
try {
|
||||
uint64_t address = binary_original->predict_function_rva(imports_lhs[i].name(), entries_lhs[j].name());
|
||||
uint64_t address = binary_original->predict_function_rva(imports_lhs[i].name(), entries_lhs[j].name());
|
||||
if (address > 0) {
|
||||
CHECK(address == entries_rhs[j].iat_address());
|
||||
} catch (const LIEF::not_supported& e) {
|
||||
WARN(e.what());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user