#!/usr/bin/env python import unittest import lief import tempfile import sys import subprocess import stat import os import logging import random import itertools from subprocess import Popen from unittest import TestCase from utils import get_sample class TestMachODyld(TestCase): def setUp(self): self.logger = logging.getLogger(__name__) def test_exports_trie(self): target = lief.parse(get_sample('MachO/MachO64_x86-64_binary_exports-trie-LLVM.bin')) self.assertTrue(target.has_dyld_info) exports = target.dyld_info.exports self.assertEqual(len(exports), 6) self.assertEqual(exports[0].address, 0) self.assertEqual(exports[0].symbol.name, "_malloc") self.assertEqual(exports[1].address, 0) self.assertEqual(exports[1].symbol.name, "_myfree") self.assertEqual(exports[2].address, 0xf70) self.assertEqual(exports[2].symbol.name, "_myWeak") self.assertEqual(exports[3].address, 0x1018) self.assertEqual(exports[3].symbol.name, "_myTLV") self.assertEqual(exports[4].address, 0x12345678) self.assertEqual(exports[4].symbol.name, "_myAbs") self.assertEqual(exports[5].address, 0xf60) self.assertEqual(exports[5].symbol.name, "_foo") def test_bind(self): target = lief.parse(get_sample('MachO/MachO64_x86-64_binary_bind-LLVM.bin')) self.assertTrue(target.has_dyld_info) bindings = target.dyld_info.bindings self.assertEqual(len(bindings), 7) self.assertEqual(bindings[0].binding_class, lief.MachO.BINDING_CLASS.STANDARD) self.assertEqual(bindings[0].binding_type, lief.MachO.BIND_TYPES.POINTER) self.assertEqual(bindings[0].address, 0x1028) self.assertEqual(bindings[0].symbol.name, "_any") self.assertEqual(bindings[0].segment.name, "__DATA") self.assertEqual(bindings[0].library_ordinal, -2) self.assertEqual(bindings[1].binding_class, lief.MachO.BINDING_CLASS.STANDARD) self.assertEqual(bindings[1].binding_type, lief.MachO.BIND_TYPES.POINTER) self.assertEqual(bindings[1].address, 0x1020) self.assertEqual(bindings[1].symbol.name, "_fromApp") self.assertEqual(bindings[1].segment.name, "__DATA") self.assertEqual(bindings[1].library_ordinal, -1) self.assertEqual(bindings[2].binding_class, lief.MachO.BINDING_CLASS.STANDARD) self.assertEqual(bindings[2].binding_type, lief.MachO.BIND_TYPES.POINTER) self.assertEqual(bindings[2].address, 0x1018) self.assertEqual(bindings[2].symbol.name, "_myfunc") self.assertEqual(bindings[2].segment.name, "__DATA") self.assertEqual(bindings[2].library_ordinal, 0) self.assertEqual(bindings[3].binding_class, lief.MachO.BINDING_CLASS.STANDARD) self.assertEqual(bindings[3].binding_type, lief.MachO.BIND_TYPES.POINTER) self.assertEqual(bindings[3].address, 0x1000) self.assertEqual(bindings[3].symbol.name, "_foo") self.assertEqual(bindings[3].segment.name, "__DATA") self.assertEqual(bindings[3].library.name, "libfoo.dylib") self.assertEqual(bindings[4].binding_class, lief.MachO.BINDING_CLASS.STANDARD) self.assertEqual(bindings[4].binding_type, lief.MachO.BIND_TYPES.POINTER) self.assertEqual(bindings[4].address, 0x1008) self.assertEqual(bindings[4].symbol.name, "_bar") self.assertEqual(bindings[4].segment.name, "__DATA") self.assertEqual(bindings[4].library.name, "libbar.dylib") self.assertEqual(bindings[5].binding_class, lief.MachO.BINDING_CLASS.STANDARD) self.assertEqual(bindings[5].binding_type, lief.MachO.BIND_TYPES.POINTER) self.assertEqual(bindings[5].address, 0x1010) self.assertEqual(bindings[5].symbol.name, "_malloc") self.assertEqual(bindings[5].segment.name, "__DATA") self.assertEqual(bindings[5].library.name, "/usr/lib/libSystem.B.dylib") # From Weak bind self.assertEqual(bindings[6].binding_class, lief.MachO.BINDING_CLASS.WEAK) self.assertEqual(bindings[6].binding_type, lief.MachO.BIND_TYPES.POINTER) self.assertEqual(bindings[6].address, 0x1000) self.assertEqual(bindings[6].symbol.name, "_foo") self.assertEqual(bindings[6].segment.name, "__DATA") def test_lazy_bind(self): target = lief.parse(get_sample('MachO/MachO64_x86-64_binary_lazy-bind-LLVM.bin')) self.assertTrue(target.has_dyld_info) bindings = list(target.dyld_info.bindings)[1:] # Skip the 1st one (Standard one) self.assertEqual(len(bindings), 3) self.assertEqual(bindings[0].binding_class, lief.MachO.BINDING_CLASS.LAZY) self.assertEqual(bindings[0].binding_type, lief.MachO.BIND_TYPES.POINTER) self.assertEqual(bindings[0].address, 0x100001010) self.assertEqual(bindings[0].symbol.name, "_foo") self.assertEqual(bindings[0].segment.name, "__DATA") self.assertEqual(bindings[0].library.name, "libfoo.dylib") self.assertEqual(bindings[1].binding_class, lief.MachO.BINDING_CLASS.LAZY) self.assertEqual(bindings[1].binding_type, lief.MachO.BIND_TYPES.POINTER) self.assertEqual(bindings[1].address, 0x100001018) self.assertEqual(bindings[1].symbol.name, "_bar") self.assertEqual(bindings[1].segment.name, "__DATA") self.assertEqual(bindings[1].library.name, "libbar.dylib") self.assertEqual(bindings[2].binding_class, lief.MachO.BINDING_CLASS.LAZY) self.assertEqual(bindings[2].binding_type, lief.MachO.BIND_TYPES.POINTER) self.assertEqual(bindings[2].address, 0x100001020) self.assertEqual(bindings[2].symbol.name, "_malloc") self.assertEqual(bindings[2].segment.name, "__DATA") self.assertEqual(bindings[2].library.name, "/usr/lib/libSystem.B.dylib") def test_rebases(self): target = lief.parse(get_sample('MachO/MachO64_x86-64_binary_rebase-LLVM.bin')) self.assertTrue(target.has_dyld_info) relocations = target.relocations self.assertEqual(len(relocations), 10) self.assertEqual(relocations[0].address, 0x00001010) self.assertEqual(relocations[0].pc_relative, False) self.assertEqual(relocations[0].type, int(lief.MachO.REBASE_TYPES.POINTER)) self.assertEqual(relocations[0].section.name, "__data") self.assertEqual(relocations[0].segment.name, "__DATA") self.assertEqual(relocations[1].address, 0x00001028) self.assertEqual(relocations[1].pc_relative, False) self.assertEqual(relocations[1].type, int(lief.MachO.REBASE_TYPES.POINTER)) self.assertEqual(relocations[1].section.name, "__data") self.assertEqual(relocations[1].segment.name, "__DATA") self.assertEqual(relocations[2].address, 0x00001030) self.assertEqual(relocations[2].pc_relative, False) self.assertEqual(relocations[2].type, int(lief.MachO.REBASE_TYPES.POINTER)) self.assertEqual(relocations[2].section.name, "__data") self.assertEqual(relocations[2].segment.name, "__DATA") self.assertEqual(relocations[3].address, 0x00001038) self.assertEqual(relocations[3].pc_relative, False) self.assertEqual(relocations[3].type, int(lief.MachO.REBASE_TYPES.POINTER)) self.assertEqual(relocations[3].section.name, "__data") self.assertEqual(relocations[3].segment.name, "__DATA") self.assertEqual(relocations[4].address, 0x00001040) self.assertEqual(relocations[4].pc_relative, False) self.assertEqual(relocations[4].type, int(lief.MachO.REBASE_TYPES.POINTER)) self.assertEqual(relocations[4].section.name, "__data") self.assertEqual(relocations[4].segment.name, "__DATA") self.assertEqual(relocations[5].address, 0x00001258) self.assertEqual(relocations[5].pc_relative, False) self.assertEqual(relocations[5].type, int(lief.MachO.REBASE_TYPES.POINTER)) self.assertEqual(relocations[5].section.name, "__data") self.assertEqual(relocations[5].segment.name, "__DATA") self.assertEqual(relocations[6].address, 0x00001278) self.assertEqual(relocations[6].pc_relative, False) self.assertEqual(relocations[6].type, int(lief.MachO.REBASE_TYPES.POINTER)) self.assertEqual(relocations[6].section.name, "__mystuff") self.assertEqual(relocations[6].segment.name, "__DATA") self.assertEqual(relocations[7].address, 0x00001288) self.assertEqual(relocations[7].pc_relative, False) self.assertEqual(relocations[7].type, int(lief.MachO.REBASE_TYPES.POINTER)) self.assertEqual(relocations[7].section.name, "__mystuff") self.assertEqual(relocations[7].segment.name, "__DATA") self.assertEqual(relocations[8].address, 0x00001298) self.assertEqual(relocations[8].pc_relative, False) self.assertEqual(relocations[8].type, int(lief.MachO.REBASE_TYPES.POINTER)) self.assertEqual(relocations[8].section.name, "__mystuff") self.assertEqual(relocations[8].segment.name, "__DATA") self.assertEqual(relocations[9].address, 0x000012A8) self.assertEqual(relocations[9].pc_relative, False) self.assertEqual(relocations[9].type, int(lief.MachO.REBASE_TYPES.POINTER)) self.assertEqual(relocations[9].section.name, "__mystuff") self.assertEqual(relocations[9].segment.name, "__DATA") if __name__ == '__main__': root_logger = logging.getLogger() root_logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) root_logger.addHandler(ch) unittest.main(verbosity=2)