Skip to content
Permalink
Browse files
Show Mach-O opcodes and export-trie
  • Loading branch information
romainthomas committed Mar 2, 2018
1 parent 135aeab commit 5d56141
Show file tree
Hide file tree
Showing 24 changed files with 1,104 additions and 23 deletions.
@@ -60,6 +60,11 @@ void init_MachO_DyldInfo_class(py::module& m) {
static_cast<setter_t<const buffer_t&>>(&DyldInfo::rebase_opcodes),
"Return Rebase's opcodes as ``list`` of bytes")

.def_property_readonly("show_rebases_opcodes",
&DyldInfo::show_rebases_opcodes,
"Return the rebase opcodes in a humman-readable way",
py::return_value_policy::reference_internal)

.def_property("bind",
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::bind),
static_cast<setter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::bind),
@@ -86,6 +91,11 @@ void init_MachO_DyldInfo_class(py::module& m) {
static_cast<setter_t<const buffer_t&>>(&DyldInfo::bind_opcodes),
"Return Binding's opcodes as ``list`` of bytes")

.def_property_readonly("show_bind_opcodes",
&DyldInfo::show_bind_opcodes,
"Return the bind opcodes in a humman-readable way",
py::return_value_policy::reference_internal)


.def_property("weak_bind",
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::weak_bind),
@@ -116,6 +126,10 @@ void init_MachO_DyldInfo_class(py::module& m) {
static_cast<setter_t<const buffer_t&>>(&DyldInfo::weak_bind_opcodes),
"Return **Weak** binding's opcodes as ``list`` of bytes")

.def_property_readonly("show_weak_bind_opcodes",
&DyldInfo::show_weak_bind_opcodes,
"Return the weak bind opcodes in a humman-readable way",
py::return_value_policy::reference_internal)

.def_property("lazy_bind",
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::lazy_bind),
@@ -143,6 +157,11 @@ void init_MachO_DyldInfo_class(py::module& m) {
static_cast<setter_t<const buffer_t&>>(&DyldInfo::lazy_bind_opcodes),
"Return **lazy** binding's opcodes as ``list`` of bytes")

.def_property_readonly("show_lazy_bind_opcodes",
&DyldInfo::show_lazy_bind_opcodes,
"Return the weak bind opcodes in a humman-readable way",
py::return_value_policy::reference_internal)

