mirror of
https://github.com/QuasarApp/LIEF.git
synced 2025-04-27 21:04:32 +00:00
Fix memory leaks in the MachO Python API and create FatBinary
API Changes: LIEF::MachO::Parser won't return a 'std::vector' of MachO::Binary* but a pointer to MachO::FatBinary object It's a kind of wrapper on std::vector<MachO::Binary*>
This commit is contained in:
parent
554fa153af
commit
3602643f5d
@ -242,7 +242,8 @@ set(LIBFUZZER_SRC_FILES)
|
|||||||
if (LIEF_FUZZING)
|
if (LIEF_FUZZING)
|
||||||
message(STATUS "Fuzzing Enabled")
|
message(STATUS "Fuzzing Enabled")
|
||||||
|
|
||||||
set(LIBFUZZER_URL "http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer")
|
set(LIBFUZZER_VERSION 314494)
|
||||||
|
set(LIBFUZZER_URL "http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer/") #\?p=${LIBFUZZER_VERSION}")
|
||||||
ExternalProject_Add(lief_libfuzzer
|
ExternalProject_Add(lief_libfuzzer
|
||||||
SVN_REPOSITORY ${LIBFUZZER_URL}
|
SVN_REPOSITORY ${LIBFUZZER_URL}
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
|
@ -23,18 +23,18 @@
|
|||||||
using namespace LIEF::MachO;
|
using namespace LIEF::MachO;
|
||||||
|
|
||||||
Macho_Binary_t** macho_parse(const char *file) {
|
Macho_Binary_t** macho_parse(const char *file) {
|
||||||
std::vector<Binary*> macho_binaries{Parser::parse(file)};
|
FatBinary* macho_binaries = Parser::parse(file);
|
||||||
|
|
||||||
Macho_Binary_t** c_macho_binaries = static_cast<Macho_Binary_t**>(
|
Macho_Binary_t** c_macho_binaries = static_cast<Macho_Binary_t**>(
|
||||||
malloc((macho_binaries.size() + 1) * sizeof(Macho_Binary_t**)));
|
malloc((macho_binaries->size() + 1) * sizeof(Macho_Binary_t**)));
|
||||||
|
|
||||||
for (size_t i = 0; i < macho_binaries.size(); ++i) {
|
for (size_t i = 0; i < macho_binaries->size(); ++i) {
|
||||||
Binary* binary = macho_binaries [i];
|
Binary& binary = (*macho_binaries)[i];
|
||||||
c_macho_binaries[i] = static_cast<Macho_Binary_t*>(malloc(sizeof(Macho_Binary_t)));
|
c_macho_binaries[i] = static_cast<Macho_Binary_t*>(malloc(sizeof(Macho_Binary_t)));
|
||||||
init_c_binary(c_macho_binaries[i], binary);
|
init_c_binary(c_macho_binaries[i], &binary);
|
||||||
}
|
}
|
||||||
|
|
||||||
c_macho_binaries[macho_binaries.size()] = nullptr;
|
c_macho_binaries[macho_binaries->size()] = nullptr;
|
||||||
|
|
||||||
return c_macho_binaries;
|
return c_macho_binaries;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ set(LIEF_PYTHON_MACHO_SRC
|
|||||||
"${CMAKE_CURRENT_LIST_DIR}/pyMachO.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/pyMachO.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDylibCommand.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDylibCommand.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pyBinary.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/objects/pyBinary.cpp"
|
||||||
|
"${CMAKE_CURRENT_LIST_DIR}/objects/pyFatBinary.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pyLoadCommand.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/objects/pyLoadCommand.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pySegmentCommand.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/objects/pySegmentCommand.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pyHeader.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/objects/pyHeader.cpp"
|
||||||
|
60
api/python/MachO/objects/pyFatBinary.cpp
Normal file
60
api/python/MachO/objects/pyFatBinary.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* Copyright 2017 R. Thomas
|
||||||
|
* Copyright 2017 Quarkslab
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "LIEF/MachO/FatBinary.hpp"
|
||||||
|
|
||||||
|
#include "pyMachO.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
void init_MachO_FatBinary_class(py::module& m) {
|
||||||
|
|
||||||
|
|
||||||
|
py::class_<FatBinary>(m, "FatBinary")
|
||||||
|
|
||||||
|
.def_property_readonly("size",
|
||||||
|
&FatBinary::size,
|
||||||
|
"Number of " RST_CLASS_REF(lief.MachO.Binary) " registred")
|
||||||
|
|
||||||
|
.def("at",
|
||||||
|
static_cast<Binary& (FatBinary::*)(size_t)>(&FatBinary::at),
|
||||||
|
"Return the " RST_CLASS_REF(lief.MachO.Binary) " at the given index",
|
||||||
|
"index"_a)
|
||||||
|
|
||||||
|
.def("__len__",
|
||||||
|
&FatBinary::size)
|
||||||
|
|
||||||
|
|
||||||
|
.def("__getitem__",
|
||||||
|
static_cast<Binary& (FatBinary::*)(size_t)>(&FatBinary::operator[]),
|
||||||
|
"",
|
||||||
|
py::return_value_policy::reference)
|
||||||
|
|
||||||
|
.def("__iter__",
|
||||||
|
static_cast<it_binaries (FatBinary::*)(void)>(&FatBinary::begin),
|
||||||
|
py::return_value_policy::reference_internal)
|
||||||
|
|
||||||
|
.def("__str__",
|
||||||
|
[] (const FatBinary& fat_binary)
|
||||||
|
{
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << fat_binary;
|
||||||
|
std::string str = stream.str();
|
||||||
|
return str;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -24,14 +24,14 @@ void init_MachO_Parser_class(py::module& m) {
|
|||||||
|
|
||||||
// Parser (Parser)
|
// Parser (Parser)
|
||||||
m.def("parse",
|
m.def("parse",
|
||||||
static_cast<std::vector<Binary*> (*) (const std::string&)>(&LIEF::MachO::Parser::parse),
|
static_cast<FatBinary* (*) (const std::string&)>(&LIEF::MachO::Parser::parse),
|
||||||
"Parse the given binary and return a **list** of " RST_CLASS_REF(lief.MachO.Binary) " objects",
|
"Parse the given binary and return a **list** of " RST_CLASS_REF(lief.MachO.Binary) " objects",
|
||||||
"filename"_a,
|
"filename"_a,
|
||||||
py::return_value_policy::take_ownership);
|
py::return_value_policy::take_ownership);
|
||||||
|
|
||||||
|
|
||||||
m.def("parse",
|
m.def("parse",
|
||||||
static_cast<std::vector<Binary*> (*) (const std::vector<uint8_t>&, const std::string&)>(&LIEF::MachO::Parser::parse),
|
static_cast<FatBinary* (*) (const std::vector<uint8_t>&, const std::string&)>(&LIEF::MachO::Parser::parse),
|
||||||
"Parse the given binary (from raw) and return a **list** of " RST_CLASS_REF(lief.MachO.Binary) " objects",
|
"Parse the given binary (from raw) and return a **list** of " RST_CLASS_REF(lief.MachO.Binary) " objects",
|
||||||
py::arg("raw"), py::arg("name") = "",
|
py::arg("raw"), py::arg("name") = "",
|
||||||
py::return_value_policy::take_ownership);
|
py::return_value_policy::take_ownership);
|
||||||
|
@ -23,10 +23,9 @@
|
|||||||
void init_MachO_module(py::module& m) {
|
void init_MachO_module(py::module& m) {
|
||||||
py::module LIEF_MachO_module = m.def_submodule("MachO", "Python API for MachO");
|
py::module LIEF_MachO_module = m.def_submodule("MachO", "Python API for MachO");
|
||||||
|
|
||||||
py::bind_vector<std::vector<Binary*>>(m, "macho_list");
|
|
||||||
|
|
||||||
// Objects
|
// Objects
|
||||||
init_MachO_Parser_class(LIEF_MachO_module);
|
init_MachO_Parser_class(LIEF_MachO_module);
|
||||||
|
init_MachO_FatBinary_class(LIEF_MachO_module);
|
||||||
init_MachO_Binary_class(LIEF_MachO_module);
|
init_MachO_Binary_class(LIEF_MachO_module);
|
||||||
init_MachO_Header_class(LIEF_MachO_module);
|
init_MachO_Header_class(LIEF_MachO_module);
|
||||||
init_MachO_LoadCommand_class(LIEF_MachO_module);
|
init_MachO_LoadCommand_class(LIEF_MachO_module);
|
||||||
|
@ -27,6 +27,7 @@ using namespace LIEF::MachO;
|
|||||||
PYBIND11_MAKE_OPAQUE(std::vector<Binary*>)
|
PYBIND11_MAKE_OPAQUE(std::vector<Binary*>)
|
||||||
|
|
||||||
void init_MachO_Parser_class(py::module&);
|
void init_MachO_Parser_class(py::module&);
|
||||||
|
void init_MachO_FatBinary_class(py::module&);
|
||||||
void init_MachO_Binary_class(py::module&);
|
void init_MachO_Binary_class(py::module&);
|
||||||
void init_MachO_Header_class(py::module&);
|
void init_MachO_Header_class(py::module&);
|
||||||
void init_MachO_LoadCommand_class(py::module&);
|
void init_MachO_LoadCommand_class(py::module&);
|
||||||
|
@ -63,6 +63,7 @@ void init_LIEF_iterators(py::module& m) {
|
|||||||
// MachO
|
// MachO
|
||||||
// =====
|
// =====
|
||||||
#if defined(LIEF_MACHO_MODULE)
|
#if defined(LIEF_MACHO_MODULE)
|
||||||
|
init_ref_iterator<LIEF::MachO::it_binaries>(m);
|
||||||
init_ref_iterator<LIEF::MachO::it_relocations>(m);
|
init_ref_iterator<LIEF::MachO::it_relocations>(m);
|
||||||
init_ref_iterator<LIEF::MachO::it_commands>(m);
|
init_ref_iterator<LIEF::MachO::it_commands>(m);
|
||||||
init_ref_iterator<LIEF::MachO::it_symbols>(m);
|
init_ref_iterator<LIEF::MachO::it_symbols>(m);
|
||||||
|
@ -13,6 +13,14 @@ Parsers
|
|||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
FatBinary
|
||||||
|
*********
|
||||||
|
|
||||||
|
.. doxygenclass:: LIEF::MachO::FatBinary
|
||||||
|
:project: lief
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
Binary
|
Binary
|
||||||
******
|
******
|
||||||
|
|
||||||
|
@ -10,6 +10,17 @@ Parser
|
|||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
FatBinary
|
||||||
|
*********
|
||||||
|
|
||||||
|
.. autoclass:: lief.MachO.FatBinary
|
||||||
|
:members:
|
||||||
|
:inherited-members:
|
||||||
|
:undoc-members:
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
|
|
||||||
.. _python-macho-binary-api-ref:
|
.. _python-macho-binary-api-ref:
|
||||||
|
|
||||||
Binary
|
Binary
|
||||||
|
@ -38,13 +38,9 @@ int main(int argc, char **argv) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MachO::Binary*> binaries = MachO::Parser::parse(argv[1]);
|
std::unique_ptr<LIEF::MachO::FatBinary> binaries{MachO::Parser::parse(argv[1])};
|
||||||
MachO::Binary* binary = binaries.back();
|
MachO::Binary& binary = binaries->back();
|
||||||
binary->write(argv[2]);
|
binary.write(argv[2]);
|
||||||
|
|
||||||
for (MachO::Binary *b : binaries) {
|
|
||||||
delete b;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,10 @@ int main(int argc, char **argv) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MachO::Binary*> binaries = MachO::Parser::parse(argv[1]);
|
std::unique_ptr<LIEF::MachO::FatBinary> binaries{MachO::Parser::parse(argv[1])};
|
||||||
MachO::Binary* binary = binaries.back();
|
MachO::Binary& binary = binaries->back();
|
||||||
auto segments = binary->segments();
|
auto&& segments = binary.segments();
|
||||||
auto itSegment = std::find_if(
|
auto&& itSegment = std::find_if(
|
||||||
std::begin(segments),
|
std::begin(segments),
|
||||||
std::end(segments),
|
std::end(segments),
|
||||||
[] (const MachO::SegmentCommand& segment) {
|
[] (const MachO::SegmentCommand& segment) {
|
||||||
@ -64,7 +64,7 @@ int main(int argc, char **argv) {
|
|||||||
segment_header.segname[segment_name.size()] = 0;
|
segment_header.segname[segment_name.size()] = 0;
|
||||||
segment_header.vmaddr = 0x200050000;
|
segment_header.vmaddr = 0x200050000;
|
||||||
segment_header.vmsize = 0x2000;
|
segment_header.vmsize = 0x2000;
|
||||||
segment_header.fileoff = binary->original_size();
|
segment_header.fileoff = binary.original_size();
|
||||||
segment_header.filesize = payload.size();
|
segment_header.filesize = payload.size();
|
||||||
segment_header.maxprot = 7;
|
segment_header.maxprot = 7;
|
||||||
segment_header.initprot = 3;
|
segment_header.initprot = 3;
|
||||||
@ -82,11 +82,8 @@ int main(int argc, char **argv) {
|
|||||||
reinterpret_cast<uint8_t*>(&segment_header) + sizeof(segment_header)
|
reinterpret_cast<uint8_t*>(&segment_header) + sizeof(segment_header)
|
||||||
});
|
});
|
||||||
//binary->insert_command(std::move(segment));
|
//binary->insert_command(std::move(segment));
|
||||||
binary->write(argv[2]);
|
binary.write(argv[2]);
|
||||||
|
|
||||||
for (MachO::Binary *b : binaries) {
|
|
||||||
delete b;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -20,23 +20,23 @@
|
|||||||
|
|
||||||
using namespace LIEF::MachO;
|
using namespace LIEF::MachO;
|
||||||
|
|
||||||
void print_binary(const Binary* binary) {
|
void print_binary(const Binary& binary) {
|
||||||
std::cout << binary->header() << std::endl;
|
std::cout << binary.header() << std::endl;
|
||||||
|
|
||||||
std::cout << "== Library ==" << std::endl;
|
std::cout << "== Library ==" << std::endl;
|
||||||
for (const DylibCommand& library : binary->libraries()) {
|
for (const DylibCommand& library : binary.libraries()) {
|
||||||
std::cout << library << std::endl;
|
std::cout << library << std::endl;
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
std::cout << "== Sections ==" << std::endl;
|
std::cout << "== Sections ==" << std::endl;
|
||||||
for (const Section& section : binary->sections()) {
|
for (const Section& section : binary.sections()) {
|
||||||
std::cout << section << std::endl;
|
std::cout << section << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::cout << "== Segments ==" << std::endl;
|
//std::cout << "== Segments ==" << std::endl;
|
||||||
|
|
||||||
//for (SegmentCommand& segment : binary->segments()) {
|
//for (SegmentCommand& segment : binary.segments()) {
|
||||||
// std::cout << segment << std::endl;
|
// std::cout << segment << std::endl;
|
||||||
// if (segment.sections().size() > 0) {
|
// if (segment.sections().size() > 0) {
|
||||||
// //std::cout << std::hex;
|
// //std::cout << std::hex;
|
||||||
@ -61,31 +61,31 @@ void print_binary(const Binary* binary) {
|
|||||||
//}
|
//}
|
||||||
//std::cout << std::endl;
|
//std::cout << std::endl;
|
||||||
|
|
||||||
//auto commands = binary->commands();
|
//auto commands = binary.commands();
|
||||||
for (const LoadCommand& cmd : binary->commands()) {
|
for (const LoadCommand& cmd : binary.commands()) {
|
||||||
std::cout << cmd << std::endl;
|
std::cout << cmd << std::endl;
|
||||||
std::cout << "======================" << std::endl;
|
std::cout << "======================" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "== Symbols ==" << std::endl;
|
std::cout << "== Symbols ==" << std::endl;
|
||||||
for (const Symbol& symbol : binary->symbols()) {
|
for (const Symbol& symbol : binary.symbols()) {
|
||||||
std::cout << symbol << std::endl;
|
std::cout << symbol << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::cout << "== Exported symbols ==" << std::endl;
|
std::cout << "== Exported symbols ==" << std::endl;
|
||||||
for (const Symbol& symbol : binary->exported_symbols()) {
|
for (const Symbol& symbol : binary.exported_symbols()) {
|
||||||
std::cout << symbol << std::endl;
|
std::cout << symbol << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "== Imported symbols ==" << std::endl;
|
std::cout << "== Imported symbols ==" << std::endl;
|
||||||
for (const Symbol& symbol : binary->imported_symbols()) {
|
for (const Symbol& symbol : binary.imported_symbols()) {
|
||||||
std::cout << symbol << std::endl;
|
std::cout << symbol << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::cout << "== Relocations ==" << std::endl;
|
std::cout << "== Relocations ==" << std::endl;
|
||||||
for (const Relocation& relocation : binary->relocations()) {
|
for (const Relocation& relocation : binary.relocations()) {
|
||||||
std::cout << relocation << std::endl;
|
std::cout << relocation << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,16 +99,12 @@ int main(int argc, char **argv) {
|
|||||||
std::cerr << "Usage: " << argv[0] << " <MachO binary>" << std::endl;
|
std::cerr << "Usage: " << argv[0] << " <MachO binary>" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
std::vector<Binary*> binaries = Parser::parse(argv[1]);
|
std::unique_ptr<FatBinary> binaries{Parser::parse(argv[1])};
|
||||||
for (const Binary* binary : binaries) {
|
for (const Binary& binary : *binaries) {
|
||||||
print_binary(binary);
|
print_binary(binary);
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Binary* binary : binaries) {
|
|
||||||
delete binary;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
include(ProcessorCount)
|
||||||
set(LIEF_FUZZER_SRC
|
set(LIEF_FUZZER_SRC
|
||||||
elf_fuzzer.cpp
|
elf_fuzzer.cpp
|
||||||
pe_fuzzer.cpp
|
pe_fuzzer.cpp
|
||||||
@ -33,7 +34,8 @@ ExternalProject_Add(lief_fuzzer_corpus
|
|||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
GIT_REPOSITORY ${SAMPLES_GIT_URL}
|
GIT_REPOSITORY ${SAMPLES_GIT_URL}
|
||||||
GIT_TAG ${SAMPLES_TAG}
|
GIT_TAG ${SAMPLES_TAG}
|
||||||
UPDATE_COMMAND ${GIT_EXECUTABLE} pull
|
#UPDATE_COMMAND ${GIT_EXECUTABLE} pull
|
||||||
|
UPDATE_COMMAND ""
|
||||||
)
|
)
|
||||||
|
|
||||||
ExternalProject_Get_Property(lief_fuzzer_corpus source_dir)
|
ExternalProject_Get_Property(lief_fuzzer_corpus source_dir)
|
||||||
@ -41,7 +43,9 @@ set(LIEF_CORUPUS_DIRECTORY "${source_dir}" CACHE INTERNAL "Path to LIEF samples"
|
|||||||
message(STATUS "Samples directory: ${LIEF_CORUPUS_DIRECTORY}")
|
message(STATUS "Samples directory: ${LIEF_CORUPUS_DIRECTORY}")
|
||||||
|
|
||||||
|
|
||||||
|
ProcessorCount(N)
|
||||||
|
set(LIB_FUZZER_ARGS -detect_leaks=1 -rss_limit_mb=0 -print_final_stats=1 -jobs=${N})
|
||||||
|
set(ASAN_OPTIONS allocator_may_return_null=1)
|
||||||
# ELF
|
# ELF
|
||||||
# ===
|
# ===
|
||||||
set(ELF_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR}/elf-output)
|
set(ELF_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR}/elf-output)
|
||||||
@ -50,7 +54,7 @@ add_custom_target(build-elf-fuzz-output
|
|||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${ELF_WORKING_DIR})
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${ELF_WORKING_DIR})
|
||||||
|
|
||||||
add_custom_target("fuzz-elf"
|
add_custom_target("fuzz-elf"
|
||||||
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/elf_fuzzer ${LIEF_CORUPUS_DIRECTORY}/ELF -detect_leaks=1 -print_final_stats=1
|
COMMAND ${CMAKE_COMMAND} -E env ASAN_OPTIONS=${ASAN_OPTIONS} ${CMAKE_CURRENT_BINARY_DIR}/elf_fuzzer ${LIEF_CORUPUS_DIRECTORY}/ELF ${LIB_FUZZER_ARGS}
|
||||||
DEPENDS elf_fuzzer LIB_LIEF_STATIC build-elf-fuzz-output lief_fuzzer_corpus
|
DEPENDS elf_fuzzer LIB_LIEF_STATIC build-elf-fuzz-output lief_fuzzer_corpus
|
||||||
WORKING_DIRECTORY ${ELF_WORKING_DIR}
|
WORKING_DIRECTORY ${ELF_WORKING_DIR}
|
||||||
COMMENT "Run ELF fuzzer")
|
COMMENT "Run ELF fuzzer")
|
||||||
@ -64,7 +68,7 @@ add_custom_target(build-pe-fuzz-output
|
|||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${PE_WORKING_DIR})
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${PE_WORKING_DIR})
|
||||||
|
|
||||||
add_custom_target("fuzz-pe"
|
add_custom_target("fuzz-pe"
|
||||||
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/pe_fuzzer ${LIEF_CORUPUS_DIRECTORY}/PE -detect_leaks=1 -print_final_stats=1
|
COMMAND ${CMAKE_COMMAND} -E env ASAN_OPTIONS="${ASAN_OPTIONS}" ${CMAKE_CURRENT_BINARY_DIR}/pe_fuzzer ${LIEF_CORUPUS_DIRECTORY}/PE ${LIB_FUZZER_ARGS}
|
||||||
DEPENDS pe_fuzzer LIB_LIEF_STATIC build-pe-fuzz-output lief_fuzzer_corpus
|
DEPENDS pe_fuzzer LIB_LIEF_STATIC build-pe-fuzz-output lief_fuzzer_corpus
|
||||||
WORKING_DIRECTORY ${PE_WORKING_DIR}
|
WORKING_DIRECTORY ${PE_WORKING_DIR}
|
||||||
COMMENT "Run PE fuzzer")
|
COMMENT "Run PE fuzzer")
|
||||||
@ -74,10 +78,10 @@ add_custom_target("fuzz-pe"
|
|||||||
set(MACHO_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR}/macho-output)
|
set(MACHO_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR}/macho-output)
|
||||||
|
|
||||||
add_custom_target(build-macho-fuzz-output
|
add_custom_target(build-macho-fuzz-output
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${MACHO_WORKING_DIR})
|
COMMAND ${CMAKE_COMMAND} -E env ASAN_OPTIONS=${ASAN_OPTIONS} ${CMAKE_COMMAND} -E make_directory ${MACHO_WORKING_DIR})
|
||||||
|
|
||||||
add_custom_target("fuzz-macho"
|
add_custom_target("fuzz-macho"
|
||||||
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/macho_fuzzer ${LIEF_CORUPUS_DIRECTORY}/MachO -detect_leaks=1 -print_final_stats=1
|
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/macho_fuzzer ${LIEF_CORUPUS_DIRECTORY}/MachO ${LIB_FUZZER_ARGS}
|
||||||
DEPENDS macho_fuzzer LIB_LIEF_STATIC build-macho-fuzz-output lief_fuzzer_corpus
|
DEPENDS macho_fuzzer LIB_LIEF_STATIC build-macho-fuzz-output lief_fuzzer_corpus
|
||||||
WORKING_DIRECTORY ${MACHO_WORKING_DIR}
|
WORKING_DIRECTORY ${MACHO_WORKING_DIR}
|
||||||
COMMENT "Run MachO fuzzer")
|
COMMENT "Run MachO fuzzer")
|
||||||
|
@ -4,14 +4,11 @@
|
|||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||||
std::vector<uint8_t> raw = {data, data + size};
|
std::vector<uint8_t> raw = {data, data + size};
|
||||||
std::vector<LIEF::MachO::Binary*> binaries;
|
std::unique_ptr<LIEF::MachO::FatBinary> binaries;
|
||||||
try {
|
try {
|
||||||
binaries = LIEF::MachO::Parser::parse(raw);
|
binaries = std::unique_ptr<LIEF::MachO::FatBinary>(LIEF::MachO::Parser::parse(raw));
|
||||||
} catch (const LIEF::exception& e) {
|
} catch (const LIEF::exception& e) {
|
||||||
std::cout << e.what() << std::endl;
|
std::cout << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
for (LIEF::MachO::Binary* b: binaries) {
|
|
||||||
delete b;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
73
include/LIEF/MachO/FatBinary.hpp
Normal file
73
include/LIEF/MachO/FatBinary.hpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/* Copyright 2017 R. Thomas
|
||||||
|
* Copyright 2017 Quarkslab
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef LIEF_MACHO_FAT_BINARY_H_
|
||||||
|
#define LIEF_MACHO_FAT_BINARY_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "LIEF/types.hpp"
|
||||||
|
#include "LIEF/visibility.h"
|
||||||
|
|
||||||
|
#include "LIEF/MachO/Binary.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace LIEF {
|
||||||
|
class Parser;
|
||||||
|
namespace MachO {
|
||||||
|
|
||||||
|
class Parser;
|
||||||
|
class Builder;
|
||||||
|
|
||||||
|
class DLL_PUBLIC FatBinary {
|
||||||
|
|
||||||
|
friend class LIEF::Parser;
|
||||||
|
friend class Parser;
|
||||||
|
friend class Builder;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FatBinary(const FatBinary&) = delete;
|
||||||
|
|
||||||
|
virtual ~FatBinary(void);
|
||||||
|
|
||||||
|
//! @brief Number of @link MachO::Binary binary @endlink registred
|
||||||
|
size_t size(void) const;
|
||||||
|
|
||||||
|
it_binaries begin(void);
|
||||||
|
it_const_binaries begin(void) const;
|
||||||
|
|
||||||
|
it_binaries end(void);
|
||||||
|
it_const_binaries end(void) const;
|
||||||
|
|
||||||
|
Binary& at(size_t index);
|
||||||
|
const Binary& at(size_t index) const;
|
||||||
|
|
||||||
|
Binary& back(void);
|
||||||
|
const Binary& back(void) const;
|
||||||
|
|
||||||
|
Binary& operator[](size_t index);
|
||||||
|
const Binary& operator[](size_t index) const;
|
||||||
|
|
||||||
|
DLL_PUBLIC friend std::ostream& operator<<(std::ostream& os, const FatBinary& fatbinary);
|
||||||
|
|
||||||
|
private:
|
||||||
|
FatBinary(void);
|
||||||
|
FatBinary(const std::vector<Binary*>& binaries);
|
||||||
|
binaries_t binaries_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace MachO
|
||||||
|
} // namespace LIEF
|
||||||
|
#endif
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "LIEF/MachO/Structures.hpp"
|
#include "LIEF/MachO/Structures.hpp"
|
||||||
#include "LIEF/MachO/Binary.hpp"
|
#include "LIEF/MachO/Binary.hpp"
|
||||||
|
#include "LIEF/MachO/FatBinary.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace LIEF {
|
namespace LIEF {
|
||||||
@ -37,8 +38,8 @@ class DLL_PUBLIC Parser : public LIEF::Parser {
|
|||||||
|
|
||||||
~Parser(void);
|
~Parser(void);
|
||||||
|
|
||||||
static std::vector<Binary*> parse(const std::string& filename);
|
static FatBinary* parse(const std::string& filename);
|
||||||
static std::vector<Binary*> parse(const std::vector<uint8_t>& data, const std::string& name = "");
|
static FatBinary* parse(const std::vector<uint8_t>& data, const std::string& name = "");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Parser(const std::string& file);
|
Parser(const std::string& file);
|
||||||
|
@ -38,6 +38,11 @@ struct KeyCmp {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
using binaries_t = std::vector<Binary*>;
|
||||||
|
using it_binaries = ref_iterator<binaries_t&>;
|
||||||
|
using it_const_binaries = const_ref_iterator<const binaries_t&>;
|
||||||
|
|
||||||
|
|
||||||
using buffer_t = std::vector<uint8_t>; ///< Container used to store raw data
|
using buffer_t = std::vector<uint8_t>; ///< Container used to store raw data
|
||||||
|
|
||||||
using commands_t = std::vector<LoadCommand*>;
|
using commands_t = std::vector<LoadCommand*>;
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "LIEF/exception.hpp"
|
#include "LIEF/exception.hpp"
|
||||||
#include "LIEF/visibility.h"
|
#include "LIEF/visibility.h"
|
||||||
|
#include "LIEF/utils.hpp"
|
||||||
|
|
||||||
#include "LIEF/Abstract/Parser.hpp"
|
#include "LIEF/Abstract/Parser.hpp"
|
||||||
|
|
||||||
@ -41,7 +42,13 @@ namespace PE {
|
|||||||
class DLL_PUBLIC Parser : public LIEF::Parser {
|
class DLL_PUBLIC Parser : public LIEF::Parser {
|
||||||
|
|
||||||
//! @brief Minimum size for a DLL's name
|
//! @brief Minimum size for a DLL's name
|
||||||
constexpr static unsigned MIN_DLL_NAME_SIZE = 4;
|
static constexpr unsigned MIN_DLL_NAME_SIZE = 4;
|
||||||
|
|
||||||
|
//! @brief Maximum size of the data read
|
||||||
|
static constexpr size_t MAX_DATA_SIZE = 3_GB;
|
||||||
|
|
||||||
|
static constexpr size_t MAX_TLS_CALLBACKS = 3000;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Binary* parse(const std::string& filename);
|
static Binary* parse(const std::string& filename);
|
||||||
|
@ -51,14 +51,13 @@ Binary* Parser::parse(const std::string& filename) {
|
|||||||
#if defined(LIEF_MACHO_MODULE)
|
#if defined(LIEF_MACHO_MODULE)
|
||||||
if (MachO::is_macho(filename)) {
|
if (MachO::is_macho(filename)) {
|
||||||
// For fat binary we take the last one...
|
// For fat binary we take the last one...
|
||||||
std::vector<MachO::Binary*> binaries = MachO::Parser::parse(filename);
|
MachO::FatBinary* binaries = MachO::Parser::parse(filename);
|
||||||
MachO::Binary* binary_return = binaries.back();
|
MachO::Binary& binary_return = (*binaries)[0];
|
||||||
binaries.pop_back();
|
|
||||||
// delete others
|
// delete others
|
||||||
for (MachO::Binary* binary : binaries) {
|
for (size_t i = 1; i < binaries->size(); ++i) {
|
||||||
delete binary;
|
delete binaries->binaries_[i];
|
||||||
}
|
}
|
||||||
return binary_return;
|
return &binary_return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -84,14 +83,13 @@ Binary* Parser::parse(const std::vector<uint8_t>& raw, const std::string& name)
|
|||||||
#if defined(LIEF_MACHO_MODULE)
|
#if defined(LIEF_MACHO_MODULE)
|
||||||
if (MachO::is_macho(raw)) {
|
if (MachO::is_macho(raw)) {
|
||||||
// For fat binary we take the last one...
|
// For fat binary we take the last one...
|
||||||
std::vector<MachO::Binary*> binaries = MachO::Parser::parse(raw, name);
|
MachO::FatBinary* binaries = MachO::Parser::parse(raw, name);
|
||||||
MachO::Binary* binary_return = binaries.back();
|
MachO::Binary& binary_return = (*binaries)[0];
|
||||||
binaries.pop_back();
|
|
||||||
// delete others
|
// delete others
|
||||||
for (MachO::Binary* binary : binaries) {
|
for (size_t i = 1; i < binaries->size(); ++i) {
|
||||||
delete binary;
|
delete binaries->binaries_[i];
|
||||||
}
|
}
|
||||||
return binary_return;
|
return &binary_return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -101,11 +101,13 @@ std::string VectorStream::get_string(uint64_t offset, uint64_t size) const {
|
|||||||
throw LIEF::read_out_of_bound(offset);
|
throw LIEF::read_out_of_bound(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t max_size = this->size() - (offset + size);
|
size_t max_size = static_cast<size_t>(this->size() - (offset + size));
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
max_size = std::min<uint64_t>(max_size, size);
|
max_size = std::min<size_t>(max_size, size);
|
||||||
}
|
}
|
||||||
std::string tmp{this->read_string(offset, max_size), max_size};
|
const char* str = this->read_string(offset);
|
||||||
|
const char* it_null = std::find(str, str + max_size, '\0');
|
||||||
|
std::string tmp{str, it_null};
|
||||||
return tmp.c_str();
|
return tmp.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ void Parser::parse_notes(uint64_t offset, uint64_t size) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string name = {this->stream_->read_string(current_offset, namesz), namesz - 1};
|
std::string name = this->stream_->get_string(current_offset, namesz);
|
||||||
VLOG(VDEBUG) << "Name: " << name << std::endl;
|
VLOG(VDEBUG) << "Name: " << name << std::endl;
|
||||||
current_offset += namesz;
|
current_offset += namesz;
|
||||||
current_offset = align(current_offset, sizeof(uint32_t));
|
current_offset = align(current_offset, sizeof(uint32_t));
|
||||||
|
@ -837,8 +837,8 @@ void Parser::parse_sections(void) {
|
|||||||
const Section* string_section = this->binary_->sections_[section_string_index];
|
const Section* string_section = this->binary_->sections_[section_string_index];
|
||||||
for (Section* section : this->binary_->sections_) {
|
for (Section* section : this->binary_->sections_) {
|
||||||
try {
|
try {
|
||||||
section->name({this->stream_->read_string(
|
section->name(this->stream_->get_string(
|
||||||
string_section->file_offset() + section->name_idx())});
|
string_section->file_offset() + section->name_idx()));
|
||||||
} catch (const LIEF::read_out_of_bound&) {
|
} catch (const LIEF::read_out_of_bound&) {
|
||||||
LOG(WARNING) << "Section's name is corrupted";
|
LOG(WARNING) << "Section's name is corrupted";
|
||||||
}
|
}
|
||||||
@ -884,7 +884,7 @@ void Parser::parse_segments(void) {
|
|||||||
this->stream_->read(offset_to_content, size));
|
this->stream_->read(offset_to_content, size));
|
||||||
segment->content({content, content + size});
|
segment->content({content, content + size});
|
||||||
if (segment->type() == SEGMENT_TYPES::PT_INTERP) {
|
if (segment->type() == SEGMENT_TYPES::PT_INTERP) {
|
||||||
this->binary_->interpreter_ = this->stream_->read_string(offset_to_content, segment->physical_size());
|
this->binary_->interpreter_ = this->stream_->get_string(offset_to_content, segment->physical_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (const LIEF::read_out_of_bound&) {
|
} catch (const LIEF::read_out_of_bound&) {
|
||||||
@ -957,8 +957,8 @@ void Parser::parse_static_symbols(uint64_t offset, uint32_t nbSymbols, const Sec
|
|||||||
for (uint32_t i = 0; i < nbSymbols; ++i) {
|
for (uint32_t i = 0; i < nbSymbols; ++i) {
|
||||||
std::unique_ptr<Symbol> symbol{new Symbol{&symbol_headers[i]}};
|
std::unique_ptr<Symbol> symbol{new Symbol{&symbol_headers[i]}};
|
||||||
try {
|
try {
|
||||||
std::string symbol_name = {this->stream_->read_string(
|
std::string symbol_name = this->stream_->get_string(
|
||||||
string_section->file_offset() + symbol_headers[i].st_name)};
|
string_section->file_offset() + symbol_headers[i].st_name);
|
||||||
symbol->name(symbol_name);
|
symbol->name(symbol_name);
|
||||||
} catch (const LIEF::read_out_of_bound& e) {
|
} catch (const LIEF::read_out_of_bound& e) {
|
||||||
LOG(WARNING) << e.what();
|
LOG(WARNING) << e.what();
|
||||||
@ -994,7 +994,7 @@ void Parser::parse_dynamic_symbols(uint64_t offset) {
|
|||||||
if (symbol_headers->st_name > 0) {
|
if (symbol_headers->st_name > 0) {
|
||||||
try {
|
try {
|
||||||
std::string name{
|
std::string name{
|
||||||
this->stream_->read_string(string_offset + symbol_headers->st_name)};
|
this->stream_->get_string(string_offset + symbol_headers->st_name)};
|
||||||
symbol->name(name);
|
symbol->name(name);
|
||||||
} catch (const exception& e) {
|
} catch (const exception& e) {
|
||||||
VLOG(VDEBUG) << e.what();
|
VLOG(VDEBUG) << e.what();
|
||||||
@ -1046,8 +1046,7 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
|||||||
if (dynamic_string_offset == 0) {
|
if (dynamic_string_offset == 0) {
|
||||||
LOG(WARNING) << "Unable to find the .dynstr section";
|
LOG(WARNING) << "Unable to find the .dynstr section";
|
||||||
} else {
|
} else {
|
||||||
std::string library_name = {
|
std::string library_name = this->stream_->get_string(dynamic_string_offset + dynamic_entry->value());
|
||||||
this->stream_->read_string(dynamic_string_offset + dynamic_entry->value())};
|
|
||||||
dynamic_entry->name(library_name);
|
dynamic_entry->name(library_name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1061,8 +1060,7 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
|||||||
if (dynamic_string_offset == 0) {
|
if (dynamic_string_offset == 0) {
|
||||||
LOG(WARNING) << "Unable to find the .dynstr section";
|
LOG(WARNING) << "Unable to find the .dynstr section";
|
||||||
} else {
|
} else {
|
||||||
std::string sharename = {
|
std::string sharename = this->stream_->get_string(dynamic_string_offset + dynamic_entry->value());
|
||||||
this->stream_->read_string(dynamic_string_offset + dynamic_entry->value())};
|
|
||||||
dynamic_entry->name(sharename);
|
dynamic_entry->name(sharename);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1075,8 +1073,7 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
|||||||
if (dynamic_string_offset == 0) {
|
if (dynamic_string_offset == 0) {
|
||||||
LOG(WARNING) << "Unable to find the .dynstr section";
|
LOG(WARNING) << "Unable to find the .dynstr section";
|
||||||
} else {
|
} else {
|
||||||
std::string name = {
|
std::string name = this->stream_->get_string(dynamic_string_offset + dynamic_entry->value());
|
||||||
this->stream_->read_string(dynamic_string_offset + dynamic_entry->value())};
|
|
||||||
dynamic_entry->name(name);
|
dynamic_entry->name(name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1090,8 +1087,7 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
|||||||
if (dynamic_string_offset == 0) {
|
if (dynamic_string_offset == 0) {
|
||||||
LOG(WARNING) << "Unable to find the .dynstr section";
|
LOG(WARNING) << "Unable to find the .dynstr section";
|
||||||
} else {
|
} else {
|
||||||
std::string name = {
|
std::string name = this->stream_->get_string(dynamic_string_offset + dynamic_entry->value());
|
||||||
this->stream_->read_string(dynamic_string_offset + dynamic_entry->value())};
|
|
||||||
dynamic_entry->name(name);
|
dynamic_entry->name(name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1378,8 +1374,8 @@ void Parser::parse_symbol_version_requirement(uint64_t offset, uint32_t nb_entri
|
|||||||
|
|
||||||
std::unique_ptr<SymbolVersionRequirement> symbol_version_requirement{new SymbolVersionRequirement{header}};
|
std::unique_ptr<SymbolVersionRequirement> symbol_version_requirement{new SymbolVersionRequirement{header}};
|
||||||
if (string_offset != 0) {
|
if (string_offset != 0) {
|
||||||
symbol_version_requirement->name({
|
symbol_version_requirement->name(
|
||||||
this->stream_->read_string(string_offset + header->vn_file)});
|
this->stream_->get_string(string_offset + header->vn_file));
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t nb_symbol_aux = header->vn_cnt;
|
const uint32_t nb_symbol_aux = header->vn_cnt;
|
||||||
@ -1401,7 +1397,7 @@ void Parser::parse_symbol_version_requirement(uint64_t offset, uint32_t nb_entri
|
|||||||
|
|
||||||
std::unique_ptr<SymbolVersionAuxRequirement> svar{new SymbolVersionAuxRequirement{aux_header}};
|
std::unique_ptr<SymbolVersionAuxRequirement> svar{new SymbolVersionAuxRequirement{aux_header}};
|
||||||
if (string_offset != 0) {
|
if (string_offset != 0) {
|
||||||
svar->name({this->stream_->read_string(string_offset + aux_header->vna_name)});
|
svar->name(this->stream_->get_string(string_offset + aux_header->vna_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
symbol_version_requirement->symbol_version_aux_requirement_.push_back(svar.release());
|
symbol_version_requirement->symbol_version_aux_requirement_.push_back(svar.release());
|
||||||
@ -1463,7 +1459,7 @@ void Parser::parse_symbol_version_definition(uint64_t offset, uint32_t nb_entrie
|
|||||||
offset + next_symbol_offset + svd_header->vd_aux + next_aux_offset,
|
offset + next_symbol_offset + svd_header->vd_aux + next_aux_offset,
|
||||||
sizeof(Elf_Verdaux)));
|
sizeof(Elf_Verdaux)));
|
||||||
if (string_offset != 0) {
|
if (string_offset != 0) {
|
||||||
std::string name = {this->stream_->read_string(string_offset + svda_header->vda_name)};
|
std::string name = this->stream_->get_string(string_offset + svda_header->vda_name);
|
||||||
symbol_version_definition->symbol_version_aux_.push_back(new SymbolVersionAux{name});
|
symbol_version_definition->symbol_version_aux_.push_back(new SymbolVersionAux{name});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ void BinaryParser::parse_export_trie(uint64_t start, uint64_t current_offset, ui
|
|||||||
const uint8_t nb_children = this->stream_->read_integer<uint8_t>(children_offset);
|
const uint8_t nb_children = this->stream_->read_integer<uint8_t>(children_offset);
|
||||||
children_offset += sizeof(uint8_t);
|
children_offset += sizeof(uint8_t);
|
||||||
for (size_t i = 0; i < nb_children; ++i) {
|
for (size_t i = 0; i < nb_children; ++i) {
|
||||||
std::string suffix = this->stream_->read_string(children_offset);
|
std::string suffix = this->stream_->get_string(children_offset);
|
||||||
std::string name = prefix + suffix;
|
std::string name = prefix + suffix;
|
||||||
|
|
||||||
children_offset += suffix.size() + 1;
|
children_offset += suffix.size() + 1;
|
||||||
|
@ -152,7 +152,7 @@ void BinaryParser::parse_load_commands(void) {
|
|||||||
|
|
||||||
load_command = std::unique_ptr<DylibCommand>{new DylibCommand{cmd}};
|
load_command = std::unique_ptr<DylibCommand>{new DylibCommand{cmd}};
|
||||||
const uint32_t str_name_offset = cmd->dylib.name;
|
const uint32_t str_name_offset = cmd->dylib.name;
|
||||||
std::string name = {this->stream_->read_string(loadcommands_offset + str_name_offset)};
|
std::string name = this->stream_->get_string(loadcommands_offset + str_name_offset);
|
||||||
|
|
||||||
dynamic_cast<DylibCommand*>(load_command.get())->name(name);
|
dynamic_cast<DylibCommand*>(load_command.get())->name(name);
|
||||||
break;
|
break;
|
||||||
@ -182,9 +182,9 @@ void BinaryParser::parse_load_commands(void) {
|
|||||||
this->stream_->read(loadcommands_offset, sizeof(dylinker_command)));
|
this->stream_->read(loadcommands_offset, sizeof(dylinker_command)));
|
||||||
|
|
||||||
const uint32_t linker_name_offset = cmd->name;
|
const uint32_t linker_name_offset = cmd->name;
|
||||||
std::string name = {this->stream_->read_string(
|
std::string name = this->stream_->get_string(
|
||||||
loadcommands_offset +
|
loadcommands_offset +
|
||||||
linker_name_offset)};
|
linker_name_offset);
|
||||||
|
|
||||||
load_command = std::unique_ptr<DylinkerCommand>{new DylinkerCommand{cmd}};
|
load_command = std::unique_ptr<DylinkerCommand>{new DylinkerCommand{cmd}};
|
||||||
dynamic_cast<DylinkerCommand*>(load_command.get())->name(name);
|
dynamic_cast<DylinkerCommand*>(load_command.get())->name(name);
|
||||||
@ -204,9 +204,9 @@ void BinaryParser::parse_load_commands(void) {
|
|||||||
this->stream_->read(loadcommands_offset, sizeof(prebound_dylib_command)));
|
this->stream_->read(loadcommands_offset, sizeof(prebound_dylib_command)));
|
||||||
|
|
||||||
|
|
||||||
std::string name = {this->stream_->read_string(
|
std::string name = this->stream_->get_string(
|
||||||
loadcommands_offset +
|
loadcommands_offset +
|
||||||
cmd->name)};
|
cmd->name);
|
||||||
|
|
||||||
//uint32_t sizeof_linked_modules = (cmd->nmodules / 8) + (cmd->nmodules % 8);
|
//uint32_t sizeof_linked_modules = (cmd->nmodules / 8) + (cmd->nmodules % 8);
|
||||||
|
|
||||||
@ -308,7 +308,7 @@ void BinaryParser::parse_load_commands(void) {
|
|||||||
uint32_t idx = nlist[j].n_strx;
|
uint32_t idx = nlist[j].n_strx;
|
||||||
if (idx > 0) {
|
if (idx > 0) {
|
||||||
symbol->name(
|
symbol->name(
|
||||||
this->stream_->read_string(cmd->stroff + idx));
|
this->stream_->get_string(cmd->stroff + idx));
|
||||||
}
|
}
|
||||||
this->binary_->symbols_.push_back(symbol.release());
|
this->binary_->symbols_.push_back(symbol.release());
|
||||||
}
|
}
|
||||||
@ -879,7 +879,7 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
|||||||
|
|
||||||
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
||||||
{
|
{
|
||||||
symbol_name = this->stream_->read_string(current_offset);
|
symbol_name = this->stream_->get_string(current_offset);
|
||||||
current_offset += symbol_name.size() + 1;
|
current_offset += symbol_name.size() + 1;
|
||||||
|
|
||||||
if ((imm & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) {
|
if ((imm & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) {
|
||||||
@ -1069,7 +1069,7 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
|||||||
|
|
||||||
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
||||||
{
|
{
|
||||||
symbol_name = this->stream_->read_string(current_offset);
|
symbol_name = this->stream_->get_string(current_offset);
|
||||||
current_offset += symbol_name.size() + 1;
|
current_offset += symbol_name.size() + 1;
|
||||||
|
|
||||||
if ((imm & BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) != 0) {
|
if ((imm & BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) != 0) {
|
||||||
@ -1289,7 +1289,7 @@ void BinaryParser::parse_dyldinfo_lazy_bind() {
|
|||||||
|
|
||||||
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
||||||
{
|
{
|
||||||
symbol_name = this->stream_->read_string(current_offset);
|
symbol_name = this->stream_->get_string(current_offset);
|
||||||
current_offset += symbol_name.size() + 1;
|
current_offset += symbol_name.size() + 1;
|
||||||
|
|
||||||
if ((imm & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) {
|
if ((imm & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) {
|
||||||
@ -1366,26 +1366,17 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
|
|||||||
// Address to bind
|
// Address to bind
|
||||||
uint64_t address = segment.virtual_address() + segment_offset;
|
uint64_t address = segment.virtual_address() + segment_offset;
|
||||||
|
|
||||||
// Check if a relocation already exists:
|
std::unique_ptr<RelocationDyld> new_relocation{new RelocationDyld{address, type}};
|
||||||
Relocation* reloc = nullptr;
|
auto&& result = segment.relocations_.emplace(new_relocation.get());
|
||||||
std::unique_ptr<Relocation> new_relocation{nullptr};
|
Relocation* reloc = *result.first;
|
||||||
bool reloc_exists = false;
|
if (result.second) {
|
||||||
|
new_relocation.release();
|
||||||
auto&& it_reloc = std::find_if(
|
|
||||||
std::begin(segment.relocations_),
|
|
||||||
std::end(segment.relocations_),
|
|
||||||
[address] (const Relocation* r) {
|
|
||||||
return r->address() == address;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (it_reloc != std::end(segment.relocations_)) {
|
|
||||||
reloc = *it_reloc;
|
|
||||||
reloc_exists = true;
|
|
||||||
} else {
|
} else {
|
||||||
new_relocation = std::unique_ptr<Relocation>{new RelocationDyld{address, type}};
|
delete new_relocation.release();
|
||||||
reloc = new_relocation.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
reloc->architecture_ = this->binary_->header().cpu_type();
|
reloc->architecture_ = this->binary_->header().cpu_type();
|
||||||
|
|
||||||
switch (static_cast<BIND_TYPES>(type)) {
|
switch (static_cast<BIND_TYPES>(type)) {
|
||||||
@ -1445,9 +1436,7 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
|
|||||||
LOG(ERROR) << "New symbol found: " << symbol_name;
|
LOG(ERROR) << "New symbol found: " << symbol_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not reloc_exists) {
|
|
||||||
segment.relocations_.emplace(new_relocation.release());
|
|
||||||
}
|
|
||||||
this->binary_->dyld_info().binding_info_.push_back(binding_info.release());
|
this->binary_->dyld_info().binding_info_.push_back(binding_info.release());
|
||||||
VLOG(VDEBUG) << to_string(cls) << segment.name() << " - " << symbol_name;
|
VLOG(VDEBUG) << to_string(cls) << segment.name() << " - " << symbol_name;
|
||||||
}
|
}
|
||||||
@ -1467,15 +1456,13 @@ void BinaryParser::do_rebase(uint8_t type, uint8_t segment_idx, uint64_t segment
|
|||||||
uint64_t address = segment.virtual_address() + segment_offset;
|
uint64_t address = segment.virtual_address() + segment_offset;
|
||||||
|
|
||||||
// Check if a relocation already exists:
|
// Check if a relocation already exists:
|
||||||
Relocation* reloc = nullptr;
|
std::unique_ptr<RelocationDyld> new_relocation{new RelocationDyld{address, type}};
|
||||||
bool reloc_exists = false;
|
auto&& result = segment.relocations_.emplace(new_relocation.get());
|
||||||
|
Relocation* reloc = *result.first;
|
||||||
reloc = new RelocationDyld{address, type};
|
if (result.second) {
|
||||||
auto&& it_reloc = segment.relocations_.find(reloc);
|
new_relocation.release();
|
||||||
if (it_reloc != std::end(segment.relocations_)) {
|
} else {
|
||||||
delete reloc;
|
delete new_relocation.release();
|
||||||
reloc = *it_reloc;
|
|
||||||
reloc_exists = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reloc->architecture_ = this->binary_->header().cpu_type();
|
reloc->architecture_ = this->binary_->header().cpu_type();
|
||||||
@ -1500,9 +1487,6 @@ void BinaryParser::do_rebase(uint8_t type, uint8_t segment_idx, uint64_t segment
|
|||||||
LOG(ERROR) << "Unsuported relocation type: 0x" << std::hex << type;
|
LOG(ERROR) << "Unsuported relocation type: 0x" << std::hex << type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (not reloc_exists) {
|
|
||||||
segment.relocations_.insert(it_reloc, reloc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ set(LIEF_MACHO_SRC
|
|||||||
"${CMAKE_CURRENT_LIST_DIR}/Binary.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/Binary.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/UUIDCommand.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/UUIDCommand.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/Symbol.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/Symbol.cpp"
|
||||||
|
"${CMAKE_CURRENT_LIST_DIR}/FatBinary.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/EnumToString.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/EnumToString.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/Header.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/Header.cpp"
|
||||||
"${CMAKE_CURRENT_LIST_DIR}/DynamicSymbolCommand.cpp"
|
"${CMAKE_CURRENT_LIST_DIR}/DynamicSymbolCommand.cpp"
|
||||||
@ -47,6 +48,7 @@ set(LIEF_MACHO_SRC
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(LIEF_MACHO_INCLUDE_FILES
|
set(LIEF_MACHO_INCLUDE_FILES
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/FatBinary.hpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/Binary.hpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/Binary.hpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/BinaryParser.hpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/BinaryParser.hpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/Builder.hpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/Builder.hpp"
|
||||||
|
101
src/MachO/FatBinary.cpp
Normal file
101
src/MachO/FatBinary.cpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/* Copyright 2017 R. Thomas
|
||||||
|
* Copyright 2017 Quarkslab
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#include <numeric>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
#include "LIEF/MachO/FatBinary.hpp"
|
||||||
|
|
||||||
|
namespace LIEF {
|
||||||
|
namespace MachO {
|
||||||
|
|
||||||
|
FatBinary::FatBinary(void) :
|
||||||
|
binaries_{}
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
FatBinary::FatBinary(const std::vector<Binary*>& binaries) :
|
||||||
|
binaries_{binaries}
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
size_t FatBinary::size(void) const {
|
||||||
|
return this->binaries_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
it_binaries FatBinary::begin(void) {
|
||||||
|
return this->binaries_;
|
||||||
|
}
|
||||||
|
|
||||||
|
it_const_binaries FatBinary::begin(void) const {
|
||||||
|
return this->binaries_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
it_binaries FatBinary::end(void) {
|
||||||
|
return it_binaries{this->binaries_}.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
it_const_binaries FatBinary::end(void) const {
|
||||||
|
return it_const_binaries{this->binaries_}.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Binary& FatBinary::at(size_t index) {
|
||||||
|
return const_cast<Binary&>(static_cast<const FatBinary*>(this)->at(index));
|
||||||
|
}
|
||||||
|
const Binary& FatBinary::at(size_t index) const {
|
||||||
|
if (index >= this->size()) {
|
||||||
|
throw std::out_of_range("Bad index");
|
||||||
|
}
|
||||||
|
return *this->binaries_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Binary& FatBinary::back(void) {
|
||||||
|
return const_cast<Binary&>(static_cast<const FatBinary*>(this)->back());
|
||||||
|
}
|
||||||
|
const Binary& FatBinary::back(void) const {
|
||||||
|
return *this->binaries_.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
Binary& FatBinary::operator[](size_t index) {
|
||||||
|
return const_cast<Binary&>(static_cast<const FatBinary*>(this)->operator[](index));
|
||||||
|
}
|
||||||
|
|
||||||
|
const Binary& FatBinary::operator[](size_t index) const {
|
||||||
|
return this->at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const FatBinary& fatbinary) {
|
||||||
|
for (const Binary& binary : fatbinary) {
|
||||||
|
os << binary;
|
||||||
|
os << std::endl << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatBinary::~FatBinary(void) {
|
||||||
|
for (Binary* b : this->binaries_) {
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -51,13 +51,13 @@ Parser::Parser(const std::string& file) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<Binary*> Parser::parse(const std::string& filename) {
|
FatBinary* Parser::parse(const std::string& filename) {
|
||||||
if (not is_macho(filename)) {
|
if (not is_macho(filename)) {
|
||||||
throw bad_file("'" + filename + "' is not a MachO binary");
|
throw bad_file("'" + filename + "' is not a MachO binary");
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser parser{filename};
|
Parser parser{filename};
|
||||||
return parser.binaries_;
|
return new FatBinary{parser.binaries_};
|
||||||
}
|
}
|
||||||
|
|
||||||
// From Vector
|
// From Vector
|
||||||
@ -73,13 +73,13 @@ Parser::Parser(const std::vector<uint8_t>& data, const std::string& name) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<Binary*> Parser::parse(const std::vector<uint8_t>& data, const std::string& name) {
|
FatBinary* Parser::parse(const std::vector<uint8_t>& data, const std::string& name) {
|
||||||
if (not is_macho(data)) {
|
if (not is_macho(data)) {
|
||||||
throw bad_file("'" + name + "' is not a MachO binary");
|
throw bad_file("'" + name + "' is not a MachO binary");
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser parser{data, name};
|
Parser parser{data, name};
|
||||||
return parser.binaries_;
|
return new FatBinary{parser.binaries_};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,6 +210,9 @@ void Parser::build_sections(void) {
|
|||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (size_to_read > Parser::MAX_DATA_SIZE) {
|
||||||
|
LOG(WARNING) << "Section '" << section->name() << "' data is too large!";
|
||||||
|
} else {
|
||||||
const uint8_t* ptr_to_rawdata = reinterpret_cast<const uint8_t*>(this->stream_->read(
|
const uint8_t* ptr_to_rawdata = reinterpret_cast<const uint8_t*>(this->stream_->read(
|
||||||
offset,
|
offset,
|
||||||
size_to_read));
|
size_to_read));
|
||||||
@ -218,6 +221,7 @@ void Parser::build_sections(void) {
|
|||||||
ptr_to_rawdata,
|
ptr_to_rawdata,
|
||||||
ptr_to_rawdata + size_to_read
|
ptr_to_rawdata + size_to_read
|
||||||
};
|
};
|
||||||
|
}
|
||||||
} catch (const std::bad_alloc& e) {
|
} catch (const std::bad_alloc& e) {
|
||||||
LOG(WARNING) << "Section " << section->name() << " corrupted: " << e.what();
|
LOG(WARNING) << "Section " << section->name() << " corrupted: " << e.what();
|
||||||
} catch (const read_out_of_bound& e) {
|
} catch (const read_out_of_bound& e) {
|
||||||
@ -464,7 +468,7 @@ void Parser::build_symbols(void) {
|
|||||||
this->binary_->header().numberof_symbols() * STRUCT_SIZES::Symbol16Size +
|
this->binary_->header().numberof_symbols() * STRUCT_SIZES::Symbol16Size +
|
||||||
offset;
|
offset;
|
||||||
try {
|
try {
|
||||||
symbol.name_ = this->stream_->read_string(offset_name);
|
symbol.name_ = this->stream_->get_string(offset_name);
|
||||||
} catch (const LIEF::read_out_of_bound&) { // Corrupted
|
} catch (const LIEF::read_out_of_bound&) { // Corrupted
|
||||||
LOG(WARNING) << "Symbol name is corrupted";
|
LOG(WARNING) << "Symbol name is corrupted";
|
||||||
}
|
}
|
||||||
@ -577,7 +581,7 @@ void Parser::build_exports(void) {
|
|||||||
uint32_t name_offset = this->binary_->rva_to_offset(export_directory_table->NameRVA);
|
uint32_t name_offset = this->binary_->rva_to_offset(export_directory_table->NameRVA);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
export_object.name_ = this->stream_->read_string(name_offset);
|
export_object.name_ = this->stream_->get_string(name_offset);
|
||||||
} catch (const LIEF::read_out_of_bound& e) {
|
} catch (const LIEF::read_out_of_bound& e) {
|
||||||
LOG(WARNING) << e.what();
|
LOG(WARNING) << e.what();
|
||||||
}
|
}
|
||||||
@ -617,7 +621,7 @@ void Parser::build_exports(void) {
|
|||||||
|
|
||||||
ExportEntry entry;
|
ExportEntry entry;
|
||||||
try {
|
try {
|
||||||
entry.name_ = this->stream_->read_string(name_offset);
|
entry.name_ = this->stream_->get_string(name_offset);
|
||||||
} catch (const LIEF::read_out_of_bound& e) {
|
} catch (const LIEF::read_out_of_bound& e) {
|
||||||
LOG(WARNING) << e.what();
|
LOG(WARNING) << e.what();
|
||||||
}
|
}
|
||||||
|
@ -271,7 +271,7 @@ void Parser::build_import_table(void) {
|
|||||||
}
|
}
|
||||||
// Offset to the Import (Library) name
|
// Offset to the Import (Library) name
|
||||||
const uint64_t offsetName = this->binary_->rva_to_offset(import.name_RVA_);
|
const uint64_t offsetName = this->binary_->rva_to_offset(import.name_RVA_);
|
||||||
import.name_ = this->stream_->read_string(offsetName);
|
import.name_ = this->stream_->get_string(offsetName);
|
||||||
|
|
||||||
|
|
||||||
// We assume that a DLL name should be at least 4 length size and "printable
|
// We assume that a DLL name should be at least 4 length size and "printable
|
||||||
@ -329,7 +329,7 @@ void Parser::build_import_table(void) {
|
|||||||
|
|
||||||
if(not entry.is_ordinal()) {
|
if(not entry.is_ordinal()) {
|
||||||
|
|
||||||
entry.name_ = this->stream_->read_string(
|
entry.name_ = this->stream_->get_string(
|
||||||
this->binary_->rva_to_offset(entry.hint_name_rva()) + sizeof(uint16_t));
|
this->binary_->rva_to_offset(entry.hint_name_rva()) + sizeof(uint16_t));
|
||||||
|
|
||||||
entry.hint_ = *reinterpret_cast<const uint16_t*>(
|
entry.hint_ = *reinterpret_cast<const uint16_t*>(
|
||||||
@ -368,19 +368,26 @@ void Parser::build_tls(void) {
|
|||||||
|
|
||||||
const uint64_t imagebase = this->binary_->optional_header().imagebase();
|
const uint64_t imagebase = this->binary_->optional_header().imagebase();
|
||||||
|
|
||||||
try {
|
const uint64_t start_data_rva = tls_header->RawDataStartVA - imagebase;
|
||||||
const uint64_t startDataRVA = tls_header->RawDataStartVA - imagebase;
|
const uint64_t stop_data_rva = tls_header->RawDataEndVA - imagebase;
|
||||||
const uint64_t stopDataRVA = tls_header->RawDataEndVA - imagebase;
|
|
||||||
const uint__ offsetStartTemplate = this->binary_->rva_to_offset(startDataRVA);
|
|
||||||
const uint__ offsetEndTemplate = this->binary_->rva_to_offset(stopDataRVA);
|
|
||||||
|
|
||||||
|
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!";
|
||||||
|
} else {
|
||||||
const uint8_t* template_ptr = reinterpret_cast<const uint8_t*>(
|
const uint8_t* template_ptr = reinterpret_cast<const uint8_t*>(
|
||||||
this->stream_->read(offsetStartTemplate, offsetEndTemplate - offsetStartTemplate));
|
this->stream_->read(start_template_offset, size_to_read));
|
||||||
std::vector<uint8_t> templateData = {
|
std::vector<uint8_t> template_data = {
|
||||||
template_ptr,
|
template_ptr,
|
||||||
template_ptr + offsetEndTemplate - offsetStartTemplate
|
template_ptr + size_to_read
|
||||||
};
|
};
|
||||||
tls.data_template(templateData);
|
tls.data_template(std::move(template_data));
|
||||||
|
}
|
||||||
|
|
||||||
} catch (const read_out_of_bound&) {
|
} catch (const read_out_of_bound&) {
|
||||||
throw corrupted("TLS corrupted (data template)");
|
throw corrupted("TLS corrupted (data template)");
|
||||||
@ -388,13 +395,15 @@ void Parser::build_tls(void) {
|
|||||||
throw corrupted("TLS corrupted (data template)");
|
throw corrupted("TLS corrupted (data template)");
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint64_t offsetToCallbacks = this->binary_->rva_to_offset(tls.addressof_callbacks() - imagebase);
|
uint64_t callbacks_offset = this->binary_->rva_to_offset(tls.addressof_callbacks() - imagebase);
|
||||||
const uint__ *rvaCallbacksAddress = reinterpret_cast<const uint__*>(
|
uint__ callback_rva = this->stream_->read_integer<uint__>(callbacks_offset);
|
||||||
this->stream_->read(offsetToCallbacks, sizeof(uint__)));
|
callbacks_offset += sizeof(uint__);
|
||||||
|
|
||||||
while (*rvaCallbacksAddress != 0) {
|
size_t count = 0;
|
||||||
tls.callbacks_.push_back(static_cast<uint64_t>(*rvaCallbacksAddress));
|
while (callback_rva > 0 and count < Parser::MAX_TLS_CALLBACKS) {
|
||||||
rvaCallbacksAddress++;
|
tls.callbacks_.push_back(static_cast<uint64_t>(callback_rva));
|
||||||
|
callback_rva = this->stream_->read_integer<uint__>(callbacks_offset);
|
||||||
|
callbacks_offset += sizeof(uint__);
|
||||||
}
|
}
|
||||||
|
|
||||||
tls.directory_ = &(this->binary_->data_directory(DATA_DIRECTORY::TLS_TABLE));
|
tls.directory_ = &(this->binary_->data_directory(DATA_DIRECTORY::TLS_TABLE));
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
include(ProcessorCount)
|
||||||
find_package(Git REQUIRED)
|
find_package(Git REQUIRED)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
@ -329,6 +330,11 @@ add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/macho")
|
|||||||
# /!\ Bad Hack /!\
|
# /!\ Bad Hack /!\
|
||||||
add_dependencies(LIB_LIEF_STATIC lief_samples)
|
add_dependencies(LIB_LIEF_STATIC lief_samples)
|
||||||
add_dependencies(LIB_LIEF_SHARED lief_samples)
|
add_dependencies(LIB_LIEF_SHARED lief_samples)
|
||||||
|
ProcessorCount(N)
|
||||||
|
if(N EQUAL 0)
|
||||||
|
set(N 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_custom_target(check-lief COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
|
|
||||||
|
add_custom_target(check-lief COMMAND ${CMAKE_CTEST_COMMAND} --parallel 1 --output-on-failure
|
||||||
DEPENDS lief_samples)
|
DEPENDS lief_samples)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@echo off
|
@echo on
|
||||||
|
|
||||||
|
|
||||||
set PYTHONPATH=%PYTHONPATH%;@PROJECT_BINARY_DIR@/api/python
|
set PYTHONPATH=%PYTHONPATH%;@PROJECT_BINARY_DIR@/api/python
|
||||||
|
Loading…
x
Reference in New Issue
Block a user