Exemple #1
0
    def load_dyn_sym(self):
        arch = self.elf.get_machine_arch()

        if arch == "ARM" or arch == "MIPS":
            for (rel, symtab) in self.__iter_reloc():
                self.__resolve_symtab(rel, symtab, arch)
            return

        # x86/x64

        # TODO: .plt can be renamed ?
        plt = self.elf.get_section_by_name(b".plt")

        if plt is None:
            warning(".plt section not found")
            return

        # TODO: .got.plt can be renamed or may be removed ?
        got_plt = self.elf.get_section_by_name(b".got.plt")
        addr_size = 8 if arch == "x64" else 4

        if got_plt is None:
            warning(".got.plt section not found")
            return

        for (rel, symtab) in self.__iter_reloc():
            self.__x86_resolve_reloc(rel, symtab, plt, got_plt, addr_size)
Exemple #2
0
    def load_dyn_sym(self):
        arch = self.elf.get_machine_arch()

        if arch == "ARM" or arch == "MIPS":
            for (rel, symtab) in self.__iter_reloc():
                self.__resolve_symtab(rel, symtab)
            return

        # x86/x64

        # TODO: .plt can be renamed ?
        plt = self.elf.get_section_by_name(b".plt")

        if plt is None:
            warning(".plt section not found")
            return

        # TODO: .got.plt can be renamed or may be removed ?
        got_plt = self.elf.get_section_by_name(b".got.plt")
        addr_size = 8 if arch == "x64" else 4

        if got_plt is None:
            warning(".got.plt section not found")
            return

        for (rel, symtab) in self.__iter_reloc():
            self.__x86_resolve_reloc(rel, symtab, plt, got_plt, addr_size)
Exemple #3
0
    def __x86_resolve_reloc(self, rel, symtab, plt, got_plt, addr_size):
        # Save all got offsets with the corresponding symbol
        got_off = {}
        for r in rel.iter_relocations():
            sym = symtab.get_symbol(r.entry.r_info_sym)
            name = sym.name.decode()
            ad = r.entry.r_offset
            if name and ad:
                ty = self.sym_type_lookup.get(sym.entry.st_info.type, MEM_UNK)
                got_off[ad] = [name + "@plt", ty]

        data = got_plt.data()

        unpack_str = "<" if self.elf.little_endian else ">"
        unpack_str += str(int(len(data) / addr_size))
        unpack_str += "Q" if addr_size == 8 else "I"

        got_values = struct.unpack(unpack_str, data)
        plt_data = plt.data()
        wrong_jump_opcode = False
        off = got_plt.header.sh_addr

        # Read the .got.plt and for each address in the plt, substract 6
        # to go at the begining of the plt entry.

        opcode_jmp = [b"\xff\x25", b"\xff\xa3"]

        for jump_in_plt in got_values:
            if off in got_off:
                plt_start = jump_in_plt - 6
                plt_off = plt_start - plt.header.sh_addr

                # Check "jmp *(ADDR)" opcode.
                if plt_data[plt_off:plt_off+2] not in opcode_jmp:
                    wrong_jump_opcode = True
                    continue

                name, ty = got_off[off]
                if name in self.classbinary.symbols:
                    continue

                self.classbinary.imports[plt_start] = True
                self.classbinary.reverse_symbols[plt_start] = name
                self.classbinary.symbols[name] = plt_start

                self.mem.add(plt_start, 1, ty)

            off += addr_size

        if wrong_jump_opcode:
            warning("I'm expecting to see a jmp *(ADDR) on each plt entry")
            warning("opcode \\xff\\x25 was not found, please report")
Exemple #4
0
    def load(self, filename):
        gc.disable()

        self.__init_vars()

        dirname = os.path.dirname(filename)
        self.path = dirname + "/" if dirname != "" else ""
        self.path += "." + os.path.basename(filename) + ".db"

        if os.path.exists(self.path):
            info("open database %s" % self.path)

            fd = open(self.path, "rb")

            data = self.__check_old_json_db(fd)
            if data is None:
                data = fd.read()
                if data.startswith(b"ZLIB"):
                    data = zlib.decompress(data[4:])
                data = msgpack.unpackb(data, encoding="utf-8")
                fd.close()

            self.__load_meta(data)
            self.__load_memory(data)
            self.__load_symbols(data)
            self.__load_jmptables(data)
            self.__load_comments(data)
            self.__load_functions(data)
            self.__load_history(data)
            self.__load_xrefs(data)
            self.__load_imports(data)

            if self.version <= 1.5:
                self.__load_labels(data)

            if self.version != VERSION:
                warning(
                    "the database version is old, some information may be missing"
                )

            self.loaded = True

        gc.enable()