.def_property_readonly("bindings",
static_cast<no_const_getter<it_binding_info>>(&DyldInfo::bindings),
"Return an iterator over Dyld's " RST_CLASS_REF(lief.MachO.BindingInfo) "",
@@ -190,6 +209,11 @@ void init_MachO_DyldInfo_class(py::module& m) {
"Return an iterator over Dyld's " RST_CLASS_REF(lief.MachO.ExportInfo) "",
py::return_value_policy::reference_internal)

.def_property_readonly("show_export_trie",
&DyldInfo::show_export_trie,
"Return the export trie in a humman-readable way",
py::return_value_policy::reference_internal)

.def("set_rebase_offset",
&DyldInfo::set_rebase_offset,
"offset"_a)
@@ -58,6 +58,10 @@ void init_MachO_Symbol_class(py::module& m) {
&Symbol::has_export_info,
"``True`` if the symbol has a " RST_CLASS_REF(lief.MachO.ExportInfo) " associated with")

.def_property_readonly("origin",
&Symbol::origin,
"Return the " RST_CLASS_REF(lief.MachO.SYMBOL_ORIGINS) " of this symbol")

.def_property_readonly("export_info",
static_cast<ExportInfo& (Symbol::*)(void)>(&Symbol::export_info),
"" RST_CLASS_REF(lief.MachO.ExportInfo) " associated with the symbol (if any)",
@@ -316,6 +316,13 @@ void init_MachO_Structures_enum(py::module& m) {
.export_values();


py::enum_<LIEF::MachO::SYMBOL_ORIGINS>(m, "SYMBOL_ORIGINS")
.value(PY_ENUM(LIEF::MachO::SYMBOL_ORIGINS::SYM_ORIGIN_UNKNOWN))
.value(PY_ENUM(LIEF::MachO::SYMBOL_ORIGINS::SYM_ORIGIN_DYLD_EXPORT))
.value(PY_ENUM(LIEF::MachO::SYMBOL_ORIGINS::SYM_ORIGIN_LC_SYMTAB))
.export_values();





@@ -327,3 +327,6 @@ Enums
.. doxygenenum:: LIEF::MachO::VM_PROTECTIONS
:project: lief

.. doxygenenum:: LIEF::MachO::SYMBOL_ORIGINS
:project: lief

@@ -482,3 +482,14 @@ VM_PROTECTIONS
:members:
:inherited-members:
:undoc-members:


----------

SYMBOL_ORIGINS
~~~~~~~~~~~~~~

.. autoclass:: lief.MachO.SYMBOL_ORIGINS
:members:
:inherited-members:
:undoc-members:
@@ -23,6 +23,7 @@

terminal_columns = int(terminal_columns)
terminal_rows = int(terminal_rows)
EXIT_STATUS = 0

class exceptions_handler(object):
func = None
@@ -38,6 +39,9 @@ def __call__(self, *args, **kwargs):
try:
return self.func(*args, **kwargs)
except self.exceptions as e:
global EXIT_STATUS
print("{} raised: {}".format(self.func.__name__, e))
EXIT_STATUS = 1
if self.on_except_callback is not None:
self.on_except_callback(e)
else:
@@ -363,6 +367,47 @@ def print_dyld_info(binary):

print("")


@exceptions_handler(Exception)
def print_rebase_opcodes(binary):
print("== Rebase opcodes ==")

print(binary.dyld_info.show_rebases_opcodes)

print("")

@exceptions_handler(Exception)
def print_bind_opcodes(binary):
print("== Bind opcodes ==")

print(binary.dyld_info.show_bind_opcodes)

print("")

@exceptions_handler(Exception)
def print_weak_bind_opcodes(binary):
print("== Weak bind opcodes ==")

print(binary.dyld_info.show_weak_bind_opcodes)

print("")

@exceptions_handler(Exception)
def print_lazy_bind_opcodes(binary):
print("== Lazy bind opcodes ==")

print(binary.dyld_info.show_lazy_bind_opcodes)

print("")

@exceptions_handler(Exception)
def print_export_trie(binary):
print("== Export trie ==")

print(binary.dyld_info.show_export_trie)

print("")

@exceptions_handler(Exception)
def print_source_version(binary):
print("== Source Version ==")
@@ -506,6 +551,10 @@ def main():
action='store_true', dest='show_function_starts',
help='Display the FunctionStarts command')

parser.add_argument('--rebase-opcodes',
action='store_true', dest='show_rebase_opcodes',
help='Display the "Rebase" opcodes')

parser.add_argument('--source-version',
action='store_true', dest='show_source_version',
help="Display the 'Source Version' command")
@@ -522,6 +571,26 @@ def main():
action='store_true', dest='show_rpath_command',
help="Display the 'Rpath Command' command")

parser.add_argument('--bind-opcodes',
action='store_true', dest='show_bind_opcodes',
help='Display the "Bind" opcodes')

parser.add_argument('--weak-bind-opcodes',
action='store_true', dest='show_weak_bind_opcodes',
help='Display the "Weak Bind" opcodes')

parser.add_argument('--lazy-bind-opcodes',
action='store_true', dest='show_lazy_bind_opcodes',
help='Display the "Lazy Bind" opcodes')

parser.add_argument('--export-trie',
action='store_true', dest='show_export_trie',
help='Display the export trie')

parser.add_argument('--opcodes',
action='store_true', dest='show_opcodes',
help='Display the bind and rebase opcodes')

parser.add_argument("binary",
metavar="<macho-file>",
help='Target Mach-O File')
@@ -587,6 +656,23 @@ def main():
if (args.show_rpath_command or args.show_all) and binary.has_rpath:
print_rpath_command(binary)

if (args.show_rebase_opcodes or args.show_opcodes) and binary.has_dyld_info:
print_rebase_opcodes(binary)

if (args.show_bind_opcodes or args.show_opcodes) and binary.has_dyld_info:
print_bind_opcodes(binary)

if (args.show_weak_bind_opcodes or args.show_opcodes) and binary.has_dyld_info:
print_weak_bind_opcodes(binary)

if (args.show_lazy_bind_opcodes or args.show_opcodes) and binary.has_dyld_info:
print_lazy_bind_opcodes(binary)

if (args.show_export_trie or args.show_opcodes) and binary.has_dyld_info:
print_export_trie(binary)

sys.exit(EXIT_STATUS)


if __name__ == "__main__":
main()
@@ -20,6 +20,7 @@
#include <iostream>
#include <array>

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

@@ -46,9 +47,11 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
DyldInfo(void);
DyldInfo(const dyld_info_command *dyld_info_cmd);

DyldInfo& operator=(const DyldInfo& copy);
DyldInfo& operator=(DyldInfo other);
DyldInfo(const DyldInfo& copy);

void swap(DyldInfo& other);

virtual ~DyldInfo(void);

//! @brief *Rebase* information
@@ -73,6 +76,10 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
//! @brief Set new opcodes
void rebase_opcodes(const buffer_t& raw);


//! Return the rebase opcodes in a humman-readable way
std::string show_rebases_opcodes(void) const;

//! @brief *Bind* information
//!
//! Dyld binds an image during the loading process, if the image
@@ -96,6 +103,9 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
//! @brief Set new opcodes
void bind_opcodes(const buffer_t& raw);

//! Return the bind opcodes in a humman-readable way
std::string show_bind_opcodes(void) const;

//! @brief *Weak Bind* information
//!
//! Some C++ programs require dyld to unique symbols so that all
@@ -122,6 +132,9 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
//! @brief Set new opcodes
void weak_bind_opcodes(const buffer_t& raw);

//! Return the bind opcodes in a humman-readable way
std::string show_weak_bind_opcodes(void) const;

//! @brief *Lazy Bind* information
//!
//! Some uses of external symbols do not need to be bound immediately.
@@ -145,6 +158,9 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
//! @brief Set new opcodes
void lazy_bind_opcodes(const buffer_t& raw);

//! Return the lazy opcodes in a humman-readable way
std::string show_lazy_bind_opcodes(void) const;

//! @brief Iterator over BindingInfo entries
it_binding_info bindings(void);
it_const_binding_info bindings(void) const;
@@ -188,6 +204,9 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
//! @brief Set new trie
void export_trie(const buffer_t& raw);

//! Return the export trie in a humman-readable way
std::string show_export_trie(void) const;

void rebase(const info_t& info);
void bind(const info_t& info);
void weak_bind(const info_t& info);
@@ -217,6 +236,10 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
virtual std::ostream& print(std::ostream& os) const override;

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;

info_t rebase_;
buffer_t rebase_opcodes_;

@@ -235,6 +258,8 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
export_info_t export_info_;
binding_info_t binding_info_;

Binary* binary_{nullptr};

};

}
@@ -47,6 +47,7 @@ DLL_PUBLIC const char* to_string(BIND_SPECIAL_DYLIB e);
DLL_PUBLIC const char* to_string(BIND_OPCODES e);
DLL_PUBLIC const char* to_string(EXPORT_SYMBOL_KINDS e);
DLL_PUBLIC const char* to_string(VM_PROTECTIONS e);
DLL_PUBLIC const char* to_string(SYMBOL_ORIGINS e);

} // namespace MachO
} // namespace LIEF
@@ -37,6 +37,8 @@ class DLL_PUBLIC LoadCommand : public Visitable {
LoadCommand& operator=(const LoadCommand& copy);
LoadCommand(const LoadCommand& copy);

void swap(LoadCommand& other);

virtual ~LoadCommand(void);

LOAD_COMMAND_TYPES command(void) const;
@@ -72,6 +72,8 @@ class DLL_PUBLIC Symbol : public LIEF::Symbol {

bool is_external(void) const;

SYMBOL_ORIGINS origin(void) const;

virtual void accept(Visitor& visitor) const override;

bool operator==(const Symbol& rhs) const;
@@ -87,6 +89,8 @@ class DLL_PUBLIC Symbol : public LIEF::Symbol {

BindingInfo* binding_info_;
ExportInfo* export_info_;

SYMBOL_ORIGINS origin_;
};

}
@@ -270,7 +270,7 @@ enum BIND_OPCODES {
};

enum EXPORT_SYMBOL_FLAGS {
EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03u,
EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03u, ///< Mask to access to EXPORT_SYMBOL_KINDS
EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION = 0x04u,
EXPORT_SYMBOL_FLAGS_REEXPORT = 0x08u,
EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER = 0x10u
@@ -387,6 +387,13 @@ enum RELOCATION_ORIGINS {
ORIGIN_RELOC_TABLE = 2,
};


enum SYMBOL_ORIGINS {
SYM_ORIGIN_UNKNOWN = 0,
SYM_ORIGIN_DYLD_EXPORT = 1,
SYM_ORIGIN_LC_SYMTAB = 2,
};

enum X86_RELOCATION {
GENERIC_RELOC_VANILLA = 0, /**< A generic relocation entry for both addresses contained in data and addresses contained in CPU instructions. */
GENERIC_RELOC_PAIR = 1, /**< The second relocation entry of a pair. */

0 comments on commit 5d56141

Please sign in to comment.