Skip to content
Permalink
Browse files
Parse Mach-O 'Version Min' command
Resolve: #44
  • Loading branch information
romainthomas committed Jul 27, 2017
1 parent f330fa8 commit 5b99311
Show file tree
Hide file tree
Showing 15 changed files with 334 additions and 12 deletions.
@@ -10,6 +10,7 @@ set(LIEF_PYTHON_MACHO_SRC
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbol.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyUUID.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySourceVersion.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyVersionMin.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyMainCommand.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDylinker.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDyldInfo.cpp"
@@ -159,6 +159,16 @@ void init_MachO_Binary_class(py::module& m) {
"Return binary's " RST_CLASS_REF(lief.MachO.SourceVersion) " if any.",
py::return_value_policy::reference)

.def_property_readonly("has_version_min",
&Binary::has_version_min,
"``True`` if the binary has a " RST_CLASS_REF(lief.MachO.VersionMin) " command.",
py::return_value_policy::reference_internal)

.def_property_readonly("version_min",
static_cast<no_const_getter<VersionMin&>>(&Binary::version_min),
"Return binary's " RST_CLASS_REF(lief.MachO.VersionMin) " if any.",
py::return_value_policy::reference)

.def("virtual_address_to_offset",
&Binary::virtual_address_to_offset,
"Convert the virtual address to an offset in the binary",
@@ -0,0 +1,68 @@
/* 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 <string>
#include <sstream>

#include "LIEF/visitors/Hash.hpp"
#include "LIEF/MachO/VersionMin.hpp"

#include "pyMachO.hpp"

template<class T>
using getter_t = T (VersionMin::*)(void) const;

template<class T>
using setter_t = void (VersionMin::*)(T);


void init_MachO_VersionMin_class(py::module& m) {

py::class_<VersionMin, LoadCommand>(m, "VersionMin")

.def_property("version",
static_cast<getter_t<const VersionMin::version_t&>>(&VersionMin::version),
static_cast<setter_t<const VersionMin::version_t&>>(&VersionMin::version),
"Version as a tuple of **3** integers",
py::return_value_policy::reference_internal)


.def_property("sdk",
static_cast<getter_t<const VersionMin::version_t&>>(&VersionMin::sdk),
static_cast<setter_t<const VersionMin::version_t&>>(&VersionMin::sdk),
"SDK as a tuple of **3** integers",
py::return_value_policy::reference_internal)


.def("__eq__", &VersionMin::operator==)
.def("__ne__", &VersionMin::operator!=)
.def("__hash__",
[] (const VersionMin& version) {
return LIEF::Hash::hash(version);
})


.def("__str__",
[] (const VersionMin& version)
{
std::ostringstream stream;
stream << version;
std::string str = stream.str();
return str;
});

}
@@ -40,6 +40,7 @@ void init_MachO_module(py::module& m) {
init_MachO_DyldInfo_class(LIEF_MachO_module);
init_MachO_FunctionStarts_class(LIEF_MachO_module);
init_MachO_SourceVersion_class(LIEF_MachO_module);
init_MachO_VersionMin_class(LIEF_MachO_module);
init_MachO_Relocation_class(LIEF_MachO_module);


@@ -40,6 +40,7 @@ void init_MachO_DylinkerCommand_class(py::module&);
void init_MachO_DyldInfo_class(py::module&);
void init_MachO_FunctionStarts_class(py::module&);
void init_MachO_SourceVersion_class(py::module&);
void init_MachO_VersionMin_class(py::module&);
void init_MachO_Relocation_class(py::module&);

// Enums
@@ -143,6 +143,15 @@ Source Version

----------


Version Min
***********

.. doxygenclass:: LIEF::MachO::VersionMin
:project: lief

----------

Relocation
**********

@@ -152,6 +152,17 @@ Source Version
----------


Version Min
***********

.. autoclass:: lief.MachO.VersionMin
:members:
:inherited-members:
:undoc-members:

----------


Relocation
**********

@@ -297,6 +297,19 @@ def print_source_version(binary):
print("")


@exceptions_handler(Exception)
def print_version_min(binary):
print("== Version Min ==")

version = binary.version_min.version
sdk = binary.version_min.sdk

print("Version: {:d}.{:d}.{:d}".format(*version))
print("SDK: {:d}.{:d}.{:d}".format(*sdk))

print("")


def main():
parser = argparse.ArgumentParser(usage='%(prog)s [options] <macho-file>')
parser.add_argument('-a', '--all',
@@ -351,6 +364,10 @@ def main():
action='store_true', dest='show_source_version',
help="Display the 'Source Version' command")

parser.add_argument('--version-min',
action='store_true', dest='show_version_min',
help="Display the 'Version Min' command")

parser.add_argument("binary",
metavar="<macho-file>",
help='Target Mach-O File')
@@ -404,6 +421,9 @@ def main():
if (args.show_source_version or args.show_all) and binary.has_source_version:
print_source_version(binary)

if (args.show_version_min or args.show_all) and binary.has_version_min:
print_version_min(binary)


if __name__ == "__main__":
main()
@@ -38,6 +38,7 @@
#include "LIEF/MachO/DyldInfo.hpp"
#include "LIEF/MachO/FunctionStarts.hpp"
#include "LIEF/MachO/SourceVersion.hpp"
#include "LIEF/MachO/VersionMin.hpp"

namespace LIEF {
namespace MachO {
@@ -221,6 +222,13 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
SourceVersion& source_version(void);
const SourceVersion& source_version(void) const;

//! @brief ``true`` if the binary has a MachO::VersionMin command.
bool has_version_min(void) const;

//! @brief Return the MachO::VersionMin command
VersionMin& version_min(void);
const VersionMin& version_min(void) const;

template<class T>
bool has_command(void) const;

@@ -0,0 +1,67 @@
/* 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_VERSION_MIN_COMMAND_H_
#define LIEF_MACHO_VERSION_MIN_COMMAND_H_
#include <string>
#include <vector>
#include <iostream>
#include <array>

#include "LIEF/visibility.h"
#include "LIEF/types.hpp"

#include "LIEF/MachO/LoadCommand.hpp"

namespace LIEF {
namespace MachO {

class DLL_PUBLIC VersionMin : public LoadCommand {

public:
//! @brief Version is an array of **3** integers
using version_t = std::array<uint32_t, 3>;

VersionMin(void);
VersionMin(const version_min_command *version_cmd);

VersionMin& operator=(const VersionMin& copy);
VersionMin(const VersionMin& copy);

virtual ~VersionMin(void);

//! @brief Return the version as an array
const VersionMin::version_t& version(void) const;
void version(const VersionMin::version_t& version);

//! @brief Return the sdk as an array
const VersionMin::version_t& sdk(void) const;
void sdk(const VersionMin::version_t& sdk);

bool operator==(const VersionMin& rhs) const;
bool operator!=(const VersionMin& rhs) const;

virtual void accept(Visitor& visitor) const override;

virtual std::ostream& print(std::ostream& os) const override;

private:
VersionMin::version_t version_;
VersionMin::version_t sdk_;
};

}
}
#endif
@@ -604,6 +604,21 @@ const SourceVersion& Binary::source_version(void) const {
return this->get_command<SourceVersion>();
}

// Version Min
// +++++++++++
bool Binary::has_version_min(void) const {
return this->has_command<VersionMin>();
}

VersionMin& Binary::version_min(void) {
return this->get_command<VersionMin>();
}

const VersionMin& Binary::version_min(void) const {
return this->get_command<VersionMin>();
}





@@ -16,6 +16,7 @@
#include "LIEF/MachO/DyldInfo.hpp"
#include "LIEF/MachO/FunctionStarts.hpp"
#include "LIEF/MachO/SourceVersion.hpp"
#include "LIEF/MachO/VersionMin.hpp"

#include "easylogging++.h"

@@ -279,20 +280,20 @@ void BinaryParser::parse_load_commands(void) {
break;
}

//case LOAD_COMMAND_TYPES::LC_VERSION_MIN_MACOSX:
//case LOAD_COMMAND_TYPES::LC_VERSION_MIN_IPHONEOS:
// {
// LOG(DEBUG) << "[+] Parsing " << to_string(static_cast<LOAD_COMMAND_TYPES>(command->cmd));
case LOAD_COMMAND_TYPES::LC_VERSION_MIN_MACOSX:
case LOAD_COMMAND_TYPES::LC_VERSION_MIN_IPHONEOS:
{
LOG(DEBUG) << "[+] 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)));
// LOG(DEBUG) << "Version: " << std::hex << cmd->version;
// LOG(DEBUG) << "SDK: " << std::hex << cmd->sdk;
const version_min_command* cmd =
reinterpret_cast<const version_min_command*>(
this->stream_->read(loadcommands_offset, sizeof(version_min_command)));
LOG(DEBUG) << "Version: " << std::hex << cmd->version;
LOG(DEBUG) << "SDK: " << std::hex << cmd->sdk;

// load_command = new LoadCommand{command};
// break;
// }
load_command = new VersionMin{cmd};
break;
}



@@ -37,6 +37,7 @@ set(LIEF_MACHO_SRC
"${CMAKE_CURRENT_LIST_DIR}/BinaryParser.tcc"
"${CMAKE_CURRENT_LIST_DIR}/FunctionStarts.cpp"
"${CMAKE_CURRENT_LIST_DIR}/SourceVersion.cpp"
"${CMAKE_CURRENT_LIST_DIR}/VersionMin.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Relocation.cpp"
)

@@ -63,6 +64,7 @@ set(LIEF_MACHO_INCLUDE_FILES
"${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/MachO/Structures.hpp"
"${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/MachO/enums.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/SourceVersion.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/VersionMin.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/Relocation.hpp"
)

0 comments on commit 5b99311

Please sign in to comment.