Exemple #5
0
def init_entry_addr(ctx):
    if ctx.calls_in_section is not None:
        s = ctx.dis.binary.get_section_by_name(ctx.calls_in_section)
        if s is None:
            error("section %s not found" % ctx.calls_in_section)
            if ctx.interactive:
                return False
            die()
        entry_addr = s.start

    elif ctx.entry == "EP":
        entry_addr = ctx.dis.binary.get_entry_point()

    else:
        try:
            entry_addr = ctx.dis.get_addr_from_string(ctx.entry,
                                                      ctx.raw_type != None)

            # An exception is raised if the symbol was not found
            if ctx.entry is None:
                ctx.entry = "main"
        except ExcSymNotFound as e:
            error("symbol %s not found" % e.symname)
            if ctx.interactive:
                return False
            error("You can see all symbols with -s (if resolution is done).")
            error("Note: --dump need the option -x.")
            die()

    s = ctx.dis.binary.get_section(entry_addr)
    if s is None:
        error("the address 0x%x was not found" % entry_addr)
        if ctx.interactive:
            return False
        die()

    if not s.is_exec:
        warning("the address 0x%x is not in an executable section" %
                entry_addr)

    ctx.entry_addr = entry_addr

    return True
Exemple #6
0
def init_entry_addr(ctx):
    if ctx.calls_in_section is not None:
        try:
            entry_addr = ctx.dis.binary.section_start(ctx.calls_in_section)
        except ExcSectionNotFound as e:
            error("section %s not found" % e.section)
            if ctx.interactive:
                return False
            die()

    elif ctx.entry == "EP":
        entry_addr = ctx.dis.binary.get_entry_point()

    else:
        try:
            entry_addr = ctx.dis.get_addr_from_string(ctx.entry, ctx.raw_type != None)

            # An exception is raised if the symbol was not found
            if ctx.entry is None:
                ctx.entry = "main"
        except ExcSymNotFound as e:
            error("symbol %s not found" % e.symname)
            if ctx.interactive:
                return False
            error("You can see all symbols with -s (if resolution is done).")
            error("Note: --dump need the option -x.")
            die()

    try:
        ctx.dis.check_addr(ctx, entry_addr)
    except ExcNotExec as e:
        warning("the address 0x%x is not in an executable section" % e.addr)
    except ExcNotAddr as e:
        error("the address 0x%x cannot be found" % e.addr)
        if ctx.interactive:
            return False
        die()

    ctx.entry_addr = entry_addr

    return True
Exemple #7
0
    def load(self, filename):
        gc.disable()

        self.__init_vars()

        dirname = os.path.dirname(filename)
        self.path = dirname + "/" if dirname != "" else ""
        self.path +=  "." + os.path.basename(filename) + ".db"

        if os.path.exists(self.path):
            info("open database %s" % self.path)

            fd = open(self.path, "rb")

            data = self.__check_old_json_db(fd)
            if data is None:
                data = fd.read()
                if data.startswith(b"ZLIB"):
                    data = zlib.decompress(data[4:])
                data = msgpack.unpackb(data, encoding="utf-8")
                fd.close()

            self.__load_meta(data)
            self.__load_memory(data)
            self.__load_symbols(data)
            self.__load_jmptables(data)
            self.__load_comments(data)
            self.__load_functions(data)
            self.__load_history(data)
            self.__load_xrefs(data)
            self.__load_imports(data)

            if self.version <= 1.5:
                self.__load_labels(data)

            if self.version != VERSION:
                warning("the database version is old, some information may be missing")

            self.loaded = True

        gc.enable()
Exemple #8
0
    def __x86_resolve_reloc(self, rel, symtab, plt, got_plt, addr_size):
        # Save all got offsets with the corresponding symbol
        got_off = {}
        for r in rel.iter_relocations():
            sym = symtab.get_symbol(r.entry.r_info_sym)
            got_off[r.entry.r_offset] = sym.name.decode() + "@plt"

        data = got_plt.data()

        unpack_str = "<" if self.elf.little_endian else ">"
        unpack_str += str(int(len(data) / addr_size))
        unpack_str += "Q" if addr_size == 8 else "I"

        got_values = struct.unpack(unpack_str, data)
        plt_data = plt.data()
        wrong_jump_opcode = False
        off = got_plt.header.sh_addr

        # Read the .got.plt and for each address in the plt, substract 6
        # to go at the begining of the plt entry.
        for jump_in_plt in got_values:
            if off in got_off:
                plt_start = jump_in_plt - 6
                plt_off = plt_start - plt.header.sh_addr

                # Check "jmp *(ADDR)" opcode.
                if plt_data[plt_off:plt_off + 2] != b"\xff\x25":
                    wrong_jump_opcode = True
                    continue

                name = got_off[off]
                self.classbinary.reverse_symbols[plt_start] = name
                self.classbinary.symbols[name] = plt_start

            off += addr_size

        if wrong_jump_opcode:
            warning("I'm expecting to see a jmp *(ADDR) on each plt entry")
            warning("opcode \\xff\\x25 was not found, please report")
Exemple #9
0
    def __x86_resolve_reloc(self, rel, symtab, plt, got_plt, addr_size):
        # Save all got offsets with the corresponding symbol
        got_off = {}
        for r in rel.iter_relocations():
            sym = symtab.get_symbol(r.entry.r_info_sym)
            got_off[r.entry.r_offset] = sym.name.decode() + "@plt"

        data = got_plt.data()

        unpack_str = "<" if self.elf.little_endian else ">"
        unpack_str += str(int(len(data) / addr_size))
        unpack_str += "Q" if addr_size == 8 else "I"

        got_values = struct.unpack(unpack_str, data)
        plt_data = plt.data()
        wrong_jump_opcode = False
        off = got_plt.header.sh_addr

        # Read the .got.plt and for each address in the plt, substract 6
        # to go at the begining of the plt entry.
        for jump_in_plt in got_values:
            if off in got_off:
                plt_start = jump_in_plt - 6
                plt_off = plt_start - plt.header.sh_addr

                # Check "jmp *(ADDR)" opcode.
                if plt_data[plt_off:plt_off+2] != b"\xff\x25":
                    wrong_jump_opcode = True
                    continue

                name = got_off[off]
                self.classbinary.reverse_symbols[plt_start] = name
                self.classbinary.symbols[name] = plt_start

            off += addr_size

        if wrong_jump_opcode:
            warning("I'm expecting to see a jmp *(ADDR) on each plt entry")
            warning("opcode \\xff\\x25 was not found, please report")
Exemple #10
0
    def __init__(self):
        self.__init_vars()

        if msgpack.version < (0, 4, 6):
            warning("your version of msgpack is less than 0.4.6")
Exemple #11
0
import pefile
from capstone.x86 import (X86_OP_INVALID, X86_OP_IMM, X86_OP_MEM, X86_REG_RIP,
                          X86_REG_EIP)
from ctypes import sizeof

from lib.exceptions import ExcPEFail
from lib.fileformat.pefile2 import PE2, SymbolEntry, PE_DT_FCN
from lib.fileformat.binary import SectionAbs, SYM_UNK, SYM_FUNC
from lib.utils import warning

try:
    # This folder is not present in simonzack/pefile-py3k
    import ordlookup
except:
    warning("you should use the most recent port of pefile")
    warning("https://github.com/mlaferrera/python3-pefile")
    pass


class PE:
    def __init__(self, classbinary, filename):
        import capstone as CAPSTONE

        self.classbinary = classbinary
        self.pe = PE2(filename, fast_load=True)
        self.__data_sections = []
        self.__data_sections_content = []
        self.__exec_sections = []

        self.arch_lookup = {
Exemple #12
0
    def __init__(self):
        self.__init_vars()

        if msgpack.version < (0, 4, 6):
            warning("your version of msgpack is less than 0.4.6")
Exemple #13
0
import pefile
from capstone.x86 import (X86_OP_INVALID, X86_OP_IMM, X86_OP_MEM, X86_REG_RIP,
        X86_REG_EIP)
from ctypes import sizeof

from lib.exceptions import ExcPEFail
from lib.fileformat.pefile2 import PE2, SymbolEntry, PE_DT_FCN
from lib.fileformat.binary import SectionAbs
from lib.utils import warning
from lib.memory import MEM_FUNC, MEM_UNK

try:
    # This folder is not present in simonzack/pefile-py3k
    import ordlookup
except:
    warning("you should use the most recent port of pefile")
    warning("https://github.com/mlaferrera/python3-pefile")
    pass


class PE:
    def __init__(self, mem, classbinary, filename):
        import capstone as CAPSTONE

        self.classbinary = classbinary
        self.mem = mem

        self.pe = PE2(filename, fast_load=True)
        self.__data_sections = []
        self.__data_sections_content = []
        self.__exec_sections = []